rubyfb 0.5.2-x86-mswin32-60

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.
Files changed (77) hide show
  1. data/CHANGELOG +6 -0
  2. data/LICENSE +411 -0
  3. data/Manifest +75 -0
  4. data/README +460 -0
  5. data/Rakefile +21 -0
  6. data/examples/example01.rb +65 -0
  7. data/ext/AddUser.c +464 -0
  8. data/ext/AddUser.h +37 -0
  9. data/ext/Backup.c +783 -0
  10. data/ext/Backup.h +37 -0
  11. data/ext/Blob.c +421 -0
  12. data/ext/Blob.h +65 -0
  13. data/ext/Common.c +54 -0
  14. data/ext/Common.h +37 -0
  15. data/ext/Connection.c +863 -0
  16. data/ext/Connection.h +50 -0
  17. data/ext/DataArea.c +274 -0
  18. data/ext/DataArea.h +38 -0
  19. data/ext/Database.c +449 -0
  20. data/ext/Database.h +48 -0
  21. data/ext/FireRuby.c +240 -0
  22. data/ext/FireRuby.h +50 -0
  23. data/ext/FireRubyException.c +268 -0
  24. data/ext/FireRubyException.h +51 -0
  25. data/ext/Generator.c +689 -0
  26. data/ext/Generator.h +53 -0
  27. data/ext/RemoveUser.c +212 -0
  28. data/ext/RemoveUser.h +37 -0
  29. data/ext/Restore.c +855 -0
  30. data/ext/Restore.h +37 -0
  31. data/ext/ResultSet.c +810 -0
  32. data/ext/ResultSet.h +60 -0
  33. data/ext/Row.c +965 -0
  34. data/ext/Row.h +55 -0
  35. data/ext/ServiceManager.c +316 -0
  36. data/ext/ServiceManager.h +48 -0
  37. data/ext/Services.c +124 -0
  38. data/ext/Services.h +42 -0
  39. data/ext/Statement.c +785 -0
  40. data/ext/Statement.h +62 -0
  41. data/ext/Transaction.c +684 -0
  42. data/ext/Transaction.h +50 -0
  43. data/ext/TypeMap.c +1182 -0
  44. data/ext/TypeMap.h +51 -0
  45. data/ext/extconf.rb +30 -0
  46. data/lib/SQLType.rb +224 -0
  47. data/lib/active_record/connection_adapters/rubyfb_adapter.rb +805 -0
  48. data/lib/mkdoc +1 -0
  49. data/lib/rubyfb.rb +2 -0
  50. data/lib/rubyfb_lib.so +0 -0
  51. data/lib/src.rb +1800 -0
  52. data/mswin32fb/fbclient_ms.lib +0 -0
  53. data/mswin32fb/ibase.h +2555 -0
  54. data/mswin32fb/iberror.h +1741 -0
  55. data/rubyfb.gemspec +31 -0
  56. data/test/AddRemoveUserTest.rb +56 -0
  57. data/test/BackupRestoreTest.rb +99 -0
  58. data/test/BlobTest.rb +57 -0
  59. data/test/CharacterSetTest.rb +63 -0
  60. data/test/ConnectionTest.rb +111 -0
  61. data/test/DDLTest.rb +54 -0
  62. data/test/DatabaseTest.rb +83 -0
  63. data/test/GeneratorTest.rb +50 -0
  64. data/test/KeyTest.rb +140 -0
  65. data/test/ResultSetTest.rb +162 -0
  66. data/test/RoleTest.rb +73 -0
  67. data/test/RowCountTest.rb +65 -0
  68. data/test/RowTest.rb +203 -0
  69. data/test/SQLTest.rb +182 -0
  70. data/test/SQLTypeTest.rb +101 -0
  71. data/test/ServiceManagerTest.rb +29 -0
  72. data/test/StatementTest.rb +135 -0
  73. data/test/TestSetup.rb +11 -0
  74. data/test/TransactionTest.rb +112 -0
  75. data/test/TypeTest.rb +92 -0
  76. data/test/UnitTest.rb +65 -0
  77. metadata +143 -0
