rubyfb 0.5.5 → 0.5.6
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.
- data/CHANGELOG +6 -0
- data/Manifest +0 -1
- data/Rakefile +1 -1
- data/ext/AddUser.c +217 -248
- data/ext/AddUser.h +3 -3
- data/ext/Backup.c +337 -404
- data/ext/Backup.h +3 -3
- data/ext/Blob.c +197 -248
- data/ext/Blob.h +30 -31
- data/ext/Common.c +17 -18
- data/ext/Common.h +10 -10
- data/ext/Connection.c +413 -487
- data/ext/Connection.h +18 -19
- data/ext/DataArea.c +172 -189
- data/ext/DataArea.h +11 -11
- data/ext/Database.c +198 -238
- data/ext/Database.h +16 -17
- data/ext/FireRuby.c +118 -142
- data/ext/FireRuby.h +17 -17
- data/ext/FireRubyException.c +68 -138
- data/ext/FireRubyException.h +14 -21
- data/ext/Generator.c +296 -377
- data/ext/Generator.h +17 -18
- data/ext/RemoveUser.c +91 -102
- data/ext/RemoveUser.h +3 -3
- data/ext/Restore.c +353 -423
- data/ext/Restore.h +3 -3
- data/ext/ResultSet.c +423 -456
- data/ext/ResultSet.h +26 -27
- data/ext/Row.c +505 -568
- data/ext/Row.h +27 -28
- data/ext/ServiceManager.c +143 -164
- data/ext/ServiceManager.h +17 -18
- data/ext/Services.c +58 -67
- data/ext/Services.h +3 -3
- data/ext/Statement.c +388 -449
- data/ext/Statement.h +30 -31
- data/ext/Transaction.c +374 -448
- data/ext/Transaction.h +17 -18
- data/ext/TypeMap.c +654 -774
- data/ext/TypeMap.h +17 -17
- data/ext/rfbint.h +3 -3
- data/lib/active_record/connection_adapters/rubyfb_adapter.rb +1 -1
- data/lib/rubyfb_lib.so +0 -0
- data/lib/src.rb +33 -0
- data/rubyfb.gemspec +3 -3
- data/test/ResultSetTest.rb +13 -0
- data/test/RowTest.rb +16 -0
- metadata +4 -5
- data/test/UnitTest.rb +0 -65
data/ext/Statement.c
CHANGED
@@ -3,26 +3,26 @@
|
|
3
3
|
*----------------------------------------------------------------------------*/
|
4
4
|
/**
|
5
5
|
* Copyright � Peter Wood, 2005
|
6
|
-
*
|
6
|
+
*
|
7
7
|
* The contents of this file are subject to the Mozilla Public License Version
|
8
8
|
* 1.1 (the "License"); you may not use this file except in compliance with the
|
9
|
-
* License. You may obtain a copy of the License at
|
9
|
+
* License. You may obtain a copy of the License at
|
10
10
|
*
|
11
11
|
* http://www.mozilla.org/MPL/
|
12
|
-
*
|
12
|
+
*
|
13
13
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
14
14
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
15
15
|
* the specificlanguage governing rights and limitations under the License.
|
16
|
-
*
|
16
|
+
*
|
17
17
|
* The Original Code is the FireRuby extension for the Ruby language.
|
18
|
-
*
|
19
|
-
* The Initial Developer of the Original Code is Peter Wood. All Rights
|
18
|
+
*
|
19
|
+
* The Initial Developer of the Original Code is Peter Wood. All Rights
|
20
20
|
* Reserved.
|
21
21
|
*
|
22
22
|
* @author Peter Wood
|
23
23
|
* @version 1.0
|
24
24
|
*/
|
25
|
-
|
25
|
+
|
26
26
|
/* Includes. */
|
27
27
|
#include "Statement.h"
|
28
28
|
#include "Common.h"
|
@@ -58,23 +58,21 @@ VALUE cStatement;
|
|
58
58
|
* @return A reference to the newly allocated Statement object.
|
59
59
|
*
|
60
60
|
*/
|
61
|
-
VALUE allocateStatement(VALUE klass)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
return(Data_Wrap_Struct(klass, NULL, statementFree, statement));
|
61
|
+
VALUE allocateStatement(VALUE klass) {
|
62
|
+
StatementHandle *statement = ALLOC(StatementHandle);
|
63
|
+
|
64
|
+
if(statement == NULL) {
|
65
|
+
rb_raise(rb_eNoMemError,
|
66
|
+
"Memory allocation failure allocating a statement.");
|
67
|
+
}
|
68
|
+
|
69
|
+
statement->handle = 0;
|
70
|
+
statement->type = -1;
|
71
|
+
statement->inputs = 0;
|
72
|
+
statement->dialect = 0;
|
73
|
+
statement->parameters = NULL;
|
74
|
+
|
75
|
+
return(Data_Wrap_Struct(klass, NULL, statementFree, statement));
|
78
76
|
}
|
79
77
|
|
80
78
|
|
@@ -96,65 +94,52 @@ VALUE allocateStatement(VALUE klass)
|
|
96
94
|
*
|
97
95
|
*/
|
98
96
|
VALUE initializeStatement(VALUE self, VALUE connection, VALUE transaction,
|
99
|
-
VALUE sql, VALUE dialect)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
else
|
128
|
-
{
|
129
|
-
rb_fireruby_raise(NULL, "Invalid transaction specified for statement.");
|
130
|
-
}
|
131
|
-
|
132
|
-
value = rb_funcall(dialect, rb_intern("to_i"), 0);
|
133
|
-
if(TYPE(value) == T_FIXNUM)
|
134
|
-
{
|
135
|
-
setting = FIX2INT(value);
|
136
|
-
if(setting < 1 || setting > 3)
|
137
|
-
{
|
138
|
-
rb_fireruby_raise(NULL,
|
139
|
-
"Invalid dialect value specified for statement. "\
|
140
|
-
"The dialect value must be between 1 and 3.");
|
141
|
-
}
|
142
|
-
}
|
143
|
-
else
|
144
|
-
{
|
97
|
+
VALUE sql, VALUE dialect) {
|
98
|
+
StatementHandle *statement = NULL;
|
99
|
+
short setting = 0;
|
100
|
+
VALUE value = Qnil;
|
101
|
+
|
102
|
+
/* Validate the inputs. */
|
103
|
+
if(TYPE(connection) == T_DATA &&
|
104
|
+
RDATA(connection)->dfree == (RUBY_DATA_FUNC)connectionFree) {
|
105
|
+
if(rb_funcall(connection, rb_intern("open?"), 0) == Qfalse) {
|
106
|
+
rb_fireruby_raise(NULL, "Closed connection specified for statement.");
|
107
|
+
}
|
108
|
+
} else {
|
109
|
+
rb_fireruby_raise(NULL, "Invalid connection specified for statement.");
|
110
|
+
}
|
111
|
+
|
112
|
+
if(TYPE(transaction) == T_DATA &&
|
113
|
+
RDATA(transaction)->dfree == (RUBY_DATA_FUNC)transactionFree) {
|
114
|
+
if(rb_funcall(transaction, rb_intern("active?"), 0) == Qfalse) {
|
115
|
+
rb_fireruby_raise(NULL, "Inactive transaction specified for statement.");
|
116
|
+
}
|
117
|
+
} else {
|
118
|
+
rb_fireruby_raise(NULL, "Invalid transaction specified for statement.");
|
119
|
+
}
|
120
|
+
|
121
|
+
value = rb_funcall(dialect, rb_intern("to_i"), 0);
|
122
|
+
if(TYPE(value) == T_FIXNUM) {
|
123
|
+
setting = FIX2INT(value);
|
124
|
+
if(setting < 1 || setting > 3) {
|
145
125
|
rb_fireruby_raise(NULL,
|
146
|
-
"Invalid dialect value specified for statement.
|
147
|
-
"dialect value must be between 1 and 3.");
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
126
|
+
"Invalid dialect value specified for statement. " \
|
127
|
+
"The dialect value must be between 1 and 3.");
|
128
|
+
}
|
129
|
+
} else {
|
130
|
+
rb_fireruby_raise(NULL,
|
131
|
+
"Invalid dialect value specified for statement. The " \
|
132
|
+
"dialect value must be between 1 and 3.");
|
133
|
+
}
|
134
|
+
|
135
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
136
|
+
rb_iv_set(self, "@connection", connection);
|
137
|
+
rb_iv_set(self, "@transaction", transaction);
|
138
|
+
rb_iv_set(self, "@sql", rb_funcall(sql, rb_intern("to_s"), 0));
|
139
|
+
rb_iv_set(self, "@dialect", value);
|
140
|
+
statement->dialect = setting;
|
141
|
+
|
142
|
+
return(self);
|
158
143
|
}
|
159
144
|
|
160
145
|
|
@@ -167,9 +152,8 @@ VALUE initializeStatement(VALUE self, VALUE connection, VALUE transaction,
|
|
167
152
|
* @return A reference to a String containing the SQL statement.
|
168
153
|
*
|
169
154
|
*/
|
170
|
-
VALUE getStatementSQL(VALUE self)
|
171
|
-
|
172
|
-
return(rb_iv_get(self, "@sql"));
|
155
|
+
VALUE getStatementSQL(VALUE self) {
|
156
|
+
return(rb_iv_get(self, "@sql"));
|
173
157
|
}
|
174
158
|
|
175
159
|
|
@@ -182,9 +166,8 @@ VALUE getStatementSQL(VALUE self)
|
|
182
166
|
* @return A reference to a Connection object.
|
183
167
|
*
|
184
168
|
*/
|
185
|
-
VALUE getStatementConnection(VALUE self)
|
186
|
-
|
187
|
-
return(rb_iv_get(self, "@connection"));
|
169
|
+
VALUE getStatementConnection(VALUE self) {
|
170
|
+
return(rb_iv_get(self, "@connection"));
|
188
171
|
}
|
189
172
|
|
190
173
|
|
@@ -197,9 +180,8 @@ VALUE getStatementConnection(VALUE self)
|
|
197
180
|
* @return A reference to a Transaction object.
|
198
181
|
*
|
199
182
|
*/
|
200
|
-
VALUE getStatementTransaction(VALUE self)
|
201
|
-
|
202
|
-
return(rb_iv_get(self, "@transaction"));
|
183
|
+
VALUE getStatementTransaction(VALUE self) {
|
184
|
+
return(rb_iv_get(self, "@transaction"));
|
203
185
|
}
|
204
186
|
|
205
187
|
|
@@ -212,9 +194,8 @@ VALUE getStatementTransaction(VALUE self)
|
|
212
194
|
* @return A reference to an integer containing the SQL dialect setting.
|
213
195
|
*
|
214
196
|
*/
|
215
|
-
VALUE getStatementDialect(VALUE self)
|
216
|
-
|
217
|
-
return(rb_iv_get(self, "@dialect"));
|
197
|
+
VALUE getStatementDialect(VALUE self) {
|
198
|
+
return(rb_iv_get(self, "@dialect"));
|
218
199
|
}
|
219
200
|
|
220
201
|
|
@@ -228,27 +209,25 @@ VALUE getStatementDialect(VALUE self)
|
|
228
209
|
* @return A reference to an integer containing the SQL type details.
|
229
210
|
*
|
230
211
|
*/
|
231
|
-
VALUE getStatementType(VALUE self)
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
return(INT2FIX(statement->type));
|
212
|
+
VALUE getStatementType(VALUE self) {
|
213
|
+
StatementHandle *statement = NULL;
|
214
|
+
ConnectionHandle *connection = NULL;
|
215
|
+
TransactionHandle *transaction = NULL;
|
216
|
+
int outputs = 0;
|
217
|
+
VALUE tmp_str = Qnil;
|
218
|
+
|
219
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
220
|
+
Data_Get_Struct(rb_iv_get(self, "@connection"), ConnectionHandle, connection);
|
221
|
+
Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle, transaction);
|
222
|
+
if(statement->handle == 0) {
|
223
|
+
tmp_str = rb_iv_get(self, "@sql");
|
224
|
+
prepare(&connection->handle, &transaction->handle,
|
225
|
+
StringValuePtr(tmp_str), &statement->handle,
|
226
|
+
statement->dialect, &statement->type, &statement->inputs,
|
227
|
+
&outputs);
|
228
|
+
}
|
229
|
+
|
230
|
+
return(INT2FIX(statement->type));
|
252
231
|
}
|
253
232
|
|
254
233
|
|
@@ -261,17 +240,15 @@ VALUE getStatementType(VALUE self)
|
|
261
240
|
* @return A reference to an integer containing the statement parameter count.
|
262
241
|
*
|
263
242
|
*/
|
264
|
-
VALUE getStatementParameterCount(VALUE self)
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
return(INT2NUM(statement->inputs));
|
243
|
+
VALUE getStatementParameterCount(VALUE self) {
|
244
|
+
StatementHandle *statement = NULL;
|
245
|
+
|
246
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
247
|
+
if(statement->handle == 0) {
|
248
|
+
getStatementType(self);
|
249
|
+
}
|
250
|
+
|
251
|
+
return(INT2NUM(statement->inputs));
|
275
252
|
}
|
276
253
|
|
277
254
|
|
@@ -281,50 +258,48 @@ VALUE getStatementParameterCount(VALUE self)
|
|
281
258
|
* @param self A reference to the Statement object to call the method on.
|
282
259
|
*
|
283
260
|
* @return One of a count of the number of rows affected by the SQL statement,
|
284
|
-
* a ResultSet object for a query or nil.
|
261
|
+
* a ResultSet object for a query or nil.
|
285
262
|
*
|
286
263
|
*/
|
287
|
-
VALUE executeStatement(VALUE self)
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
return(result);
|
264
|
+
VALUE executeStatement(VALUE self) {
|
265
|
+
VALUE result;
|
266
|
+
int type = FIX2INT(getStatementType(self));
|
267
|
+
long affected = 0;
|
268
|
+
StatementHandle *statement = NULL;
|
269
|
+
TransactionHandle *transaction = NULL;
|
270
|
+
|
271
|
+
switch(type) {
|
272
|
+
case isc_info_sql_stmt_select:
|
273
|
+
case isc_info_sql_stmt_select_for_upd:
|
274
|
+
case isc_info_sql_stmt_exec_procedure:
|
275
|
+
result = rb_result_set_new(rb_iv_get(self, "@connection"),
|
276
|
+
rb_iv_get(self, "@transaction"),
|
277
|
+
rb_iv_get(self, "@sql"),
|
278
|
+
rb_iv_get(self, "@dialect"),
|
279
|
+
rb_ary_new());
|
280
|
+
break;
|
281
|
+
|
282
|
+
case isc_info_sql_stmt_insert:
|
283
|
+
case isc_info_sql_stmt_update:
|
284
|
+
case isc_info_sql_stmt_delete:
|
285
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
286
|
+
Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
|
287
|
+
transaction);
|
288
|
+
execute(&transaction->handle, &statement->handle, statement->dialect,
|
289
|
+
NULL, statement->type, &affected);
|
290
|
+
result = INT2NUM(affected);
|
291
|
+
break;
|
292
|
+
|
293
|
+
default:
|
294
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
295
|
+
Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
|
296
|
+
transaction);
|
297
|
+
execute(&transaction->handle, &statement->handle, statement->dialect,
|
298
|
+
NULL, statement->type, &affected);
|
299
|
+
result = Qnil;
|
300
|
+
}
|
301
|
+
|
302
|
+
return(result);
|
328
303
|
}
|
329
304
|
|
330
305
|
|
@@ -337,73 +312,65 @@ VALUE executeStatement(VALUE self)
|
|
337
312
|
* executing the statement.
|
338
313
|
*
|
339
314
|
* @return One of a count of the number of rows affected by the SQL statement,
|
340
|
-
* a ResultSet object for a query or nil.
|
315
|
+
* a ResultSet object for a query or nil.
|
341
316
|
*
|
342
317
|
*/
|
343
|
-
VALUE executeStatementFor(VALUE self, VALUE parameters)
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
if(
|
366
|
-
|
367
|
-
|
368
|
-
int size = 0;
|
369
|
-
|
370
|
-
if(parameters == Qnil)
|
371
|
-
{
|
372
|
-
rb_fireruby_raise(NULL,
|
373
|
-
"Empty parameter list specified for statement.");
|
374
|
-
}
|
375
|
-
|
376
|
-
value = rb_funcall(parameters, rb_intern("size"), 0);
|
377
|
-
size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
|
378
|
-
if(size < statement->inputs)
|
379
|
-
{
|
380
|
-
rb_fireruby_raise(NULL,
|
381
|
-
"Insufficient parameters specified for statement.");
|
382
|
-
}
|
383
|
-
|
384
|
-
/* Allocate the XSQLDA and populate it. */
|
385
|
-
statement->parameters = allocateInXSQLDA(statement->inputs,
|
386
|
-
&statement->handle,
|
387
|
-
statement->dialect);
|
388
|
-
prepareDataArea(statement->parameters);
|
389
|
-
setParameters(statement->parameters, parameters, self);
|
318
|
+
VALUE executeStatementFor(VALUE self, VALUE parameters) {
|
319
|
+
VALUE result = Qnil;
|
320
|
+
int type = FIX2INT(getStatementType(self));
|
321
|
+
long affected = 0;
|
322
|
+
StatementHandle *statement = NULL;
|
323
|
+
TransactionHandle *transaction = NULL;
|
324
|
+
|
325
|
+
if(type == isc_info_sql_stmt_select ||
|
326
|
+
type == isc_info_sql_stmt_select_for_upd) {
|
327
|
+
/* Execute the statement via a ResultSet object. */
|
328
|
+
result = rb_result_set_new(rb_iv_get(self, "@connection"),
|
329
|
+
rb_iv_get(self, "@transaction"),
|
330
|
+
rb_iv_get(self, "@sql"),
|
331
|
+
rb_iv_get(self, "@dialect"),
|
332
|
+
parameters);
|
333
|
+
} else {
|
334
|
+
/* Check that sufficient parameters have been specified. */
|
335
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
336
|
+
if(statement->inputs > 0) {
|
337
|
+
VALUE value = Qnil;
|
338
|
+
int size = 0;
|
339
|
+
|
340
|
+
if(parameters == Qnil) {
|
341
|
+
rb_fireruby_raise(NULL,
|
342
|
+
"Empty parameter list specified for statement.");
|
390
343
|
}
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
statement->parameters, statement->type, &affected);
|
398
|
-
if(type == isc_info_sql_stmt_insert ||
|
399
|
-
type == isc_info_sql_stmt_update ||
|
400
|
-
type == isc_info_sql_stmt_delete)
|
401
|
-
{
|
402
|
-
result = INT2NUM(affected);
|
344
|
+
|
345
|
+
value = rb_funcall(parameters, rb_intern("size"), 0);
|
346
|
+
size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
|
347
|
+
if(size < statement->inputs) {
|
348
|
+
rb_fireruby_raise(NULL,
|
349
|
+
"Insufficient parameters specified for statement.");
|
403
350
|
}
|
404
|
-
|
405
|
-
|
406
|
-
|
351
|
+
|
352
|
+
/* Allocate the XSQLDA and populate it. */
|
353
|
+
statement->parameters = allocateInXSQLDA(statement->inputs,
|
354
|
+
&statement->handle,
|
355
|
+
statement->dialect);
|
356
|
+
prepareDataArea(statement->parameters);
|
357
|
+
setParameters(statement->parameters, parameters, self);
|
358
|
+
}
|
359
|
+
|
360
|
+
/* Execute the statement. */
|
361
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
362
|
+
Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
|
363
|
+
transaction);
|
364
|
+
execute(&transaction->handle, &statement->handle, statement->dialect,
|
365
|
+
statement->parameters, statement->type, &affected);
|
366
|
+
if(type == isc_info_sql_stmt_insert ||
|
367
|
+
type == isc_info_sql_stmt_update ||
|
368
|
+
type == isc_info_sql_stmt_delete) {
|
369
|
+
result = INT2NUM(affected);
|
370
|
+
}
|
371
|
+
}
|
372
|
+
|
373
|
+
return(result);
|
407
374
|
}
|
408
375
|
|
409
376
|
|
@@ -416,27 +383,23 @@ VALUE executeStatementFor(VALUE self, VALUE parameters)
|
|
416
383
|
* @return A reference to the newly closed Statement object.
|
417
384
|
*
|
418
385
|
*/
|
419
|
-
VALUE closeStatement(VALUE self)
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
}
|
437
|
-
}
|
438
|
-
|
439
|
-
return(self);
|
386
|
+
VALUE closeStatement(VALUE self) {
|
387
|
+
StatementHandle *statement = NULL;
|
388
|
+
|
389
|
+
Data_Get_Struct(self, StatementHandle, statement);
|
390
|
+
if(statement->handle != 0) {
|
391
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
392
|
+
|
393
|
+
if(isc_dsql_free_statement(status, &statement->handle, DSQL_drop)) {
|
394
|
+
rb_fireruby_raise(status, "Error closing statement.");
|
395
|
+
}
|
396
|
+
|
397
|
+
if(statement->parameters != NULL) {
|
398
|
+
releaseDataArea(statement->parameters);
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
return(self);
|
440
403
|
}
|
441
404
|
|
442
405
|
|
@@ -461,52 +424,46 @@ VALUE closeStatement(VALUE self)
|
|
461
424
|
*/
|
462
425
|
void prepare(isc_db_handle *connection, isc_tr_handle *transaction,
|
463
426
|
char *sql, isc_stmt_handle *statement, short dialect,
|
464
|
-
int *type, int *inputs, int *outputs)
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
if(isc_dsql_sql_info(status, statement, 1, list, 20, info) ||
|
505
|
-
info[0] != isc_info_sql_stmt_type)
|
506
|
-
{
|
507
|
-
rb_fireruby_raise(status, "Error determining SQL statement type.");
|
508
|
-
}
|
509
|
-
*type = isc_vax_integer(&info[3], isc_vax_integer(&info[1], 2));
|
427
|
+
int *type, int *inputs, int *outputs) {
|
428
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
429
|
+
XSQLDA *da = NULL;
|
430
|
+
char list[] = {isc_info_sql_stmt_type},
|
431
|
+
info[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
432
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
433
|
+
|
434
|
+
/* Prepare the statement. */
|
435
|
+
if(isc_dsql_allocate_statement(status, connection, statement)) {
|
436
|
+
rb_fireruby_raise(status, "Error allocating a SQL statement.");
|
437
|
+
}
|
438
|
+
|
439
|
+
da = (XSQLDA *)ALLOC_N(char, XSQLDA_LENGTH(1));
|
440
|
+
if(da == NULL) {
|
441
|
+
rb_raise(rb_eNoMemError,
|
442
|
+
"Memory allocation failure preparing a statement.");
|
443
|
+
}
|
444
|
+
da->version = SQLDA_VERSION1;
|
445
|
+
da->sqln = 1;
|
446
|
+
if(isc_dsql_prepare(status, transaction, statement, 0, sql, dialect,
|
447
|
+
da)) {
|
448
|
+
free(da);
|
449
|
+
rb_fireruby_raise(status, "Error preparing a SQL statement.");
|
450
|
+
}
|
451
|
+
*outputs = da->sqld;
|
452
|
+
|
453
|
+
/* Get the parameter count. */
|
454
|
+
if(isc_dsql_describe_bind(status, statement, dialect, da)) {
|
455
|
+
free(da);
|
456
|
+
rb_fireruby_raise(status, "Error determining statement parameters.");
|
457
|
+
}
|
458
|
+
*inputs = da->sqld;
|
459
|
+
free(da);
|
460
|
+
|
461
|
+
/* Get the statement type details. */
|
462
|
+
if(isc_dsql_sql_info(status, statement, 1, list, 20, info) ||
|
463
|
+
info[0] != isc_info_sql_stmt_type) {
|
464
|
+
rb_fireruby_raise(status, "Error determining SQL statement type.");
|
465
|
+
}
|
466
|
+
*type = isc_vax_integer(&info[3], isc_vax_integer(&info[1], 2));
|
510
467
|
}
|
511
468
|
|
512
469
|
|
@@ -517,8 +474,8 @@ void prepare(isc_db_handle *connection, isc_tr_handle *transaction,
|
|
517
474
|
* executing the statement.
|
518
475
|
* @param statement A pointer to the Firebird statement handle to be used in
|
519
476
|
* executing the statement.
|
520
|
-
* @param dialect
|
521
|
-
*
|
477
|
+
* @param dialect Database dialect used in the statement
|
478
|
+
*
|
522
479
|
* @param parameters A pointer to the XSQLDA block that contains the input
|
523
480
|
* parameters for the SQL statement.
|
524
481
|
* @param type A integer containing the type details relating to the
|
@@ -529,69 +486,62 @@ void prepare(isc_db_handle *connection, isc_tr_handle *transaction,
|
|
529
486
|
* data generated by the execution.
|
530
487
|
*/
|
531
488
|
void execute_2(isc_tr_handle *transaction, isc_stmt_handle *statement,
|
532
|
-
|
533
|
-
|
534
|
-
ISC_STATUS
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
{
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
temp[1] = isc_vax_integer(position, temp[0]);
|
586
|
-
position += temp[0];
|
587
|
-
|
588
|
-
if(current == info)
|
589
|
-
{
|
590
|
-
*affected = temp[1];
|
591
|
-
done = 1;
|
592
|
-
}
|
489
|
+
short dialect, XSQLDA *parameters, int type, long *affected, XSQLDA *output) {
|
490
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
491
|
+
ISC_STATUS execute_result;
|
492
|
+
|
493
|
+
if(output) {
|
494
|
+
execute_result = isc_dsql_execute2(status, transaction, statement, dialect, parameters, output);
|
495
|
+
} else {
|
496
|
+
execute_result = isc_dsql_execute(status, transaction, statement, dialect, parameters);
|
497
|
+
}
|
498
|
+
if(execute_result) {
|
499
|
+
rb_fireruby_raise(status, "Error executing SQL statement.");
|
500
|
+
}
|
501
|
+
|
502
|
+
/* Check if a row count is needed. */
|
503
|
+
if(type == isc_info_sql_stmt_update || type == isc_info_sql_stmt_delete ||
|
504
|
+
type == isc_info_sql_stmt_insert) {
|
505
|
+
int info = 0,
|
506
|
+
done = 0;
|
507
|
+
char items[] = {isc_info_sql_records},
|
508
|
+
buffer[40],
|
509
|
+
*position = buffer + 3;
|
510
|
+
|
511
|
+
switch(type) {
|
512
|
+
case isc_info_sql_stmt_update:
|
513
|
+
info = isc_info_req_update_count;
|
514
|
+
break;
|
515
|
+
|
516
|
+
case isc_info_sql_stmt_delete:
|
517
|
+
info = isc_info_req_delete_count;
|
518
|
+
break;
|
519
|
+
|
520
|
+
case isc_info_sql_stmt_insert:
|
521
|
+
info = isc_info_req_insert_count;
|
522
|
+
break;
|
523
|
+
}
|
524
|
+
|
525
|
+
if(isc_dsql_sql_info(status, statement, sizeof(items), items,
|
526
|
+
sizeof(buffer), buffer)) {
|
527
|
+
rb_fireruby_raise(status, "Error retrieving affected row count.");
|
528
|
+
}
|
529
|
+
|
530
|
+
while(*position != isc_info_end && done == 0) {
|
531
|
+
char current = *position++;
|
532
|
+
long temp[] = {0, 0};
|
533
|
+
|
534
|
+
temp[0] = isc_vax_integer(position, 2);
|
535
|
+
position += 2;
|
536
|
+
temp[1] = isc_vax_integer(position, temp[0]);
|
537
|
+
position += temp[0];
|
538
|
+
|
539
|
+
if(current == info) {
|
540
|
+
*affected = temp[1];
|
541
|
+
done = 1;
|
593
542
|
}
|
594
|
-
|
543
|
+
}
|
544
|
+
}
|
595
545
|
}
|
596
546
|
|
597
547
|
|
@@ -602,8 +552,8 @@ void execute_2(isc_tr_handle *transaction, isc_stmt_handle *statement,
|
|
602
552
|
* executing the statement.
|
603
553
|
* @param statement A pointer to the Firebird statement handle to be used in
|
604
554
|
* executing the statement.
|
605
|
-
* @param dialect
|
606
|
-
*
|
555
|
+
* @param dialect Database dialect used in the statement
|
556
|
+
*
|
607
557
|
* @param parameters A pointer to the XSQLDA block that contains the input
|
608
558
|
* parameters for the SQL statement.
|
609
559
|
* @param type A integer containing the type details relating to the
|
@@ -612,9 +562,8 @@ void execute_2(isc_tr_handle *transaction, isc_stmt_handle *statement,
|
|
612
562
|
* of rows affected by inserts, updates or deletes.
|
613
563
|
*/
|
614
564
|
void execute(isc_tr_handle *transaction, isc_stmt_handle *statement,
|
615
|
-
short dialect, XSQLDA *parameters, int type, long *affected)
|
616
|
-
|
617
|
-
execute_2(transaction, statement, dialect, parameters, type, affected, NULL);
|
565
|
+
short dialect, XSQLDA *parameters, int type, long *affected) {
|
566
|
+
execute_2(transaction, statement, dialect, parameters, type, affected, NULL);
|
618
567
|
}
|
619
568
|
|
620
569
|
/**
|
@@ -633,13 +582,12 @@ void execute(isc_tr_handle *transaction, isc_stmt_handle *statement,
|
|
633
582
|
*
|
634
583
|
*/
|
635
584
|
VALUE rb_statement_new(VALUE connection, VALUE transaction, VALUE sql,
|
636
|
-
VALUE dialect)
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
return(statement);
|
585
|
+
VALUE dialect) {
|
586
|
+
VALUE statement = allocateStatement(cStatement);
|
587
|
+
|
588
|
+
initializeStatement(statement, connection, transaction, sql, dialect);
|
589
|
+
|
590
|
+
return(statement);
|
643
591
|
}
|
644
592
|
|
645
593
|
|
@@ -652,9 +600,8 @@ VALUE rb_statement_new(VALUE connection, VALUE transaction, VALUE sql,
|
|
652
600
|
* @return A reference to the results of executing the statement.
|
653
601
|
*
|
654
602
|
*/
|
655
|
-
VALUE rb_execute_statement(VALUE statement)
|
656
|
-
|
657
|
-
return(executeStatement(statement));
|
603
|
+
VALUE rb_execute_statement(VALUE statement) {
|
604
|
+
return(executeStatement(statement));
|
658
605
|
}
|
659
606
|
|
660
607
|
|
@@ -669,9 +616,8 @@ VALUE rb_execute_statement(VALUE statement)
|
|
669
616
|
* @return A reference to the results of executing the statement.
|
670
617
|
*
|
671
618
|
*/
|
672
|
-
VALUE rb_execute_statement_for(VALUE statement, VALUE parameters)
|
673
|
-
|
674
|
-
return(executeStatementFor(statement, parameters));
|
619
|
+
VALUE rb_execute_statement_for(VALUE statement, VALUE parameters) {
|
620
|
+
return(executeStatementFor(statement, parameters));
|
675
621
|
}
|
676
622
|
|
677
623
|
|
@@ -683,9 +629,8 @@ VALUE rb_execute_statement_for(VALUE statement, VALUE parameters)
|
|
683
629
|
* @return A reference to an integer containing the statement type details.
|
684
630
|
*
|
685
631
|
*/
|
686
|
-
VALUE rb_get_statement_type(VALUE statement)
|
687
|
-
|
688
|
-
return(getStatementType(statement));
|
632
|
+
VALUE rb_get_statement_type(VALUE statement) {
|
633
|
+
return(getStatementType(statement));
|
689
634
|
}
|
690
635
|
|
691
636
|
|
@@ -695,9 +640,8 @@ VALUE rb_get_statement_type(VALUE statement)
|
|
695
640
|
* @param statement A reference to the Statement object to be closed.
|
696
641
|
*
|
697
642
|
*/
|
698
|
-
void rb_statement_close(VALUE statement)
|
699
|
-
|
700
|
-
closeStatement(statement);
|
643
|
+
void rb_statement_close(VALUE statement) {
|
644
|
+
closeStatement(statement);
|
701
645
|
}
|
702
646
|
|
703
647
|
|
@@ -709,25 +653,21 @@ void rb_statement_close(VALUE statement)
|
|
709
653
|
* object being collected.
|
710
654
|
*
|
711
655
|
*/
|
712
|
-
void statementFree(void *handle)
|
713
|
-
{
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
releaseDataArea(statement->parameters);
|
728
|
-
}
|
729
|
-
free(statement);
|
730
|
-
}
|
656
|
+
void statementFree(void *handle) {
|
657
|
+
if(handle != NULL) {
|
658
|
+
StatementHandle *statement = (StatementHandle *)handle;
|
659
|
+
|
660
|
+
if(statement->handle != 0) {
|
661
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
662
|
+
|
663
|
+
isc_dsql_free_statement(status, &statement->handle, DSQL_drop);
|
664
|
+
}
|
665
|
+
|
666
|
+
if(statement->parameters) {
|
667
|
+
releaseDataArea(statement->parameters);
|
668
|
+
}
|
669
|
+
free(statement);
|
670
|
+
}
|
731
671
|
}
|
732
672
|
|
733
673
|
|
@@ -740,48 +680,47 @@ void statementFree(void *handle)
|
|
740
680
|
* @param module A reference to the module to create the class within.
|
741
681
|
*
|
742
682
|
*/
|
743
|
-
void Init_Statement(VALUE module)
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
INT2FIX(isc_info_sql_stmt_savepoint));
|
683
|
+
void Init_Statement(VALUE module) {
|
684
|
+
cStatement = rb_define_class_under(module, "Statement", rb_cObject);
|
685
|
+
rb_define_alloc_func(cStatement, allocateStatement);
|
686
|
+
rb_define_method(cStatement, "initialize", initializeStatement, 4);
|
687
|
+
rb_define_method(cStatement, "initialize_copy", forbidObjectCopy, 1);
|
688
|
+
rb_define_method(cStatement, "sql", getStatementSQL, 0);
|
689
|
+
rb_define_method(cStatement, "connection", getStatementConnection, 0);
|
690
|
+
rb_define_method(cStatement, "transaction", getStatementTransaction, 0);
|
691
|
+
rb_define_method(cStatement, "dialect", getStatementDialect, 0);
|
692
|
+
rb_define_method(cStatement, "type", getStatementType, 0);
|
693
|
+
rb_define_method(cStatement, "execute", executeStatement, 0);
|
694
|
+
rb_define_method(cStatement, "execute_for", executeStatementFor, 1);
|
695
|
+
rb_define_method(cStatement, "close", closeStatement, 0);
|
696
|
+
rb_define_method(cStatement, "parameter_count", getStatementParameterCount, 0);
|
697
|
+
|
698
|
+
rb_define_const(cStatement, "SELECT_STATEMENT",
|
699
|
+
INT2FIX(isc_info_sql_stmt_select));
|
700
|
+
rb_define_const(cStatement, "INSERT_STATEMENT",
|
701
|
+
INT2FIX(isc_info_sql_stmt_insert));
|
702
|
+
rb_define_const(cStatement, "UPDATE_STATEMENT",
|
703
|
+
INT2FIX(isc_info_sql_stmt_update));
|
704
|
+
rb_define_const(cStatement, "DELETE_STATEMENT",
|
705
|
+
INT2FIX(isc_info_sql_stmt_delete));
|
706
|
+
rb_define_const(cStatement, "DDL_STATEMENT",
|
707
|
+
INT2FIX(isc_info_sql_stmt_ddl));
|
708
|
+
rb_define_const(cStatement, "GET_SEGMENT_STATEMENT",
|
709
|
+
INT2FIX(isc_info_sql_stmt_get_segment));
|
710
|
+
rb_define_const(cStatement, "PUT_SEGMENT_STATEMENT",
|
711
|
+
INT2FIX(isc_info_sql_stmt_put_segment));
|
712
|
+
rb_define_const(cStatement, "EXECUTE_PROCEDURE_STATEMENT",
|
713
|
+
INT2FIX(isc_info_sql_stmt_exec_procedure));
|
714
|
+
rb_define_const(cStatement, "START_TRANSACTION_STATEMENT",
|
715
|
+
INT2FIX(isc_info_sql_stmt_start_trans));
|
716
|
+
rb_define_const(cStatement, "COMMIT_STATEMENT",
|
717
|
+
INT2FIX(isc_info_sql_stmt_commit));
|
718
|
+
rb_define_const(cStatement, "ROLLBACK_STATEMENT",
|
719
|
+
INT2FIX(isc_info_sql_stmt_rollback));
|
720
|
+
rb_define_const(cStatement, "SELECT_FOR_UPDATE_STATEMENT",
|
721
|
+
INT2FIX(isc_info_sql_stmt_select_for_upd));
|
722
|
+
rb_define_const(cStatement, "SET_GENERATOR_STATEMENT",
|
723
|
+
INT2FIX(isc_info_sql_stmt_set_generator));
|
724
|
+
rb_define_const(cStatement, "SAVE_POINT_STATEMENT",
|
725
|
+
INT2FIX(isc_info_sql_stmt_savepoint));
|
787
726
|
}
|