Merge lp:~wiml-omni/libdrizzle/date-time into lp:libdrizzle

Proposed by Wim Lewis
Status: Merged
Approved by: Andrew Hutchings
Approved revision: 115
Merged at revision: 111
Proposed branch: lp:~wiml-omni/libdrizzle/date-time
Merge into: lp:libdrizzle
Diff against target: 279 lines (+95/-66)
5 files modified
libdrizzle-5.1/constants.h (+2/-0)
libdrizzle/pack.cc (+50/-44)
libdrizzle/pack.h (+2/-2)
libdrizzle/statement.cc (+2/-2)
libdrizzle/statement_param.cc (+39/-18)
To merge this branch: bzr merge lp:~wiml-omni/libdrizzle/date-time
Reviewer Review Type Date Requested Status
Wim Lewis (community) Needs Fixing
Andrew Hutchings Approve
Review via email: mp+156381@code.launchpad.net

Commit message

This fixes a handful of bugs related to dates and times in prepared statements, mostly found by the datetypes unit test.

Description of the change

This fixes a handful of bugs related to dates and times in prepared statements, mostly found by the datetypes unit test.

To post a comment you must log in.
Revision history for this message
Andrew Hutchings (linuxjedi) wrote :

Many great fixes :)

review: Approve
Revision history for this message
Andrew Hutchings (linuxjedi) wrote :

So, there are two problems that flagged up when trying to merge this. I don't quite see how they are related to this branch yet, but:

Ubuntu 12.04:

../tests/unit/numbers.c:307: main Assertion 'FLOAT_EQ_EXACT(col_dblval, expect_dblval)' [ Floating-point values 291.000000 != 291.271111 (difference is -0.271111) ]
Row 1
  Column 2: 1 "1" 1.000000
  Column 3: 1 "1" 1.000000
  Column 4: 1 "1" 1.000000
  Column 5: 1 "1" 1.000000
  Column 6: 1 "1" 1.000000
  Column 7: 1 "1.000000" 1.000000
  Column 8: 1 "1.000000" 1.000000
Row 2
  Column 2: 127 "127" 127.000000
  Column 3: 32687 "32687" 32687.000000
  Column 4: 8388351 "8388351" 8388351.000000
  Column 5: 2147352575 "2147352575" 2147352575.000000
  Column 6: 9222246136947920895 "9222246136947920895" 9222246136947920896.000000
  Column 7: 443664 "443664.000000" 443664.000000
FAIL: tests/unit/numbers

Fedora 17:
/usr/bin/ld: tests/unit/numbers.o: undefined reference to symbol 'truncf@@GLIBC_2.2.5'
/usr/bin/ld: note: 'truncf@@GLIBC_2.2.5' is defined in DSO /lib64/libm.so.6 so try adding it to the linker command line
/lib64/libm.so.6: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
make[1]: *** [tests/unit/numbers] Error 1

I'll look into these later this evening.

Revision history for this message
Wim Lewis (wiml-omni) wrote :

On 2 Apr 2013, at 11:36 AM, Andrew Hutchings wrote:
> So, there are two problems that flagged up when trying to merge this. I don't quite see how they are related to this branch yet, but:
>
> Ubuntu 12.04:
>
> ../tests/unit/numbers.c:307: main Assertion 'FLOAT_EQ_EXACT(col_dblval, expect_dblval)' [ Floating-point values 291.000000 != 291.271111 (difference is -0.271111) ]

Oho. I've fixed that, but haven't cleaned it up to commit yet, and had forgotten that numbers.c would hit it. (The problem, IIRC, is that drizzle_stmt_get_double() casts the value to uint64 or something before returning it as a double.)

> Fedora 17:
> /usr/bin/ld: tests/unit/numbers.o: undefined reference to symbol 'truncf@@GLIBC_2.2.5'
> /usr/bin/ld: note: 'truncf@@GLIBC_2.2.5' is defined in DSO /lib64/libm.so.6 so try adding it to the linker command line
> /lib64/libm.so.6: could not read symbols: Invalid operation
> collect2: error: ld returned 1 exit status
> make[1]: *** [tests/unit/numbers] Error 1