data/ext/Statement.h ADDED
@@ -0,0 +1,62 @@
1
+ /*------------------------------------------------------------------------------
2
+ * Statement.h
3
+ *----------------------------------------------------------------------------*/
4
+ /**
5
+ * Copyright � Peter Wood, 2005
6
+ *
7
+ * The contents of this file are subject to the Mozilla Public License Version
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
10
+ *
11
+ * http://www.mozilla.org/MPL/
12
+ *
13
+ * Software distributed under the License is distributed on an "AS IS" basis,
14
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
15
+ * the specificlanguage governing rights and limitations under the License.
16
+ *
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
20
+ * Reserved.
21
+ *
22
+ * @author Peter Wood
23
+ * @version 1.0
24
+ */
25
+ #ifndef FIRERUBY_STATEMENT_H
26
+ #define FIRERUBY_STATEMENT_H
27
+
28
+ /* Includes. */
29
+ #ifndef IBASE_H_INCLUDED
30
+ #include "ibase.h"
31
+ #define IBASE_H_INCLUDED
32
+ #endif
33
+
34
+ #ifndef RUBY_H_INCLUDED
35
+ #include "ruby.h"
36
+ #define RUBY_H_INCLUDED
37
+ #endif
38
+
39
+ /* Type definitions. */
40
+ typedef struct
41
+ {
42
+ isc_stmt_handle handle;
43
+ int type,
44
+ inputs;
45
+ short dialect;
46
+ XSQLDA *parameters;
47
+ } StatementHandle;
48
+
49
+ /* Function prototypes. */
50
+ void prepare(isc_db_handle *, isc_tr_handle *, char *, isc_stmt_handle *,
51
+ short, int *, int *, int *);
52
+ void execute(isc_tr_handle *, isc_stmt_handle *, short, XSQLDA *,
53
+ int, long *);
54
+ VALUE rb_statement_new(VALUE, VALUE, VALUE, VALUE);
55
+ VALUE rb_execute_statement(VALUE);
56
+ VALUE rb_execute_statement_for(VALUE, VALUE);
57
+ VALUE rb_get_statement_type(VALUE);
58
+ void rb_statement_close(VALUE);
59
+ void statementFree(void *);
60
+ void Init_Statement(VALUE);
61
+
62
+ #endif /* FIRERUBY_STATEMENT_H */
data/ext/Transaction.c ADDED
@@ -0,0 +1,684 @@
1
+ /*------------------------------------------------------------------------------
2
+ * Transaction.c
3
+ *----------------------------------------------------------------------------*/
4
+ /**
5
+ * Copyright � Peter Wood, 2005
6
+ *
7
+ * The contents of this file are subject to the Mozilla Public License Version
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
10
+ *
11
+ * http://www.mozilla.org/MPL/
12
+ *
13
+ * Software distributed under the License is distributed on an "AS IS" basis,
14
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
15
+ * the specificlanguage governing rights and limitations under the License.
16
+ *
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
20
+ * Reserved.
21
+ *
22
+ * @author Peter Wood
23
+ * @version 1.0
24
+ */
25
+
26
+ /* Includes. */
27
+ #include "Transaction.h"
28
+ #include "Common.h"
29
+ #include "Connection.h"
30
+ #include "ResultSet.h"
31
+ #include "Statement.h"
32
+
33
+ /* Function prototypes. */
34
+ static VALUE allocateTransaction(VALUE);
35
+ static VALUE commitTransaction(VALUE);
36
+ static VALUE rollbackTransaction(VALUE);
37
+ static VALUE getTransactionConnections(VALUE);
38
+ static VALUE isTransactionFor(VALUE, VALUE);
39
+ static VALUE executeOnTransaction(VALUE, VALUE);
40
+ static VALUE createTransaction(VALUE, VALUE, VALUE);
41
+ void startTransaction(TransactionHandle *, VALUE, long, char *);
42
+ void transactionFree(void *);
43
+
44
+ /* Globals. */
45
+ VALUE cTransaction;
46
+
47
+ /* Type definitions. */
48
+ typedef struct
49
+ {
50
+ isc_db_handle *database;
51
+ long length;
52
+ char *tpb;
53
+ } ISC_TEB;
54
+
55
+ static char DEFAULT_TEB[] = {isc_tpb_version3,
56
+ isc_tpb_write,
57
+ isc_tpb_wait,
58
+ isc_tpb_rec_version,
59
+ isc_tpb_read_committed};
60
+ static int DEFAULT_TEB_SIZE = 5;
61
+
62
+
63
+ /**
64
+ * This function provides for the allocation of a new object of the Transaction
65
+ * class.
66
+ *
67
+ * @param klass A reference to the Transaction Class object
68
+ *
69
+ * @return A reference to the newly allocated object.
70
+ *
71
+ */
72
+ static VALUE allocateTransaction(VALUE klass)
73
+ {
74
+ VALUE transaction = Qnil;
75
+ TransactionHandle *handle = ALLOC(TransactionHandle);
76
+
77
+ if(handle != NULL)
78
+ {
79
+ handle->handle = 0;
80
+ transaction = Data_Wrap_Struct(klass, NULL, transactionFree, handle);
81
+ }
82
+ else
83
+ {
84
+ rb_raise(rb_eNoMemError,
85
+ "Memory allocation failure allocating a transaction.");
86
+ }
87
+
88
+ return(transaction);
89
+ }
90
+
91
+
92
+ /**
93
+ * This function provides the initialize method for the Transaction class.
94
+ *
95
+ * @param self A reference to the new Transaction class instance.
96
+ * @param connections Either a reference to a single Connection object or to
97
+ * an array of Connection objects that the transaction
98
+ * will apply to.
99
+ *
100
+ */
101
+ static VALUE transactionInitialize(VALUE self, VALUE connections)
102
+ {
103
+ TransactionHandle *transaction = NULL;
104
+ VALUE array = Qnil;
105
+
106
+ /* Determine if an array has been passed as a parameter. */
107
+ if(TYPE(connections) == T_ARRAY)
108
+ {
109
+ array = connections;
110
+ }
111
+ else if(TYPE(connections) == T_DATA &&
112
+ RDATA(connections)->dfree == (RUBY_DATA_FUNC)connectionFree)
113
+ {
114
+ array = rb_ary_new();
115
+ rb_ary_push(array, connections);
116
+ }
117
+ else
118
+ {
119
+ rb_fireruby_raise(NULL,
120
+ "Invalid connection parameter(s) for transaction.");
121
+ }
122
+
123
+ /* Store the database details. */
124
+ rb_iv_set(self, "@connections", array);
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);
132
+ }
133
+
134
+
135
+ /**
136
+ * This function provides the commit method for the Transaction class.
137
+ *
138
+ * @param self A reference to the Transaction object being committed.
139
+ *
140
+ * @return A reference to self if successful, nil otherwise.
141
+ *
142
+ */
143
+ static VALUE commitTransaction(VALUE self)
144
+ {
145
+ TransactionHandle *transaction = NULL;
146
+
147
+ Data_Get_Struct(self, TransactionHandle, transaction);
148
+
149
+ /* Commit the transaction. */
150
+ if(transaction->handle != 0)
151
+ {
152
+ ISC_STATUS status[20];
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
+ {
163
+ /* Generate an error. */
164
+ rb_fireruby_raise(NULL, "1. Transaction is not active.");
165
+ }
166
+
167
+ /* Notify each connection of the transactions end. */
168
+ rb_tx_released(rb_iv_get(self, "@connections"), self);
169
+
170
+ /* Clear the connections list. */
171
+ rb_iv_set(self, "@connections", rb_ary_new());
172
+
173
+ return(self);
174
+ }
175
+
176
+
177
+ /**
178
+ * This function provides the rollback method for the Transaction class.
179
+ *
180
+ * @param self A reference to the Transaction object being rolled back.
181
+ *
182
+ * @return A reference to self if successful, nil otherwise.
183
+ *
184
+ */
185
+ static VALUE rollbackTransaction(VALUE self)
186
+ {
187
+ TransactionHandle *transaction = NULL;
188
+
189
+ Data_Get_Struct(self, TransactionHandle, transaction);
190
+
191
+ /* Roll back the transaction. */
192
+ if(transaction->handle != 0)
193
+ {
194
+ ISC_STATUS status[20];
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
+ {
205
+ /* Generate an error. */
206
+ rb_fireruby_raise(NULL, "2. Transaction is not active.");
207
+ }
208
+
209
+ /* Notify each connection of the transactions end. */
210
+ rb_tx_released(rb_iv_get(self, "@connections"), self);
211
+
212
+ /* Clear the connections list. */
213
+ rb_iv_set(self, "@connections", rb_ary_new());
214
+
215
+ return(self);
216
+ }
217
+
218
+
219
+ /**
220
+ * This function provides the active? method for the Transaction class.
221
+ *
222
+ * @param self A reference to the Transcation object to perform the check for.
223
+ *
224
+ * @return Qtrue if the transaction is active, Qfalse otherwise.
225
+ *
226
+ */
227
+ static VALUE transactionIsActive(VALUE self)
228
+ {
229
+ VALUE result = Qfalse;
230
+ TransactionHandle *transaction = NULL;
231
+
232
+ Data_Get_Struct(self, TransactionHandle, transaction);
233
+ if(transaction->handle != 0)
234
+ {
235
+ result = Qtrue;
236
+ }
237
+
238
+ return(result);
239
+ }
240
+
241
+
242
+ /**
243
+ * This function provides the accessor for the connections Transaction class
244
+ * attribute.
245
+ *
246
+ * @param self A reference to the Transaction object to fetch the connections
247
+ * for.
248
+ *
249
+ * @return An Array containing the connections associated with the Transaction
250
+ * object.
251
+ *
252
+ */
253
+ static VALUE getTransactionConnections(VALUE self)
254
+ {
255
+ return(rb_iv_get(self, "@connections"));
256
+ }
257
+
258
+
259
+ /**
260
+ * This function provides the for? method of the Transaction class.
261
+ *
262
+ * @param self A reference to the Transaction object to make the check
263
+ * on
264
+ * @param connection A reference to the Database object to make the check for.
265
+ *
266
+ * @return Qtrue if the specified database is covered by the Transaction,
267
+ * Qfalse otherwise.
268
+ *
269
+ */
270
+ static VALUE isTransactionFor(VALUE self, VALUE connection)
271
+ {
272
+ VALUE result = Qfalse,
273
+ array = rb_iv_get(self, "@connections"),
274
+ value = rb_funcall(array, rb_intern("size"), 0);
275
+ int size = 0,
276
+ index;
277
+ ConnectionHandle *instance = NULL;
278
+ TransactionHandle *transaction = NULL;
279
+
280
+ size = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
281
+ Data_Get_Struct(self, TransactionHandle, transaction);
282
+ Data_Get_Struct(connection, ConnectionHandle, instance);
283
+
284
+ for(index = 0; index < size && result == Qfalse; index++)
285
+ {
286
+ ConnectionHandle *handle;
287
+
288
+ value = rb_ary_entry(array, index);
289
+ Data_Get_Struct(value, ConnectionHandle, handle);
290
+ result = (handle == instance ? Qtrue : Qfalse);
291
+ }
292
+
293
+ return(result);
294
+ }
295
+
296
+
297
+ /**
298
+ * This function provides the execute method for the Transaction class. This
299
+ * method only works when a transaction applies to a single connection.
300
+ *
301
+ * @param self A reference to the Transaction object that the execute has
302
+ * been called for.
303
+ * @param sql A reference to the SQL statement to be executed.
304
+ *
305
+ * @return A reference to a result set of the SQL statement represents a
306
+ * query, nil otherwise.
307
+ *
308
+ */
309
+ static VALUE executeOnTransaction(VALUE self, VALUE sql)
310
+ {
311
+ VALUE results = Qnil,
312
+ list = rb_iv_get(self, "@connections"),
313
+ value = 0,
314
+ connection = Qnil,
315
+ statement = Qnil;
316
+ TransactionHandle *transaction = NULL;
317
+ int size = 0;
318
+
319
+ /* Check that the transaction is active. */
320
+ Data_Get_Struct(self, TransactionHandle, transaction);
321
+ if(transaction->handle == 0)
322
+ {
323
+ rb_fireruby_raise(NULL, "Executed called on inactive transaction.");
324
+ }
325
+
326
+ /* Check that we have only one connection for the transaction. */
327
+ value = rb_funcall(list, rb_intern("size"), 0);
328
+ size = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
329
+ if(size > 1)
330
+ {
331
+ rb_fireruby_raise(NULL,
332
+ "Execute called on a transaction that spans multiple "\
333
+ "connections. Unable to determine which connection to "\
334
+ "execute the SQL statement through.");
335
+ }
336
+
337
+ connection = rb_ary_entry(list, 0);
338
+ statement = rb_statement_new(connection, self, sql, INT2FIX(3));
339
+ results = rb_execute_statement(statement);
340
+
341
+ if(results != Qnil && rb_obj_is_kind_of(results, rb_cInteger) == Qfalse)
342
+ {
343
+ if(rb_block_given_p())
344
+ {
345
+ VALUE row = rb_funcall(results, rb_intern("fetch"), 0),
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;
355
+ }
356
+ }
357
+ rb_statement_close(statement);
358
+
359
+ return(results);
360
+ }
361
+
362
+
363
+ /**
364
+ * This function creates a new Transaction object for a connection. This method
365
+ * provides the create class method for the Transaction class and allows for the
366
+ * specification of transaction parameters.
367
+ *
368
+ * @param unused Like it says, not used.
369
+ * @param connections A reference to the array of Connection objects that the
370
+ * transaction will be associated with.
371
+ * @param parameters A reference to an array containing the parameters to be
372
+ * used in creating the transaction.
373
+ *
374
+ * @return A reference to the newly created Transaction object.
375
+ *
376
+ */
377
+ static VALUE createTransaction(VALUE unused, VALUE connections, VALUE parameters)
378
+ {
379
+ VALUE instance = Qnil,
380
+ list = Qnil;
381
+ TransactionHandle *transaction = ALLOC(TransactionHandle);
382
+
383
+ if(transaction == NULL)
384
+ {
385
+ rb_raise(rb_eNoMemError,
386
+ "Memory allocation failure allocating a transaction.");
387
+ }
388
+ transaction->handle = 0;
389
+
390
+ if(TYPE(connections) != T_ARRAY)
391
+ {
392
+ list = rb_ary_new();
393
+ rb_ary_push(list, connections);
394
+ }
395
+ else
396
+ {
397
+ list = connections;
398
+ }
399
+
400
+ if(TYPE(parameters) != T_ARRAY)
401
+ {
402
+ rb_fireruby_raise(NULL,
403
+ "Invalid transaction parameter set specified.");
404
+ }
405
+
406
+ if(transaction != NULL)
407
+ {
408
+ VALUE value = rb_funcall(parameters, rb_intern("size"), 0);
409
+ long size = 0,
410
+ index;
411
+ char *buffer = NULL;
412
+
413
+ size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
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.");
438
+ }
439
+ }
440
+ else
441
+ {
442
+ rb_raise(rb_eNoMemError,
443
+ "Memory allocation failure allocating transaction.");
444
+ }
445
+
446
+ return(instance);
447
+ }
448
+
449
+
450
+ /**
451
+ * This function begins a transaction on all of the database associated with
452
+ * the Transaction object.
453
+ *
454
+ * @param transaction A reference to the Transaction object being started.
455
+ * @param connections An array of the databases that the transaction applies
456
+ * to.
457
+ * @param size The length of the transaction parameter buffer passed
458
+ * to the function.
459
+ * @param buffer The transaction parameter buffer to be used in creating
460
+ * the transaction.
461
+ *
462
+ */
463
+ void startTransaction(TransactionHandle *transaction,
464
+ VALUE connections,
465
+ long size,
466
+ char *buffer)
467
+ {
468
+ ISC_TEB *teb = NULL;
469
+ VALUE value = rb_funcall(connections, rb_intern("size"), 0),
470
+ head = rb_ary_entry(connections, 0);
471
+ short length = 0;
472
+ ConnectionHandle *first = NULL;
473
+
474
+ /* Attempt a retrieval of the first connection. */
475
+ if(value != Qnil)
476
+ {
477
+ /* Check that we have a connection. */
478
+ if(TYPE(head) == T_DATA &&
479
+ RDATA(head)->dfree == (RUBY_DATA_FUNC)connectionFree)
480
+ {
481
+ Data_Get_Struct(head, ConnectionHandle, first);
482
+ }
483
+ }
484
+
485
+ /* Generate the list of connections. */
486
+ length = (TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value));
487
+ if(length > 0)
488
+ {
489
+ if((teb = ALLOC_N(ISC_TEB, length)) != NULL)
490
+ {
491
+ int i;
492
+
493
+ for(i = 0; i < length; i++)
494
+ {
495
+ VALUE entry = rb_ary_entry(connections, i);
496
+
497
+ /* Check that we have a connection. */
498
+ if(TYPE(entry) == T_DATA &&
499
+ RDATA(entry)->dfree == (RUBY_DATA_FUNC)connectionFree)
500
+ {
501
+ ConnectionHandle *connection = NULL;
502
+
503
+ Data_Get_Struct(entry, ConnectionHandle, connection);
504
+ if(connection->handle != 0)
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.");
535
+ }
536
+ }
537
+ }
538
+ else
539
+ {
540
+ rb_raise(rb_eNoMemError,
541
+ "Memory allocation error starting transaction.");
542
+ }
543
+ }
544
+ else
545
+ {
546
+ /* Generate an exception. */
547
+ rb_fireruby_raise(NULL, "No connections specified for transaction.");
548
+ }
549
+
550
+ /* Check that theres been no errors and that we have a connection list. */
551
+ if(teb != NULL)
552
+ {
553
+ ISC_STATUS status[20];
554
+
555
+ /* Attempt a transaction start. */
556
+ if(isc_start_multiple(status, &transaction->handle, length, teb) != 0)
557
+ {
558
+ /* Generate an error. */
559
+ rb_fireruby_raise(status, "Error starting transaction.");
560
+ }
561
+ }
562
+
563
+ /* Free the database details list if need be. */
564
+ if(teb != NULL)
565
+ {
566
+ free(teb);
567
+ }
568
+ }
569
+
570
+
571
+ /**
572
+ * This function is used to integrate with the Ruby garbage collector to insure
573
+ * that the resources associated with a Transaction object are released when the
574
+ * collector comes a calling.
575
+ *
576
+ * @param transaction A pointer to the TransactionHandle structure associated
577
+ * with the Transaction object being collected.
578
+ *
579
+ */
580
+ void transactionFree(void *transaction)
581
+ {
582
+ if(transaction != NULL)
583
+ {
584
+ TransactionHandle *handle = (TransactionHandle *)transaction;
585
+
586
+ if(handle->handle != 0)
587
+ {
588
+ ISC_STATUS status[20];
589
+
590
+ isc_rollback_transaction(status, &handle->handle);
591
+ }
592
+ free(handle);
593
+ }
594
+ }
595
+
596
+
597
+ /**
598
+ * This function provides a programmatic method of creating a Transaction
599
+ * object.
600
+ *
601
+ * @param connections Either an single Connection object or an array of
602
+ * Connection objects that the transaction will apply
603
+ * to.
604
+ *
605
+ * @return A reference to the Transaction object, or nil if an error occurs.
606
+ *
607
+ */
608
+ VALUE rb_transaction_new(VALUE connections)
609
+ {
610
+ VALUE transaction = allocateTransaction(cTransaction);
611
+
612
+ transactionInitialize(transaction, connections);
613
+
614
+ return(transaction);
615
+ }
616
+
617
+ /**
618
+ * This function provides a convenient means of checking whether a connection
619
+ * is covered by a transaction.
620
+ *
621
+ * @param transaction A reference to the transaction to perform the check on.
622
+ * @param connection A reference to the connection to perform the check for.
623
+ *
624
+ * @return Non-zero if the connection is covered by the transaction, zero if
625
+ * it is not.
626
+ *
627
+ */
628
+ int coversConnection(VALUE transaction, VALUE connection)
629
+ {
630
+ int result = 0;
631
+ VALUE boolean = isTransactionFor(transaction, connection);
632
+
633
+ if(boolean == Qtrue)
634
+ {
635
+ result = 1;
636
+ }
637
+
638
+ return(result);
639
+ }
640
+
641
+
642
+ /**
643
+ * This function initializes the Transaction class within the Ruby environment.
644
+ * The class is established under the module specified to the function.
645
+ *
646
+ * @param module A reference to the module to create the class within.
647
+ *
648
+ */
649
+ void Init_Transaction(VALUE module)
650
+ {
651
+ cTransaction = rb_define_class_under(module, "Transaction", rb_cObject);
652
+ rb_define_alloc_func(cTransaction, allocateTransaction);
653
+ rb_define_method(cTransaction, "initialize", transactionInitialize, 1);
654
+ rb_define_method(cTransaction, "initialize_copy", forbidObjectCopy, 1);
655
+ rb_define_method(cTransaction, "active?", transactionIsActive, 0);
656
+ rb_define_method(cTransaction, "commit", commitTransaction, 0);
657
+ rb_define_method(cTransaction, "rollback", rollbackTransaction, 0);
658
+ rb_define_method(cTransaction, "connections", getTransactionConnections, 0);
659
+ rb_define_method(cTransaction, "for_connection?", isTransactionFor, 1);
660
+ rb_define_module_function(cTransaction, "create", createTransaction, 2);
661
+ rb_define_method(cTransaction, "execute", executeOnTransaction, 1);
662
+ rb_define_const(cTransaction, "TPB_VERSION_1", INT2FIX(isc_tpb_version1));
663
+ rb_define_const(cTransaction, "TPB_VERSION_3", INT2FIX(isc_tpb_version3));
664
+ rb_define_const(cTransaction, "TPB_CONSISTENCY", INT2FIX(isc_tpb_consistency));
665
+ rb_define_const(cTransaction, "TPB_CONCURRENCY", INT2FIX(isc_tpb_concurrency));
666
+ rb_define_const(cTransaction, "TPB_SHARED", INT2FIX(isc_tpb_shared));
667
+ rb_define_const(cTransaction, "TPB_PROTECTED", INT2FIX(isc_tpb_protected));
668
+ rb_define_const(cTransaction, "TPB_EXCLUSIVE", INT2FIX(isc_tpb_exclusive));
669
+ rb_define_const(cTransaction, "TPB_WAIT", INT2FIX(isc_tpb_wait));
670
+ rb_define_const(cTransaction, "TPB_NO_WAIT", INT2FIX(isc_tpb_nowait));
671
+ rb_define_const(cTransaction, "TPB_READ", INT2FIX(isc_tpb_read));
672
+ rb_define_const(cTransaction, "TPB_WRITE", INT2FIX(isc_tpb_write));
673
+ rb_define_const(cTransaction, "TPB_LOCK_READ", INT2FIX(isc_tpb_lock_read));
674
+ rb_define_const(cTransaction, "TPB_LOCK_WRITE", INT2FIX(isc_tpb_lock_write));
675
+ rb_define_const(cTransaction, "TPB_VERB_TIME", INT2FIX(isc_tpb_verb_time));
676
+ rb_define_const(cTransaction, "TPB_COMMIT_TIME", INT2FIX(isc_tpb_commit_time));
677
+ rb_define_const(cTransaction, "TPB_IGNORE_LIMBO", INT2FIX(isc_tpb_ignore_limbo));
678
+ rb_define_const(cTransaction, "TPB_READ_COMMITTED", INT2FIX(isc_tpb_read_committed));
679
+ rb_define_const(cTransaction, "TPB_AUTO_COMMIT", INT2FIX(isc_tpb_autocommit));
680
+ rb_define_const(cTransaction, "TPB_REC_VERSION", INT2FIX(isc_tpb_rec_version));
681
+ rb_define_const(cTransaction, "TPB_NO_REC_VERSION", INT2FIX(isc_tpb_no_rec_version));
682
+ rb_define_const(cTransaction, "TPB_RESTART_REQUESTS", INT2FIX(isc_tpb_restart_requests));
683
+ rb_define_const(cTransaction, "TPB_NO_AUTO_UNDO", INT2FIX(isc_tpb_no_auto_undo));
684
+ }