@@ -786,6 +786,66 @@ static void rb_mysql_row_query_options(VALUE opts, ID *db_timezone, ID *app_time
786786 }
787787}
788788
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+
789849static VALUE rb_mysql_result_each_ (VALUE self ,
790850 VALUE (* fetch_row_func )(VALUE , MYSQL_FIELD * fields , const result_each_args * args ),
791851 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