I guess the unit tests need to be linked against -lm if they're using trunc(). I missed that one since libc and libm are the same library on OSX.

Revision history for this message
Wim Lewis (wiml-omni) wrote :

I'm working on some cleaning up my fixes for the first of those problems and I'll commit them to this branch when I have a chance.

review: Needs Fixing
Revision history for this message
Andrew Hutchings (linuxjedi) wrote :

awesome, thanks.

When that is ready I'll fix the Fedora builder problem.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libdrizzle-5.1/constants.h'
--- libdrizzle-5.1/constants.h 2013-03-05 03:27:07 +0000
+++ libdrizzle-5.1/constants.h 2013-04-01 17:45:26 +0000
@@ -621,6 +621,8 @@
621 ((uint64_t)drizzle_get_byte4(((uint8_t *)__buffer)+4) << 32))621 ((uint64_t)drizzle_get_byte4(((uint8_t *)__buffer)+4) << 32))
622622
623/* Protocol packing macros. */623/* Protocol packing macros. */
624#define drizzle_set_byte1(__buffer, __int) do { \
625 (__buffer)[0] = (uint8_t)(__int); } while (0)
624#define drizzle_set_byte2(__buffer, __int) do { \626#define drizzle_set_byte2(__buffer, __int) do { \
625 (__buffer)[0]= (uint8_t)((__int) & 0xFF); \627 (__buffer)[0]= (uint8_t)((__int) & 0xFF); \
626 (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0)628 (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0)
627629
=== modified file 'libdrizzle/pack.cc'
--- libdrizzle/pack.cc 2013-03-12 16:33:14 +0000
+++ libdrizzle/pack.cc 2013-04-01 17:45:26 +0000
@@ -193,71 +193,78 @@
193{193{
194 uint8_t length= 0;194 uint8_t length= 0;
195195
196 /* If nothing is set then we are sending a 0 length time */
197 if (time->day || time->hour || time->minute || time->second)
198 {
199 ptr[0]= (time->negative) ? 1 : 0;
200 drizzle_set_byte4(&ptr[1], time->day);
201 ptr[5]= (uint8_t) time->hour;
202 ptr[6]= time->minute;
203 ptr[7]= time->second;
204 length= 8;
205 }
206 /* NOTE: MySQL has a bug here and doesn't follow this part of the protocol196 /* NOTE: MySQL has a bug here and doesn't follow this part of the protocol
207 * when packing, we will for now, no idea if it works197 * when packing, we will for now, no idea if it works
208 * */198 * */
209 if (time->microsecond)199 if (time->microsecond)
210 {200 {
211 drizzle_set_byte4(&ptr[8], time->microsecond);201 drizzle_set_byte4(ptr+9, time->microsecond);
212 length= 12;202 length= 12;
213 }203 }
214 return ptr+length;204
205 if (length || time->day || time->hour || time->minute || time->second)
206 {
207 ptr[1]= (time->negative) ? 1 : 0;
208 drizzle_set_byte4(ptr+2, time->day);
209 drizzle_set_byte1(ptr+6, time->hour);
210 drizzle_set_byte1(ptr+7, time->minute);
211 drizzle_set_byte1(ptr+8, time->second);
212 /* If no microseconds, then we are packing 8 bytes */
213 if (!length)
214 length= 8;
215 }
216
217 /* If nothing is set then we are sending a 0 length time */
218
219 drizzle_set_byte1(ptr, length);
220 return ptr + 1 + length;
215}221}
216222
217unsigned char *drizzle_pack_datetime(drizzle_datetime_st *datetime, unsigned char *ptr)223unsigned char *drizzle_pack_datetime(drizzle_datetime_st *datetime, unsigned char *ptr)
218{224{
219 uint8_t length= 0;225 uint8_t length= 0;
220226
227 if (datetime->microsecond)
228 {
229 drizzle_set_byte4(ptr+8, datetime->microsecond);
230 length = 11;
231 }
232
233 if (length || datetime->hour || datetime->minute || datetime->second)
234 {
235 drizzle_set_byte1(ptr+5, datetime->hour);
236 drizzle_set_byte1(ptr+6, datetime->minute);
237 drizzle_set_byte1(ptr+7, datetime->second);
238 /* If only date+time is provided then we are packing 7 bytes */
239 if (!length)
240 length = 7;
241 }
242
243 if (length || datetime->year || datetime->month || datetime->day)
244 {
245 drizzle_set_byte2(ptr+1, datetime->year);
246 drizzle_set_byte1(ptr+3, datetime->month);
247 drizzle_set_byte1(ptr+4, datetime->day);
248 /* If only date is provided then we are packing 4 bytes */
249 if (!length)
250 length = 4;
251 }
252
221 /* If nothing is set then we are sending a 0 length datetime */253 /* If nothing is set then we are sending a 0 length datetime */
222254
223 /* If only date is provided then we are packing 4 bytes */255 drizzle_set_byte1(ptr, length);
224 if (datetime->year || datetime->month || datetime->day)256 return ptr + 1 + length;
225 {
226 drizzle_set_byte2(ptr, datetime->year);
227 ptr[2]= datetime->month;
228 ptr[3]= datetime->day;
229 length= 4;
230 }
231
232 if (datetime->hour || datetime->minute || datetime->second)
233 {
234 ptr[4]= (uint8_t) datetime->hour;
235 ptr[5]= datetime->minute;
236 ptr[6]= datetime->second;
237 length= 7;
238 }
239
240 if (datetime->microsecond)
241 {
242 drizzle_set_byte4(&ptr[7], datetime->microsecond);
243 length= 11;
244 }
245
246 return ptr + length;
247}257}
248258
249void drizzle_unpack_time(drizzle_field_t field, size_t length, unsigned char *data)259void drizzle_unpack_time(drizzle_field_t field, size_t length, drizzle_datetime_st *datetime)
250{260{
251 drizzle_datetime_st *datetime= (drizzle_datetime_st*) data;261 memset(datetime, 0, sizeof(*datetime));
252 memset(datetime, 0, length);
253262
254 if (length)263 if (length)
255 {264 {
256 datetime->negative= field[0];265 datetime->negative= field[0];
257 datetime->day= drizzle_get_byte4(&field[1]);266 datetime->day= drizzle_get_byte4(&field[1]);
258 datetime->hour= field[5];267 datetime->hour= field[5];
259 datetime->hour= datetime->day * 24;
260 datetime->day= 0;
261 datetime->minute= field[6];268 datetime->minute= field[6];
262 datetime->second= field[7];269 datetime->second= field[7];
263 if (length > 8)270 if (length > 8)
@@ -267,10 +274,9 @@
267 }274 }
268}275}
269276
270void drizzle_unpack_datetime(drizzle_field_t field, size_t length, unsigned char *data)277void drizzle_unpack_datetime(drizzle_field_t field, size_t length, drizzle_datetime_st *datetime)
271{278{
272 drizzle_datetime_st *datetime= (drizzle_datetime_st*) data;279 memset(datetime, 0, sizeof(*datetime));
273 memset(datetime, 0, length);
274280
275 if (length)281 if (length)
276 {282 {
277283
=== modified file 'libdrizzle/pack.h'
--- libdrizzle/pack.h 2013-03-06 18:05:42 +0000
+++ libdrizzle/pack.h 2013-04-01 17:45:26 +0000
@@ -79,9 +79,9 @@
7979
80unsigned char *drizzle_pack_datetime(drizzle_datetime_st *datetime, unsigned char *ptr);80unsigned char *drizzle_pack_datetime(drizzle_datetime_st *datetime, unsigned char *ptr);
8181
82void drizzle_unpack_time(drizzle_field_t field, size_t length, unsigned char *data);82void drizzle_unpack_time(drizzle_field_t field, size_t length, drizzle_datetime_st *datetime);
8383
84void drizzle_unpack_datetime(drizzle_field_t field, size_t length, unsigned char *data);84void drizzle_unpack_datetime(drizzle_field_t field, size_t length, drizzle_datetime_st *datetime);
8585
86/**86/**
87 * Unpack length-encoded string.87 * Unpack length-encoded string.
8888
=== modified file 'libdrizzle/statement.cc'
--- libdrizzle/statement.cc 2013-03-21 10:44:02 +0000
+++ libdrizzle/statement.cc 2013-04-01 17:45:26 +0000
@@ -471,13 +471,13 @@
471 break;471 break;
472 case DRIZZLE_COLUMN_TYPE_TIME:472 case DRIZZLE_COLUMN_TYPE_TIME:
473 param->data= param->data_buffer;473 param->data= param->data_buffer;
474 drizzle_unpack_time(row[column_counter], param->length, (unsigned char*)param->data);474 drizzle_unpack_time(row[column_counter], param->length, (drizzle_datetime_st *)param->data);
475 break;475 break;
476 case DRIZZLE_COLUMN_TYPE_DATE:476 case DRIZZLE_COLUMN_TYPE_DATE:
477 case DRIZZLE_COLUMN_TYPE_DATETIME:477 case DRIZZLE_COLUMN_TYPE_DATETIME:
478 case DRIZZLE_COLUMN_TYPE_TIMESTAMP:478 case DRIZZLE_COLUMN_TYPE_TIMESTAMP:
479 param->data= param->data_buffer;479 param->data= param->data_buffer;
480 drizzle_unpack_datetime(row[column_counter], param->length, (unsigned char*)param->data);480 drizzle_unpack_datetime(row[column_counter], param->length, (drizzle_datetime_st *)param->data);
481 break;481 break;
482 case DRIZZLE_COLUMN_TYPE_TINY_BLOB:482 case DRIZZLE_COLUMN_TYPE_TINY_BLOB:
483 case DRIZZLE_COLUMN_TYPE_MEDIUM_BLOB:483 case DRIZZLE_COLUMN_TYPE_MEDIUM_BLOB:
484484
=== modified file 'libdrizzle/statement_param.cc'
--- libdrizzle/statement_param.cc 2013-03-11 17:33:00 +0000
+++ libdrizzle/statement_param.cc 2013-04-01 17:45:26 +0000
@@ -129,6 +129,8 @@
129 drizzle_datetime_st *time;129 drizzle_datetime_st *time;
130 time= (drizzle_datetime_st*) stmt->query_params[param_num].data_buffer;130 time= (drizzle_datetime_st*) stmt->query_params[param_num].data_buffer;
131131
132 bzero(time, sizeof(*time));
133
132 time->negative= is_negative;134 time->negative= is_negative;
133 time->day= days;135 time->day= days;
134 time->hour= hours;136 time->hour= hours;
@@ -145,6 +147,8 @@
145 drizzle_datetime_st *timestamp;147 drizzle_datetime_st *timestamp;
146 timestamp= (drizzle_datetime_st*) stmt->query_params[param_num].data_buffer;148 timestamp= (drizzle_datetime_st*) stmt->query_params[param_num].data_buffer;
147149
150 bzero(timestamp, sizeof(*timestamp));
151
148 timestamp->negative= false;152 timestamp->negative= false;
149 timestamp->year= year;153 timestamp->year= year;
150 timestamp->day= day;154 timestamp->day= day;
@@ -156,7 +160,7 @@
156 timestamp->microsecond= microseconds;160 timestamp->microsecond= microseconds;
157161
158 /* Length not important because we will figure that out when packing */ 162 /* Length not important because we will figure that out when packing */
159 return drizzle_stmt_set_param(stmt, param_num, DRIZZLE_COLUMN_TYPE_TIME, timestamp, 0, false);163 return drizzle_stmt_set_param(stmt, param_num, DRIZZLE_COLUMN_TYPE_TIMESTAMP, timestamp, 0, false);
160}164}
161165
162bool drizzle_stmt_get_is_null_from_name(drizzle_stmt_st *stmt, const char *column_name, drizzle_return_t *ret_ptr)166bool drizzle_stmt_get_is_null_from_name(drizzle_stmt_st *stmt, const char *column_name, drizzle_return_t *ret_ptr)
@@ -619,29 +623,46 @@
619{623{
620 /* Max time is -HHH:MM:SS.ssssss + NUL = 17 */624 /* Max time is -HHH:MM:SS.ssssss + NUL = 17 */
621 char* buffer= param->data_buffer + 50;625 char* buffer= param->data_buffer + 50;
622 if (time->microsecond == 0)626 int buffersize = 17;
623 {627 int used = 0;
624 snprintf(buffer, 17, "%s%"PRIu16":%"PRIu8":%"PRIu8, (time->negative) ? "-" : "", time->hour, time->minute, time->second);628
625 }629 /* Values are transferred with days separated from hours, but presented with days folded into hours. */
626 else630 used = snprintf(buffer, buffersize-used, "%s%02u:%02"PRIu8":%02"PRIu8, (time->negative) ? "-" : "", time->hour + 24 * time->day, time->minute, time->second);
627 {631
628 snprintf(buffer, 17, "%s%"PRIu16":%"PRIu8":%"PRIu8".%"PRIu32, (time->negative) ? "-" : "", time->hour, time->minute, time->second, time->microsecond);632 /* TODO: the existence (and length) of the decimals should be decided based on the number of fields sent by the server or possibly the column's "decimals" value, not by whether the microseconds are 0 */
629 }633 if (time->microsecond)
634 used += snprintf(buffer+used, buffersize-used, ".%06" PRIu32, time->microsecond);
635
636 assert(used < buffersize);
637
630 return buffer;638 return buffer;
631}639}
632640
633char *timestamp_to_string(drizzle_bind_st *param, drizzle_datetime_st *timestamp)641char *timestamp_to_string(drizzle_bind_st *param, drizzle_datetime_st *timestamp)
634{642{
635 /* Max timestamp is YYYY-MM-DD HH:MM:SS.ssssss + NUL = 26 */643 /* Max timestamp is YYYY-MM-DD HH:MM:SS.ssssss + NUL = 27 */
636 char* buffer= param->data_buffer + 50;644 char* buffer= param->data_buffer + 50;
637 if (timestamp->microsecond == 0)645 int buffersize = 27;
638 {646 int used = 0;
639 snprintf(buffer, 26, "%"PRIu16"-%"PRIu8"-%"PRIu32" %"PRIu16":%"PRIu8":%"PRIu8, timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second);647
640 }648 used += snprintf(buffer, buffersize-used, "%"PRIu16"-%02"PRIu8"-%02"PRIu32,
641 else649 timestamp->year, timestamp->month, timestamp->day);
642 {650 assert(used < buffersize);
643 snprintf(buffer, 26, "%"PRIu16"-%"PRIu8"-%"PRIu32" %"PRIu16":%"PRIu8":%"PRIu8".%"PRIu32, timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second, timestamp->microsecond);651
644 }652 if (param->type == DRIZZLE_COLUMN_TYPE_DATE)
653 return buffer;
654
655 used += snprintf(buffer+used, buffersize-used, " %02"PRIu16":%02"PRIu8":%02"PRIu8,
656 timestamp->hour, timestamp->minute, timestamp->second);
657
658 /* TODO: the existence (and length) of the decimals should be decided based on the number of fields sent by the server or possibly the column's "decimals" value, not by whether the microseconds are 0 */
659 if (timestamp->microsecond)
660 {
661 used += snprintf(buffer+used, buffersize-used, ".%06"PRIu32, timestamp->microsecond);
662 }
663
664 assert(used < buffersize);
665
645 return buffer;666 return buffer;
646}667}
647668

Subscribers

People subscribed via source and target branches

to all changes: