@@ -50,6 +50,18 @@ static rb_encoding *binaryEncoding;
5050#define MYSQL2_MIN_TIME 62171150401ULL
5151#endif
5252
53+ typedef struct {
54+ int symbolizeKeys ;
55+ int asArray ;
56+ int castBool ;
57+ int cacheRows ;
58+ int cast ;
59+ int streaming ;
60+ ID db_timezone ;
61+ ID app_timezone ;
62+ int block_given ;
63+ } result_each_args ;
64+
5365VALUE cBigDecimal , cDateTime , cDate ;
5466static VALUE cMysql2Result ;
5567static VALUE opt_decimal_zero , opt_float_zero , opt_time_year , opt_time_month , opt_utc_offset ;
@@ -294,7 +306,8 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
294306 }
295307}
296308
297- static VALUE rb_mysql_result_stmt_fetch_row (VALUE self , ID db_timezone , ID app_timezone , int symbolizeKeys , int asArray , int castBool , MYSQL_FIELD * fields ) {
309+ static VALUE rb_mysql_result_fetch_row_stmt (VALUE self , MYSQL_FIELD * fields , const result_each_args * args )
310+ {
298311 VALUE rowVal ;
299312 mysql2_result_wrapper * wrapper ;
300313 unsigned int i = 0 ;
@@ -310,7 +323,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
310323 conn_enc = rb_to_encoding (wrapper -> encoding );
311324#endif
312325
313- if (asArray ) {
326+ if (args -> asArray ) {
314327 rowVal = rb_ary_new2 (wrapper -> numberOfFields );
315328 } else {
316329 rowVal = rb_hash_new ();
@@ -357,7 +370,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
357370 }
358371
359372 for (i = 0 ; i < wrapper -> numberOfFields ; i ++ ) {
360- VALUE field = rb_mysql_result_fetch_field (self , i , symbolizeKeys );
373+ VALUE field = rb_mysql_result_fetch_field (self , i , args -> symbolizeKeys );
361374 VALUE val = Qnil ;
362375 MYSQL_TIME * ts ;
363376
@@ -368,7 +381,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
368381
369382 switch (result_buffer -> buffer_type ) {
370383 case MYSQL_TYPE_TINY : // signed char
371- if (castBool && fields [i ].length == 1 ) {
384+ if (args -> castBool && fields [i ].length == 1 ) {
372385 val = (* ((unsigned char * )result_buffer -> buffer ) != 0 ) ? Qtrue : Qfalse ;
373386 break ;
374387 }
@@ -414,9 +427,9 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
414427 break ;
415428 case MYSQL_TYPE_TIME : // MYSQL_TIME
416429 ts = (MYSQL_TIME * )result_buffer -> buffer ;
417- val = rb_funcall (rb_cTime , db_timezone , 6 , opt_time_year , opt_time_month , opt_time_month , UINT2NUM (ts -> hour ), UINT2NUM (ts -> minute ), UINT2NUM (ts -> second ));
418- if (!NIL_P (app_timezone )) {
419- if (app_timezone == intern_local ) {
430+ val = rb_funcall (rb_cTime , args -> db_timezone , 6 , opt_time_year , opt_time_month , opt_time_month , UINT2NUM (ts -> hour ), UINT2NUM (ts -> minute ), UINT2NUM (ts -> second ));
431+ if (!NIL_P (args -> app_timezone )) {
432+ if (args -> app_timezone == intern_local ) {
420433 val = rb_funcall (val , intern_localtime , 0 );
421434 } else { // utc
422435 val = rb_funcall (val , intern_utc , 0 );
@@ -432,22 +445,22 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
432445
433446 if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME ) { // use DateTime instead
434447 VALUE offset = INT2NUM (0 );
435- if (db_timezone == intern_local ) {
448+ if (args -> db_timezone == intern_local ) {
436449 offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
437450 }
438451 val = rb_funcall (cDateTime , intern_civil , 7 , UINT2NUM (ts -> year ), UINT2NUM (ts -> month ), UINT2NUM (ts -> day ), UINT2NUM (ts -> hour ), UINT2NUM (ts -> minute ), UINT2NUM (ts -> second ), offset );
439- if (!NIL_P (app_timezone )) {
440- if (app_timezone == intern_local ) {
452+ if (!NIL_P (args -> app_timezone )) {
453+ if (args -> app_timezone == intern_local ) {
441454 offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
442455 val = rb_funcall (val , intern_new_offset , 1 , offset );
443456 } else { // utc
444457 val = rb_funcall (val , intern_new_offset , 1 , opt_utc_offset );
445458 }
446459 }
447460 } else {
448- val = rb_funcall (rb_cTime , db_timezone , 6 , UINT2NUM (ts -> year ), UINT2NUM (ts -> month ), UINT2NUM (ts -> day ), UINT2NUM (ts -> hour ), UINT2NUM (ts -> minute ), UINT2NUM (ts -> second ));
449- if (!NIL_P (app_timezone )) {
450- if (app_timezone == intern_local ) {
461+ val = rb_funcall (rb_cTime , args -> db_timezone , 6 , UINT2NUM (ts -> year ), UINT2NUM (ts -> month ), UINT2NUM (ts -> day ), UINT2NUM (ts -> hour ), UINT2NUM (ts -> minute ), UINT2NUM (ts -> second ));
462+ if (!NIL_P (args -> app_timezone )) {
463+ if (args -> app_timezone == intern_local ) {
451464 val = rb_funcall (val , intern_localtime , 0 );
452465 } else { // utc
453466 val = rb_funcall (val , intern_utc , 0 );
@@ -483,7 +496,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
483496 }
484497 }
485498
486- if (asArray ) {
499+ if (args -> asArray ) {
487500 rb_ary_push (rowVal , val );
488501 } else {
489502 rb_hash_aset (rowVal , field , val );
@@ -494,7 +507,8 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
494507}
495508
496509
497- static VALUE rb_mysql_result_fetch_row (VALUE self , ID db_timezone , ID app_timezone , int symbolizeKeys , int asArray , int castBool , int cast , MYSQL_FIELD * fields ) {
510+ static VALUE rb_mysql_result_fetch_row (VALUE self , MYSQL_FIELD * fields , const result_each_args * args )
511+ {
498512 VALUE rowVal ;
499513 mysql2_result_wrapper * wrapper ;
500514 MYSQL_ROW row ;
@@ -518,7 +532,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
518532 return Qnil ;
519533 }
520534
521- if (asArray ) {
535+ if (args -> asArray ) {
522536 rowVal = rb_ary_new2 (wrapper -> numberOfFields );
523537 } else {
524538 rowVal = rb_hash_new ();
@@ -530,12 +544,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
530544 }
531545
532546 for (i = 0 ; i < wrapper -> numberOfFields ; i ++ ) {
533- VALUE field = rb_mysql_result_fetch_field (self , i , symbolizeKeys );
547+ VALUE field = rb_mysql_result_fetch_field (self , i , args -> symbolizeKeys );
534548 if (row [i ]) {
535549 VALUE val = Qnil ;
536550 enum enum_field_types type = fields [i ].type ;
537551
538- if (!cast ) {
552+ if (!args -> cast ) {
539553 if (type == MYSQL_TYPE_NULL ) {
540554 val = Qnil ;
541555 } else {
@@ -550,14 +564,14 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
550564 val = Qnil ;
551565 break ;
552566 case MYSQL_TYPE_BIT : /* BIT field (MySQL 5.0.3 and up) */
553- if (castBool && fields [i ].length == 1 ) {
567+ if (args -> castBool && fields [i ].length == 1 ) {
554568 val = * row [i ] == 1 ? Qtrue : Qfalse ;
555569 }else {
556570 val = rb_str_new (row [i ], fieldLengths [i ]);
557571 }
558572 break ;
559573 case MYSQL_TYPE_TINY : /* TINYINT field */
560- if (castBool && fields [i ].length == 1 ) {
574+ if (args -> castBool && fields [i ].length == 1 ) {
561575 val = * row [i ] != '0' ? Qtrue : Qfalse ;
562576 break ;
563577 }
@@ -600,9 +614,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
600614 break ;
601615 }
602616 msec = msec_char_to_uint (msec_char , sizeof (msec_char ));
603- val = rb_funcall (rb_cTime , db_timezone , 7 , opt_time_year , opt_time_month , opt_time_month , UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
604- if (!NIL_P (app_timezone )) {
605- if (app_timezone == intern_local ) {
617+ val = rb_funcall (rb_cTime , args -> db_timezone , 7 , opt_time_year , opt_time_month , opt_time_month , UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
618+ if (!NIL_P (args -> app_timezone )) {
619+ if (args -> app_timezone == intern_local ) {
606620 val = rb_funcall (val , intern_localtime , 0 );
607621 } else { /* utc */
608622 val = rb_funcall (val , intern_utc , 0 );
@@ -633,12 +647,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
633647 } else {
634648 if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME ) { /* use DateTime for larger date range, does not support microseconds */
635649 VALUE offset = INT2NUM (0 );
636- if (db_timezone == intern_local ) {
650+ if (args -> db_timezone == intern_local ) {
637651 offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
638652 }
639653 val = rb_funcall (cDateTime , intern_civil , 7 , UINT2NUM (year ), UINT2NUM (month ), UINT2NUM (day ), UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), offset );
640- if (!NIL_P (app_timezone )) {
641- if (app_timezone == intern_local ) {
654+ if (!NIL_P (args -> app_timezone )) {
655+ if (args -> app_timezone == intern_local ) {
642656 offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
643657 val = rb_funcall (val , intern_new_offset , 1 , offset );
644658 } else { /* utc */
@@ -647,9 +661,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
647661 }
648662 } else {
649663 msec = msec_char_to_uint (msec_char , sizeof (msec_char ));
650- val = rb_funcall (rb_cTime , db_timezone , 7 , UINT2NUM (year ), UINT2NUM (month ), UINT2NUM (day ), UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
651- if (!NIL_P (app_timezone )) {
652- if (app_timezone == intern_local ) {
664+ val = rb_funcall (rb_cTime , args -> db_timezone , 7 , UINT2NUM (year ), UINT2NUM (month ), UINT2NUM (day ), UINT2NUM (hour ), UINT2NUM (min ), UINT2NUM (sec ), UINT2NUM (msec ));
665+ if (!NIL_P (args -> app_timezone )) {
666+ if (args -> app_timezone == intern_local ) {
653667 val = rb_funcall (val , intern_localtime , 0 );
654668 } else { /* utc */
655669 val = rb_funcall (val , intern_utc , 0 );
@@ -699,13 +713,13 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
699713 break ;
700714 }
701715 }
702- if (asArray ) {
716+ if (args -> asArray ) {
703717 rb_ary_push (rowVal , val );
704718 } else {
705719 rb_hash_aset (rowVal , field , val );
706720 }
707721 } else {
708- if (asArray ) {
722+ if (args -> asArray ) {
709723 rb_ary_push (rowVal , Qnil );
710724 } else {
711725 rb_hash_aset (rowVal , field , Qnil );
@@ -743,19 +757,10 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
743757 return wrapper -> fields ;
744758}
745759
746- typedef struct {
747- int symbolizeKeys ;
748- int asArray ;
749- int castBool ;
750- int cacheRows ;
751- int cast ;
752- int streaming ;
753- ID db_timezone ;
754- ID app_timezone ;
755- int block_given ;
756- } result_each_args ;
757-
758- static VALUE rb_mysql_result_each_nonstmt (VALUE self , const result_each_args * args ) {
760+ static VALUE rb_mysql_result_each_ (VALUE self ,
761+ VALUE (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args ),
762+ const result_each_args * args )
763+ {
759764 mysql2_result_wrapper * wrapper ;
760765 unsigned long i ;
761766 const char * errstr ;
@@ -775,114 +780,16 @@ static VALUE rb_mysql_result_each_nonstmt(VALUE self, const result_each_args* ar
775780 fields = mysql_fetch_fields (wrapper -> result );
776781
777782 do {
778- row = rb_mysql_result_fetch_row (self , args -> db_timezone , args -> app_timezone , args -> symbolizeKeys , args -> asArray , args -> castBool , args -> cast , fields );
779- if (row != Qnil ) {
780- wrapper -> numberOfRows ++ ;
781- if (args -> block_given != Qnil ) {
782- rb_yield (row );
783- }
784- }
785- } while (row != Qnil );
786-
787- rb_mysql_result_free_result (wrapper );
788- wrapper -> streamingComplete = 1 ;
789-
790- // Check for errors, the connection might have gone out from under us
791- // mysql_error returns an empty string if there is no error
792- errstr = mysql_error (wrapper -> client_wrapper -> client );
793- if (errstr [0 ]) {
794- rb_raise (cMysql2Error , "%s" , errstr );
795- }
796- } else {
797- rb_raise (cMysql2Error , "You have already fetched all the rows for this query and streaming is true. (to reiterate you must requery)." );
798- }
799- } else {
800- if (wrapper -> lastRowProcessed == 0 ) {
801- wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
802- if (wrapper -> numberOfRows == 0 ) {
803- wrapper -> rows = rb_ary_new ();
804- return wrapper -> rows ;
805- }
806- wrapper -> rows = rb_ary_new2 (wrapper -> numberOfRows );
807- }
808-
809- if (args -> cacheRows && wrapper -> lastRowProcessed == wrapper -> numberOfRows ) {
810- /* we've already read the entire dataset from the C result into our */
811- /* internal array. Lets hand that over to the user since it's ready to go */
812- for (i = 0 ; i < wrapper -> numberOfRows ; i ++ ) {
813- rb_yield (rb_ary_entry (wrapper -> rows , i ));
814- }
815- } else {
816- unsigned long rowsProcessed = 0 ;
817- rowsProcessed = RARRAY_LEN (wrapper -> rows );
818- fields = mysql_fetch_fields (wrapper -> result );
819-
820- for (i = 0 ; i < wrapper -> numberOfRows ; i ++ ) {
821- VALUE row ;
822- if (args -> cacheRows && i < rowsProcessed ) {
823- row = rb_ary_entry (wrapper -> rows , i );
824- } else {
825- row = rb_mysql_result_fetch_row (self , args -> db_timezone , args -> app_timezone , args -> symbolizeKeys , args -> asArray , args -> castBool , args -> cast , fields );
826- if (args -> cacheRows ) {
827- rb_ary_store (wrapper -> rows , i , row );
828- }
829- wrapper -> lastRowProcessed ++ ;
830- }
831-
832- if (row == Qnil ) {
833- /* we don't need the mysql C dataset around anymore, peace it */
834- rb_mysql_result_free_result (wrapper );
835- return Qnil ;
836- }
837-
838- if (args -> block_given != Qnil ) {
839- rb_yield (row );
840- }
841- }
842- if (wrapper -> lastRowProcessed == wrapper -> numberOfRows ) {
843- /* we don't need the mysql C dataset around anymore, peace it */
844- rb_mysql_result_free_result (wrapper );
845- }
846- }
847- }
848-
849- // FIXME return Enumerator instead?
850- // return rb_ary_each(wrapper->rows);
851- return wrapper -> rows ;
852- }
853-
854- static VALUE rb_mysql_result_each_stmt (VALUE self , const result_each_args * args ) {
855- unsigned long i ;
856- const char * errstr ;
857- mysql2_result_wrapper * wrapper ;
858- MYSQL_FIELD * fields = NULL ;
859-
860- GetMysql2Result (self , wrapper );
861-
862- if (wrapper -> is_streaming ) {
863- /* When streaming, we will only yield rows, not return them. */
864- if (wrapper -> rows == Qnil ) {
865- wrapper -> rows = rb_ary_new ();
866- }
867-
868- if (!wrapper -> streamingComplete ) {
869- VALUE row ;
870-
871- fields = mysql_fetch_fields (wrapper -> result );
872-
873- do {
874- row = rb_mysql_result_stmt_fetch_row (self , args -> db_timezone , args -> app_timezone , args -> symbolizeKeys , args -> asArray , args -> castBool , fields );
783+ row = fetch_row_func (self , fields , args );
875784 if (row != Qnil ) {
876785 wrapper -> numberOfRows ++ ;
877786 if (args -> block_given != Qnil ) {
878787 rb_yield (row );
879- wrapper -> lastRowProcessed ++ ;
880788 }
881789 }
882790 } while (row != Qnil );
883791
884792 rb_mysql_result_free_result (wrapper );
885- wrapper -> numberOfRows = wrapper -> lastRowProcessed ;
886793 wrapper -> streamingComplete = 1 ;
887794
888795 // Check for errors, the connection might have gone out from under us
@@ -911,7 +818,7 @@ static VALUE rb_mysql_result_each_stmt(VALUE self, const result_each_args* args)
911818 if (args -> cacheRows && i < rowsProcessed ) {
912819 row = rb_ary_entry (wrapper -> rows , i );
913820 } else {
914- row = rb_mysql_result_stmt_fetch_row (self , args -> db_timezone , args -> app_timezone , args -> symbolizeKeys , args -> asArray , args -> castBool , fields );
821+ row = fetch_row_func (self , fields , args );
915822 if (args -> cacheRows ) {
916823 rb_ary_store (wrapper -> rows , i , row );
917824 }
@@ -1015,15 +922,14 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
1015922 args .app_timezone = app_timezone ;
1016923 args .block_given = block ;
1017924
1018- if (!wrapper -> stmt )
1019- {
1020- return rb_mysql_result_each_nonstmt (self , & args );
1021- }
1022- else
1023- {
1024- return rb_mysql_result_each_stmt (self , & args );
925+ VALUE (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
926+ if (wrapper -> stmt ) {
927+ fetch_row_func = rb_mysql_result_fetch_row_stmt ;
928+ } else {
929+ fetch_row_func = rb_mysql_result_fetch_row ;
1025930 }
1026931
932+ return rb_mysql_result_each_ (self , fetch_row_func , & args );
1027933}
1028934
1029935static VALUE rb_mysql_result_count (VALUE self ) {
0 commit comments