tiny_tds 3.2.1-aarch64-linux-gnu → 3.3.0-aarch64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +21 -0
- data/.devcontainer/boot.sh +6 -0
- data/.devcontainer/compose.yaml +40 -0
- data/.devcontainer/devcontainer.json +30 -0
- data/.github/workflows/ci.yml +17 -5
- data/CHANGELOG.md +7 -0
- data/README.md +17 -33
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/astyle.conf +8 -0
- data/ext/tiny_tds/client.c +163 -64
- data/ext/tiny_tds/extconsts.rb +2 -2
- data/ext/tiny_tds/result.c +171 -42
- data/ext/tiny_tds/result.h +2 -2
- data/ext/tiny_tds/tiny_tds_ext.c +2 -1
- data/lib/tiny_tds/2.7/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.0/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.1/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.2/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.3/tiny_tds.so +0 -0
- data/lib/tiny_tds/3.4/tiny_tds.so +0 -0
- data/lib/tiny_tds/bin.rb +2 -2
- data/lib/tiny_tds/gem.rb +6 -6
- data/lib/tiny_tds.rb +1 -2
- data/ports/aarch64-linux-gnu/bin/defncopy +0 -0
- data/ports/aarch64-linux-gnu/bin/tsql +0 -0
- data/ports/aarch64-linux-gnu/lib/libsybdb.so.5 +0 -0
- data/test/bin/restore-from-native-gem.ps1 +7 -1
- data/test/gem_test.rb +23 -28
- data/test/thread_test.rb +1 -1
- data/tiny_tds.gemspec +2 -2
- metadata +7 -10
- data/docker-compose.yml +0 -34
- data/setup_cimgruby_dev.sh +0 -25
- data/start_dev.sh +0 -21
- data/test/bin/install-mssql.ps1 +0 -42
- data/test/bin/install-mssqltools.sh +0 -9
- data/test/bin/install-openssl.sh +0 -18
- data/test/bin/setup_tinytds_db.sh +0 -7
- data/test/bin/setup_volume_permissions.sh +0 -10
data/ext/tiny_tds/result.c
CHANGED
@@ -9,7 +9,7 @@ extern VALUE mTinyTds, cTinyTdsClient, cTinyTdsError;
|
|
9
9
|
VALUE cKernel, cDate;
|
10
10
|
VALUE opt_decimal_zero, opt_float_zero, opt_one, opt_zero, opt_four, opt_19hdr, opt_onek, opt_tenk, opt_onemil, opt_onebil;
|
11
11
|
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_merge,
|
12
|
-
|
12
|
+
intern_civil, intern_new_offset, intern_plus, intern_divide, intern_bigd;
|
13
13
|
static ID sym_symbolize_keys, sym_as, sym_array, sym_cache_rows, sym_first, sym_timezone, sym_local, sym_utc, sym_empty_sets;
|
14
14
|
|
15
15
|
|
@@ -35,9 +35,10 @@ rb_encoding *binaryEncoding;
|
|
35
35
|
|
36
36
|
|
37
37
|
// Lib Backend (Memory Management)
|
38
|
-
|
39
|
-
|
38
|
+
static void rb_tinytds_result_mark(void *ptr)
|
39
|
+
{
|
40
40
|
tinytds_result_wrapper *rwrap = (tinytds_result_wrapper *)ptr;
|
41
|
+
|
41
42
|
if (rwrap) {
|
42
43
|
rb_gc_mark(rwrap->local_offset);
|
43
44
|
rb_gc_mark(rwrap->fields);
|
@@ -47,14 +48,31 @@ static void rb_tinytds_result_mark(void *ptr) {
|
|
47
48
|
}
|
48
49
|
}
|
49
50
|
|
50
|
-
static void rb_tinytds_result_free(void *ptr)
|
51
|
+
static void rb_tinytds_result_free(void *ptr)
|
52
|
+
{
|
51
53
|
xfree(ptr);
|
52
54
|
}
|
53
55
|
|
54
|
-
|
56
|
+
static size_t tinytds_result_wrapper_size(const void* data)
|
57
|
+
{
|
58
|
+
return sizeof(tinytds_result_wrapper);
|
59
|
+
}
|
60
|
+
|
61
|
+
const rb_data_type_t tinytds_result_wrapper_type = {
|
62
|
+
.wrap_struct_name = "tinytds_result_wrapper",
|
63
|
+
.function = {
|
64
|
+
.dmark = rb_tinytds_result_mark,
|
65
|
+
.dfree = rb_tinytds_result_free,
|
66
|
+
.dsize = tinytds_result_wrapper_size,
|
67
|
+
},
|
68
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
69
|
+
};
|
70
|
+
|
71
|
+
VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap)
|
72
|
+
{
|
55
73
|
VALUE obj;
|
56
74
|
tinytds_result_wrapper *rwrap;
|
57
|
-
obj =
|
75
|
+
obj = TypedData_Make_Struct(cTinyTdsResult, tinytds_result_wrapper, &tinytds_result_wrapper_type, rwrap);
|
58
76
|
rwrap->cwrap = cwrap;
|
59
77
|
rwrap->client = cwrap->client;
|
60
78
|
rwrap->local_offset = Qnil;
|
@@ -77,13 +95,15 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
|
|
77
95
|
(rb_unblock_function_t*)dbcancel_ubf, _client ) \
|
78
96
|
)
|
79
97
|
|
80
|
-
static void dbcancel_ubf(DBPROCESS *client)
|
98
|
+
static void dbcancel_ubf(DBPROCESS *client)
|
99
|
+
{
|
81
100
|
GET_CLIENT_USERDATA(client);
|
82
101
|
dbcancel(client);
|
83
102
|
userdata->dbcancel_sent = 1;
|
84
103
|
}
|
85
104
|
|
86
|
-
static void nogvl_setup(DBPROCESS *client)
|
105
|
+
static void nogvl_setup(DBPROCESS *client)
|
106
|
+
{
|
87
107
|
GET_CLIENT_USERDATA(client);
|
88
108
|
userdata->nonblocking = 1;
|
89
109
|
userdata->nonblocking_errors_length = 0;
|
@@ -91,7 +111,8 @@ static void nogvl_setup(DBPROCESS *client) {
|
|
91
111
|
userdata->nonblocking_errors_size = ERRORS_STACK_INIT_SIZE;
|
92
112
|
}
|
93
113
|
|
94
|
-
static void nogvl_cleanup(DBPROCESS *client)
|
114
|
+
static void nogvl_cleanup(DBPROCESS *client)
|
115
|
+
{
|
95
116
|
GET_CLIENT_USERDATA(client);
|
96
117
|
userdata->nonblocking = 0;
|
97
118
|
userdata->timing_out = 0;
|
@@ -100,14 +121,17 @@ static void nogvl_cleanup(DBPROCESS *client) {
|
|
100
121
|
exceptions based on errors from SQL Server.
|
101
122
|
*/
|
102
123
|
short int i;
|
124
|
+
|
103
125
|
for (i = 0; i < userdata->nonblocking_errors_length; i++) {
|
104
126
|
tinytds_errordata error = userdata->nonblocking_errors[i];
|
105
127
|
|
106
128
|
// lookahead to drain any info messages ahead of raising error
|
107
129
|
if (!error.is_message) {
|
108
130
|
short int j;
|
131
|
+
|
109
132
|
for (j = i; j < userdata->nonblocking_errors_length; j++) {
|
110
133
|
tinytds_errordata msg_error = userdata->nonblocking_errors[j];
|
134
|
+
|
111
135
|
if (msg_error.is_message) {
|
112
136
|
rb_tinytds_raise_error(client, msg_error);
|
113
137
|
}
|
@@ -122,7 +146,8 @@ static void nogvl_cleanup(DBPROCESS *client) {
|
|
122
146
|
userdata->nonblocking_errors_size = 0;
|
123
147
|
}
|
124
148
|
|
125
|
-
static RETCODE nogvl_dbsqlok(DBPROCESS *client)
|
149
|
+
static RETCODE nogvl_dbsqlok(DBPROCESS *client)
|
150
|
+
{
|
126
151
|
int retcode = FAIL;
|
127
152
|
GET_CLIENT_USERDATA(client);
|
128
153
|
nogvl_setup(client);
|
@@ -132,7 +157,8 @@ static RETCODE nogvl_dbsqlok(DBPROCESS *client) {
|
|
132
157
|
return retcode;
|
133
158
|
}
|
134
159
|
|
135
|
-
static RETCODE nogvl_dbsqlexec(DBPROCESS *client)
|
160
|
+
static RETCODE nogvl_dbsqlexec(DBPROCESS *client)
|
161
|
+
{
|
136
162
|
int retcode = FAIL;
|
137
163
|
nogvl_setup(client);
|
138
164
|
retcode = NOGVL_DBCALL(dbsqlexec, client);
|
@@ -140,7 +166,8 @@ static RETCODE nogvl_dbsqlexec(DBPROCESS *client) {
|
|
140
166
|
return retcode;
|
141
167
|
}
|
142
168
|
|
143
|
-
static RETCODE nogvl_dbresults(DBPROCESS *client)
|
169
|
+
static RETCODE nogvl_dbresults(DBPROCESS *client)
|
170
|
+
{
|
144
171
|
int retcode = FAIL;
|
145
172
|
nogvl_setup(client);
|
146
173
|
retcode = NOGVL_DBCALL(dbresults, client);
|
@@ -148,7 +175,8 @@ static RETCODE nogvl_dbresults(DBPROCESS *client) {
|
|
148
175
|
return retcode;
|
149
176
|
}
|
150
177
|
|
151
|
-
static RETCODE nogvl_dbnextrow(DBPROCESS * client)
|
178
|
+
static RETCODE nogvl_dbnextrow(DBPROCESS * client)
|
179
|
+
{
|
152
180
|
int retcode = FAIL;
|
153
181
|
nogvl_setup(client);
|
154
182
|
retcode = NOGVL_DBCALL(dbnextrow, client);
|
@@ -158,11 +186,13 @@ static RETCODE nogvl_dbnextrow(DBPROCESS * client) {
|
|
158
186
|
|
159
187
|
// Lib Backend (Helpers)
|
160
188
|
|
161
|
-
static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self)
|
189
|
+
static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self)
|
190
|
+
{
|
162
191
|
VALUE ruby_rc;
|
163
192
|
RETCODE db_rc;
|
164
193
|
GET_RESULT_WRAPPER(self);
|
165
194
|
ruby_rc = rb_ary_entry(rwrap->dbresults_retcodes, rwrap->number_of_results);
|
195
|
+
|
166
196
|
if (NIL_P(ruby_rc)) {
|
167
197
|
db_rc = nogvl_dbresults(rwrap->client);
|
168
198
|
ruby_rc = INT2FIX(db_rc);
|
@@ -170,20 +200,26 @@ static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
|
|
170
200
|
} else {
|
171
201
|
db_rc = FIX2INT(ruby_rc);
|
172
202
|
}
|
203
|
+
|
173
204
|
return db_rc;
|
174
205
|
}
|
175
206
|
|
176
|
-
static RETCODE rb_tinytds_result_ok_helper(DBPROCESS *client)
|
207
|
+
static RETCODE rb_tinytds_result_ok_helper(DBPROCESS *client)
|
208
|
+
{
|
177
209
|
GET_CLIENT_USERDATA(client);
|
210
|
+
|
178
211
|
if (userdata->dbsqlok_sent == 0) {
|
179
212
|
userdata->dbsqlok_retcode = nogvl_dbsqlok(client);
|
180
213
|
}
|
214
|
+
|
181
215
|
return userdata->dbsqlok_retcode;
|
182
216
|
}
|
183
217
|
|
184
|
-
static void rb_tinytds_result_exec_helper(DBPROCESS *client)
|
218
|
+
static void rb_tinytds_result_exec_helper(DBPROCESS *client)
|
219
|
+
{
|
185
220
|
RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(client);
|
186
221
|
GET_CLIENT_USERDATA(client);
|
222
|
+
|
187
223
|
if (dbsqlok_rc == SUCCEED) {
|
188
224
|
/*
|
189
225
|
This is to just process each result set. Commands such as backup and
|
@@ -199,12 +235,14 @@ static void rb_tinytds_result_exec_helper(DBPROCESS *client) {
|
|
199
235
|
while (dbnextrow(client) != NO_MORE_ROWS);
|
200
236
|
}
|
201
237
|
}
|
238
|
+
|
202
239
|
dbcancel(client);
|
203
240
|
userdata->dbcancel_sent = 1;
|
204
241
|
userdata->dbsql_sent = 0;
|
205
242
|
}
|
206
243
|
|
207
|
-
static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_keys, int as_array)
|
244
|
+
static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_keys, int as_array)
|
245
|
+
{
|
208
246
|
VALUE row;
|
209
247
|
/* Storing Values */
|
210
248
|
unsigned int i;
|
@@ -212,6 +250,7 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
212
250
|
GET_RESULT_WRAPPER(self);
|
213
251
|
/* Create Empty Row */
|
214
252
|
row = as_array ? rb_ary_new2(rwrap->number_of_fields) : rb_hash_new();
|
253
|
+
|
215
254
|
for (i = 0; i < rwrap->number_of_fields; i++) {
|
216
255
|
VALUE val = Qnil;
|
217
256
|
int col = i+1;
|
@@ -219,23 +258,29 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
219
258
|
BYTE *data = dbdata(rwrap->client, col);
|
220
259
|
DBINT data_len = dbdatlen(rwrap->client, col);
|
221
260
|
int null_val = ((data == NULL) && (data_len == 0));
|
261
|
+
|
222
262
|
if (!null_val) {
|
223
263
|
switch(coltype) {
|
224
264
|
case SYBINT1:
|
225
265
|
val = INT2FIX(*(DBTINYINT *)data);
|
226
266
|
break;
|
267
|
+
|
227
268
|
case SYBINT2:
|
228
269
|
val = INT2FIX(*(DBSMALLINT *)data);
|
229
270
|
break;
|
271
|
+
|
230
272
|
case SYBINT4:
|
231
273
|
val = INT2NUM(*(DBINT *)data);
|
232
274
|
break;
|
275
|
+
|
233
276
|
case SYBINT8:
|
234
277
|
val = LL2NUM(*(DBBIGINT *)data);
|
235
278
|
break;
|
279
|
+
|
236
280
|
case SYBBIT:
|
237
281
|
val = *(int *)data ? Qtrue : Qfalse;
|
238
282
|
break;
|
283
|
+
|
239
284
|
case SYBNUMERIC:
|
240
285
|
case SYBDECIMAL: {
|
241
286
|
DBTYPEINFO *data_info = dbcoltypeinfo(rwrap->client, col);
|
@@ -245,16 +290,19 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
245
290
|
val = rb_funcall(cKernel, intern_bigd, 1, rb_str_new2((char *)converted_decimal));
|
246
291
|
break;
|
247
292
|
}
|
293
|
+
|
248
294
|
case SYBFLT8: {
|
249
295
|
double col_to_double = *(double *)data;
|
250
296
|
val = (col_to_double == 0.000000) ? opt_float_zero : rb_float_new(col_to_double);
|
251
297
|
break;
|
252
298
|
}
|
299
|
+
|
253
300
|
case SYBREAL: {
|
254
301
|
float col_to_float = *(float *)data;
|
255
302
|
val = (col_to_float == 0.0) ? opt_float_zero : rb_float_new(col_to_float);
|
256
303
|
break;
|
257
304
|
}
|
305
|
+
|
258
306
|
case SYBMONEY: {
|
259
307
|
DBMONEY *money = (DBMONEY *)data;
|
260
308
|
char converted_money[25];
|
@@ -264,6 +312,7 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
264
312
|
val = rb_funcall(val, intern_divide, 1, opt_tenk);
|
265
313
|
break;
|
266
314
|
}
|
315
|
+
|
267
316
|
case SYBMONEY4: {
|
268
317
|
DBMONEY4 *money = (DBMONEY4 *)data;
|
269
318
|
char converted_money[20];
|
@@ -271,54 +320,65 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
271
320
|
val = rb_funcall(cKernel, intern_bigd, 1, rb_str_new2(converted_money));
|
272
321
|
break;
|
273
322
|
}
|
323
|
+
|
274
324
|
case SYBBINARY:
|
275
325
|
case SYBIMAGE:
|
276
326
|
val = rb_str_new((char *)data, (long)data_len);
|
277
327
|
#ifdef HAVE_RUBY_ENCODING_H
|
278
|
-
|
328
|
+
rb_enc_associate(val, binaryEncoding);
|
279
329
|
#endif
|
280
330
|
break;
|
331
|
+
|
281
332
|
case 36: { // SYBUNIQUE
|
282
333
|
char converted_unique[37];
|
283
334
|
dbconvert(rwrap->client, coltype, data, 37, SYBVARCHAR, (BYTE *)converted_unique, -1);
|
284
335
|
val = ENCODED_STR_NEW2(converted_unique);
|
285
336
|
break;
|
286
337
|
}
|
338
|
+
|
287
339
|
case SYBDATETIME4: {
|
288
340
|
DBDATETIME new_data;
|
289
341
|
dbconvert(rwrap->client, coltype, data, data_len, SYBDATETIME, (BYTE *)&new_data, sizeof(new_data));
|
290
342
|
data = (BYTE *)&new_data;
|
291
343
|
data_len = sizeof(new_data);
|
292
344
|
}
|
345
|
+
|
293
346
|
case SYBDATETIME: {
|
294
347
|
DBDATEREC dr;
|
295
348
|
dbdatecrack(rwrap->client, &dr, (DBDATETIME *)data);
|
349
|
+
|
296
350
|
if (dr.year + dr.month + dr.day + dr.hour + dr.minute + dr.second + dr.millisecond != 0) {
|
297
351
|
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr.year), INT2NUM(dr.month), INT2NUM(dr.day), INT2NUM(dr.hour), INT2NUM(dr.minute), INT2NUM(dr.second), INT2NUM(dr.millisecond*1000));
|
298
352
|
}
|
353
|
+
|
299
354
|
break;
|
300
355
|
}
|
356
|
+
|
301
357
|
case SYBMSDATE:
|
302
358
|
case SYBMSTIME:
|
303
359
|
case SYBMSDATETIME2:
|
304
360
|
case SYBMSDATETIMEOFFSET: {
|
305
361
|
DBDATEREC2 dr2;
|
306
362
|
dbanydatecrack(rwrap->client, &dr2, coltype, data);
|
363
|
+
|
307
364
|
switch(coltype) {
|
308
365
|
case SYBMSDATE: {
|
309
366
|
val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
|
310
367
|
break;
|
311
368
|
}
|
369
|
+
|
312
370
|
case SYBMSTIME: {
|
313
371
|
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
314
372
|
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
315
373
|
break;
|
316
374
|
}
|
375
|
+
|
317
376
|
case SYBMSDATETIME2: {
|
318
377
|
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
319
378
|
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
320
379
|
break;
|
321
380
|
}
|
381
|
+
|
322
382
|
case SYBMSDATETIMEOFFSET: {
|
323
383
|
long long numerator = ((long)dr2.second * (long long)1000000000) + (long long)dr2.nanosecond;
|
324
384
|
VALUE rational_sec = rb_Rational(LL2NUM(numerator), opt_onebil);
|
@@ -326,12 +386,15 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
326
386
|
break;
|
327
387
|
}
|
328
388
|
}
|
389
|
+
|
329
390
|
break;
|
330
391
|
}
|
392
|
+
|
331
393
|
case SYBCHAR:
|
332
394
|
case SYBTEXT:
|
333
395
|
val = ENCODED_STR_NEW(data, data_len);
|
334
396
|
break;
|
397
|
+
|
335
398
|
case 98: { // SYBVARIANT
|
336
399
|
if (data_len == 4) {
|
337
400
|
val = INT2NUM(*(DBINT *)data);
|
@@ -341,53 +404,66 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
341
404
|
break;
|
342
405
|
}
|
343
406
|
}
|
407
|
+
|
344
408
|
default:
|
345
409
|
val = ENCODED_STR_NEW(data, data_len);
|
346
410
|
break;
|
347
411
|
}
|
348
412
|
}
|
413
|
+
|
349
414
|
if (as_array) {
|
350
415
|
rb_ary_store(row, i, val);
|
351
416
|
} else {
|
352
417
|
VALUE key;
|
418
|
+
|
353
419
|
if (rwrap->number_of_results == 0) {
|
354
420
|
key = rb_ary_entry(rwrap->fields, i);
|
355
421
|
} else {
|
356
422
|
key = rb_ary_entry(rb_ary_entry(rwrap->fields, rwrap->number_of_results), i);
|
357
423
|
}
|
424
|
+
|
358
425
|
rb_hash_aset(row, key, val);
|
359
426
|
}
|
360
427
|
}
|
428
|
+
|
361
429
|
return row;
|
362
430
|
}
|
363
431
|
|
364
432
|
|
365
433
|
// TinyTds::Client (public)
|
366
434
|
|
367
|
-
static VALUE rb_tinytds_result_fields(VALUE self)
|
435
|
+
static VALUE rb_tinytds_result_fields(VALUE self)
|
436
|
+
{
|
368
437
|
RETCODE dbsqlok_rc, dbresults_rc;
|
369
438
|
VALUE fields_processed;
|
370
439
|
GET_RESULT_WRAPPER(self);
|
371
440
|
dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
|
372
441
|
dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
|
373
442
|
fields_processed = rb_ary_entry(rwrap->fields_processed, rwrap->number_of_results);
|
443
|
+
|
374
444
|
if ((dbsqlok_rc == SUCCEED) && (dbresults_rc == SUCCEED) && (fields_processed == Qnil)) {
|
375
445
|
/* Default query options. */
|
376
446
|
int symbolize_keys = 0;
|
377
447
|
VALUE qopts = rb_iv_get(self, "@query_options");
|
378
|
-
|
379
|
-
|
448
|
+
|
449
|
+
if (rb_hash_aref(qopts, sym_symbolize_keys) == Qtrue) {
|
450
|
+
symbolize_keys = 1;
|
451
|
+
}
|
452
|
+
|
380
453
|
/* Set number_of_fields count for this result set. */
|
381
454
|
rwrap->number_of_fields = dbnumcols(rwrap->client);
|
455
|
+
|
382
456
|
if (rwrap->number_of_fields > 0) {
|
383
457
|
/* Create fields for this result set. */
|
384
458
|
unsigned int fldi = 0;
|
385
459
|
VALUE fields = rb_ary_new2(rwrap->number_of_fields);
|
460
|
+
|
386
461
|
for (fldi = 0; fldi < rwrap->number_of_fields; fldi++) {
|
387
462
|
char *colname = dbcolname(rwrap->client, fldi+1);
|
388
463
|
VALUE field = symbolize_keys ? rb_str_intern(ENCODED_STR_NEW2(colname)) : rb_obj_freeze(ENCODED_STR_NEW2(colname));
|
389
464
|
rb_ary_store(fields, fldi, field);
|
390
465
|
}
|
466
|
+
|
391
467
|
/* Store the fields. */
|
392
468
|
if (rwrap->number_of_results == 0) {
|
393
469
|
rwrap->fields = fields;
|
@@ -400,12 +476,15 @@ static VALUE rb_tinytds_result_fields(VALUE self) {
|
|
400
476
|
rb_ary_store(rwrap->fields, rwrap->number_of_results, fields);
|
401
477
|
}
|
402
478
|
}
|
479
|
+
|
403
480
|
rb_ary_store(rwrap->fields_processed, rwrap->number_of_results, Qtrue);
|
404
481
|
}
|
482
|
+
|
405
483
|
return rwrap->fields;
|
406
484
|
}
|
407
485
|
|
408
|
-
static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self)
|
486
|
+
static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self)
|
487
|
+
{
|
409
488
|
/* Local Vars */
|
410
489
|
VALUE qopts, opts, block;
|
411
490
|
ID timezone;
|
@@ -415,18 +494,30 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
415
494
|
userdata = (tinytds_client_userdata *)dbgetuserdata(rwrap->client);
|
416
495
|
/* Merge Options Hash To Query Options. Populate Opts & Block Var. */
|
417
496
|
qopts = rb_iv_get(self, "@query_options");
|
418
|
-
|
497
|
+
|
498
|
+
if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
|
419
499
|
qopts = rb_funcall(qopts, intern_merge, 1, opts);
|
500
|
+
}
|
501
|
+
|
420
502
|
rb_iv_set(self, "@query_options", qopts);
|
503
|
+
|
421
504
|
/* Locals From Options */
|
422
|
-
if (rb_hash_aref(qopts, sym_first) == Qtrue)
|
505
|
+
if (rb_hash_aref(qopts, sym_first) == Qtrue) {
|
423
506
|
first = 1;
|
424
|
-
|
507
|
+
}
|
508
|
+
|
509
|
+
if (rb_hash_aref(qopts, sym_symbolize_keys) == Qtrue) {
|
425
510
|
symbolize_keys = 1;
|
426
|
-
|
511
|
+
}
|
512
|
+
|
513
|
+
if (rb_hash_aref(qopts, sym_as) == sym_array) {
|
427
514
|
as_array = 1;
|
428
|
-
|
515
|
+
}
|
516
|
+
|
517
|
+
if (rb_hash_aref(qopts, sym_cache_rows) == Qtrue) {
|
429
518
|
cache_rows = 1;
|
519
|
+
}
|
520
|
+
|
430
521
|
if (rb_hash_aref(qopts, sym_timezone) == sym_local) {
|
431
522
|
timezone = intern_local;
|
432
523
|
} else if (rb_hash_aref(qopts, sym_timezone) == sym_utc) {
|
@@ -435,35 +526,51 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
435
526
|
rb_warn(":timezone option must be :utc or :local - defaulting to :local");
|
436
527
|
timezone = intern_local;
|
437
528
|
}
|
438
|
-
|
529
|
+
|
530
|
+
if (rb_hash_aref(qopts, sym_empty_sets) == Qtrue) {
|
439
531
|
empty_sets = 1;
|
532
|
+
}
|
533
|
+
|
440
534
|
/* Make The Results Or Yield Existing */
|
441
535
|
if (NIL_P(rwrap->results)) {
|
442
536
|
RETCODE dbsqlok_rc, dbresults_rc;
|
443
537
|
rwrap->results = rb_ary_new();
|
444
538
|
dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
|
445
539
|
dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
|
540
|
+
|
446
541
|
while ((dbsqlok_rc == SUCCEED) && (dbresults_rc == SUCCEED)) {
|
447
542
|
int has_rows = (DBROWS(rwrap->client) == SUCCEED) ? 1 : 0;
|
448
|
-
|
543
|
+
|
544
|
+
if (has_rows || empty_sets || (rwrap->number_of_results == 0)) {
|
449
545
|
rb_tinytds_result_fields(self);
|
546
|
+
}
|
547
|
+
|
450
548
|
if ((has_rows || empty_sets) && rwrap->number_of_fields > 0) {
|
451
549
|
/* Create rows for this result set. */
|
452
550
|
unsigned long rowi = 0;
|
453
551
|
VALUE result = rb_ary_new();
|
552
|
+
|
454
553
|
while (nogvl_dbnextrow(rwrap->client) != NO_MORE_ROWS) {
|
455
554
|
VALUE row = rb_tinytds_result_fetch_row(self, timezone, symbolize_keys, as_array);
|
456
|
-
|
555
|
+
|
556
|
+
if (cache_rows) {
|
457
557
|
rb_ary_store(result, rowi, row);
|
458
|
-
|
558
|
+
}
|
559
|
+
|
560
|
+
if (!NIL_P(block)) {
|
459
561
|
rb_yield(row);
|
562
|
+
}
|
563
|
+
|
460
564
|
if (first) {
|
461
565
|
dbcanquery(rwrap->client);
|
462
566
|
userdata->dbcancel_sent = 1;
|
463
567
|
}
|
568
|
+
|
464
569
|
rowi++;
|
465
570
|
}
|
571
|
+
|
466
572
|
rwrap->number_of_rows = rowi;
|
573
|
+
|
467
574
|
/* Store the result. */
|
468
575
|
if (cache_rows) {
|
469
576
|
if (rwrap->number_of_results == 0) {
|
@@ -477,6 +584,7 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
477
584
|
rb_ary_store(rwrap->results, rwrap->number_of_results, result);
|
478
585
|
}
|
479
586
|
}
|
587
|
+
|
480
588
|
// If we find results increment the counter that helpers use and setup the next loop.
|
481
589
|
rwrap->number_of_results = rwrap->number_of_results + 1;
|
482
590
|
dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
|
@@ -489,33 +597,43 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
|
|
489
597
|
rb_ary_store(rwrap->fields_processed, rwrap->number_of_results, Qnil);
|
490
598
|
}
|
491
599
|
}
|
492
|
-
|
600
|
+
|
601
|
+
if (dbresults_rc == FAIL) {
|
493
602
|
rb_warn("TinyTDS: Something in the dbresults() while loop set the return code to FAIL.\n");
|
603
|
+
}
|
604
|
+
|
494
605
|
userdata->dbsql_sent = 0;
|
495
606
|
} else if (!NIL_P(block)) {
|
496
607
|
unsigned long i;
|
608
|
+
|
497
609
|
for (i = 0; i < rwrap->number_of_rows; i++) {
|
498
610
|
rb_yield(rb_ary_entry(rwrap->results, i));
|
499
611
|
}
|
500
612
|
}
|
613
|
+
|
501
614
|
return rwrap->results;
|
502
615
|
}
|
503
616
|
|
504
|
-
static VALUE rb_tinytds_result_cancel(VALUE self)
|
617
|
+
static VALUE rb_tinytds_result_cancel(VALUE self)
|
618
|
+
{
|
505
619
|
tinytds_client_userdata *userdata;
|
506
620
|
GET_RESULT_WRAPPER(self);
|
507
621
|
userdata = (tinytds_client_userdata *)dbgetuserdata(rwrap->client);
|
622
|
+
|
508
623
|
if (rwrap->client && !userdata->dbcancel_sent) {
|
509
624
|
rb_tinytds_result_ok_helper(rwrap->client);
|
510
625
|
dbcancel(rwrap->client);
|
511
626
|
userdata->dbcancel_sent = 1;
|
512
627
|
userdata->dbsql_sent = 0;
|
513
628
|
}
|
629
|
+
|
514
630
|
return Qtrue;
|
515
631
|
}
|
516
632
|
|
517
|
-
static VALUE rb_tinytds_result_do(VALUE self)
|
633
|
+
static VALUE rb_tinytds_result_do(VALUE self)
|
634
|
+
{
|
518
635
|
GET_RESULT_WRAPPER(self);
|
636
|
+
|
519
637
|
if (rwrap->client) {
|
520
638
|
rb_tinytds_result_exec_helper(rwrap->client);
|
521
639
|
return LONG2NUM((long)dbcount(rwrap->client));
|
@@ -524,8 +642,10 @@ static VALUE rb_tinytds_result_do(VALUE self) {
|
|
524
642
|
}
|
525
643
|
}
|
526
644
|
|
527
|
-
static VALUE rb_tinytds_result_affected_rows(VALUE self)
|
645
|
+
static VALUE rb_tinytds_result_affected_rows(VALUE self)
|
646
|
+
{
|
528
647
|
GET_RESULT_WRAPPER(self);
|
648
|
+
|
529
649
|
if (rwrap->client) {
|
530
650
|
return LONG2NUM((long)dbcount(rwrap->client));
|
531
651
|
} else {
|
@@ -534,8 +654,10 @@ static VALUE rb_tinytds_result_affected_rows(VALUE self) {
|
|
534
654
|
}
|
535
655
|
|
536
656
|
/* Duplicated in client.c */
|
537
|
-
static VALUE rb_tinytds_result_return_code(VALUE self)
|
657
|
+
static VALUE rb_tinytds_result_return_code(VALUE self)
|
658
|
+
{
|
538
659
|
GET_RESULT_WRAPPER(self);
|
660
|
+
|
539
661
|
if (rwrap->client && dbhasretstat(rwrap->client)) {
|
540
662
|
return LONG2NUM((long)dbretstatus(rwrap->client));
|
541
663
|
} else {
|
@@ -543,24 +665,30 @@ static VALUE rb_tinytds_result_return_code(VALUE self) {
|
|
543
665
|
}
|
544
666
|
}
|
545
667
|
|
546
|
-
static VALUE rb_tinytds_result_insert(VALUE self)
|
668
|
+
static VALUE rb_tinytds_result_insert(VALUE self)
|
669
|
+
{
|
547
670
|
GET_RESULT_WRAPPER(self);
|
671
|
+
|
548
672
|
if (rwrap->client) {
|
549
673
|
VALUE identity = Qnil;
|
550
674
|
rb_tinytds_result_exec_helper(rwrap->client);
|
551
675
|
dbcmd(rwrap->client, rwrap->cwrap->identity_insert_sql);
|
676
|
+
|
552
677
|
if (nogvl_dbsqlexec(rwrap->client) != FAIL
|
553
|
-
|
554
|
-
|
678
|
+
&& nogvl_dbresults(rwrap->client) != FAIL
|
679
|
+
&& DBROWS(rwrap->client) != FAIL) {
|
555
680
|
while (nogvl_dbnextrow(rwrap->client) != NO_MORE_ROWS) {
|
556
681
|
int col = 1;
|
557
682
|
BYTE *data = dbdata(rwrap->client, col);
|
558
683
|
DBINT data_len = dbdatlen(rwrap->client, col);
|
559
684
|
int null_val = ((data == NULL) && (data_len == 0));
|
560
|
-
|
685
|
+
|
686
|
+
if (!null_val) {
|
561
687
|
identity = LL2NUM(*(DBBIGINT *)data);
|
688
|
+
}
|
562
689
|
}
|
563
690
|
}
|
691
|
+
|
564
692
|
return identity;
|
565
693
|
} else {
|
566
694
|
return Qnil;
|
@@ -570,7 +698,8 @@ static VALUE rb_tinytds_result_insert(VALUE self) {
|
|
570
698
|
|
571
699
|
// Lib Init
|
572
700
|
|
573
|
-
void init_tinytds_result()
|
701
|
+
void init_tinytds_result()
|
702
|
+
{
|
574
703
|
/* Data Classes */
|
575
704
|
cKernel = rb_const_get(rb_cObject, rb_intern("Kernel"));
|
576
705
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
@@ -621,6 +750,6 @@ void init_tinytds_result() {
|
|
621
750
|
opt_onebil = INT2NUM(1000000000);
|
622
751
|
/* Encoding */
|
623
752
|
#ifdef HAVE_RUBY_ENCODING_H
|
624
|
-
|
753
|
+
binaryEncoding = rb_enc_find("binary");
|
625
754
|
#endif
|
626
755
|
}
|
data/ext/tiny_tds/result.h
CHANGED
@@ -19,12 +19,12 @@ typedef struct {
|
|
19
19
|
unsigned long number_of_rows;
|
20
20
|
} tinytds_result_wrapper;
|
21
21
|
|
22
|
+
extern const rb_data_type_t tinytds_result_wrapper_type;
|
22
23
|
|
23
24
|
// Lib Macros
|
24
|
-
|
25
25
|
#define GET_RESULT_WRAPPER(self) \
|
26
26
|
tinytds_result_wrapper *rwrap; \
|
27
|
-
|
27
|
+
TypedData_Get_Struct(self, tinytds_result_wrapper, &tinytds_result_wrapper_type, rwrap)
|
28
28
|
|
29
29
|
|
30
30
|
|
data/ext/tiny_tds/tiny_tds_ext.c
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|