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