@@ -475,49 +475,81 @@ static void rb_mysql_row_query_options(VALUE opts, ID *db_timezone, ID *app_time
475475 }
476476}
477477
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 ;
480481 ID db_timezone , app_timezone ;
481- long offset ;
482+ long i , c_seek , c_count = 0 ;
482483 int symbolizeKeys , asArray , castBool , cacheRows , cast ;
483484 mysql2_result_wrapper * wrapper ;
484485
485486 GetMysql2Result (self , wrapper );
486487
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+ }
488494
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 ();
491500 }
492501
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+ }
494508 rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
495509
496510 if (wrapper -> is_streaming ) {
497511 rb_raise (cMysql2Error , "Element reference operator #[] cannot be used in streaming mode." );
498512 }
499513
514+ if (!wrapper -> numberOfRows ) {
515+ wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
516+ }
517+
500518 /* 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 ;
503521 }
504522
505523 /* negative offset was too big */
506- if (offset < 0 ) {
524+ if (c_seek < 0 ) {
507525 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); */
509527 }
510528
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); */
514533 }
515534
516- mysql_data_seek (wrapper -> result , offset );
535+ mysql_data_seek (wrapper -> result , c_seek );
517536
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+ }
519545
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 ;
521553}
522554
523555static VALUE rb_mysql_result_each (int argc , VALUE * argv , VALUE self ) {
@@ -679,7 +711,7 @@ void init_mysql2_result() {
679711 cDateTime = rb_const_get (rb_cObject , rb_intern ("DateTime" ));
680712
681713 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 );
683715 rb_define_method (cMysql2Result , "each" , rb_mysql_result_each , -1 );
684716 rb_define_method (cMysql2Result , "fields" , rb_mysql_result_fetch_fields , 0 );
685717 rb_define_method (cMysql2Result , "count" , rb_mysql_result_count , 0 );
0 commit comments