rubyfb 0.5.2-x86-linux

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 (75) hide show
  1. data/CHANGELOG +6 -0
  2. data/LICENSE +411 -0
  3. data/Manifest +73 -0
  4. data/README +460 -0
  5. data/Rakefile +20 -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 +809 -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 +28 -0
  46. data/ext/mkmf.bat +1 -0
  47. data/lib/SQLType.rb +224 -0
  48. data/lib/active_record/connection_adapters/rubyfb_adapter.rb +805 -0
  49. data/lib/mkdoc +1 -0
  50. data/lib/rubyfb.rb +2 -0
  51. data/lib/rubyfb_lib.so +0 -0
  52. data/lib/src.rb +1800 -0
  53. data/rubyfb.gemspec +31 -0
  54. data/test/AddRemoveUserTest.rb +56 -0
  55. data/test/BackupRestoreTest.rb +99 -0
  56. data/test/BlobTest.rb +57 -0
  57. data/test/CharacterSetTest.rb +63 -0
  58. data/test/ConnectionTest.rb +111 -0
  59. data/test/DDLTest.rb +54 -0
  60. data/test/DatabaseTest.rb +83 -0
  61. data/test/GeneratorTest.rb +50 -0
  62. data/test/KeyTest.rb +140 -0
  63. data/test/ResultSetTest.rb +162 -0
  64. data/test/RoleTest.rb +73 -0
  65. data/test/RowCountTest.rb +65 -0
  66. data/test/RowTest.rb +203 -0
  67. data/test/SQLTest.rb +182 -0
  68. data/test/SQLTypeTest.rb +101 -0
  69. data/test/ServiceManagerTest.rb +29 -0
  70. data/test/StatementTest.rb +135 -0
  71. data/test/TestSetup.rb +11 -0
  72. data/test/TransactionTest.rb +112 -0
  73. data/test/TypeTest.rb +92 -0
  74. data/test/UnitTest.rb +65 -0
  75. metadata +149 -0
