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.
- data/CHANGELOG +6 -0
- data/LICENSE +411 -0
- data/Manifest +75 -0
- data/README +460 -0
- data/Rakefile +21 -0
- data/examples/example01.rb +65 -0
- data/ext/AddUser.c +464 -0
- data/ext/AddUser.h +37 -0
- data/ext/Backup.c +783 -0
- data/ext/Backup.h +37 -0
- data/ext/Blob.c +421 -0
- data/ext/Blob.h +65 -0
- data/ext/Common.c +54 -0
- data/ext/Common.h +37 -0
- data/ext/Connection.c +863 -0
- data/ext/Connection.h +50 -0
- data/ext/DataArea.c +274 -0
- data/ext/DataArea.h +38 -0
- data/ext/Database.c +449 -0
- data/ext/Database.h +48 -0
- data/ext/FireRuby.c +240 -0
- data/ext/FireRuby.h +50 -0
- data/ext/FireRubyException.c +268 -0
- data/ext/FireRubyException.h +51 -0
- data/ext/Generator.c +689 -0
- data/ext/Generator.h +53 -0
- data/ext/RemoveUser.c +212 -0
- data/ext/RemoveUser.h +37 -0
- data/ext/Restore.c +855 -0
- data/ext/Restore.h +37 -0
- data/ext/ResultSet.c +810 -0
- data/ext/ResultSet.h +60 -0
- data/ext/Row.c +965 -0
- data/ext/Row.h +55 -0
- data/ext/ServiceManager.c +316 -0
- data/ext/ServiceManager.h +48 -0
- data/ext/Services.c +124 -0
- data/ext/Services.h +42 -0
- data/ext/Statement.c +785 -0
- data/ext/Statement.h +62 -0
- data/ext/Transaction.c +684 -0
- data/ext/Transaction.h +50 -0
- data/ext/TypeMap.c +1182 -0
- data/ext/TypeMap.h +51 -0
- data/ext/extconf.rb +30 -0
- data/lib/SQLType.rb +224 -0
- data/lib/active_record/connection_adapters/rubyfb_adapter.rb +805 -0
- data/lib/mkdoc +1 -0
- data/lib/rubyfb.rb +2 -0
- data/lib/rubyfb_lib.so +0 -0
- data/lib/src.rb +1800 -0
- data/mswin32fb/fbclient_ms.lib +0 -0
- data/mswin32fb/ibase.h +2555 -0
- data/mswin32fb/iberror.h +1741 -0
- data/rubyfb.gemspec +31 -0
- data/test/AddRemoveUserTest.rb +56 -0
- data/test/BackupRestoreTest.rb +99 -0
- data/test/BlobTest.rb +57 -0
- data/test/CharacterSetTest.rb +63 -0
- data/test/ConnectionTest.rb +111 -0
- data/test/DDLTest.rb +54 -0
- data/test/DatabaseTest.rb +83 -0
- data/test/GeneratorTest.rb +50 -0
- data/test/KeyTest.rb +140 -0
- data/test/ResultSetTest.rb +162 -0
- data/test/RoleTest.rb +73 -0
- data/test/RowCountTest.rb +65 -0
- data/test/RowTest.rb +203 -0
- data/test/SQLTest.rb +182 -0
- data/test/SQLTypeTest.rb +101 -0
- data/test/ServiceManagerTest.rb +29 -0
- data/test/StatementTest.rb +135 -0
- data/test/TestSetup.rb +11 -0
- data/test/TransactionTest.rb +112 -0
- data/test/TypeTest.rb +92 -0
- data/test/UnitTest.rb +65 -0
- metadata +143 -0
data/ext/Services.h
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
/*------------------------------------------------------------------------------
|
2
|
+
* Services.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_SERVICES_H
|
26
|
+
#define FIRERUBY_SERVICES_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
|
+
/* Function prototypes. */
|
40
|
+
VALUE queryService(isc_svc_handle *);
|
41
|
+
|
42
|
+
#endif /* FIRERUBY_SERVICES_H */
|
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
|
+
}
|