@@ -475,49 +475,81 @@ static void rb_mysql_row_query_options(VALUE opts, ID *db_timezone, ID *app_time
475
475
}
476
476
}
477
477
478
- static VALUE rb_mysql_result_element (VALUE self , VALUE seek ) {
479
- VALUE row , opts ;
478
+ static VALUE rb_mysql_result_element (int argc , VALUE * argv , VALUE self ) {
479
+ VALUE seek , count , defaults , opts ;
480
+ VALUE row , rows ;
480
481
ID db_timezone , app_timezone ;
481
- long offset ;
482
+ long i , c_seek , c_count = 0 ;
482
483
int symbolizeKeys , asArray , castBool , cacheRows , cast ;
483
484
mysql2_result_wrapper * wrapper ;
484
485
485
486
GetMysql2Result (self , wrapper );
486
487
487
- offset = NUM2LONG (seek );
488
+ rb_scan_args (argc , argv , "12" , & seek , & count , & opts );
489
+ /* If the second arg is a hash, it's the opts and there's no count */
490
+ if (TYPE (count ) == T_HASH ) {
491
+ opts = count ;
492
+ count = Qnil ;
493
+ }
488
494
489
- if (!wrapper -> numberOfRows ) {
490
- wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
495
+ c_seek = NUM2LONG (seek );
496
+ if (!NIL_P (count )) {
497
+ c_count = NUM2LONG (count );
498
+ /* Special case: ary[x, 0] returns []*/
499
+ if (!c_count ) return rb_ary_new ();
491
500
}
492
501
493
- opts = rb_iv_get (self , "@query_options" );
502
+ defaults = rb_iv_get (self , "@query_options" );
503
+ if (!NIL_P (opts )) {
504
+ opts = rb_funcall (defaults , intern_merge , 1 , opts );
505
+ } else {
506
+ opts = defaults ;
507
+ }
494
508
rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
495
509
496
510
if (wrapper -> is_streaming ) {
497
511
rb_raise (cMysql2Error , "Element reference operator #[] cannot be used in streaming mode." );
498
512
}
499
513
514
+ if (!wrapper -> numberOfRows ) {
515
+ wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
516
+ }
517
+
500
518
/* count back from the end if passed a negative number */
501
- if (offset < 0 ) {
502
- offset = wrapper -> numberOfRows + offset ;
519
+ if (c_seek < 0 ) {
520
+ c_seek = wrapper -> numberOfRows + c_seek ;
503
521
}
504
522
505
523
/* negative offset was too big */
506
- if (offset < 0 ) {
524
+ if (c_seek < 0 ) {
507
525
return Qnil ;
508
- /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset , wrapper->numberOfRows); */
526
+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", c_seek , wrapper->numberOfRows); */
509
527
}
510
528
511
- if (wrapper -> numberOfRows <= (unsigned long )offset ) {
512
- return Qnil ;
513
- /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset, wrapper->numberOfRows); */
529
+ if (wrapper -> numberOfRows <= (unsigned long )c_seek ) {
530
+ if (!c_count ) return Qnil ;
531
+ else return rb_ary_new ();
532
+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", c_seek, wrapper->numberOfRows); */
514
533
}
515
534
516
- mysql_data_seek (wrapper -> result , offset );
535
+ mysql_data_seek (wrapper -> result , c_seek );
517
536
518
- row = rb_mysql_result_fetch_row (self , db_timezone , app_timezone , symbolizeKeys , asArray , castBool , cast );
537
+ if (!c_count ) {
538
+ return rb_mysql_result_fetch_row (self , db_timezone , app_timezone , symbolizeKeys , asArray , castBool , cast );
539
+ }
540
+
541
+ /* given ary = [1, 2, 3] then ary[1, 100] returns [2, 3] */
542
+ if ((unsigned long )(c_seek + c_count ) > wrapper -> numberOfRows ) {
543
+ c_count = wrapper -> numberOfRows - c_seek ;
544
+ }
519
545
520
- return row ;
546
+ /* return an array! */
547
+ rows = rb_ary_new2 (c_count );
548
+ for (i = 0 ; i < c_count ; i ++ ) {
549
+ row = rb_mysql_result_fetch_row (self , db_timezone , app_timezone , symbolizeKeys , asArray , castBool , cast );
550
+ rb_ary_store (rows , i , row );
551
+ }
552
+ return rows ;
521
553
}
522
554
523
555
static VALUE rb_mysql_result_each (int argc , VALUE * argv , VALUE self ) {
@@ -679,7 +711,7 @@ void init_mysql2_result() {
679
711
cDateTime = rb_const_get (rb_cObject , rb_intern ("DateTime" ));
680
712
681
713
cMysql2Result = rb_define_class_under (mMysql2 , "Result" , rb_cObject );
682
- rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , 1 );
714
+ rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , - 1 );
683
715
rb_define_method (cMysql2Result , "each" , rb_mysql_result_each , -1 );
684
716
rb_define_method (cMysql2Result , "fields" , rb_mysql_result_fetch_fields , 0 );
685
717
rb_define_method (cMysql2Result , "count" , rb_mysql_result_count , 0 );
0 commit comments