data/ext/Statement.c ADDED
@@ -0,0 +1,785 @@
1
+ /*------------------------------------------------------------------------------
2
+ * Statement.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 "Statement.h"
28
+ #include "Common.h"
29
+ #include "Connection.h"
30
+ #include "Transaction.h"
31
+ #include "DataArea.h"
32
+ #include "TypeMap.h"
33
+ #include "ResultSet.h"
34
+
35
+ /* Function prototypes. */
36
+ static VALUE allocateStatement(VALUE);
37
+ static VALUE initializeStatement(VALUE, VALUE, VALUE, VALUE, VALUE);
38
+ static VALUE getStatementSQL(VALUE);
39
+ static VALUE getStatementTransaction(VALUE);
40
+ static VALUE getStatementConnection(VALUE);
41
+ static VALUE getStatementDialect(VALUE);
42
+ static VALUE getStatementType(VALUE);
43
+ static VALUE getStatementParameterCount(VALUE);
44
+ static VALUE executeStatement(VALUE);
45
+ static VALUE executeStatementFor(VALUE, VALUE);
46
+ static VALUE closeStatement(VALUE);
47
+
48
+ /* Globals. */
49
+ VALUE cStatement;
50
+
51
+
52
+ /**
53
+ * This function integrates with the Ruby memory control system to provide for
54
+ * the allocation of Statement objects.
55
+ *
56
+ * @param klass A reference to the Statement Class object.
57
+ *
58
+ * @return A reference to the newly allocated Statement object.
59
+ *
60
+ */
61
+ VALUE allocateStatement(VALUE klass)
62
+ {
63
+ StatementHandle *statement = ALLOC(StatementHandle);
64
+
65
+ if(statement == NULL)
66
+ {
67
+ rb_raise(rb_eNoMemError,
68
+ "Memory allocation failure allocating a statement.");
69
+ }
70
+
71
+ statement->handle = 0;
72
+ statement->type = -1;
73
+ statement->inputs = 0;
74
+ statement->dialect = 0;
75
+ statement->parameters = NULL;
76
+
77
+ return(Data_Wrap_Struct(klass, NULL, statementFree, statement));
78
+ }
79
+
80
+
81
+ /**
82
+ * This function provides the initialize method for the Statement class.
83
+ *
84
+ * @param self A reference to the Statement object to be initialized.
85
+ * @param connection A reference to the Connection object that the statement
86
+ * will execute through.
87
+ * @param transaction A reference to the Transaction object that the statement
88
+ * will work under.
89
+ * @param sql A reference to a String object containing the text of
90
+ * the SQL statement to be executed.
91
+ * @param dialect A reference to an integer object specifying the dialect
92
+ * to be used in executing the statement. This should be a
93
+ * value of between 1 and 3.
94
+ *
95
+ * @return A reference to the newly initialized Statement object.
96
+ *
97
+ */
98
+ VALUE initializeStatement(VALUE self, VALUE connection, VALUE transaction,
99
+ VALUE sql, VALUE dialect)
100
+ {
101
+ StatementHandle *statement = NULL;
102
+ short setting = 0;
103
+ VALUE value = Qnil;
104
+
105
+ /* Validate the inputs. */
106
+ if(TYPE(connection) == T_DATA &&
107
+ RDATA(connection)->dfree == (RUBY_DATA_FUNC)connectionFree)
108
+ {
109
+ if(rb_funcall(connection, rb_intern("open?"), 0) == Qfalse)
110
+ {
111
+ rb_fireruby_raise(NULL, "Closed connection specified for statement.");
112
+ }
113
+ }
114
+ else
115
+ {
116
+ rb_fireruby_raise(NULL, "Invalid connection specified for statement.");
117
+ }
118
+
119
+ if(TYPE(transaction) == T_DATA &&
120
+ RDATA(transaction)->dfree == (RUBY_DATA_FUNC)transactionFree)
121
+ {
122
+ if(rb_funcall(transaction, rb_intern("active?"), 0) == Qfalse)
123
+ {
124
+ rb_fireruby_raise(NULL, "Inactive transaction specified for statement.");
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
+ {
145
+ rb_fireruby_raise(NULL,
146
+ "Invalid dialect value specified for statement. The "\
147
+ "dialect value must be between 1 and 3.");
148
+ }
149
+
150
+ Data_Get_Struct(self, StatementHandle, statement);
151
+ rb_iv_set(self, "@connection", connection);
152
+ rb_iv_set(self, "@transaction", transaction);
153
+ rb_iv_set(self, "@sql", rb_funcall(sql, rb_intern("to_s"), 0));
154
+ rb_iv_set(self, "@dialect", value);
155
+ statement->dialect = setting;
156
+
157
+ return(self);
158
+ }
159
+
160
+
161
+ /**
162
+ * This function provides the sql sttribute accessor method for the Statement
163
+ * class.
164
+ *
165
+ * @param self A reference to the Statement object to call the method on.
166
+ *
167
+ * @return A reference to a String containing the SQL statement.
168
+ *
169
+ */
170
+ VALUE getStatementSQL(VALUE self)
171
+ {
172
+ return(rb_iv_get(self, "@sql"));
173
+ }
174
+
175
+
176
+ /**
177
+ * This function provides the connection sttribute accessor method for the
178
+ * Statement class.
179
+ *
180
+ * @param self A reference to the Statement object to call the method on.
181
+ *
182
+ * @return A reference to a Connection object.
183
+ *
184
+ */
185
+ VALUE getStatementConnection(VALUE self)
186
+ {
187
+ return(rb_iv_get(self, "@connection"));
188
+ }
189
+
190
+
191
+ /**
192
+ * This function provides the transaction sttribute accessor method for the
193
+ * Statement class.
194
+ *
195
+ * @param self A reference to the Statement object to call the method on.
196
+ *
197
+ * @return A reference to a Transaction object.
198
+ *
199
+ */
200
+ VALUE getStatementTransaction(VALUE self)
201
+ {
202
+ return(rb_iv_get(self, "@transaction"));
203
+ }
204
+
205
+
206
+ /**
207
+ * This function provides the dialect sttribute accessor method for the
208
+ * Statement class.
209
+ *
210
+ * @param self A reference to the Statement object to call the method on.
211
+ *
212
+ * @return A reference to an integer containing the SQL dialect setting.
213
+ *
214
+ */
215
+ VALUE getStatementDialect(VALUE self)
216
+ {
217
+ return(rb_iv_get(self, "@dialect"));
218
+ }
219
+
220
+
221
+
222
+ /**
223
+ * This function provides the type attribute accessor method for the Statement
224
+ * class.
225
+ *
226
+ * @param self A reference to the Statement object to call the method on.
227
+ *
228
+ * @return A reference to an integer containing the SQL type details.
229
+ *
230
+ */
231
+ VALUE getStatementType(VALUE self)
232
+ {
233
+ StatementHandle *statement = NULL;
234
+ ConnectionHandle *connection = NULL;
235
+ TransactionHandle *transaction = NULL;
236
+ int outputs = 0;
237
+
238
+ Data_Get_Struct(self, StatementHandle, statement);
239
+ Data_Get_Struct(rb_iv_get(self, "@connection"), ConnectionHandle, connection);
240
+ Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle, transaction);
241
+ if(statement->handle == 0)
242
+ {
243
+ prepare(&connection->handle, &transaction->handle,
244
+ STR2CSTR(rb_iv_get(self, "@sql")), &statement->handle,
245
+ statement->dialect, &statement->type, &statement->inputs,
246
+ &outputs);
247
+ }
248
+
249
+ return(INT2FIX(statement->type));
250
+ }
251
+
252
+
253
+ /**
254
+ * This function provides the parameter count sttribute accessor method for the
255
+ * Statement class.
256
+ *
257
+ * @param self A reference to the Statement object to call the method on.
258
+ *
259
+ * @return A reference to an integer containing the statement parameter count.
260
+ *
261
+ */
262
+ VALUE getStatementParameterCount(VALUE self)
263
+ {
264
+ StatementHandle *statement = NULL;
265
+
266
+ Data_Get_Struct(self, StatementHandle, statement);
267
+ if(statement->handle == 0)
268
+ {
269
+ getStatementType(self);
270
+ }
271
+
272
+ return(INT2NUM(statement->inputs));
273
+ }
274
+
275
+
276
+ /**
277
+ * This method provides the execute method for the Statement class.
278
+ *
279
+ * @param self A reference to the Statement object to call the method on.
280
+ *
281
+ * @return One of a count of the number of rows affected by the SQL statement,
282
+ * a ResultSet object for a query or nil.
283
+ *
284
+ */
285
+ VALUE executeStatement(VALUE self)
286
+ {
287
+ VALUE result;
288
+ int type = FIX2INT(getStatementType(self));
289
+ long affected = 0;
290
+ StatementHandle *statement = NULL;
291
+ TransactionHandle *transaction = NULL;
292
+
293
+ switch(type)
294
+ {
295
+ case isc_info_sql_stmt_select :
296
+ case isc_info_sql_stmt_select_for_upd :
297
+ case isc_info_sql_stmt_exec_procedure :
298
+ result = rb_result_set_new(rb_iv_get(self, "@connection"),
299
+ rb_iv_get(self, "@transaction"),
300
+ rb_iv_get(self, "@sql"),
301
+ rb_iv_get(self, "@dialect"),
302
+ rb_ary_new());
303
+ break;
304
+
305
+ case isc_info_sql_stmt_insert :
306
+ case isc_info_sql_stmt_update :
307
+ case isc_info_sql_stmt_delete :
308
+ Data_Get_Struct(self, StatementHandle, statement);
309
+ Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
310
+ transaction);
311
+ execute(&transaction->handle, &statement->handle, statement->dialect,
312
+ NULL, statement->type, &affected);
313
+ result = INT2NUM(affected);
314
+ break;
315
+
316
+ default :
317
+ Data_Get_Struct(self, StatementHandle, statement);
318
+ Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
319
+ transaction);
320
+ execute(&transaction->handle, &statement->handle, statement->dialect,
321
+ NULL, statement->type, &affected);
322
+ result = Qnil;
323
+ }
324
+
325
+ return(result);
326
+ }
327
+
328
+
329
+ /**
330
+ * This method provides the execute method for the Statement class.
331
+ *
332
+ * @param self A reference to the Statement object to call the method
333
+ * on.
334
+ * @param parameters An array containing the parameters to be used in
335
+ * executing the statement.
336
+ *
337
+ * @return One of a count of the number of rows affected by the SQL statement,
338
+ * a ResultSet object for a query or nil.
339
+ *
340
+ */
341
+ VALUE executeStatementFor(VALUE self, VALUE parameters)
342
+ {
343
+ VALUE result = Qnil;
344
+ int type = FIX2INT(getStatementType(self));
345
+ long affected = 0;
346
+ StatementHandle *statement = NULL;
347
+ TransactionHandle *transaction = NULL;
348
+
349
+ if(type == isc_info_sql_stmt_select ||
350
+ type == isc_info_sql_stmt_select_for_upd)
351
+ {
352
+ /* Execute the statement via a ResultSet object. */
353
+ result = rb_result_set_new(rb_iv_get(self, "@connection"),
354
+ rb_iv_get(self, "@transaction"),
355
+ rb_iv_get(self, "@sql"),
356
+ rb_iv_get(self, "@dialect"),
357
+ parameters);
358
+ }
359
+ else
360
+ {
361
+ /* Check that sufficient parameters have been specified. */
362
+ Data_Get_Struct(self, StatementHandle, statement);
363
+ if(statement->inputs > 0)
364
+ {
365
+ VALUE value = Qnil;
366
+ int size = 0;
367
+
368
+ if(parameters == Qnil)
369
+ {
370
+ rb_fireruby_raise(NULL,
371
+ "Empty parameter list specified for statement.");
372
+ }
373
+
374
+ value = rb_funcall(parameters, rb_intern("size"), 0);
375
+ size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
376
+ if(size < statement->inputs)
377
+ {
378
+ rb_fireruby_raise(NULL,
379
+ "Insufficient parameters specified for statement.");
380
+ }
381
+
382
+ /* Allocate the XSQLDA and populate it. */
383
+ statement->parameters = allocateInXSQLDA(statement->inputs,
384
+ &statement->handle,
385
+ statement->dialect);
386
+ prepareDataArea(statement->parameters);
387
+ setParameters(statement->parameters, parameters, self);
388
+ }
389
+
390
+ /* Execute the statement. */
391
+ Data_Get_Struct(self, StatementHandle, statement);
392
+ Data_Get_Struct(rb_iv_get(self, "@transaction"), TransactionHandle,
393
+ transaction);
394
+ execute(&transaction->handle, &statement->handle, statement->dialect,
395
+ statement->parameters, statement->type, &affected);
396
+ if(type == isc_info_sql_stmt_insert ||
397
+ type == isc_info_sql_stmt_update ||
398
+ type == isc_info_sql_stmt_delete)
399
+ {
400
+ result = INT2NUM(affected);
401
+ }
402
+ }
403
+
404
+ return(result);
405
+ }
406
+
407
+
408
+
409
+ /**
410
+ * This function provides the close method for the Statement class.
411
+ *
412
+ * @param self A reference to the Statement object to call the method on.
413
+ *
414
+ * @return A reference to the newly closed Statement object.
415
+ *
416
+ */
417
+ VALUE closeStatement(VALUE self)
418
+ {
419
+ StatementHandle *statement = NULL;
420
+
421
+ Data_Get_Struct(self, StatementHandle, statement);
422
+ if(statement->handle != 0)
423
+ {
424
+ ISC_STATUS status[20];
425
+
426
+ if(isc_dsql_free_statement(status, &statement->handle, DSQL_drop))
427
+ {
428
+ rb_fireruby_raise(status, "Error closing statement.");
429
+ }
430
+
431
+ if(statement->parameters != NULL)
432
+ {
433
+ releaseDataArea(statement->parameters);
434
+ }
435
+ }
436
+
437
+ return(self);
438
+ }
439
+
440
+
441
+ /**
442
+ * This function prepares a Firebird SQL statement for execution.
443
+ *
444
+ * @param connection A pointer to the database connection that will be used
445
+ * to prepare the statement.
446
+ * @param transaction A pointer to the database transaction that will be used
447
+ * to prepare the statement.
448
+ * @param sql A string containing the SQL statement to be executed.
449
+ * @param statement A pointer to a Firebird statement that will be prepared.
450
+ * @param dialect A short integer containing the SQL dialect to be used in
451
+ * preparing the statement.
452
+ * @param type A pointer to an integer that will be assigned the type
453
+ * of the SQL statement prepared.
454
+ * @param inputs A pointer to an integer that will be assigned a count of
455
+ * the parameters for the SQL statement.
456
+ * @param outputs A pointer to an integer that will be assigned a count of
457
+ * the output columns for the SQL statement.
458
+ *
459
+ */
460
+ void prepare(isc_db_handle *connection, isc_tr_handle *transaction,
461
+ char *sql, isc_stmt_handle *statement, short dialect,
462
+ int *type, int *inputs, int *outputs)
463
+ {
464
+ ISC_STATUS status[20];
465
+ XSQLDA *da = NULL;
466
+ char list[] = {isc_info_sql_stmt_type},
467
+ info[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
468
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
469
+
470
+ /* Prepare the statement. */
471
+ if(isc_dsql_allocate_statement(status, connection, statement))
472
+ {
473
+ rb_fireruby_raise(status, "Error allocating a SQL statement.");
474
+ }
475
+
476
+ da = (XSQLDA *)ALLOC_N(char, XSQLDA_LENGTH(1));
477
+ if(da == NULL)
478
+ {
479
+ rb_raise(rb_eNoMemError,
480
+ "Memory allocation failure preparing a statement.");
481
+ }
482
+ da->version = SQLDA_VERSION1;
483
+ da->sqln = 1;
484
+ if(isc_dsql_prepare(status, transaction, statement, 0, sql, dialect,
485
+ da))
486
+ {
487
+ free(da);
488
+ rb_fireruby_raise(status, "Error preparing a SQL statement.");
489
+ }
490
+ *outputs = da->sqld;
491
+
492
+ /* Get the parameter count. */
493
+ if(isc_dsql_describe_bind(status, statement, dialect, da))
494
+ {
495
+ free(da);
496
+ rb_fireruby_raise(status, "Error determining statement parameters.");
497
+ }
498
+ *inputs = da->sqld;
499
+ free(da);
500
+
501
+ /* Get the statement type details. */
502
+ if(isc_dsql_sql_info(status, statement, 1, list, 20, info) ||
503
+ info[0] != isc_info_sql_stmt_type)
504
+ {
505
+ rb_fireruby_raise(status, "Error determining SQL statement type.");
506
+ }
507
+ *type = isc_vax_integer(&info[3], isc_vax_integer(&info[1], 2));
508
+ }
509
+
510
+
511
+ /**
512
+ * This function executes a previously prepare SQL statement.
513
+ *
514
+ * @param transaction A pointer to the Firebird transaction handle to be used in
515
+ * executing the statement.
516
+ * @param statement A pointer to the Firebird statement handle to be used in
517
+ * executing the statement.
518
+ * @param dialect Database dialect used in the statement
519
+ *
520
+ * @param parameters A pointer to the XSQLDA block that contains the input
521
+ * parameters for the SQL statement.
522
+ * @param type A integer containing the type details relating to the
523
+ * statement being executed.
524
+ * @param affected A pointer to a long integer that will be assigned a count
525
+ * of rows affected by inserts, updates or deletes.
526
+ * @param output A pointer to the XSQLDA block that will hold the output
527
+ * data generated by the execution.
528
+ */
529
+ void execute_2(isc_tr_handle *transaction, isc_stmt_handle *statement,
530
+ short dialect, XSQLDA *parameters, int type, long *affected, XSQLDA *output)
531
+ {
532
+ ISC_STATUS status[20];
533
+ ISC_STATUS execute_result;
534
+
535
+ if(output) {
536
+ execute_result = isc_dsql_execute2(status, transaction, statement, dialect, parameters, output);
537
+ } else {
538
+ execute_result = isc_dsql_execute(status, transaction, statement, dialect, parameters);
539
+ }
540
+ if(execute_result)
541
+ {
542
+ rb_fireruby_raise(status, "Error executing SQL statement.");
543
+ }
544
+
545
+ /* Check if a row count is needed. */
546
+ if(type == isc_info_sql_stmt_update || type == isc_info_sql_stmt_delete ||
547
+ type == isc_info_sql_stmt_insert)
548
+ {
549
+ int info = 0,
550
+ done = 0;
551
+ char items[] = {isc_info_sql_records},
552
+ buffer[40],
553
+ *position = buffer + 3;
554
+
555
+ switch(type)
556
+ {
557
+ case isc_info_sql_stmt_update :
558
+ info = isc_info_req_update_count;
559
+ break;
560
+
561
+ case isc_info_sql_stmt_delete :
562
+ info = isc_info_req_delete_count;
563
+ break;
564
+
565
+ case isc_info_sql_stmt_insert :
566
+ info = isc_info_req_insert_count;
567
+ break;
568
+ }
569
+
570
+ if(isc_dsql_sql_info(status, statement, sizeof(items), items,
571
+ sizeof(buffer), buffer))
572
+ {
573
+ rb_fireruby_raise(status, "Error retrieving affected row count.");
574
+ }
575
+
576
+ while(*position != isc_info_end && done == 0)
577
+ {
578
+ char current = *position++;
579
+ long temp[] = {0, 0};
580
+
581
+ temp[0] = isc_vax_integer(position, 2);
582
+ position += 2;
583
+ temp[1] = isc_vax_integer(position, temp[0]);
584
+ position += temp[0];
585
+
586
+ if(current == info)
587
+ {
588
+ *affected = temp[1];
589
+ done = 1;
590
+ }
591
+ }
592
+ }
593
+ }
594
+
595
+
596
+ /**
597
+ * This function executes a previously prepare SQL statement.
598
+ *
599
+ * @param transaction A pointer to the Firebird transaction handle to be used in
600
+ * executing the statement.
601
+ * @param statement A pointer to the Firebird statement handle to be used in
602
+ * executing the statement.
603
+ * @param dialect Database dialect used in the statement
604
+ *
605
+ * @param parameters A pointer to the XSQLDA block that contains the input
606
+ * parameters for the SQL statement.
607
+ * @param type A integer containing the type details relating to the
608
+ * statement being executed.
609
+ * @param affected A pointer to a long integer that will be assigned a count
610
+ * of rows affected by inserts, updates or deletes.
611
+ */
612
+ void execute(isc_tr_handle *transaction, isc_stmt_handle *statement,
613
+ short dialect, XSQLDA *parameters, int type, long *affected)
614
+ {
615
+ execute_2(transaction, statement, dialect, parameters, type, affected, NULL);
616
+ }
617
+
618
+ /**
619
+ * This function provides a programmatic means of creating a Statement object.
620
+ *
621
+ * @param connection A reference to a Connection object that will be used by
622
+ * the Statement.
623
+ * @param transaction A reference to a Transaction object that will be used
624
+ * by the Statement.
625
+ * @param sql A reference to a String object containing the text of
626
+ * of a SQL statement for the Statement.
627
+ * @param dialect A reference to an integer object that contains the SQL
628
+ * dialect setting for the Statement.
629
+ *
630
+ * @return A reference to the newly created Statement object.
631
+ *
632
+ */
633
+ VALUE rb_statement_new(VALUE connection, VALUE transaction, VALUE sql,
634
+ VALUE dialect)
635
+ {
636
+ VALUE statement = allocateStatement(cStatement);
637
+
638
+ initializeStatement(statement, connection, transaction, sql, dialect);
639
+
640
+ return(statement);
641
+ }
642
+
643
+
644
+ /**
645
+ * This function provides a programmatic way of executing a Statement object
646
+ * without parameters.
647
+ *
648
+ * @param statement A reference to the statement object to be executed.
649
+ *
650
+ * @return A reference to the results of executing the statement.
651
+ *
652
+ */
653
+ VALUE rb_execute_statement(VALUE statement)
654
+ {
655
+ return(executeStatement(statement));
656
+ }
657
+
658
+
659
+ /**
660
+ * This function provides a programmatic way of executing a Statement object
661
+ * with parameters.
662
+ *
663
+ * @param statement A reference to the statement object to be executed.
664
+ * @param parameters A reference to an array of parameters to be used in the
665
+ * execution of the statement.
666
+ *
667
+ * @return A reference to the results of executing the statement.
668
+ *
669
+ */
670
+ VALUE rb_execute_statement_for(VALUE statement, VALUE parameters)
671
+ {
672
+ return(executeStatementFor(statement, parameters));
673
+ }
674
+
675
+
676
+ /**
677
+ * This method retrieves the type information for a Statement object.
678
+ *
679
+ * @param statement A reference to a Statement object.
680
+ *
681
+ * @return A reference to an integer containing the statement type details.
682
+ *
683
+ */
684
+ VALUE rb_get_statement_type(VALUE statement)
685
+ {
686
+ return(getStatementType(statement));
687
+ }
688
+
689
+
690
+ /**
691
+ * This function provides a programmatic means of closing a Statement object.
692
+ *
693
+ * @param statement A reference to the Statement object to be closed.
694
+ *
695
+ */
696
+ void rb_statement_close(VALUE statement)
697
+ {
698
+ closeStatement(statement);
699
+ }
700
+
701
+
702
+ /**
703
+ * This function integrates with the Ruby garbage collector to release the
704
+ * resources associated with a Statement object that is being collected.
705
+ *
706
+ * @param handle A pointer to the StatementHandle structure for the Statement
707
+ * object being collected.
708
+ *
709
+ */
710
+ void statementFree(void *handle)
711
+ {
712
+ if(handle != NULL)
713
+ {
714
+ StatementHandle *statement = (StatementHandle *)handle;
715
+
716
+ if(statement->handle != 0)
717
+ {
718
+ ISC_STATUS status[20];
719
+
720
+ isc_dsql_free_statement(status, &statement->handle, DSQL_drop);
721
+ }
722
+
723
+ if(statement->parameters)
724
+ {
725
+ releaseDataArea(statement->parameters);
726
+ }
727
+ free(statement);
728
+ }
729
+ }
730
+
731
+
732
+
733
+
734
+ /**
735
+ * This function initializes the Statement class within the Ruby environment.
736
+ * The class is established under the module specified to the function.
737
+ *
738
+ * @param module A reference to the module to create the class within.
739
+ *
740
+ */
741
+ void Init_Statement(VALUE module)
742
+ {
743
+ cStatement = rb_define_class_under(module, "Statement", rb_cObject);
744
+ rb_define_alloc_func(cStatement, allocateStatement);
745
+ rb_define_method(cStatement, "initialize", initializeStatement, 4);
746
+ rb_define_method(cStatement, "initialize_copy", forbidObjectCopy, 1);
747
+ rb_define_method(cStatement, "sql", getStatementSQL, 0);
748
+ rb_define_method(cStatement, "connection", getStatementConnection, 0);
749
+ rb_define_method(cStatement, "transaction", getStatementTransaction, 0);
750
+ rb_define_method(cStatement, "dialect", getStatementDialect, 0);
751
+ rb_define_method(cStatement, "type", getStatementType, 0);
752
+ rb_define_method(cStatement, "execute", executeStatement, 0);
753
+ rb_define_method(cStatement, "execute_for", executeStatementFor, 1);
754
+ rb_define_method(cStatement, "close", closeStatement, 0);
755
+ rb_define_method(cStatement, "parameter_count", getStatementParameterCount, 0);
756
+
757
+ rb_define_const(cStatement, "SELECT_STATEMENT",
758
+ INT2FIX(isc_info_sql_stmt_select));
759
+ rb_define_const(cStatement, "INSERT_STATEMENT",
760
+ INT2FIX(isc_info_sql_stmt_insert));
761
+ rb_define_const(cStatement, "UPDATE_STATEMENT",
762
+ INT2FIX(isc_info_sql_stmt_update));
763
+ rb_define_const(cStatement, "DELETE_STATEMENT",
764
+ INT2FIX(isc_info_sql_stmt_delete));
765
+ rb_define_const(cStatement, "DDL_STATEMENT",
766
+ INT2FIX(isc_info_sql_stmt_ddl));
767
+ rb_define_const(cStatement, "GET_SEGMENT_STATEMENT",
768
+ INT2FIX(isc_info_sql_stmt_get_segment));
769
+ rb_define_const(cStatement, "PUT_SEGMENT_STATEMENT",
770
+ INT2FIX(isc_info_sql_stmt_put_segment));
771
+ rb_define_const(cStatement, "EXECUTE_PROCEDURE_STATEMENT",
772
+ INT2FIX(isc_info_sql_stmt_exec_procedure));
773
+ rb_define_const(cStatement, "START_TRANSACTION_STATEMENT",
774
+ INT2FIX(isc_info_sql_stmt_start_trans));
775
+ rb_define_const(cStatement, "COMMIT_STATEMENT",
776
+ INT2FIX(isc_info_sql_stmt_commit));
777
+ rb_define_const(cStatement, "ROLLBACK_STATEMENT",
778
+ INT2FIX(isc_info_sql_stmt_rollback));
779
+ rb_define_const(cStatement, "SELECT_FOR_UPDATE_STATEMENT",
780
+ INT2FIX(isc_info_sql_stmt_select_for_upd));
781
+ rb_define_const(cStatement, "SET_GENERATOR_STATEMENT",
782
+ INT2FIX(isc_info_sql_stmt_set_generator));
783
+ rb_define_const(cStatement, "SAVE_POINT_STATEMENT",
784
+ INT2FIX(isc_info_sql_stmt_savepoint));
785
+ }