@@ -786,6 +786,66 @@ 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 ) {
790
+ result_each_args args ;
791
+ MYSQL_FIELD * fields = NULL ;
792
+ long offset ;
793
+ ID db_timezone , app_timezone ;
794
+ int symbolizeKeys , asArray , castBool , cacheRows , cast ;
795
+ VALUE opts , (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
796
+
797
+ GET_RESULT (self );
798
+
799
+ offset = NUM2LONG (seek );
800
+
801
+ if (!wrapper -> numberOfRows ) {
802
+ wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
803
+ }
804
+
805
+ opts = rb_iv_get (self , "@query_options" );
806
+ rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
807
+
808
+ if (wrapper -> is_streaming ) {
809
+ rb_raise (cMysql2Error , "Element reference operator #[] cannot be used in streaming mode." );
810
+ }
811
+
812
+ /* count back from the end if passed a negative number */
813
+ if (offset < 0 ) {
814
+ offset = wrapper -> numberOfRows + offset ;
815
+ }
816
+
817
+ /* negative offset was too big */
818
+ if (offset < 0 ) {
819
+ return Qnil ;
820
+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset, wrapper->numberOfRows); */
821
+ }
822
+
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); */
826
+ }
827
+
828
+ mysql_data_seek (wrapper -> result , offset );
829
+
830
+ // Backward compat
831
+ args .symbolizeKeys = symbolizeKeys ;
832
+ args .asArray = asArray ;
833
+ args .castBool = castBool ;
834
+ args .cacheRows = cacheRows ;
835
+ args .cast = cast ;
836
+ args .db_timezone = db_timezone ;
837
+ args .app_timezone = app_timezone ;
838
+ args .block_given = Qnil ;
839
+
840
+ if (wrapper -> stmt ) {
841
+ fetch_row_func = rb_mysql_result_fetch_row_stmt ;
842
+ } else {
843
+ fetch_row_func = rb_mysql_result_fetch_row ;
844
+ }
845
+
846
+ return fetch_row_func (self , fields , & args );
847
+ }
848
+
789
849
static VALUE rb_mysql_result_each_ (VALUE self ,
790
850
VALUE (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args ),
791
851
const result_each_args * args )
@@ -878,7 +938,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
878
938
static VALUE rb_mysql_result_each (int argc , VALUE * argv , VALUE self ) {
879
939
result_each_args args ;
880
940
VALUE defaults , opts , block , (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
881
- ID db_timezone , app_timezone , dbTz , appTz ;
941
+ ID db_timezone , app_timezone ;
882
942
int symbolizeKeys , asArray , castBool , cacheRows , cast ;
883
943
884
944
GET_RESULT (self );
@@ -891,44 +951,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
891
951
opts = defaults ;
892
952
}
893
953
894
- symbolizeKeys = RTEST (rb_hash_aref (opts , sym_symbolize_keys ));
895
- asArray = rb_hash_aref (opts , sym_as ) == sym_array ;
896
- castBool = RTEST (rb_hash_aref (opts , sym_cast_booleans ));
897
- cacheRows = RTEST (rb_hash_aref (opts , sym_cache_rows ));
898
- cast = RTEST (rb_hash_aref (opts , sym_cast ));
899
-
900
- if (wrapper -> is_streaming && cacheRows ) {
901
- rb_warn (":cache_rows is ignored if :stream is true" );
902
- }
903
-
904
- if (wrapper -> stmt && !cacheRows && !wrapper -> is_streaming ) {
905
- rb_warn (":cache_rows is forced for prepared statements (if not streaming)" );
906
- }
907
-
908
- if (wrapper -> stmt && !cast ) {
909
- rb_warn (":cast is forced for prepared statements" );
910
- }
911
-
912
- dbTz = rb_hash_aref (opts , sym_database_timezone );
913
- if (dbTz == sym_local ) {
914
- db_timezone = intern_local ;
915
- } else if (dbTz == sym_utc ) {
916
- db_timezone = intern_utc ;
917
- } else {
918
- if (!NIL_P (dbTz )) {
919
- rb_warn (":database_timezone option must be :utc or :local - defaulting to :local" );
920
- }
921
- db_timezone = intern_local ;
922
- }
923
-
924
- appTz = rb_hash_aref (opts , sym_application_timezone );
925
- if (appTz == sym_local ) {
926
- app_timezone = intern_local ;
927
- } else if (appTz == sym_utc ) {
928
- app_timezone = intern_utc ;
929
- } else {
930
- app_timezone = Qnil ;
931
- }
954
+ rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
932
955
933
956
if (wrapper -> lastRowProcessed == 0 && !wrapper -> is_streaming ) {
934
957
wrapper -> numberOfRows = wrapper -> stmt ? mysql_stmt_num_rows (wrapper -> stmt ) : mysql_num_rows (wrapper -> result );
@@ -1019,6 +1042,7 @@ void init_mysql2_result() {
1019
1042
cDateTime = rb_const_get (rb_cObject , rb_intern ("DateTime" ));
1020
1043
1021
1044
cMysql2Result = rb_define_class_under (mMysql2 , "Result" , rb_cObject );
1045
+ rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , 1 );
1022
1046
rb_define_method (cMysql2Result , "each" , rb_mysql_result_each , -1 );
1023
1047
rb_define_method (cMysql2Result , "fields" , rb_mysql_result_fetch_fields , 0 );
1024
1048
rb_define_method (cMysql2Result , "count" , rb_mysql_result_count , 0 );
0 commit comments