@@ -50,6 +50,18 @@ static rb_encoding *binaryEncoding;
50
50
#define MYSQL2_MIN_TIME 62171150401ULL
51
51
#endif
52
52
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
+
53
65
VALUE cBigDecimal , cDateTime , cDate ;
54
66
static VALUE cMysql2Result ;
55
67
static 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
294
306
}
295
307
}
296
308
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
+ {
298
311
VALUE rowVal ;
299
312
mysql2_result_wrapper * wrapper ;
300
313
unsigned int i = 0 ;
@@ -310,7 +323,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
310
323
conn_enc = rb_to_encoding (wrapper -> encoding );
311
324
#endif
312
325
313
- if (asArray ) {
326
+ if (args -> asArray ) {
314
327
rowVal = rb_ary_new2 (wrapper -> numberOfFields );
315
328
} else {
316
329
rowVal = rb_hash_new ();
@@ -357,7 +370,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
357
370
}
358
371
359
372
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 );
361
374
VALUE val = Qnil ;
362
375
MYSQL_TIME * ts ;
363
376
@@ -368,7 +381,7 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
368
381
369
382
switch (result_buffer -> buffer_type ) {
370
383
case MYSQL_TYPE_TINY : // signed char
371
- if (castBool && fields [i ].length == 1 ) {
384
+ if (args -> castBool && fields [i ].length == 1 ) {
372
385
val = (* ((unsigned char * )result_buffer -> buffer ) != 0 ) ? Qtrue : Qfalse ;
373
386
break ;
374
387
}
@@ -414,9 +427,9 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
414
427
break ;
415
428
case MYSQL_TYPE_TIME : // MYSQL_TIME
416
429
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 ) {
420
433
val = rb_funcall (val , intern_localtime , 0 );
421
434
} else { // utc
422
435
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
432
445
433
446
if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME ) { // use DateTime instead
434
447
VALUE offset = INT2NUM (0 );
435
- if (db_timezone == intern_local ) {
448
+ if (args -> db_timezone == intern_local ) {
436
449
offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
437
450
}
438
451
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 ) {
441
454
offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
442
455
val = rb_funcall (val , intern_new_offset , 1 , offset );
443
456
} else { // utc
444
457
val = rb_funcall (val , intern_new_offset , 1 , opt_utc_offset );
445
458
}
446
459
}
447
460
} 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 ) {
451
464
val = rb_funcall (val , intern_localtime , 0 );
452
465
} else { // utc
453
466
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
483
496
}
484
497
}
485
498
486
- if (asArray ) {
499
+ if (args -> asArray ) {
487
500
rb_ary_push (rowVal , val );
488
501
} else {
489
502
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
494
507
}
495
508
496
509
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
+ {
498
512
VALUE rowVal ;
499
513
mysql2_result_wrapper * wrapper ;
500
514
MYSQL_ROW row ;
@@ -518,7 +532,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
518
532
return Qnil ;
519
533
}
520
534
521
- if (asArray ) {
535
+ if (args -> asArray ) {
522
536
rowVal = rb_ary_new2 (wrapper -> numberOfFields );
523
537
} else {
524
538
rowVal = rb_hash_new ();
@@ -530,12 +544,12 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
530
544
}
531
545
532
546
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 );
534
548
if (row [i ]) {
535
549
VALUE val = Qnil ;
536
550
enum enum_field_types type = fields [i ].type ;
537
551
538
- if (!cast ) {
552
+ if (!args -> cast ) {
539
553
if (type == MYSQL_TYPE_NULL ) {
540
554
val = Qnil ;
541
555
} else {
@@ -550,14 +564,14 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
550
564
val = Qnil ;
551
565
break ;
552
566
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 ) {
554
568
val = * row [i ] == 1 ? Qtrue : Qfalse ;
555
569
}else {
556
570
val = rb_str_new (row [i ], fieldLengths [i ]);
557
571
}
558
572
break ;
559
573
case MYSQL_TYPE_TINY : /* TINYINT field */
560
- if (castBool && fields [i ].length == 1 ) {
574
+ if (args -> castBool && fields [i ].length == 1 ) {
561
575
val = * row [i ] != '0' ? Qtrue : Qfalse ;
562
576
break ;
563
577
}
@@ -600,9 +614,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
600
614
break ;
601
615
}
602
616
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 ) {
606
620
val = rb_funcall (val , intern_localtime , 0 );
607
621
} else { /* utc */
608
622
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
633
647
} else {
634
648
if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME ) { /* use DateTime for larger date range, does not support microseconds */
635
649
VALUE offset = INT2NUM (0 );
636
- if (db_timezone == intern_local ) {
650
+ if (args -> db_timezone == intern_local ) {
637
651
offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
638
652
}
639
653
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 ) {
642
656
offset = rb_funcall (cMysql2Client , intern_local_offset , 0 );
643
657
val = rb_funcall (val , intern_new_offset , 1 , offset );
644
658
} else { /* utc */
@@ -647,9 +661,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
647
661
}
648
662
} else {
649
663
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 ) {
653
667
val = rb_funcall (val , intern_localtime , 0 );
654
668
} else { /* utc */
655
669
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
699
713
break ;
700
714
}
701
715
}
702
- if (asArray ) {
716
+ if (args -> asArray ) {
703
717
rb_ary_push (rowVal , val );
704
718
} else {
705
719
rb_hash_aset (rowVal , field , val );
706
720
}
707
721
} else {
708
- if (asArray ) {
722
+ if (args -> asArray ) {
709
723
rb_ary_push (rowVal , Qnil );
710
724
} else {
711
725
rb_hash_aset (rowVal , field , Qnil );
@@ -743,19 +757,10 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
743
757
return wrapper -> fields ;
744
758
}
745
759
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
+ {
759
764
mysql2_result_wrapper * wrapper ;
760
765
unsigned long i ;
761
766
const char * errstr ;
@@ -775,114 +780,16 @@ static VALUE rb_mysql_result_each_nonstmt(VALUE self, const result_each_args* ar
775
780
fields = mysql_fetch_fields (wrapper -> result );
776
781
777
782
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 );
875
784
if (row != Qnil ) {
876
785
wrapper -> numberOfRows ++ ;
877
786
if (args -> block_given != Qnil ) {
878
787
rb_yield (row );
879
- wrapper -> lastRowProcessed ++ ;
880
788
}
881
789
}
882
790
} while (row != Qnil );
883
791
884
792
rb_mysql_result_free_result (wrapper );
885
- wrapper -> numberOfRows = wrapper -> lastRowProcessed ;
886
793
wrapper -> streamingComplete = 1 ;
887
794
888
795
// 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)
911
818
if (args -> cacheRows && i < rowsProcessed ) {
912
819
row = rb_ary_entry (wrapper -> rows , i );
913
820
} 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 );
915
822
if (args -> cacheRows ) {
916
823
rb_ary_store (wrapper -> rows , i , row );
917
824
}
@@ -1015,15 +922,14 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
1015
922
args .app_timezone = app_timezone ;
1016
923
args .block_given = block ;
1017
924
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 ;
1025
930
}
1026
931
932
+ return rb_mysql_result_each_ (self , fetch_row_func , & args );
1027
933
}
1028
934
1029
935
static VALUE rb_mysql_result_count (VALUE self ) {
0 commit comments