@@ -79,35 +79,73 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
7979
8080#define NOGVL_DBCALL (_dbfunction , _client ) ( \
8181 (RETCODE)rb_thread_blocking_region( \
82- (rb_blocking_function_t*)nogvl_ ## _dbfunction, _client, \
82+ (rb_blocking_function_t*)_dbfunction, _client, \
8383 (rb_unblock_function_t*)dbcancel_ubf, _client ) \
8484)
8585
86+ static void dbcancel_ubf (DBPROCESS * client ) {
87+ GET_CLIENT_USERDATA (client );
88+ dbcancel (client );
89+ userdata -> dbcancel_sent = 1 ;
90+ userdata -> dbsql_sent = 0 ;
91+ }
92+
93+ static void nogvl_setup (DBPROCESS * client ) {
94+ GET_CLIENT_USERDATA (client );
95+ userdata -> nonblocking = 1 ;
96+ }
97+
98+ static void nogvl_cleanup (DBPROCESS * client ) {
99+ GET_CLIENT_USERDATA (client );
100+ userdata -> nonblocking = 0 ;
101+ /*
102+ Now that the blocking operation is done, we can finally throw any
103+ exceptions based on errors from SQL Server.
104+ */
105+ if (userdata -> nonblocking_error .is_set ) {
106+ userdata -> nonblocking_error .is_set = 0 ;
107+ rb_tinytds_raise_error (client ,
108+ userdata -> nonblocking_error .cancel ,
109+ & userdata -> nonblocking_error .error ,
110+ & userdata -> nonblocking_error .source ,
111+ userdata -> nonblocking_error .severity ,
112+ userdata -> nonblocking_error .dberr ,
113+ userdata -> nonblocking_error .oserr );
114+ }
115+ }
116+
86117static RETCODE nogvl_dbsqlok (DBPROCESS * client ) {
87118 int retcode = FAIL ;
88119 GET_CLIENT_USERDATA (client );
89- retcode = dbsqlok (client );
120+ nogvl_setup (client );
121+ retcode = NOGVL_DBCALL (dbsqlok , client );
122+ nogvl_cleanup (client );
90123 userdata -> dbsqlok_sent = 1 ;
91124 return retcode ;
92125}
93126
94127static RETCODE nogvl_dbsqlexec (DBPROCESS * client ) {
95- return dbsqlexec (client );
128+ int retcode = FAIL ;
129+ nogvl_setup (client );
130+ retcode = NOGVL_DBCALL (dbsqlexec , client );
131+ nogvl_cleanup (client );
132+ return retcode ;
96133}
97134
98135static RETCODE nogvl_dbresults (DBPROCESS * client ) {
99- return dbresults (client );
136+ int retcode = FAIL ;
137+ nogvl_setup (client );
138+ retcode = NOGVL_DBCALL (dbresults , client );
139+ nogvl_cleanup (client );
140+ return retcode ;
100141}
101142
102143static RETCODE nogvl_dbnextrow (DBPROCESS * client ) {
103- return dbnextrow (client );
104- }
105-
106- static void dbcancel_ubf (DBPROCESS * client ) {
107- GET_CLIENT_USERDATA (client );
108- dbcancel (client );
109- userdata -> dbcancel_sent = 1 ;
110- userdata -> dbsql_sent = 0 ;
144+ int retcode = FAIL ;
145+ nogvl_setup (client );
146+ retcode = NOGVL_DBCALL (dbnextrow , client );
147+ nogvl_cleanup (client );
148+ return retcode ;
111149}
112150
113151// Lib Backend (Helpers)
@@ -118,7 +156,7 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
118156 RETCODE db_rc ;
119157 ruby_rc = rb_ary_entry (rwrap -> dbresults_retcodes , rwrap -> number_of_results );
120158 if (NIL_P (ruby_rc )) {
121- db_rc = NOGVL_DBCALL ( dbresults , rwrap -> client );
159+ db_rc = nogvl_dbresults ( rwrap -> client );
122160 ruby_rc = INT2FIX (db_rc );
123161 rb_ary_store (rwrap -> dbresults_retcodes , rwrap -> number_of_results , ruby_rc );
124162 } else {
@@ -130,7 +168,7 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
130168static RETCODE rb_tinytds_result_ok_helper (DBPROCESS * client ) {
131169 GET_CLIENT_USERDATA (client );
132170 if (userdata -> dbsqlok_sent == 0 ) {
133- userdata -> dbsqlok_retcode = NOGVL_DBCALL ( dbsqlok , client );
171+ userdata -> dbsqlok_retcode = nogvl_dbsqlok ( client );
134172 }
135173 return userdata -> dbsqlok_retcode ;
136174}
@@ -373,7 +411,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
373411 /* Create rows for this result set. */
374412 unsigned long rowi = 0 ;
375413 VALUE result = rb_ary_new ();
376- while (NOGVL_DBCALL ( dbnextrow , rwrap -> client ) != NO_MORE_ROWS ) {
414+ while (nogvl_dbnextrow ( rwrap -> client ) != NO_MORE_ROWS ) {
377415 VALUE row = rb_tinytds_result_fetch_row (self , timezone , symbolize_keys , as_array );
378416 if (cache_rows )
379417 rb_ary_store (result , rowi , row );
@@ -406,7 +444,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
406444 } else {
407445 // If we do not find results, side step the rb_tinytds_result_dbresults_retcode helper and
408446 // manually populate its memoized array while nullifing any memoized fields too before loop.
409- dbresults_rc = NOGVL_DBCALL ( dbresults , rwrap -> client );
447+ dbresults_rc = nogvl_dbresults ( rwrap -> client );
410448 rb_ary_store (rwrap -> dbresults_retcodes , rwrap -> number_of_results , INT2FIX (dbresults_rc ));
411449 rb_ary_store (rwrap -> fields_processed , rwrap -> number_of_results , Qnil );
412450 }
@@ -466,10 +504,10 @@ static VALUE rb_tinytds_result_insert(VALUE self) {
466504 rb_tinytds_result_cancel_helper (rwrap -> client );
467505 VALUE identity = Qnil ;
468506 dbcmd (rwrap -> client , rwrap -> cwrap -> identity_insert_sql );
469- if (NOGVL_DBCALL ( dbsqlexec , rwrap -> client ) != FAIL
470- && NOGVL_DBCALL ( dbresults , rwrap -> client ) != FAIL
507+ if (nogvl_dbsqlexec ( rwrap -> client ) != FAIL
508+ && nogvl_dbresults ( rwrap -> client ) != FAIL
471509 && DBROWS (rwrap -> client ) != FAIL ) {
472- while (NOGVL_DBCALL ( dbnextrow , rwrap -> client ) != NO_MORE_ROWS ) {
510+ while (nogvl_dbnextrow ( rwrap -> client ) != NO_MORE_ROWS ) {
473511 int col = 1 ;
474512 BYTE * data = dbdata (rwrap -> client , col );
475513 DBINT data_len = dbdatlen (rwrap -> client , col );
0 commit comments