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.
- data/CHANGELOG +6 -0
- data/LICENSE +411 -0
- data/Manifest +73 -0
- data/README +460 -0
- data/Rakefile +20 -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 +809 -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 +28 -0
- data/ext/mkmf.bat +1 -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/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 +149 -0
data/ext/Generator.c
ADDED
@@ -0,0 +1,689 @@
|
|
1
|
+
/*------------------------------------------------------------------------------
|
2
|
+
* Generator.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 "Generator.h"
|
28
|
+
#include "Common.h"
|
29
|
+
#include "ResultSet.h"
|
30
|
+
#include "Statement.h"
|
31
|
+
#include "Transaction.h"
|
32
|
+
#include "DataArea.h"
|
33
|
+
#ifdef OS_UNIX
|
34
|
+
#include <inttypes.h>
|
35
|
+
#else
|
36
|
+
typedef short int16_t;
|
37
|
+
typedef long int32_t;
|
38
|
+
typedef long long int64_t;
|
39
|
+
#endif
|
40
|
+
|
41
|
+
/* Function prototypes. */
|
42
|
+
static VALUE allocateGenerator(VALUE);
|
43
|
+
static VALUE initializeGenerator(VALUE, VALUE, VALUE);
|
44
|
+
static VALUE getGeneratorName(VALUE);
|
45
|
+
static VALUE getGeneratorConnection(VALUE);
|
46
|
+
static VALUE getLastGeneratorValue(VALUE);
|
47
|
+
static VALUE getNextGeneratorValue(VALUE, VALUE);
|
48
|
+
static VALUE dropGenerator(VALUE);
|
49
|
+
static VALUE doesGeneratorExist(VALUE, VALUE, VALUE);
|
50
|
+
static VALUE createGenerator(VALUE, VALUE, VALUE);
|
51
|
+
int checkForGenerator(const char *, isc_db_handle *);
|
52
|
+
int installGenerator(const char *, isc_db_handle *);
|
53
|
+
int deleteGenerator(const char *, isc_db_handle *);
|
54
|
+
XSQLDA *createStorage(void);
|
55
|
+
int32_t getGeneratorValue(const char *, int, isc_db_handle *);
|
56
|
+
|
57
|
+
/* Globals. */
|
58
|
+
VALUE cGenerator;
|
59
|
+
|
60
|
+
|
61
|
+
/**
|
62
|
+
* This function provides for the allocation of new Generator objects through
|
63
|
+
* the Ruby language.
|
64
|
+
*
|
65
|
+
* @param klass A reference to the Generator Class object.
|
66
|
+
*
|
67
|
+
* @return A reference to the newly allocated Generator object.
|
68
|
+
*
|
69
|
+
*/
|
70
|
+
static VALUE allocateGenerator(VALUE klass)
|
71
|
+
{
|
72
|
+
VALUE instance = Qnil;
|
73
|
+
GeneratorHandle *generator = ALLOC(GeneratorHandle);
|
74
|
+
|
75
|
+
if(generator != NULL)
|
76
|
+
{
|
77
|
+
generator->connection = NULL;
|
78
|
+
instance = Data_Wrap_Struct(klass, NULL, generatorFree,
|
79
|
+
generator);
|
80
|
+
}
|
81
|
+
else
|
82
|
+
{
|
83
|
+
rb_raise(rb_eNoMemError,
|
84
|
+
"Memory allocation failure allocating a generator.");
|
85
|
+
}
|
86
|
+
|
87
|
+
return(instance);
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/**
|
92
|
+
* This function provides the initialize method for the Generator class.
|
93
|
+
*
|
94
|
+
* @param self A reference to the object instance being initialized.
|
95
|
+
* @param name A reference to a string containing the name of the
|
96
|
+
* generator.
|
97
|
+
* @param connection A reference to the Connection object that will be used
|
98
|
+
* by the Generator.
|
99
|
+
*
|
100
|
+
* @return A reference to the newly initialized Generator object.
|
101
|
+
*
|
102
|
+
*/
|
103
|
+
static VALUE initializeGenerator(VALUE self,
|
104
|
+
VALUE name,
|
105
|
+
VALUE connection)
|
106
|
+
{
|
107
|
+
GeneratorHandle *generator = NULL;
|
108
|
+
ConnectionHandle *handle = NULL;
|
109
|
+
|
110
|
+
if(TYPE(name) != T_STRING)
|
111
|
+
{
|
112
|
+
rb_fireruby_raise(NULL, "Invalid generator name specified.");
|
113
|
+
}
|
114
|
+
|
115
|
+
if(TYPE(connection) != T_DATA &&
|
116
|
+
RDATA(connection)->dfree != (RUBY_DATA_FUNC)connectionFree)
|
117
|
+
{
|
118
|
+
rb_fireruby_raise(NULL, "Invalid connection specified for generator.");
|
119
|
+
}
|
120
|
+
|
121
|
+
rb_iv_set(self, "@name", name);
|
122
|
+
rb_iv_set(self, "@connection", connection);
|
123
|
+
|
124
|
+
Data_Get_Struct(connection, ConnectionHandle, handle);
|
125
|
+
Data_Get_Struct(self, GeneratorHandle, generator);
|
126
|
+
generator->connection = &handle->handle;
|
127
|
+
|
128
|
+
return(self);
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
/**
|
133
|
+
* This function provides the accessor for the name attribute of the Generator
|
134
|
+
* class.
|
135
|
+
*
|
136
|
+
* @param self A reference to the Generator object to fetch the name for.
|
137
|
+
*
|
138
|
+
* @return A reference to a String containing the Generator name.
|
139
|
+
*
|
140
|
+
*/
|
141
|
+
static VALUE getGeneratorName(VALUE self)
|
142
|
+
{
|
143
|
+
return(rb_iv_get(self, "@name"));
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
/**
|
148
|
+
* This function provides the accessor for the connection attribute for the
|
149
|
+
* Generator class.
|
150
|
+
*
|
151
|
+
* @param self A reference to the Generator object to fetch the connection
|
152
|
+
* for.
|
153
|
+
*
|
154
|
+
* @return A reference to the Connection object for the generator.
|
155
|
+
*
|
156
|
+
*/
|
157
|
+
static VALUE getGeneratorConnection(VALUE self)
|
158
|
+
{
|
159
|
+
return(rb_iv_get(self, "@connection"));
|
160
|
+
}
|
161
|
+
|
162
|
+
|
163
|
+
/**
|
164
|
+
* This function fetches the last value retrieved from a Generator.
|
165
|
+
*
|
166
|
+
* @param self A reference to the Generator to fetch the value for.
|
167
|
+
*
|
168
|
+
* @return A reference to the last value retrieved from the generator.
|
169
|
+
*
|
170
|
+
*/
|
171
|
+
static VALUE getLastGeneratorValue(VALUE self)
|
172
|
+
{
|
173
|
+
VALUE name = rb_iv_get(self, "@name");
|
174
|
+
GeneratorHandle *generator = NULL;
|
175
|
+
int32_t number = 0;
|
176
|
+
|
177
|
+
Data_Get_Struct(self, GeneratorHandle, generator);
|
178
|
+
|
179
|
+
number = getGeneratorValue(STR2CSTR(name), 0, generator->connection);
|
180
|
+
|
181
|
+
return(INT2NUM(number));
|
182
|
+
}
|
183
|
+
|
184
|
+
|
185
|
+
/**
|
186
|
+
* This function provides the next method for the Generator class.
|
187
|
+
*
|
188
|
+
* @param self A reference to the Generator object to fetch the next value
|
189
|
+
* for.
|
190
|
+
* @param step The amount of increment to be applied to the Generator.
|
191
|
+
*
|
192
|
+
* @return A reference to an integer containing the next generator value.
|
193
|
+
*
|
194
|
+
*/
|
195
|
+
static VALUE getNextGeneratorValue(VALUE self, VALUE step)
|
196
|
+
{
|
197
|
+
VALUE name = rb_iv_get(self, "@name");
|
198
|
+
GeneratorHandle *generator = NULL;
|
199
|
+
int32_t number = 0;
|
200
|
+
|
201
|
+
Data_Get_Struct(self, GeneratorHandle, generator);
|
202
|
+
|
203
|
+
/* Check the step type. */
|
204
|
+
if(TYPE(step) != T_FIXNUM)
|
205
|
+
{
|
206
|
+
rb_fireruby_raise(NULL, "Invalid generator step value.");
|
207
|
+
}
|
208
|
+
|
209
|
+
number = getGeneratorValue(STR2CSTR(name), FIX2INT(step),
|
210
|
+
generator->connection);
|
211
|
+
|
212
|
+
return(INT2NUM(number));
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
/**
|
217
|
+
* This function provides the drop method for the Generator class.
|
218
|
+
*
|
219
|
+
* @param self A reference to the Generator object to be dropped.
|
220
|
+
*
|
221
|
+
* @return A reference to the Generator object dropped.
|
222
|
+
*
|
223
|
+
*/
|
224
|
+
static VALUE dropGenerator(VALUE self)
|
225
|
+
{
|
226
|
+
GeneratorHandle *generator = NULL;
|
227
|
+
VALUE name;
|
228
|
+
|
229
|
+
Data_Get_Struct(self, GeneratorHandle, generator);
|
230
|
+
name = rb_iv_get(self, "@name");
|
231
|
+
|
232
|
+
/* Drop the generator. */
|
233
|
+
deleteGenerator(STR2CSTR(name), generator->connection);
|
234
|
+
|
235
|
+
return(self);
|
236
|
+
}
|
237
|
+
|
238
|
+
|
239
|
+
/**
|
240
|
+
* This method provides the exists? class method for the Generator class.
|
241
|
+
*
|
242
|
+
* @param klass This parameter is ignored.
|
243
|
+
* @param name A reference to a String containing the generator name to
|
244
|
+
* check for.
|
245
|
+
* @param connection A reference to the Connection object that the check will
|
246
|
+
* be made through.
|
247
|
+
*
|
248
|
+
* @return True if the generator already exists in the database, false
|
249
|
+
* otherwise.
|
250
|
+
*
|
251
|
+
*/
|
252
|
+
static VALUE doesGeneratorExist(VALUE klass, VALUE name, VALUE connection)
|
253
|
+
{
|
254
|
+
VALUE exists = Qfalse;
|
255
|
+
ConnectionHandle *handle = NULL;
|
256
|
+
|
257
|
+
if(TYPE(connection) != T_DATA ||
|
258
|
+
RDATA(connection)->dfree != (RUBY_DATA_FUNC)connectionFree)
|
259
|
+
{
|
260
|
+
rb_fireruby_raise(NULL, "Invalid connection specified.");
|
261
|
+
}
|
262
|
+
|
263
|
+
Data_Get_Struct(connection, ConnectionHandle, handle);
|
264
|
+
|
265
|
+
if(handle->handle == 0)
|
266
|
+
{
|
267
|
+
rb_fireruby_raise(NULL, "Connection is closed.");
|
268
|
+
}
|
269
|
+
|
270
|
+
if(checkForGenerator(STR2CSTR(name), &handle->handle))
|
271
|
+
{
|
272
|
+
exists = Qtrue;
|
273
|
+
}
|
274
|
+
|
275
|
+
return(exists);
|
276
|
+
}
|
277
|
+
|
278
|
+
|
279
|
+
/**
|
280
|
+
* This function attempts to create a new Generator given a name and database
|
281
|
+
* connection. The function provides the create class method for the Generator
|
282
|
+
* class.
|
283
|
+
*
|
284
|
+
* @param klass This parameter is ignored.
|
285
|
+
* @param name A reference to a String containing the name of the new
|
286
|
+
* generator.
|
287
|
+
* @param connection A reference to the Connection object to create the new
|
288
|
+
* generator through.
|
289
|
+
*
|
290
|
+
* @return A reference to a Generator object.
|
291
|
+
*
|
292
|
+
*/
|
293
|
+
static VALUE createGenerator(VALUE klass, VALUE name, VALUE connection)
|
294
|
+
{
|
295
|
+
VALUE result = Qnil;
|
296
|
+
ConnectionHandle *handle = NULL;
|
297
|
+
|
298
|
+
if(TYPE(name) != T_STRING)
|
299
|
+
{
|
300
|
+
rb_fireruby_raise(NULL, "Invalid generator name specified.");
|
301
|
+
}
|
302
|
+
|
303
|
+
if(TYPE(connection) != T_DATA &&
|
304
|
+
RDATA(connection)->dfree != (RUBY_DATA_FUNC)connectionFree)
|
305
|
+
{
|
306
|
+
rb_fireruby_raise(NULL,
|
307
|
+
"Invalid connection specified for generator creation.");
|
308
|
+
}
|
309
|
+
|
310
|
+
Data_Get_Struct(connection, ConnectionHandle, handle);
|
311
|
+
if(handle->handle != 0)
|
312
|
+
{
|
313
|
+
installGenerator(STR2CSTR(name), &handle->handle);
|
314
|
+
result = rb_generator_new(name, connection);
|
315
|
+
}
|
316
|
+
else
|
317
|
+
{
|
318
|
+
rb_fireruby_raise(NULL,
|
319
|
+
"Closed connection specified for generator creation.");
|
320
|
+
}
|
321
|
+
|
322
|
+
return(result);
|
323
|
+
}
|
324
|
+
|
325
|
+
|
326
|
+
/**
|
327
|
+
* This function executes a check for a named generator.
|
328
|
+
*
|
329
|
+
* @param name A pointer to the string containing the generator name
|
330
|
+
* to check for.
|
331
|
+
* @param connection A pointer to the connection to be used to perform the
|
332
|
+
* check.
|
333
|
+
*
|
334
|
+
* @return Returns 0 if the generator does not exist, 1 if the generator does
|
335
|
+
* exist or -1 if there was an error.
|
336
|
+
*
|
337
|
+
*/
|
338
|
+
int checkForGenerator(const char *name, isc_db_handle *connection)
|
339
|
+
{
|
340
|
+
int result = -1;
|
341
|
+
isc_stmt_handle statement = 0;
|
342
|
+
ISC_STATUS status[20];
|
343
|
+
|
344
|
+
if(isc_dsql_allocate_statement(status, connection, &statement) == 0)
|
345
|
+
{
|
346
|
+
isc_tr_handle transaction = 0;
|
347
|
+
|
348
|
+
if(isc_start_transaction(status, &transaction, 1, connection, 0,
|
349
|
+
NULL) == 0)
|
350
|
+
{
|
351
|
+
XSQLDA *da = (XSQLDA *)ALLOC_N(char, XSQLDA_LENGTH(1));
|
352
|
+
|
353
|
+
if(da != NULL)
|
354
|
+
{
|
355
|
+
char sql[100];
|
356
|
+
|
357
|
+
da->version = SQLDA_VERSION1;
|
358
|
+
da->sqln = 1;
|
359
|
+
sprintf(sql, "SELECT COUNT(*) FROM %sS WHERE %s_NAME = UPPER('%s')",
|
360
|
+
"RDB$GENERATOR", "RDB$GENERATOR", name);
|
361
|
+
if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql),
|
362
|
+
sql, 3, da) == 0)
|
363
|
+
{
|
364
|
+
/* Prepare the XSQLDA and provide it with data room. */
|
365
|
+
allocateOutXSQLDA(da->sqld, &statement, 3);
|
366
|
+
prepareDataArea(da);
|
367
|
+
if(isc_dsql_execute(status, &transaction, &statement,
|
368
|
+
3, da) == 0)
|
369
|
+
{
|
370
|
+
if(isc_dsql_fetch(status, &statement, 3, da) == 0)
|
371
|
+
{
|
372
|
+
int32_t count = *((long *)da->sqlvar->sqldata);
|
373
|
+
|
374
|
+
result = (count > 0 ? 1 : 0);
|
375
|
+
}
|
376
|
+
else
|
377
|
+
{
|
378
|
+
rb_fireruby_raise(status,
|
379
|
+
"Error checking for generator.");
|
380
|
+
}
|
381
|
+
}
|
382
|
+
else
|
383
|
+
{
|
384
|
+
rb_fireruby_raise(status,
|
385
|
+
"Error checking for generator.");
|
386
|
+
}
|
387
|
+
}
|
388
|
+
else
|
389
|
+
{
|
390
|
+
rb_fireruby_raise(status, "Error checking for generator.");
|
391
|
+
}
|
392
|
+
|
393
|
+
releaseDataArea(da);
|
394
|
+
}
|
395
|
+
else
|
396
|
+
{
|
397
|
+
rb_raise(rb_eNoMemError, "Memory allocation failure checking "\
|
398
|
+
"generator existence.");
|
399
|
+
}
|
400
|
+
|
401
|
+
if(transaction != 0)
|
402
|
+
{
|
403
|
+
isc_commit_transaction(status, &transaction);
|
404
|
+
}
|
405
|
+
}
|
406
|
+
else
|
407
|
+
{
|
408
|
+
rb_fireruby_raise(status, "Error checking for generator.");
|
409
|
+
}
|
410
|
+
|
411
|
+
isc_dsql_free_statement(status, &statement, DSQL_drop);
|
412
|
+
}
|
413
|
+
|
414
|
+
return(result);
|
415
|
+
}
|
416
|
+
|
417
|
+
|
418
|
+
/**
|
419
|
+
* This function creates a new generator within a database.
|
420
|
+
*
|
421
|
+
* @param name A pointer to the string containing the generator name
|
422
|
+
* to be created.
|
423
|
+
* @param connection A pointer to the connection to be used to create the new
|
424
|
+
* generator.
|
425
|
+
*
|
426
|
+
* @return Returns 0 if the generator was created or -1 if there was an error.
|
427
|
+
*
|
428
|
+
*/
|
429
|
+
int installGenerator(const char *name, isc_db_handle *connection)
|
430
|
+
{
|
431
|
+
int result = -1;
|
432
|
+
isc_stmt_handle statement = 0;
|
433
|
+
ISC_STATUS status[20];
|
434
|
+
|
435
|
+
if(isc_dsql_allocate_statement(status, connection, &statement) == 0)
|
436
|
+
{
|
437
|
+
isc_tr_handle transaction = 0;
|
438
|
+
|
439
|
+
if(isc_start_transaction(status, &transaction, 1, connection, 0,
|
440
|
+
NULL) == 0)
|
441
|
+
{
|
442
|
+
char sql[100];
|
443
|
+
|
444
|
+
sprintf(sql, "CREATE GENERATOR %s", name);
|
445
|
+
if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql),
|
446
|
+
sql, 3, NULL) == 0)
|
447
|
+
{
|
448
|
+
if(isc_dsql_execute(status, &transaction, &statement,
|
449
|
+
3, NULL) == 0)
|
450
|
+
{
|
451
|
+
result = 0;
|
452
|
+
}
|
453
|
+
else
|
454
|
+
{
|
455
|
+
rb_fireruby_raise(status, "Error creating generator.");
|
456
|
+
}
|
457
|
+
}
|
458
|
+
else
|
459
|
+
{
|
460
|
+
rb_fireruby_raise(status, "Error creating generator.");
|
461
|
+
}
|
462
|
+
|
463
|
+
if(transaction != 0)
|
464
|
+
{
|
465
|
+
isc_commit_transaction(status, &transaction);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
else
|
469
|
+
{
|
470
|
+
rb_fireruby_raise(status, "Error creating generator.");
|
471
|
+
}
|
472
|
+
|
473
|
+
isc_dsql_free_statement(status, &statement, DSQL_drop);
|
474
|
+
}
|
475
|
+
|
476
|
+
return(result);
|
477
|
+
}
|
478
|
+
|
479
|
+
|
480
|
+
/**
|
481
|
+
* This function drops an existing generator within a database.
|
482
|
+
*
|
483
|
+
* @param name A pointer to the string containing the generator name
|
484
|
+
* to be dropped.
|
485
|
+
* @param connection A pointer to the connection to be used to drop the
|
486
|
+
* generator.
|
487
|
+
*
|
488
|
+
* @return Returns 0 if the generator was dropped or -1 if there was an error.
|
489
|
+
*
|
490
|
+
*/
|
491
|
+
int deleteGenerator(const char *name, isc_db_handle *connection)
|
492
|
+
{
|
493
|
+
int result = -1;
|
494
|
+
isc_stmt_handle statement = 0;
|
495
|
+
ISC_STATUS status[20];
|
496
|
+
|
497
|
+
if(isc_dsql_allocate_statement(status, connection, &statement) == 0)
|
498
|
+
{
|
499
|
+
isc_tr_handle transaction = 0;
|
500
|
+
|
501
|
+
if(isc_start_transaction(status, &transaction, 1, connection, 0,
|
502
|
+
NULL) == 0)
|
503
|
+
{
|
504
|
+
char sql[100];
|
505
|
+
|
506
|
+
sprintf(sql, "DROP GENERATOR %s", name);
|
507
|
+
if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql),
|
508
|
+
sql, 3, NULL) == 0)
|
509
|
+
{
|
510
|
+
if(isc_dsql_execute(status, &transaction, &statement,
|
511
|
+
3, NULL) == 0)
|
512
|
+
{
|
513
|
+
result = 0;
|
514
|
+
}
|
515
|
+
else
|
516
|
+
{
|
517
|
+
rb_fireruby_raise(status, "Error dropping generator.");
|
518
|
+
}
|
519
|
+
}
|
520
|
+
else
|
521
|
+
{
|
522
|
+
rb_fireruby_raise(status, "Error dropping generator.");
|
523
|
+
}
|
524
|
+
|
525
|
+
if(transaction != 0)
|
526
|
+
{
|
527
|
+
isc_commit_transaction(status, &transaction);
|
528
|
+
}
|
529
|
+
}
|
530
|
+
else
|
531
|
+
{
|
532
|
+
rb_fireruby_raise(status, "Error dropping generator.");
|
533
|
+
}
|
534
|
+
|
535
|
+
isc_dsql_free_statement(status, &statement, DSQL_drop);
|
536
|
+
}
|
537
|
+
|
538
|
+
return(result);
|
539
|
+
}
|
540
|
+
|
541
|
+
|
542
|
+
/**
|
543
|
+
* This function prepares storage space for statements that will fetch values
|
544
|
+
* from a generator.
|
545
|
+
*
|
546
|
+
* @return A pointer to an allocated XSQLDA that is ready to receive values
|
547
|
+
* from a generator.
|
548
|
+
*
|
549
|
+
*/
|
550
|
+
XSQLDA *createStorage(void)
|
551
|
+
{
|
552
|
+
XSQLDA *da = (XSQLDA *)ALLOC_N(char, XSQLDA_LENGTH(1));
|
553
|
+
|
554
|
+
if(da != NULL)
|
555
|
+
{
|
556
|
+
XSQLVAR *var = da->sqlvar;
|
557
|
+
|
558
|
+
da->version = SQLDA_VERSION1;
|
559
|
+
da->sqln = 1;
|
560
|
+
da->sqld = 1;
|
561
|
+
var->sqltype = SQL_LONG;
|
562
|
+
var->sqlscale = 0;
|
563
|
+
var->sqllen = sizeof(long);
|
564
|
+
prepareDataArea(da);
|
565
|
+
}
|
566
|
+
else
|
567
|
+
{
|
568
|
+
rb_raise(rb_eNoMemError,
|
569
|
+
"Memory allocation failure allocating generator storage space.");
|
570
|
+
}
|
571
|
+
|
572
|
+
return(da);
|
573
|
+
}
|
574
|
+
|
575
|
+
|
576
|
+
/**
|
577
|
+
* This function executes a SQL statement to fetch a value from a named
|
578
|
+
* generator in the database.
|
579
|
+
*
|
580
|
+
* @param name The name of the generator to fetch the value from.
|
581
|
+
* @param step The step interval to be used in the call to the database
|
582
|
+
* generator.
|
583
|
+
* @param connection The connection to make the call through.
|
584
|
+
*
|
585
|
+
* @return A long integer containing the generator value.
|
586
|
+
*
|
587
|
+
*/
|
588
|
+
int32_t getGeneratorValue(const char *name, int step, isc_db_handle *connection)
|
589
|
+
{
|
590
|
+
int32_t result = 0;
|
591
|
+
ISC_STATUS status[20];
|
592
|
+
isc_tr_handle transaction = 0;
|
593
|
+
XSQLDA *da = createStorage();
|
594
|
+
|
595
|
+
if(isc_start_transaction(status, &transaction, 1, connection, 0, NULL) == 0)
|
596
|
+
{
|
597
|
+
char sql[100];
|
598
|
+
|
599
|
+
sprintf(sql, "SELECT GEN_ID(%s, %d) FROM RDB$DATABASE", name, step);
|
600
|
+
if(isc_dsql_exec_immed2(status, connection, &transaction, 0, sql,
|
601
|
+
3, NULL, da) == 0)
|
602
|
+
{
|
603
|
+
result = *((int32_t *)da->sqlvar->sqldata);
|
604
|
+
}
|
605
|
+
else
|
606
|
+
{
|
607
|
+
ISC_STATUS local[20];
|
608
|
+
|
609
|
+
isc_rollback_transaction(local, &transaction);
|
610
|
+
rb_fireruby_raise(status, "Error obtaining generator value.");
|
611
|
+
}
|
612
|
+
|
613
|
+
isc_commit_transaction(status, &transaction);
|
614
|
+
}
|
615
|
+
else
|
616
|
+
{
|
617
|
+
rb_fireruby_raise(status, "Error obtaining generator value.");
|
618
|
+
}
|
619
|
+
|
620
|
+
/* Clean up. */
|
621
|
+
if(da != NULL)
|
622
|
+
{
|
623
|
+
releaseDataArea(da);
|
624
|
+
}
|
625
|
+
|
626
|
+
return(result);
|
627
|
+
}
|
628
|
+
|
629
|
+
|
630
|
+
/**
|
631
|
+
* This function provides a means of programmatically creating a Generator
|
632
|
+
* object.
|
633
|
+
*
|
634
|
+
* @param name A reference to the new generator name.
|
635
|
+
* @param step A reference to the generator interval step value.
|
636
|
+
* @param connection A reference to a Connection object.
|
637
|
+
*
|
638
|
+
* @return A reference to the new Generator object.
|
639
|
+
*
|
640
|
+
*/
|
641
|
+
VALUE rb_generator_new(VALUE name, VALUE connection)
|
642
|
+
{
|
643
|
+
VALUE instance = allocateGenerator(cGenerator);
|
644
|
+
|
645
|
+
initializeGenerator(instance, name, connection);
|
646
|
+
|
647
|
+
return(instance);
|
648
|
+
}
|
649
|
+
|
650
|
+
|
651
|
+
/**
|
652
|
+
* This function integrates with the Ruby garbage collector to insure that all
|
653
|
+
* of the resources associated with a Generator object are release whenever a
|
654
|
+
* Generator object is collected.
|
655
|
+
*
|
656
|
+
* @param generator A pointer to the GeneratorHandle structure associated
|
657
|
+
* with the Generator object being collected.
|
658
|
+
*
|
659
|
+
*/
|
660
|
+
void generatorFree(void *generator)
|
661
|
+
{
|
662
|
+
if(generator != NULL)
|
663
|
+
{
|
664
|
+
free((GeneratorHandle *)generator);
|
665
|
+
}
|
666
|
+
}
|
667
|
+
|
668
|
+
|
669
|
+
/**
|
670
|
+
* This function initializes the Generator class within the Ruby environment.
|
671
|
+
* The class is established under the module specified to the function.
|
672
|
+
*
|
673
|
+
* @param module A reference to the module to create the class within.
|
674
|
+
*
|
675
|
+
*/
|
676
|
+
void Init_Generator(VALUE module)
|
677
|
+
{
|
678
|
+
cGenerator = rb_define_class_under(module, "Generator", rb_cObject);
|
679
|
+
rb_define_alloc_func(cGenerator, allocateGenerator);
|
680
|
+
rb_define_method(cGenerator, "initialize", initializeGenerator, 2);
|
681
|
+
rb_define_method(cGenerator, "initialize_copy", forbidObjectCopy, 1);
|
682
|
+
rb_define_method(cGenerator, "last", getLastGeneratorValue, 0);
|
683
|
+
rb_define_method(cGenerator, "next", getNextGeneratorValue, 1);
|
684
|
+
rb_define_method(cGenerator, "connection", getGeneratorConnection, 0);
|
685
|
+
rb_define_method(cGenerator, "name", getGeneratorName, 0);
|
686
|
+
rb_define_method(cGenerator, "drop", dropGenerator, 0);
|
687
|
+
rb_define_module_function(cGenerator, "exists?", doesGeneratorExist, 2);
|
688
|
+
rb_define_module_function(cGenerator, "create", createGenerator, 2);
|
689
|
+
}
|