@@ -71,11 +71,24 @@ static void rb_mysql_result_mark(void * wrapper) {
71
71
72
72
/* this may be called manually or during GC */
73
73
static void rb_mysql_result_free_result (mysql2_result_wrapper * wrapper ) {
74
+ unsigned int i ;
74
75
if (!wrapper ) return ;
75
76
76
77
if (wrapper -> resultFreed != 1 ) {
77
78
if (wrapper -> stmt ) {
78
79
mysql_stmt_free_result (wrapper -> stmt );
80
+
81
+ if (wrapper -> result_buffers ) {
82
+ for (i = 0 ; i < wrapper -> numberOfFields ; i ++ ) {
83
+ if (wrapper -> result_buffers [i ].buffer ) {
84
+ free (wrapper -> result_buffers [i ].buffer );
85
+ }
86
+ }
87
+ free (wrapper -> result_buffers );
88
+ free (wrapper -> is_null );
89
+ free (wrapper -> error );
90
+ free (wrapper -> length );
91
+ }
79
92
}
80
93
/* FIXME: this may call flush_use_result, which can hit the socket */
81
94
mysql_free_result (wrapper -> result );
@@ -196,78 +209,56 @@ static unsigned int msec_char_to_uint(char *msec_char, size_t len)
196
209
return (unsigned int )strtoul (msec_char , NULL , 10 );
197
210
}
198
211
199
- static VALUE rb_mysql_result_stmt_fetch_row (VALUE self , ID db_timezone , ID app_timezone , int symbolizeKeys , int asArray , int castBool , int cast , MYSQL_FIELD * fields ) {
212
+ static void rb_mysql_result_alloc_result_buffers (VALUE self , MYSQL_FIELD * fields ) {
213
+ unsigned int i ;
200
214
VALUE rowVal ;
201
215
mysql2_result_wrapper * wrapper ;
202
- unsigned int i = 0 ;
203
- MYSQL_BIND * result_buffers ; // FIXME: don't do this every time
204
- my_bool * is_null ;
205
- my_bool * error ;
206
- unsigned long * length ;
207
-
208
- #ifdef HAVE_RUBY_ENCODING_H
209
- rb_encoding * default_internal_enc ;
210
- rb_encoding * conn_enc ;
211
- #endif
212
216
GetMysql2Result (self , wrapper );
213
217
214
- #ifdef HAVE_RUBY_ENCODING_H
215
- default_internal_enc = rb_default_internal_encoding ();
216
- conn_enc = rb_to_encoding (wrapper -> encoding );
217
- #endif
218
-
219
- if (asArray ) {
220
- rowVal = rb_ary_new2 (wrapper -> numberOfFields );
221
- } else {
222
- rowVal = rb_hash_new ();
223
- }
224
- if (wrapper -> fields == Qnil ) {
225
- wrapper -> numberOfFields = mysql_num_fields (wrapper -> result );
226
- wrapper -> fields = rb_ary_new2 (wrapper -> numberOfFields );
227
- }
218
+ if (wrapper -> result_buffers != NULL ) return ;
228
219
229
- result_buffers = xcalloc (wrapper -> numberOfFields , sizeof (MYSQL_BIND ));
230
- is_null = xcalloc (wrapper -> numberOfFields , sizeof (my_bool ));
231
- error = xcalloc (wrapper -> numberOfFields , sizeof (my_bool ));
232
- length = xcalloc (wrapper -> numberOfFields , sizeof (unsigned long ));
220
+ wrapper -> result_buffers = xcalloc (wrapper -> numberOfFields , sizeof (MYSQL_BIND ));
221
+ wrapper -> is_null = xcalloc (wrapper -> numberOfFields , sizeof (my_bool ));
222
+ wrapper -> error = xcalloc (wrapper -> numberOfFields , sizeof (my_bool ));
223
+ wrapper -> length = xcalloc (wrapper -> numberOfFields , sizeof (unsigned long ));
233
224
234
225
for (i = 0 ; i < wrapper -> numberOfFields ; i ++ ) {
235
- result_buffers [i ].buffer_type = fields [i ].type ;
226
+ wrapper -> result_buffers [i ].buffer_type = fields [i ].type ;
236
227
237
228
// mysql type | C type
238
229
switch (fields [i ].type ) {
239
230
case MYSQL_TYPE_NULL : // NULL
240
231
break ;
241
232
case MYSQL_TYPE_TINY : // signed char
242
- result_buffers [i ].buffer = xcalloc (1 , sizeof (signed char ));
243
- result_buffers [i ].buffer_length = sizeof (signed char );
233
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (signed char ));
234
+ wrapper -> result_buffers [i ].buffer_length = sizeof (signed char );
244
235
break ;
245
236
case MYSQL_TYPE_SHORT : // short int
246
- result_buffers [i ].buffer = xcalloc (1 , sizeof (short int ));
247
- result_buffers [i ].buffer_length = sizeof (short int );
237
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (short int ));
238
+ wrapper -> result_buffers [i ].buffer_length = sizeof (short int );
248
239
break ;
249
240
case MYSQL_TYPE_INT24 : // int
250
241
case MYSQL_TYPE_LONG : // int
251
242
case MYSQL_TYPE_YEAR : // int
252
- result_buffers [i ].buffer = xcalloc (1 , sizeof (int ));
253
- result_buffers [i ].buffer_length = sizeof (int );
243
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (int ));
244
+ wrapper -> result_buffers [i ].buffer_length = sizeof (int );
254
245
break ;
255
246
case MYSQL_TYPE_LONGLONG : // long long int
256
- result_buffers [i ].buffer = xcalloc (1 , sizeof (long long int ));
257
- result_buffers [i ].buffer_length = sizeof (long long int );
247
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (long long int ));
248
+ wrapper -> result_buffers [i ].buffer_length = sizeof (long long int );
258
249
break ;
259
250
case MYSQL_TYPE_FLOAT : // float
260
251
case MYSQL_TYPE_DOUBLE : // double
261
- result_buffers [i ].buffer = xcalloc (1 , sizeof (double ));
262
- result_buffers [i ].buffer_length = sizeof (double );
252
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (double ));
253
+ wrapper -> result_buffers [i ].buffer_length = sizeof (double );
263
254
break ;
264
255
case MYSQL_TYPE_TIME : // MYSQL_TIME
265
256
case MYSQL_TYPE_DATE : // MYSQL_TIME
266
257
case MYSQL_TYPE_NEWDATE : // MYSQL_TIME
267
258
case MYSQL_TYPE_DATETIME : // MYSQL_TIME
268
259
case MYSQL_TYPE_TIMESTAMP : // MYSQL_TIME
269
- result_buffers [i ].buffer = xcalloc (1 , sizeof (MYSQL_TIME ));
270
- result_buffers [i ].buffer_length = sizeof (MYSQL_TIME );
260
+ wrapper -> result_buffers [i ].buffer = xcalloc (1 , sizeof (MYSQL_TIME ));
261
+ wrapper -> result_buffers [i ].buffer_length = sizeof (MYSQL_TIME );
271
262
break ;
272
263
case MYSQL_TYPE_DECIMAL : // char[]
273
264
case MYSQL_TYPE_NEWDECIMAL : // char[]
@@ -282,30 +273,52 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
282
273
case MYSQL_TYPE_SET : // char[]
283
274
case MYSQL_TYPE_ENUM : // char[]
284
275
case MYSQL_TYPE_GEOMETRY : // char[]
285
- result_buffers [i ].buffer = malloc (fields [i ].max_length );
286
- result_buffers [i ].buffer_length = fields [i ].max_length ;
276
+ wrapper -> result_buffers [i ].buffer = malloc (fields [i ].max_length );
277
+ wrapper -> result_buffers [i ].buffer_length = fields [i ].max_length ;
287
278
break ;
288
279
default :
289
280
rb_raise (cMysql2Error , "unhandled mysql type: %d" , fields [i ].type );
290
281
}
291
282
292
- result_buffers [i ].is_null = & is_null [i ];
293
- result_buffers [i ].length = & length [i ];
294
- result_buffers [i ].error = & error [i ];
295
- result_buffers [i ].is_unsigned = ((fields [i ].flags & UNSIGNED_FLAG ) != 0 );
283
+ wrapper -> result_buffers [i ].is_null = & wrapper -> is_null [i ];
284
+ wrapper -> result_buffers [i ].length = & wrapper -> length [i ];
285
+ wrapper -> result_buffers [i ].error = & wrapper -> error [i ];
286
+ wrapper -> result_buffers [i ].is_unsigned = ((fields [i ].flags & UNSIGNED_FLAG ) != 0 );
296
287
}
288
+ }
289
+
290
+ static VALUE rb_mysql_result_stmt_fetch_row (VALUE self , ID db_timezone , ID app_timezone , int symbolizeKeys , int asArray , int castBool , int cast , MYSQL_FIELD * fields ) {
291
+ VALUE rowVal ;
292
+ mysql2_result_wrapper * wrapper ;
293
+ unsigned int i = 0 ;
294
+
295
+ #ifdef HAVE_RUBY_ENCODING_H
296
+ rb_encoding * default_internal_enc ;
297
+ rb_encoding * conn_enc ;
298
+ #endif
299
+ GetMysql2Result (self , wrapper );
300
+
301
+ #ifdef HAVE_RUBY_ENCODING_H
302
+ default_internal_enc = rb_default_internal_encoding ();
303
+ conn_enc = rb_to_encoding (wrapper -> encoding );
304
+ #endif
305
+
306
+ if (asArray ) {
307
+ rowVal = rb_ary_new2 (wrapper -> numberOfFields );
308
+ } else {
309
+ rowVal = rb_hash_new ();
310
+ }
311
+ if (wrapper -> fields == Qnil ) {
312
+ wrapper -> numberOfFields = mysql_num_fields (wrapper -> result );
313
+ wrapper -> fields = rb_ary_new2 (wrapper -> numberOfFields );
314
+ }
315
+
316
+ if (wrapper -> result_buffers == NULL ) {
317
+ rb_mysql_result_alloc_result_buffers (self , fields );
318
+ }
319
+
320
+ if (mysql_stmt_bind_result (wrapper -> stmt , wrapper -> result_buffers )) {
297
321
298
- if (mysql_stmt_bind_result (wrapper -> stmt , result_buffers )) {
299
- // FIXME: goto this
300
- for (i = 0 ; i < wrapper -> numberOfFields ; i ++ ) {
301
- if (result_buffers [i ].buffer ) {
302
- free (result_buffers [i ].buffer );
303
- }
304
- }
305
- free (result_buffers );
306
- free (is_null );
307
- free (error );
308
- free (length );
309
322
rb_raise (cMysql2Error , "%s" , mysql_stmt_error (wrapper -> stmt ));
310
323
}
311
324
@@ -318,52 +331,54 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
318
331
VALUE val = Qnil ;
319
332
MYSQL_TIME * ts ;
320
333
321
- if (is_null [i ]) {
334
+ if (wrapper -> is_null [i ]) {
322
335
val = Qnil ;
323
336
} else {
324
- switch (result_buffers [i ].buffer_type ) {
337
+ const MYSQL_BIND * const result_buffer = & wrapper -> result_buffers [i ];
338
+
339
+ switch (result_buffer -> buffer_type ) {
325
340
case MYSQL_TYPE_TINY : // signed char
326
- if (result_buffers [ i ]. is_unsigned ) {
327
- val = UINT2NUM (* ((unsigned char * )result_buffers [ i ]. buffer ));
341
+ if (result_buffer -> is_unsigned ) {
342
+ val = UINT2NUM (* ((unsigned char * )result_buffer -> buffer ));
328
343
} else {
329
- val = INT2NUM (* ((signed char * )result_buffers [ i ]. buffer ));
344
+ val = INT2NUM (* ((signed char * )result_buffer -> buffer ));
330
345
}
331
346
break ;
332
347
case MYSQL_TYPE_SHORT : // short int
333
- if (result_buffers [ i ]. is_unsigned ) {
334
- val = UINT2NUM (* ((unsigned short int * )result_buffers [ i ]. buffer ));
348
+ if (result_buffer -> is_unsigned ) {
349
+ val = UINT2NUM (* ((unsigned short int * )result_buffer -> buffer ));
335
350
} else {
336
- val = INT2NUM (* ((short int * )result_buffers [ i ]. buffer ));
351
+ val = INT2NUM (* ((short int * )result_buffer -> buffer ));
337
352
}
338
353
break ;
339
354
case MYSQL_TYPE_INT24 : // int
340
355
case MYSQL_TYPE_LONG : // int
341
356
case MYSQL_TYPE_YEAR : // int
342
- if (result_buffers [ i ]. is_unsigned ) {
343
- val = UINT2NUM (* ((unsigned int * )result_buffers [ i ]. buffer ));
357
+ if (result_buffer -> is_unsigned ) {
358
+ val = UINT2NUM (* ((unsigned int * )result_buffer -> buffer ));
344
359
} else {
345
- val = INT2NUM (* ((int * )result_buffers [ i ]. buffer ));
360
+ val = INT2NUM (* ((int * )result_buffer -> buffer ));
346
361
}
347
362
break ;
348
363
case MYSQL_TYPE_LONGLONG : // long long int
349
- if (result_buffers [ i ]. is_unsigned ) {
350
- val = ULL2NUM (* ((unsigned long long int * )result_buffers [ i ]. buffer ));
364
+ if (result_buffer -> is_unsigned ) {
365
+ val = ULL2NUM (* ((unsigned long long int * )result_buffer -> buffer ));
351
366
} else {
352
- val = LL2NUM (* ((long long int * )result_buffers [ i ]. buffer ));
367
+ val = LL2NUM (* ((long long int * )result_buffer -> buffer ));
353
368
}
354
369
break ;
355
370
case MYSQL_TYPE_FLOAT : // float
356
- val = rb_float_new ((double )(* ((float * )result_buffers [ i ]. buffer )));
371
+ val = rb_float_new ((double )(* ((float * )result_buffer -> buffer )));
357
372
break ;
358
373
case MYSQL_TYPE_DOUBLE : // double
359
- val = rb_float_new ((double )(* ((double * )result_buffers [ i ]. buffer )));
374
+ val = rb_float_new ((double )(* ((double * )result_buffer -> buffer )));
360
375
break ;
361
376
case MYSQL_TYPE_DATE : // MYSQL_TIME
362
- ts = (MYSQL_TIME * )result_buffers [ i ]. buffer ;
377
+ ts = (MYSQL_TIME * )result_buffer -> buffer ;
363
378
val = rb_funcall (cDate , rb_intern ("new" ), 3 , INT2NUM (ts -> year ), INT2NUM (ts -> month ), INT2NUM (ts -> day ));
364
379
break ;
365
380
case MYSQL_TYPE_TIME : // MYSQL_TIME
366
- ts = (MYSQL_TIME * )result_buffers [ i ]. buffer ;
381
+ ts = (MYSQL_TIME * )result_buffer -> buffer ;
367
382
val = rb_funcall (rb_cTime ,
368
383
rb_intern ("mktime" ), 6 ,
369
384
UINT2NUM (Qnil ),
@@ -376,7 +391,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
376
391
case MYSQL_TYPE_NEWDATE : // MYSQL_TIME
377
392
case MYSQL_TYPE_DATETIME : // MYSQL_TIME
378
393
case MYSQL_TYPE_TIMESTAMP : // MYSQL_TIME
379
- ts = (MYSQL_TIME * )result_buffers [ i ]. buffer ;
394
+ ts = (MYSQL_TIME * )result_buffer -> buffer ;
380
395
val = rb_funcall (rb_cTime ,
381
396
rb_intern ("mktime" ), 6 ,
382
397
UINT2NUM (ts -> year ),
@@ -388,7 +403,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
388
403
break ;
389
404
case MYSQL_TYPE_DECIMAL : // char[]
390
405
case MYSQL_TYPE_NEWDECIMAL : // char[]
391
- val = rb_funcall (cBigDecimal , rb_intern ("new" ), 1 , rb_str_new (result_buffers [ i ]. buffer , * (result_buffers [ i ]. length )));
406
+ val = rb_funcall (cBigDecimal , rb_intern ("new" ), 1 , rb_str_new (result_buffer -> buffer , * (result_buffer -> length )));
392
407
break ;
393
408
case MYSQL_TYPE_STRING : // char[]
394
409
case MYSQL_TYPE_VAR_STRING : // char[]
@@ -401,14 +416,14 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
401
416
case MYSQL_TYPE_SET : // char[]
402
417
case MYSQL_TYPE_ENUM : // char[]
403
418
case MYSQL_TYPE_GEOMETRY : // char[]
404
- val = rb_str_new (result_buffers [ i ]. buffer , * (result_buffers [ i ]. length ));
419
+ val = rb_str_new (result_buffer -> buffer , * (result_buffer -> length ));
405
420
#ifdef HAVE_RUBY_ENCODING_H
406
421
val = mysql2_set_field_string_encoding (val , fields [i ], default_internal_enc , conn_enc );
407
422
#endif
408
423
break ;
409
424
default :
410
425
rb_raise (cMysql2Error , "unhandled buffer type: %d" ,
411
- result_buffers [ i ]. buffer_type );
426
+ result_buffer -> buffer_type );
412
427
break ;
413
428
}
414
429
}
@@ -420,10 +435,6 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
420
435
}
421
436
}
422
437
423
- free (result_buffers );
424
- free (is_null );
425
- free (error );
426
- free (length );
427
438
return rowVal ;
428
439
}
429
440
@@ -996,6 +1007,10 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
996
1007
wrapper -> client_wrapper = DATA_PTR (client );
997
1008
wrapper -> client_wrapper -> refcount ++ ;
998
1009
wrapper -> stmt = s ;
1010
+ wrapper -> result_buffers = NULL ;
1011
+ wrapper -> is_null = NULL ;
1012
+ wrapper -> error = NULL ;
1013
+ wrapper -> length = NULL ;
999
1014
1000
1015
rb_obj_call_init (obj , 0 , NULL );
1001
1016
rb_iv_set (obj , "@query_options" , options );
0 commit comments