@@ -789,6 +789,66 @@ static void rb_mysql_row_query_options(VALUE opts, ID *db_timezone, ID *app_time
789789 }
790790}
791791
792+ static VALUE rb_mysql_result_element (VALUE self , VALUE seek ) {
793+ result_each_args args ;
794+ MYSQL_FIELD * fields = NULL ;
795+ long offset ;
796+ ID db_timezone , app_timezone ;
797+ int symbolizeKeys , asArray , castBool , cacheRows , cast ;
798+ VALUE opts , (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args );
799+
800+ GET_RESULT (self );
801+
802+ offset = NUM2LONG (seek );
803+
804+ if (!wrapper -> numberOfRows ) {
805+ wrapper -> numberOfRows = mysql_num_rows (wrapper -> result );
806+ }
807+
808+ opts = rb_iv_get (self , "@query_options" );
809+ rb_mysql_row_query_options (opts , & db_timezone , & app_timezone , & symbolizeKeys , & asArray , & castBool , & cast , & cacheRows );
810+
811+ if (wrapper -> is_streaming ) {
812+ rb_raise (cMysql2Error , "Element reference operator #[] cannot be used in streaming mode." );
813+ }
814+
815+ /* count back from the end if passed a negative number */
816+ if (offset < 0 ) {
817+ offset = wrapper -> numberOfRows + offset ;
818+ }
819+
820+ /* negative offset was too big */
821+ if (offset < 0 ) {
822+ return Qnil ;
823+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset, wrapper->numberOfRows); */
824+ }
825+
826+ if (wrapper -> numberOfRows <= (unsigned long )offset ) {
827+ return Qnil ;
828+ /* rb_raise(cMysql2Error, "Out of range: offset %ld is beyond %lu rows (offset begins at 0).", offset, wrapper->numberOfRows); */
829+ }
830+
831+ mysql_data_seek (wrapper -> result , offset );
832+
833+ // Backward compat
834+ args .symbolizeKeys = symbolizeKeys ;
835+ args .asArray = asArray ;
836+ args .castBool = castBool ;
837+ args .cacheRows = cacheRows ;
838+ args .cast = cast ;
839+ args .db_timezone = db_timezone ;
840+ args .app_timezone = app_timezone ;
841+ args .block_given = Qnil ;
842+
843+ if (wrapper -> stmt ) {
844+ fetch_row_func = rb_mysql_result_fetch_row_stmt ;
845+ } else {
846+ fetch_row_func = rb_mysql_result_fetch_row ;
847+ }
848+
849+ return fetch_row_func (self , fields , & args );
850+ }
851+
792852static VALUE rb_mysql_result_each_ (VALUE self ,
793853 VALUE (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args ),
794854 const result_each_args * args )
@@ -878,7 +938,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
878938static VALUE rb_mysql_result_each (int argc , VALUE * argv , VALUE self ) {
879939 result_each_args args ;
880940 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 ;
882942 int symbolizeKeys , asArray , castBool , cacheRows , cast ;
883943
884944 GET_RESULT (self );
@@ -891,44 +951,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
891951 opts = defaults ;
892952 }
893953
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 );
932955
933956 if (wrapper -> lastRowProcessed == 0 && !wrapper -> is_streaming ) {
934957 wrapper -> numberOfRows = wrapper -> stmt ? mysql_stmt_num_rows (wrapper -> stmt ) : mysql_num_rows (wrapper -> result );
@@ -1019,6 +1042,7 @@ void init_mysql2_result() {
10191042 cDateTime = rb_const_get (rb_cObject , rb_intern ("DateTime" ));
10201043
10211044 cMysql2Result = rb_define_class_under (mMysql2 , "Result" , rb_cObject );
1045+ rb_define_method (cMysql2Result , "[]" , rb_mysql_result_element , 1 );
10221046 rb_define_method (cMysql2Result , "each" , rb_mysql_result_each , -1 );
10231047 rb_define_method (cMysql2Result , "fields" , rb_mysql_result_fetch_fields , 0 );
10241048 rb_define_method (cMysql2Result , "count" , rb_mysql_result_count , 0 );
0 commit comments