Skip to content

Commit 97507de

Browse files
sodabrewjustincase
authored andcommitted
Meld together rb_mysql_result_each_stmt and rb_mysql_result_each_nonstmt
1 parent ae5bbdc commit 97507de

File tree

1 file changed

+57
-151
lines changed

1 file changed

+57
-151
lines changed

ext/mysql2/result.c

Lines changed: 57 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
5365
VALUE cBigDecimal, cDateTime, cDate;
5466
static VALUE cMysql2Result;
5567
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
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

1029935
static VALUE rb_mysql_result_count(VALUE self) {

0 commit comments

Comments
 (0)