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/Transaction.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 "Transaction.h"
|
28
28
|
#include "Common.h"
|
@@ -45,11 +45,10 @@ void transactionFree(void *);
|
|
45
45
|
VALUE cTransaction;
|
46
46
|
|
47
47
|
/* Type definitions. */
|
48
|
-
typedef struct
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
char *tpb;
|
48
|
+
typedef struct {
|
49
|
+
isc_db_handle *database;
|
50
|
+
long length;
|
51
|
+
char *tpb;
|
53
52
|
} ISC_TEB;
|
54
53
|
|
55
54
|
static char DEFAULT_TEB[] = {isc_tpb_version3,
|
@@ -57,7 +56,7 @@ static char DEFAULT_TEB[] = {isc_tpb_version3,
|
|
57
56
|
isc_tpb_wait,
|
58
57
|
isc_tpb_rec_version,
|
59
58
|
isc_tpb_read_committed};
|
60
|
-
static int
|
59
|
+
static int DEFAULT_TEB_SIZE = 5;
|
61
60
|
|
62
61
|
|
63
62
|
/**
|
@@ -69,23 +68,19 @@ static int DEFAULT_TEB_SIZE = 5;
|
|
69
68
|
* @return A reference to the newly allocated object.
|
70
69
|
*
|
71
70
|
*/
|
72
|
-
static VALUE allocateTransaction(VALUE klass)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
"Memory allocation failure allocating a transaction.");
|
86
|
-
}
|
87
|
-
|
88
|
-
return(transaction);
|
71
|
+
static VALUE allocateTransaction(VALUE klass) {
|
72
|
+
VALUE transaction = Qnil;
|
73
|
+
TransactionHandle *handle = ALLOC(TransactionHandle);
|
74
|
+
|
75
|
+
if(handle != NULL) {
|
76
|
+
handle->handle = 0;
|
77
|
+
transaction = Data_Wrap_Struct(klass, NULL, transactionFree, handle);
|
78
|
+
} else {
|
79
|
+
rb_raise(rb_eNoMemError,
|
80
|
+
"Memory allocation failure allocating a transaction.");
|
81
|
+
}
|
82
|
+
|
83
|
+
return(transaction);
|
89
84
|
}
|
90
85
|
|
91
86
|
|
@@ -94,41 +89,35 @@ static VALUE allocateTransaction(VALUE klass)
|
|
94
89
|
*
|
95
90
|
* @param self A reference to the new Transaction class instance.
|
96
91
|
* @param connections Either a reference to a single Connection object or to
|
97
|
-
* an array of Connection objects that the transaction
|
92
|
+
* an array of Connection objects that the transaction
|
98
93
|
* will apply to.
|
99
94
|
*
|
100
95
|
*/
|
101
|
-
static VALUE transactionInitialize(VALUE self, VALUE connections)
|
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
|
-
/* Fetch the data structure and start the transaction. */
|
127
|
-
Data_Get_Struct(self, TransactionHandle, transaction);
|
128
|
-
startTransaction(transaction, array, 0, NULL);
|
129
|
-
rb_tx_started(self, array);
|
130
|
-
|
131
|
-
return(self);
|
96
|
+
static VALUE transactionInitialize(VALUE self, VALUE connections) {
|
97
|
+
TransactionHandle *transaction = NULL;
|
98
|
+
VALUE array = Qnil;
|
99
|
+
|
100
|
+
/* Determine if an array has been passed as a parameter. */
|
101
|
+
if(TYPE(connections) == T_ARRAY) {
|
102
|
+
array = connections;
|
103
|
+
} else if(TYPE(connections) == T_DATA &&
|
104
|
+
RDATA(connections)->dfree == (RUBY_DATA_FUNC)connectionFree) {
|
105
|
+
array = rb_ary_new();
|
106
|
+
rb_ary_push(array, connections);
|
107
|
+
} else {
|
108
|
+
rb_fireruby_raise(NULL,
|
109
|
+
"Invalid connection parameter(s) for transaction.");
|
110
|
+
}
|
111
|
+
|
112
|
+
/* Store the database details. */
|
113
|
+
rb_iv_set(self, "@connections", array);
|
114
|
+
|
115
|
+
/* Fetch the data structure and start the transaction. */
|
116
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
117
|
+
startTransaction(transaction, array, 0, NULL);
|
118
|
+
rb_tx_started(self, array);
|
119
|
+
|
120
|
+
return(self);
|
132
121
|
}
|
133
122
|
|
134
123
|
|
@@ -140,37 +129,32 @@ static VALUE transactionInitialize(VALUE self, VALUE connections)
|
|
140
129
|
* @return A reference to self if successful, nil otherwise.
|
141
130
|
*
|
142
131
|
*/
|
143
|
-
static VALUE commitTransaction(VALUE self)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
if(isc_commit_transaction(status, &transaction->handle) != 0)
|
155
|
-
{
|
156
|
-
/* Generate an error. */
|
157
|
-
rb_fireruby_raise(status, "Error committing transaction.");
|
158
|
-
}
|
159
|
-
transaction->handle = 0;
|
160
|
-
}
|
161
|
-
else
|
162
|
-
{
|
132
|
+
static VALUE commitTransaction(VALUE self) {
|
133
|
+
TransactionHandle *transaction = NULL;
|
134
|
+
|
135
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
136
|
+
|
137
|
+
/* Commit the transaction. */
|
138
|
+
if(transaction->handle != 0) {
|
139
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
140
|
+
|
141
|
+
if(isc_commit_transaction(status, &transaction->handle) != 0) {
|
163
142
|
/* Generate an error. */
|
164
|
-
rb_fireruby_raise(
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
143
|
+
rb_fireruby_raise(status, "Error committing transaction.");
|
144
|
+
}
|
145
|
+
transaction->handle = 0;
|
146
|
+
} else {
|
147
|
+
/* Generate an error. */
|
148
|
+
rb_fireruby_raise(NULL, "1. Transaction is not active.");
|
149
|
+
}
|
150
|
+
|
151
|
+
/* Notify each connection of the transactions end. */
|
152
|
+
rb_tx_released(rb_iv_get(self, "@connections"), self);
|
153
|
+
|
154
|
+
/* Clear the connections list. */
|
155
|
+
rb_iv_set(self, "@connections", rb_ary_new());
|
156
|
+
|
157
|
+
return(self);
|
174
158
|
}
|
175
159
|
|
176
160
|
|
@@ -182,37 +166,32 @@ static VALUE commitTransaction(VALUE self)
|
|
182
166
|
* @return A reference to self if successful, nil otherwise.
|
183
167
|
*
|
184
168
|
*/
|
185
|
-
static VALUE rollbackTransaction(VALUE self)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
if(isc_rollback_transaction(status, &transaction->handle) != 0)
|
197
|
-
{
|
198
|
-
/* Generate an error. */
|
199
|
-
rb_fireruby_raise(status, "Error rolling back transaction.");
|
200
|
-
}
|
201
|
-
transaction->handle = 0;
|
202
|
-
}
|
203
|
-
else
|
204
|
-
{
|
169
|
+
static VALUE rollbackTransaction(VALUE self) {
|
170
|
+
TransactionHandle *transaction = NULL;
|
171
|
+
|
172
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
173
|
+
|
174
|
+
/* Roll back the transaction. */
|
175
|
+
if(transaction->handle != 0) {
|
176
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
177
|
+
|
178
|
+
if(isc_rollback_transaction(status, &transaction->handle) != 0) {
|
205
179
|
/* Generate an error. */
|
206
|
-
rb_fireruby_raise(
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
180
|
+
rb_fireruby_raise(status, "Error rolling back transaction.");
|
181
|
+
}
|
182
|
+
transaction->handle = 0;
|
183
|
+
} else {
|
184
|
+
/* Generate an error. */
|
185
|
+
rb_fireruby_raise(NULL, "2. Transaction is not active.");
|
186
|
+
}
|
187
|
+
|
188
|
+
/* Notify each connection of the transactions end. */
|
189
|
+
rb_tx_released(rb_iv_get(self, "@connections"), self);
|
190
|
+
|
191
|
+
/* Clear the connections list. */
|
192
|
+
rb_iv_set(self, "@connections", rb_ary_new());
|
193
|
+
|
194
|
+
return(self);
|
216
195
|
}
|
217
196
|
|
218
197
|
|
@@ -224,18 +203,16 @@ static VALUE rollbackTransaction(VALUE self)
|
|
224
203
|
* @return Qtrue if the transaction is active, Qfalse otherwise.
|
225
204
|
*
|
226
205
|
*/
|
227
|
-
static VALUE transactionIsActive(VALUE self)
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
return(result);
|
206
|
+
static VALUE transactionIsActive(VALUE self) {
|
207
|
+
VALUE result = Qfalse;
|
208
|
+
TransactionHandle *transaction = NULL;
|
209
|
+
|
210
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
211
|
+
if(transaction->handle != 0) {
|
212
|
+
result = Qtrue;
|
213
|
+
}
|
214
|
+
|
215
|
+
return(result);
|
239
216
|
}
|
240
217
|
|
241
218
|
|
@@ -247,12 +224,11 @@ static VALUE transactionIsActive(VALUE self)
|
|
247
224
|
* for.
|
248
225
|
*
|
249
226
|
* @return An Array containing the connections associated with the Transaction
|
250
|
-
* object.
|
227
|
+
* object.
|
251
228
|
*
|
252
229
|
*/
|
253
|
-
static VALUE getTransactionConnections(VALUE self)
|
254
|
-
|
255
|
-
return(rb_iv_get(self, "@connections"));
|
230
|
+
static VALUE getTransactionConnections(VALUE self) {
|
231
|
+
return(rb_iv_get(self, "@connections"));
|
256
232
|
}
|
257
233
|
|
258
234
|
|
@@ -267,30 +243,28 @@ static VALUE getTransactionConnections(VALUE self)
|
|
267
243
|
* Qfalse otherwise.
|
268
244
|
*
|
269
245
|
*/
|
270
|
-
static VALUE isTransactionFor(VALUE self, VALUE connection)
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
return(result);
|
246
|
+
static VALUE isTransactionFor(VALUE self, VALUE connection) {
|
247
|
+
VALUE result = Qfalse,
|
248
|
+
array = rb_iv_get(self, "@connections"),
|
249
|
+
value = rb_funcall(array, rb_intern("size"), 0);
|
250
|
+
int size = 0,
|
251
|
+
index;
|
252
|
+
ConnectionHandle *instance = NULL;
|
253
|
+
TransactionHandle *transaction = NULL;
|
254
|
+
|
255
|
+
size = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
|
256
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
257
|
+
Data_Get_Struct(connection, ConnectionHandle, instance);
|
258
|
+
|
259
|
+
for(index = 0; index < size && result == Qfalse; index++) {
|
260
|
+
ConnectionHandle *handle;
|
261
|
+
|
262
|
+
value = rb_ary_entry(array, index);
|
263
|
+
Data_Get_Struct(value, ConnectionHandle, handle);
|
264
|
+
result = (handle == instance ? Qtrue : Qfalse);
|
265
|
+
}
|
266
|
+
|
267
|
+
return(result);
|
294
268
|
}
|
295
269
|
|
296
270
|
|
@@ -306,57 +280,51 @@ static VALUE isTransactionFor(VALUE self, VALUE connection)
|
|
306
280
|
* query, nil otherwise.
|
307
281
|
*
|
308
282
|
*/
|
309
|
-
static VALUE executeOnTransaction(VALUE self, VALUE sql)
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
last = Qnil;
|
347
|
-
|
348
|
-
while(row != Qnil)
|
349
|
-
{
|
350
|
-
last = rb_yield(row);
|
351
|
-
row = rb_funcall(results, rb_intern("fetch"), 0);
|
352
|
-
}
|
353
|
-
rb_funcall(results, rb_intern("close"), 0);
|
354
|
-
results = last;
|
283
|
+
static VALUE executeOnTransaction(VALUE self, VALUE sql) {
|
284
|
+
VALUE results = Qnil,
|
285
|
+
list = rb_iv_get(self, "@connections"),
|
286
|
+
value = 0,
|
287
|
+
connection = Qnil,
|
288
|
+
statement = Qnil;
|
289
|
+
TransactionHandle *transaction = NULL;
|
290
|
+
int size = 0;
|
291
|
+
|
292
|
+
/* Check that the transaction is active. */
|
293
|
+
Data_Get_Struct(self, TransactionHandle, transaction);
|
294
|
+
if(transaction->handle == 0) {
|
295
|
+
rb_fireruby_raise(NULL, "Executed called on inactive transaction.");
|
296
|
+
}
|
297
|
+
|
298
|
+
/* Check that we have only one connection for the transaction. */
|
299
|
+
value = rb_funcall(list, rb_intern("size"), 0);
|
300
|
+
size = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
|
301
|
+
if(size > 1) {
|
302
|
+
rb_fireruby_raise(NULL,
|
303
|
+
"Execute called on a transaction that spans multiple " \
|
304
|
+
"connections. Unable to determine which connection to " \
|
305
|
+
"execute the SQL statement through.");
|
306
|
+
}
|
307
|
+
|
308
|
+
connection = rb_ary_entry(list, 0);
|
309
|
+
statement = rb_statement_new(connection, self, sql, INT2FIX(3));
|
310
|
+
results = rb_execute_statement(statement);
|
311
|
+
|
312
|
+
if(results != Qnil && rb_obj_is_kind_of(results, rb_cInteger) == Qfalse) {
|
313
|
+
if(rb_block_given_p()) {
|
314
|
+
VALUE row = rb_funcall(results, rb_intern("fetch"), 0),
|
315
|
+
last = Qnil;
|
316
|
+
|
317
|
+
while(row != Qnil) {
|
318
|
+
last = rb_yield(row);
|
319
|
+
row = rb_funcall(results, rb_intern("fetch"), 0);
|
355
320
|
}
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
321
|
+
rb_funcall(results, rb_intern("close"), 0);
|
322
|
+
results = last;
|
323
|
+
}
|
324
|
+
}
|
325
|
+
rb_statement_close(statement);
|
326
|
+
|
327
|
+
return(results);
|
360
328
|
}
|
361
329
|
|
362
330
|
|
@@ -374,76 +342,63 @@ static VALUE executeOnTransaction(VALUE self, VALUE sql)
|
|
374
342
|
* @return A reference to the newly created Transaction object.
|
375
343
|
*
|
376
344
|
*/
|
377
|
-
static VALUE createTransaction(VALUE unused, VALUE connections, VALUE parameters)
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
if((buffer = ALLOC_N(char, size)) != NULL)
|
415
|
-
{
|
416
|
-
for(index = 0; index < size; index++)
|
417
|
-
{
|
418
|
-
VALUE entry = rb_ary_entry(parameters, index);
|
419
|
-
int number = 0;
|
420
|
-
|
421
|
-
number = TYPE(entry) == T_FIXNUM ? FIX2INT(entry) : NUM2INT(entry);
|
422
|
-
buffer[index] = number;
|
423
|
-
}
|
424
|
-
|
425
|
-
startTransaction(transaction, list, size, buffer);
|
426
|
-
free(buffer);
|
427
|
-
|
428
|
-
instance = Data_Wrap_Struct(cTransaction, NULL, transactionFree,
|
429
|
-
transaction);
|
430
|
-
rb_iv_set(instance, "@connections", list);
|
431
|
-
rb_tx_started(instance, connections);
|
432
|
-
}
|
433
|
-
else
|
434
|
-
{
|
435
|
-
rb_fireruby_raise(NULL,
|
436
|
-
"Memory allocation failure allocating transaction "\
|
437
|
-
"parameter buffer.");
|
345
|
+
static VALUE createTransaction(VALUE unused, VALUE connections, VALUE parameters) {
|
346
|
+
VALUE instance = Qnil,
|
347
|
+
list = Qnil;
|
348
|
+
TransactionHandle *transaction = ALLOC(TransactionHandle);
|
349
|
+
|
350
|
+
if(transaction == NULL) {
|
351
|
+
rb_raise(rb_eNoMemError,
|
352
|
+
"Memory allocation failure allocating a transaction.");
|
353
|
+
}
|
354
|
+
transaction->handle = 0;
|
355
|
+
|
356
|
+
if(TYPE(connections) != T_ARRAY) {
|
357
|
+
list = rb_ary_new();
|
358
|
+
rb_ary_push(list, connections);
|
359
|
+
} else {
|
360
|
+
list = connections;
|
361
|
+
}
|
362
|
+
|
363
|
+
if(TYPE(parameters) != T_ARRAY) {
|
364
|
+
rb_fireruby_raise(NULL,
|
365
|
+
"Invalid transaction parameter set specified.");
|
366
|
+
}
|
367
|
+
|
368
|
+
if(transaction != NULL) {
|
369
|
+
VALUE value = rb_funcall(parameters, rb_intern("size"), 0);
|
370
|
+
long size = 0,
|
371
|
+
index;
|
372
|
+
char *buffer = NULL;
|
373
|
+
|
374
|
+
size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
|
375
|
+
if((buffer = ALLOC_N(char, size)) != NULL) {
|
376
|
+
for(index = 0; index < size; index++) {
|
377
|
+
VALUE entry = rb_ary_entry(parameters, index);
|
378
|
+
int number = 0;
|
379
|
+
|
380
|
+
number = TYPE(entry) == T_FIXNUM ? FIX2INT(entry) : NUM2INT(entry);
|
381
|
+
buffer[index] = number;
|
438
382
|
}
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
383
|
+
|
384
|
+
startTransaction(transaction, list, size, buffer);
|
385
|
+
free(buffer);
|
386
|
+
|
387
|
+
instance = Data_Wrap_Struct(cTransaction, NULL, transactionFree,
|
388
|
+
transaction);
|
389
|
+
rb_iv_set(instance, "@connections", list);
|
390
|
+
rb_tx_started(instance, connections);
|
391
|
+
} else {
|
392
|
+
rb_fireruby_raise(NULL,
|
393
|
+
"Memory allocation failure allocating transaction " \
|
394
|
+
"parameter buffer.");
|
395
|
+
}
|
396
|
+
} else {
|
397
|
+
rb_raise(rb_eNoMemError,
|
398
|
+
"Memory allocation failure allocating transaction.");
|
399
|
+
}
|
400
|
+
|
401
|
+
return(instance);
|
447
402
|
}
|
448
403
|
|
449
404
|
|
@@ -463,108 +418,86 @@ static VALUE createTransaction(VALUE unused, VALUE connections, VALUE parameters
|
|
463
418
|
void startTransaction(TransactionHandle *transaction,
|
464
419
|
VALUE connections,
|
465
420
|
long size,
|
466
|
-
char *buffer)
|
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
|
-
|
505
|
-
|
506
|
-
/* Store the connection details. */
|
507
|
-
teb[i].database = &connection->handle;
|
508
|
-
if(size > 0)
|
509
|
-
{
|
510
|
-
teb[i].length = size;
|
511
|
-
teb[i].tpb = buffer;
|
512
|
-
}
|
513
|
-
else
|
514
|
-
{
|
515
|
-
teb[i].length = DEFAULT_TEB_SIZE;
|
516
|
-
teb[i].tpb = DEFAULT_TEB;
|
517
|
-
}
|
518
|
-
}
|
519
|
-
else
|
520
|
-
{
|
521
|
-
/* Clean up and raise an exception. */
|
522
|
-
free(teb);
|
523
|
-
rb_fireruby_raise(NULL,
|
524
|
-
"Disconnected connection specified "\
|
525
|
-
"starting a transaction.");
|
526
|
-
}
|
527
|
-
}
|
528
|
-
else
|
529
|
-
{
|
530
|
-
/* Clean up and thrown an exception. */
|
531
|
-
free(teb);
|
532
|
-
rb_fireruby_raise(NULL,
|
533
|
-
"Invalid connection specified starting a "\
|
534
|
-
"transaction.");
|
421
|
+
char *buffer) {
|
422
|
+
ISC_TEB *teb = NULL;
|
423
|
+
VALUE value = rb_funcall(connections, rb_intern("size"), 0),
|
424
|
+
head = rb_ary_entry(connections, 0);
|
425
|
+
short length = 0;
|
426
|
+
ConnectionHandle *first = NULL;
|
427
|
+
|
428
|
+
/* Attempt a retrieval of the first connection. */
|
429
|
+
if(value != Qnil) {
|
430
|
+
/* Check that we have a connection. */
|
431
|
+
if(TYPE(head) == T_DATA &&
|
432
|
+
RDATA(head)->dfree == (RUBY_DATA_FUNC)connectionFree) {
|
433
|
+
Data_Get_Struct(head, ConnectionHandle, first);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
437
|
+
/* Generate the list of connections. */
|
438
|
+
length = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
|
439
|
+
if(length > 0) {
|
440
|
+
if((teb = ALLOC_N(ISC_TEB, length)) != NULL) {
|
441
|
+
int i;
|
442
|
+
|
443
|
+
for(i = 0; i < length; i++) {
|
444
|
+
VALUE entry = rb_ary_entry(connections, i);
|
445
|
+
|
446
|
+
/* Check that we have a connection. */
|
447
|
+
if(TYPE(entry) == T_DATA &&
|
448
|
+
RDATA(entry)->dfree == (RUBY_DATA_FUNC)connectionFree) {
|
449
|
+
ConnectionHandle *connection = NULL;
|
450
|
+
|
451
|
+
Data_Get_Struct(entry, ConnectionHandle, connection);
|
452
|
+
if(connection->handle != 0) {
|
453
|
+
/* Store the connection details. */
|
454
|
+
teb[i].database = &connection->handle;
|
455
|
+
if(size > 0) {
|
456
|
+
teb[i].length = size;
|
457
|
+
teb[i].tpb = buffer;
|
458
|
+
} else {
|
459
|
+
teb[i].length = DEFAULT_TEB_SIZE;
|
460
|
+
teb[i].tpb = DEFAULT_TEB;
|
535
461
|
}
|
536
|
-
|
462
|
+
} else {
|
463
|
+
/* Clean up and raise an exception. */
|
464
|
+
free(teb);
|
465
|
+
rb_fireruby_raise(NULL,
|
466
|
+
"Disconnected connection specified " \
|
467
|
+
"starting a transaction.");
|
468
|
+
}
|
469
|
+
} else {
|
470
|
+
/* Clean up and thrown an exception. */
|
471
|
+
free(teb);
|
472
|
+
rb_fireruby_raise(NULL,
|
473
|
+
"Invalid connection specified starting a " \
|
474
|
+
"transaction.");
|
475
|
+
}
|
537
476
|
}
|
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
|
-
/* Free the database details list if need be. */
|
564
|
-
if(teb != NULL)
|
565
|
-
{
|
566
|
-
free(teb);
|
567
|
-
}
|
477
|
+
} else {
|
478
|
+
rb_raise(rb_eNoMemError,
|
479
|
+
"Memory allocation error starting transaction.");
|
480
|
+
}
|
481
|
+
} else {
|
482
|
+
/* Generate an exception. */
|
483
|
+
rb_fireruby_raise(NULL, "No connections specified for transaction.");
|
484
|
+
}
|
485
|
+
|
486
|
+
/* Check that theres been no errors and that we have a connection list. */
|
487
|
+
if(teb != NULL) {
|
488
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
489
|
+
|
490
|
+
/* Attempt a transaction start. */
|
491
|
+
if(isc_start_multiple(status, &transaction->handle, length, teb) != 0) {
|
492
|
+
/* Generate an error. */
|
493
|
+
rb_fireruby_raise(status, "Error starting transaction.");
|
494
|
+
}
|
495
|
+
}
|
496
|
+
|
497
|
+
/* Free the database details list if need be. */
|
498
|
+
if(teb != NULL) {
|
499
|
+
free(teb);
|
500
|
+
}
|
568
501
|
}
|
569
502
|
|
570
503
|
|
@@ -577,20 +510,17 @@ void startTransaction(TransactionHandle *transaction,
|
|
577
510
|
* with the Transaction object being collected.
|
578
511
|
*
|
579
512
|
*/
|
580
|
-
void transactionFree(void *transaction)
|
581
|
-
{
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
}
|
592
|
-
free(handle);
|
593
|
-
}
|
513
|
+
void transactionFree(void *transaction) {
|
514
|
+
if(transaction != NULL) {
|
515
|
+
TransactionHandle *handle = (TransactionHandle *)transaction;
|
516
|
+
|
517
|
+
if(handle->handle != 0) {
|
518
|
+
ISC_STATUS status[ISC_STATUS_LENGTH];
|
519
|
+
|
520
|
+
isc_rollback_transaction(status, &handle->handle);
|
521
|
+
}
|
522
|
+
free(handle);
|
523
|
+
}
|
594
524
|
}
|
595
525
|
|
596
526
|
|
@@ -605,13 +535,12 @@ void transactionFree(void *transaction)
|
|
605
535
|
* @return A reference to the Transaction object, or nil if an error occurs.
|
606
536
|
*
|
607
537
|
*/
|
608
|
-
VALUE rb_transaction_new(VALUE connections)
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
return(transaction);
|
538
|
+
VALUE rb_transaction_new(VALUE connections) {
|
539
|
+
VALUE transaction = allocateTransaction(cTransaction);
|
540
|
+
|
541
|
+
transactionInitialize(transaction, connections);
|
542
|
+
|
543
|
+
return(transaction);
|
615
544
|
}
|
616
545
|
|
617
546
|
/**
|
@@ -625,17 +554,15 @@ VALUE rb_transaction_new(VALUE connections)
|
|
625
554
|
* it is not.
|
626
555
|
*
|
627
556
|
*/
|
628
|
-
int coversConnection(VALUE transaction, VALUE connection)
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
return(result);
|
557
|
+
int coversConnection(VALUE transaction, VALUE connection) {
|
558
|
+
int result = 0;
|
559
|
+
VALUE boolean = isTransactionFor(transaction, connection);
|
560
|
+
|
561
|
+
if(boolean == Qtrue) {
|
562
|
+
result = 1;
|
563
|
+
}
|
564
|
+
|
565
|
+
return(result);
|
639
566
|
}
|
640
567
|
|
641
568
|
|
@@ -646,39 +573,38 @@ int coversConnection(VALUE transaction, VALUE connection)
|
|
646
573
|
* @param module A reference to the module to create the class within.
|
647
574
|
*
|
648
575
|
*/
|
649
|
-
void Init_Transaction(VALUE module)
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
rb_define_const(cTransaction, "TPB_NO_AUTO_UNDO", INT2FIX(isc_tpb_no_auto_undo));
|
576
|
+
void Init_Transaction(VALUE module) {
|
577
|
+
cTransaction = rb_define_class_under(module, "Transaction", rb_cObject);
|
578
|
+
rb_define_alloc_func(cTransaction, allocateTransaction);
|
579
|
+
rb_define_method(cTransaction, "initialize", transactionInitialize, 1);
|
580
|
+
rb_define_method(cTransaction, "initialize_copy", forbidObjectCopy, 1);
|
581
|
+
rb_define_method(cTransaction, "active?", transactionIsActive, 0);
|
582
|
+
rb_define_method(cTransaction, "commit", commitTransaction, 0);
|
583
|
+
rb_define_method(cTransaction, "rollback", rollbackTransaction, 0);
|
584
|
+
rb_define_method(cTransaction, "connections", getTransactionConnections, 0);
|
585
|
+
rb_define_method(cTransaction, "for_connection?", isTransactionFor, 1);
|
586
|
+
rb_define_module_function(cTransaction, "create", createTransaction, 2);
|
587
|
+
rb_define_method(cTransaction, "execute", executeOnTransaction, 1);
|
588
|
+
rb_define_const(cTransaction, "TPB_VERSION_1", INT2FIX(isc_tpb_version1));
|
589
|
+
rb_define_const(cTransaction, "TPB_VERSION_3", INT2FIX(isc_tpb_version3));
|
590
|
+
rb_define_const(cTransaction, "TPB_CONSISTENCY", INT2FIX(isc_tpb_consistency));
|
591
|
+
rb_define_const(cTransaction, "TPB_CONCURRENCY", INT2FIX(isc_tpb_concurrency));
|
592
|
+
rb_define_const(cTransaction, "TPB_SHARED", INT2FIX(isc_tpb_shared));
|
593
|
+
rb_define_const(cTransaction, "TPB_PROTECTED", INT2FIX(isc_tpb_protected));
|
594
|
+
rb_define_const(cTransaction, "TPB_EXCLUSIVE", INT2FIX(isc_tpb_exclusive));
|
595
|
+
rb_define_const(cTransaction, "TPB_WAIT", INT2FIX(isc_tpb_wait));
|
596
|
+
rb_define_const(cTransaction, "TPB_NO_WAIT", INT2FIX(isc_tpb_nowait));
|
597
|
+
rb_define_const(cTransaction, "TPB_READ", INT2FIX(isc_tpb_read));
|
598
|
+
rb_define_const(cTransaction, "TPB_WRITE", INT2FIX(isc_tpb_write));
|
599
|
+
rb_define_const(cTransaction, "TPB_LOCK_READ", INT2FIX(isc_tpb_lock_read));
|
600
|
+
rb_define_const(cTransaction, "TPB_LOCK_WRITE", INT2FIX(isc_tpb_lock_write));
|
601
|
+
rb_define_const(cTransaction, "TPB_VERB_TIME", INT2FIX(isc_tpb_verb_time));
|
602
|
+
rb_define_const(cTransaction, "TPB_COMMIT_TIME", INT2FIX(isc_tpb_commit_time));
|
603
|
+
rb_define_const(cTransaction, "TPB_IGNORE_LIMBO", INT2FIX(isc_tpb_ignore_limbo));
|
604
|
+
rb_define_const(cTransaction, "TPB_READ_COMMITTED", INT2FIX(isc_tpb_read_committed));
|
605
|
+
rb_define_const(cTransaction, "TPB_AUTO_COMMIT", INT2FIX(isc_tpb_autocommit));
|
606
|
+
rb_define_const(cTransaction, "TPB_REC_VERSION", INT2FIX(isc_tpb_rec_version));
|
607
|
+
rb_define_const(cTransaction, "TPB_NO_REC_VERSION", INT2FIX(isc_tpb_no_rec_version));
|
608
|
+
rb_define_const(cTransaction, "TPB_RESTART_REQUESTS", INT2FIX(isc_tpb_restart_requests));
|
609
|
+
rb_define_const(cTransaction, "TPB_NO_AUTO_UNDO", INT2FIX(isc_tpb_no_auto_undo));
|
684
610
|
}
|