@@ -786,46 +786,68 @@ static void rb_mysql_row_query_options(VALUE opts, ID *db_timezone, ID *app_time
786
786
}
787
787
}
788
788
789
- static VALUE rb_mysql_result_element (VALUE self , VALUE seek ) {
789
+ static VALUE rb_mysql_result_element (int argc , VALUE * argv , VALUE self ) {
790
790
result_each_args args ;
791
791
MYSQL_FIELD * fields = NULL ;
792
- long offset ;
793
792
ID db_timezone , app_timezone ;
793
+ VALUE seek , count , row , rows ;
794
+ long i , c_seek , c_count = 0 ;
794
795
int symbolizeKeys , asArray , castBool , cacheRows , cast ;
795
- VALUE opts , (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
796
+ VALUE defaults , block , opts , (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
796
797
797
798
GET_RESULT (self );
798
799
799
- offset = NUM2LONG (seek );
800
+ defaults = rb_iv_get (self , "@query_options" );
801
+ Check_Type (defaults , T_HASH );
802
+ rb_scan_args (argc , argv , "12&" , & seek , & count , & opts , & block );
800
803
801
- if (!wrapper -> numberOfRows ) {
802
- wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
804
+ /* If the second arg is a hash, it's the opts and there's no count */
805
+ if (TYPE (count ) == T_HASH ) {
806
+ opts = count ;
807
+ count = Qnil ;
808
+ }
809
+
810
+ c_seek = NUM2LONG (seek );
811
+ if (!NIL_P (count )) {
812
+ c_count = NUM2LONG (count );
813
+ /* Special case: ary[x, 0] returns []*/
814
+ if (!c_count ) return rb_ary_new ();
815
+ }
816
+
817
+ if (!NIL_P (opts )) {
818
+ opts = rb_funcall (defaults , intern_merge , 1 , opts );
819
+ } else {
820
+ opts = defaults ;
803
821
}
804
822
805
- opts = rb_iv_get (self , "@query_options" );
806
823
rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
807
824
808
825
if (wrapper -> is_streaming ) {
809
826
rb_raise (cMysql2Error , "Element reference operator #[] cannot be used in streaming mode." );
810
827
}
811
828
829
+ if (!wrapper -> numberOfRows ) {
830
+ wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
831
+ }
832
+
812
833
/* count back from the end if passed a negative number */
813
- if (offset < 0 ) {
814
- offset = wrapper -> numberOfRows + offset ;
834
+ if (c_seek < 0 ) {
835
+ c_seek = wrapper -> numberOfRows + c_seek ;
815
836
}
816
837
817
838
/* negative offset was too big */
818
- if (offset < 0 ) {
839
+ if (c_seek < 0 ) {
819
840
return Qnil ;
820
- /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset , wrapper->numberOfRows); */
841
+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", c_seek , wrapper->numberOfRows); */
821
842
}
822
843
823
- if (wrapper -> numberOfRows <= (unsigned long )offset ) {
824
- return Qnil ;
825
- /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset, wrapper->numberOfRows); */
844
+ if (wrapper -> numberOfRows <= (unsigned long )c_seek ) {
845
+ if (!c_count ) return Qnil ;
846
+ else return rb_ary_new ();
847
+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", c_seek, wrapper->numberOfRows); */
826
848
}
827
849
828
- mysql_data_seek (wrapper -> result , offset );
850
+ mysql_data_seek (wrapper -> result , c_seek );
829
851
830
852
// Backward compat
831
853
args .symbolizeKeys = symbolizeKeys ;
@@ -835,15 +857,30 @@ static VALUE rb_mysql_result_element(VALUE self, VALUE seek) {
835
857
args .cast = cast ;
836
858
args .db_timezone = db_timezone ;
837
859
args .app_timezone = app_timezone ;
838
- args .block_given = Qnil ;
860
+ args .block_given = block ;
839
861
840
862
if (wrapper -> stmt ) {
841
863
fetch_row_func = rb_mysql_result_fetch_row_stmt ;
842
864
} else {
843
865
fetch_row_func = rb_mysql_result_fetch_row ;
844
866
}
845
867
846
- return fetch_row_func (self , fields , & args );
868
+ if (!c_count ) {
869
+ return fetch_row_func (self , fields , & args );
870
+ }
871
+
872
+ /* given ary = [1, 2, 3] then ary[1, 100] returns [2, 3] */
873
+ if ((unsigned long )(c_seek + c_count ) > wrapper -> numberOfRows ) {
874
+ c_count = wrapper -> numberOfRows - c_seek ;
875
+ }
876
+
877
+ /* return an array! */
878
+ rows = rb_ary_new2 (c_count );
879
+ for (i = 0 ; i < c_count ; i ++ ) {
880
+ row = fetch_row_func (self , fields , & args );
881
+ rb_ary_store (rows , i , row );
882
+ }
883
+ return rows ;
847
884
}
848
885
849
886
static VALUE rb_mysql_result_each_ (VALUE self ,
@@ -1042,7 +1079,7 @@ void init_mysql2_result() {
1042
1079
cDateTime = rb_const_get (rb_cObject , rb_intern ("DateTime" ));
1043
1080
1044
1081
cMysql2Result = rb_define_class_under (mMysql2 , "Result" , rb_cObject );
1045
- rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , 1 );
1082
+ rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , - 1 );
1046
1083
rb_define_method (cMysql2Result , "each" , rb_mysql_result_each , -1 );
1047
1084
rb_define_method (cMysql2Result , "fields" , rb_mysql_result_fetch_fields , 0 );
1048
1085
rb_define_method (cMysql2Result , "count" , rb_mysql_result_count , 0 );
0 commit comments