rubyfb 0.6.4 → 0.6.7
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 +14 -0
- data/Manifest +6 -7
- data/Rakefile +1 -1
- data/ext/Common.c +74 -0
- data/ext/Common.h +2 -0
- data/ext/Connection.c +0 -1
- data/ext/FireRuby.c +1 -4
- data/ext/Generator.c +0 -1
- data/ext/Statement.c +186 -26
- data/ext/Statement.h +1 -0
- data/ext/Transaction.c +0 -1
- data/ext/TypeMap.c +60 -285
- data/ext/TypeMap.h +2 -10
- data/lib/active_record/connection_adapters/rubyfb_adapter.rb +17 -16
- data/lib/{Connection.rb → connection.rb} +0 -0
- data/lib/{ProcedureCall.rb → procedure_call.rb} +0 -0
- data/lib/result_set.rb +109 -0
- data/lib/row.rb +149 -0
- data/lib/rubyfb.rb +7 -3
- data/lib/rubyfb_lib.so +0 -0
- data/lib/{SQLType.rb → sql_type.rb} +0 -0
- data/lib/statement.rb +17 -0
- data/rubyfb.gemspec +4 -4
- data/test/ResultSetTest.rb +7 -4
- data/test/RowTest.rb +4 -1
- data/test/TypeTest.rb +1 -1
- metadata +14 -12
- data/ext/ResultSet.c +0 -648
- data/ext/ResultSet.h +0 -59
- data/ext/Row.c +0 -678
- data/ext/Row.h +0 -38
data/CHANGELOG
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
v0.6.7 ==
|
2
|
+
Add test to ensure row numbering scheme
|
3
|
+
Fix row numbering
|
4
|
+
Minor AR adapter improvement
|
5
|
+
|
6
|
+
v0.6.6 ==
|
7
|
+
Include Enumerable in Row And ResultSet
|
8
|
+
Update tests
|
9
|
+
|
10
|
+
v0.6.5 ==
|
11
|
+
Row: pure ruby implementation
|
12
|
+
ResultSet: pure ruby implementation
|
13
|
+
Use static vars fo rb_intern caches - this should fix os x linkage issues - https://github.com/georgiev/rubyfb/issues/11
|
14
|
+
|
1
15
|
v0.6.4 ==
|
2
16
|
Tyr to fix another Segmentation fault in Row class (GC integration issues)
|
3
17
|
|
data/Manifest
CHANGED
@@ -28,10 +28,6 @@ ext/RemoveUser.c
|
|
28
28
|
ext/RemoveUser.h
|
29
29
|
ext/Restore.c
|
30
30
|
ext/Restore.h
|
31
|
-
ext/ResultSet.c
|
32
|
-
ext/ResultSet.h
|
33
|
-
ext/Row.c
|
34
|
-
ext/Row.h
|
35
31
|
ext/ServiceManager.c
|
36
32
|
ext/ServiceManager.h
|
37
33
|
ext/Services.c
|
@@ -48,17 +44,20 @@ ext/rfbsleep.h
|
|
48
44
|
ext/rfbstr.c
|
49
45
|
ext/rfbstr.h
|
50
46
|
ext/uncrustify.cfg
|
51
|
-
lib/Connection.rb
|
52
|
-
lib/ProcedureCall.rb
|
53
|
-
lib/SQLType.rb
|
54
47
|
lib/active_record/connection_adapters/rubyfb_adapter.rb
|
55
48
|
lib/arel/visitors/fb15/rubyfb.rb
|
56
49
|
lib/arel/visitors/rubyfb.rb
|
50
|
+
lib/connection.rb
|
57
51
|
lib/mkdoc
|
52
|
+
lib/procedure_call.rb
|
53
|
+
lib/result_set.rb
|
54
|
+
lib/row.rb
|
58
55
|
lib/rubyfb.rb
|
59
56
|
lib/rubyfb_lib.so
|
60
57
|
lib/rubyfb_options.rb
|
58
|
+
lib/sql_type.rb
|
61
59
|
lib/src.rb
|
60
|
+
lib/statement.rb
|
62
61
|
mswin32fb/fbclient_mingw.def
|
63
62
|
mswin32fb/fbclient_mingw.lib
|
64
63
|
mswin32fb/fbclient_ms.lib
|
data/Rakefile
CHANGED
data/ext/Common.c
CHANGED
@@ -51,3 +51,77 @@ VALUE forbidObjectCopy(VALUE copy, VALUE original) {
|
|
51
51
|
|
52
52
|
return(Qnil);
|
53
53
|
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* This method fetches a Ruby constant definition. If the module specified to
|
57
|
+
* the function is nil then the top level is assume
|
58
|
+
*
|
59
|
+
* @param name The name of the constant to be retrieved.
|
60
|
+
* @param module A reference to the Ruby module that should contain the
|
61
|
+
* constant.
|
62
|
+
*
|
63
|
+
* @return A Ruby VALUE representing the constant.
|
64
|
+
*
|
65
|
+
*/
|
66
|
+
static VALUE getConstant(const char *name, VALUE module) {
|
67
|
+
VALUE owner = module,
|
68
|
+
constants,
|
69
|
+
exists,
|
70
|
+
entry = Qnil,
|
71
|
+
symbol = ID2SYM(rb_intern(name));
|
72
|
+
|
73
|
+
/* Check that we've got somewhere to look. */
|
74
|
+
if(owner == Qnil) {
|
75
|
+
owner = rb_cModule;
|
76
|
+
}
|
77
|
+
|
78
|
+
constants = rb_funcall(owner, rb_intern("constants"), 0),
|
79
|
+
exists = rb_funcall(constants, rb_intern("include?"), 1, symbol);
|
80
|
+
if(exists == Qfalse) {
|
81
|
+
/* 1.8 style lookup */
|
82
|
+
exists = rb_funcall(constants, rb_intern("include?"), 1, rb_str_new2(name));
|
83
|
+
}
|
84
|
+
if(exists != Qfalse) {
|
85
|
+
entry = rb_funcall(owner, rb_intern("const_get"), 1, symbol);
|
86
|
+
}
|
87
|
+
return(entry);
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/**
|
92
|
+
* This method fetches a Ruby class definition object based on a class name.
|
93
|
+
* The class is assumed to have been defined at the top level.
|
94
|
+
*
|
95
|
+
* @return A Ruby VALUE representing the requested class, or nil if the class
|
96
|
+
* could not be found.
|
97
|
+
*
|
98
|
+
*/
|
99
|
+
VALUE getClass(const char *name) {
|
100
|
+
return getClassInModule(name, Qnil);
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
/**
|
105
|
+
* This function fetches a class from a specified module.
|
106
|
+
*
|
107
|
+
* @param name The name of the class to be retrieved.
|
108
|
+
* @param owner The module to search for the class in.
|
109
|
+
*
|
110
|
+
* @return A Ruby VALUE representing the requested module, or nil if it could
|
111
|
+
* not be located.
|
112
|
+
*
|
113
|
+
*/
|
114
|
+
VALUE getClassInModule(const char *name, VALUE owner) {
|
115
|
+
VALUE klass = getConstant(name, owner);
|
116
|
+
|
117
|
+
if(klass != Qnil) {
|
118
|
+
VALUE type = rb_funcall(klass, rb_intern("class"), 0);
|
119
|
+
|
120
|
+
if(type != rb_cClass) {
|
121
|
+
klass = Qnil;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
return(klass);
|
126
|
+
}
|
127
|
+
|
data/ext/Common.h
CHANGED
data/ext/Connection.c
CHANGED
data/ext/FireRuby.c
CHANGED
@@ -34,12 +34,10 @@
|
|
34
34
|
#include "FireRubyException.h"
|
35
35
|
#include "Generator.h"
|
36
36
|
#include "RemoveUser.h"
|
37
|
-
#include "ResultSet.h"
|
38
37
|
#include "ServiceManager.h"
|
39
38
|
#include "Statement.h"
|
40
39
|
#include "Transaction.h"
|
41
40
|
#include "Restore.h"
|
42
|
-
#include "Row.h"
|
43
41
|
|
44
42
|
|
45
43
|
/**
|
@@ -202,12 +200,11 @@ void Init_rubyfb_lib(void) {
|
|
202
200
|
Init_Database(module);
|
203
201
|
Init_Connection(module);
|
204
202
|
Init_Transaction(module);
|
203
|
+
Init_TypeMap(module);
|
205
204
|
Init_Statement(module);
|
206
|
-
Init_ResultSet(module);
|
207
205
|
Init_Generator(module);
|
208
206
|
Init_FireRubyException(module);
|
209
207
|
Init_Blob(module);
|
210
|
-
Init_Row(module);
|
211
208
|
Init_ServiceManager(module);
|
212
209
|
Init_Backup(module);
|
213
210
|
Init_AddUser(module);
|
data/ext/Generator.c
CHANGED
data/ext/Statement.c
CHANGED
@@ -30,7 +30,6 @@
|
|
30
30
|
#include "Transaction.h"
|
31
31
|
#include "DataArea.h"
|
32
32
|
#include "TypeMap.h"
|
33
|
-
#include "ResultSet.h"
|
34
33
|
|
35
34
|
/* Function prototypes. */
|
36
35
|
static VALUE allocateStatement(VALUE);
|
@@ -47,20 +46,46 @@ static VALUE getStatementPrepared(VALUE);
|
|
47
46
|
static VALUE prepareStatement(int, VALUE*, VALUE);
|
48
47
|
static VALUE getStatementPlan(VALUE);
|
49
48
|
|
50
|
-
VALUE execAndManageTransaction(VALUE, VALUE, VALUE);
|
51
|
-
VALUE execAndManageStatement(VALUE, VALUE, VALUE);
|
52
|
-
VALUE rescueLocalTransaction(VALUE, VALUE);
|
53
|
-
VALUE execStatementFromArray(VALUE);
|
54
|
-
VALUE rescueStatement(VALUE, VALUE);
|
55
|
-
VALUE execInTransactionFromArray(VALUE);
|
56
|
-
VALUE execInTransaction(VALUE, VALUE, VALUE);
|
57
|
-
void prepareInTransaction(VALUE, VALUE);
|
58
|
-
VALUE prepareFromArray(VALUE);
|
59
|
-
void statementFree(void *);
|
60
|
-
StatementHandle* getPreparedHandle(VALUE self);
|
49
|
+
static VALUE execAndManageTransaction(VALUE, VALUE, VALUE);
|
50
|
+
static VALUE execAndManageStatement(VALUE, VALUE, VALUE);
|
51
|
+
static VALUE rescueLocalTransaction(VALUE, VALUE);
|
52
|
+
static VALUE execStatementFromArray(VALUE);
|
53
|
+
static VALUE rescueStatement(VALUE, VALUE);
|
54
|
+
static VALUE execInTransactionFromArray(VALUE);
|
55
|
+
static VALUE execInTransaction(VALUE, VALUE, VALUE);
|
56
|
+
static void prepareInTransaction(VALUE, VALUE);
|
57
|
+
static VALUE prepareFromArray(VALUE);
|
58
|
+
static void statementFree(void *);
|
59
|
+
static StatementHandle* getPreparedHandle(VALUE self);
|
61
60
|
|
62
61
|
/* Globals. */
|
63
|
-
VALUE cStatement;
|
62
|
+
static VALUE cStatement, cResultSet;
|
63
|
+
|
64
|
+
static ID
|
65
|
+
RB_INTERN_CREATE_COLUMN_METADATA,
|
66
|
+
RB_INTERN_AT_NAME,
|
67
|
+
RB_INTERN_AT_ALIAS,
|
68
|
+
RB_INTERN_AT_KEY,
|
69
|
+
RB_INTERN_AT_TYPE,
|
70
|
+
RB_INTERN_AT_SCALE,
|
71
|
+
RB_INTERN_AT_RELATION,
|
72
|
+
RB_INTERN_AT_METADATA,
|
73
|
+
RB_INTERN_AT_MANAGE_STATEMENT,
|
74
|
+
RB_INTERN_AT_MANAGE_TRANSACTION,
|
75
|
+
RB_INTERN_ACTIVE,
|
76
|
+
RB_INTERN_EACH,
|
77
|
+
RB_INTERN_COMMIT,
|
78
|
+
RB_INTERN_ROLLBACK,
|
79
|
+
RB_INTERN_SIZE,
|
80
|
+
RB_INTERN_CLOSE,
|
81
|
+
RB_INTERN_TO_S,
|
82
|
+
RB_INTERN_OPEN,
|
83
|
+
RB_INTERN_STRIP,
|
84
|
+
RB_INTERN_NEW;
|
85
|
+
|
86
|
+
static const ISC_STATUS FETCH_MORE = 0;
|
87
|
+
static const ISC_STATUS FETCH_COMPLETED = 100;
|
88
|
+
static const ISC_STATUS FETCH_ONE = 101;
|
64
89
|
|
65
90
|
/**
|
66
91
|
* This function prepares a Firebird SQL statement for execution.
|
@@ -176,6 +201,20 @@ long fb_query_affected(StatementHandle *statement) {
|
|
176
201
|
return (result);
|
177
202
|
}
|
178
203
|
|
204
|
+
static short isActiveResultSet(VALUE object) {
|
205
|
+
short result = 0;
|
206
|
+
if ((Qtrue == rb_obj_is_kind_of(object, cResultSet))) {
|
207
|
+
if(Qtrue == rb_funcall(object, RB_INTERN_ACTIVE, 0)) {
|
208
|
+
result = 1;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
return (result);
|
212
|
+
}
|
213
|
+
|
214
|
+
VALUE getStatementMetadata(VALUE self) {
|
215
|
+
return rb_ivar_get(self, RB_INTERN_AT_METADATA);
|
216
|
+
}
|
217
|
+
|
179
218
|
/**
|
180
219
|
* Prepare statement parsing arguments array
|
181
220
|
*
|
@@ -205,7 +244,7 @@ void prepareInTransaction(VALUE self, VALUE transaction) {
|
|
205
244
|
if(0 == hStatement->handle) {
|
206
245
|
ConnectionHandle *hConnection = NULL;
|
207
246
|
TransactionHandle *hTransaction = NULL;
|
208
|
-
VALUE sql = rb_iv_get(self, "@sql");
|
247
|
+
VALUE metadata, sql = rb_iv_get(self, "@sql");
|
209
248
|
Data_Get_Struct(getStatementConnection(self), ConnectionHandle, hConnection);
|
210
249
|
Data_Get_Struct(transaction, TransactionHandle, hTransaction);
|
211
250
|
|
@@ -214,12 +253,39 @@ void prepareInTransaction(VALUE self, VALUE transaction) {
|
|
214
253
|
StringValuePtr(sql), &hStatement->handle,
|
215
254
|
hStatement->dialect, &hStatement->type, &hStatement->inputs,
|
216
255
|
&hStatement->outputs);
|
256
|
+
|
257
|
+
metadata = rb_ary_new2(hStatement->outputs);
|
258
|
+
rb_ivar_set(self, RB_INTERN_AT_METADATA, metadata);
|
259
|
+
|
217
260
|
if(hStatement->outputs > 0) {
|
261
|
+
int index;
|
262
|
+
XSQLVAR *var;
|
263
|
+
VALUE column, name, alias, key_flag = getFireRubySetting("ALIAS_KEYS");
|
264
|
+
|
218
265
|
/* Allocate the XSQLDA */
|
219
266
|
hStatement->output = allocateOutXSQLDA(hStatement->outputs,
|
220
267
|
&hStatement->handle,
|
221
268
|
hStatement->dialect);
|
222
269
|
prepareDataArea(hStatement->output);
|
270
|
+
|
271
|
+
var = hStatement->output->sqlvar;
|
272
|
+
for(index = 0; index < hStatement->output->sqld; index++, var++) {
|
273
|
+
column = rb_funcall(self, RB_INTERN_CREATE_COLUMN_METADATA, 0);
|
274
|
+
rb_ary_store(metadata, index, column);
|
275
|
+
name = rb_str_new(var->sqlname, var->sqlname_length);
|
276
|
+
alias = rb_str_new(var->aliasname, var->aliasname_length);
|
277
|
+
rb_ivar_set(column, RB_INTERN_AT_NAME, name);
|
278
|
+
rb_ivar_set(column, RB_INTERN_AT_ALIAS, alias);
|
279
|
+
if(key_flag == Qtrue) {
|
280
|
+
rb_ivar_set(column, RB_INTERN_AT_KEY, alias);
|
281
|
+
} else {
|
282
|
+
rb_ivar_set(column, RB_INTERN_AT_KEY, name);
|
283
|
+
}
|
284
|
+
rb_ivar_set(column, RB_INTERN_AT_TYPE, getColumnType(var));
|
285
|
+
rb_ivar_set(column, RB_INTERN_AT_SCALE, INT2FIX(var->sqlscale));
|
286
|
+
rb_ivar_set(column, RB_INTERN_AT_RELATION, rb_str_new(var->relname, var->relname_length));
|
287
|
+
}
|
288
|
+
rb_obj_freeze(metadata);
|
223
289
|
}
|
224
290
|
}
|
225
291
|
}
|
@@ -268,12 +334,12 @@ VALUE initializeStatement(VALUE self, VALUE connection, VALUE sql) {
|
|
268
334
|
StatementHandle *hStatement = NULL;
|
269
335
|
short setting = 0;
|
270
336
|
|
271
|
-
sql = rb_funcall(sql,
|
337
|
+
sql = rb_funcall(sql, RB_INTERN_TO_S, 0);
|
272
338
|
|
273
339
|
/* Validate the inputs. */
|
274
340
|
if(TYPE(connection) == T_DATA &&
|
275
341
|
RDATA(connection)->dfree == (RUBY_DATA_FUNC)connectionFree) {
|
276
|
-
if(rb_funcall(connection,
|
342
|
+
if(rb_funcall(connection, RB_INTERN_OPEN, 0) == Qfalse) {
|
277
343
|
rb_fireruby_raise(NULL, "Closed connection specified for statement.");
|
278
344
|
}
|
279
345
|
} else {
|
@@ -389,9 +455,9 @@ VALUE execAndManageTransaction(VALUE self, VALUE parameters, VALUE transaction)
|
|
389
455
|
|
390
456
|
result = rb_rescue(execInTransactionFromArray, args, rescueLocalTransaction, transaction);
|
391
457
|
if(isActiveResultSet(result)) {
|
392
|
-
|
458
|
+
rb_ivar_set(result, RB_INTERN_AT_MANAGE_TRANSACTION, Qtrue);
|
393
459
|
} else {
|
394
|
-
rb_funcall(transaction,
|
460
|
+
rb_funcall(transaction, RB_INTERN_COMMIT, 0);
|
395
461
|
}
|
396
462
|
} else {
|
397
463
|
result = execInTransaction(self, transaction, parameters);
|
@@ -422,7 +488,7 @@ VALUE execAndManageStatement(VALUE self, VALUE parameters, VALUE transaction) {
|
|
422
488
|
rb_ary_push(args, transaction);
|
423
489
|
result = rb_rescue(execStatementFromArray, args, rescueStatement, self);
|
424
490
|
if(isActiveResultSet(result)) {
|
425
|
-
|
491
|
+
rb_ivar_set(result, RB_INTERN_AT_MANAGE_STATEMENT, Qtrue);
|
426
492
|
} else {
|
427
493
|
closeStatement(self);
|
428
494
|
}
|
@@ -440,7 +506,7 @@ VALUE execAndManageStatement(VALUE self, VALUE parameters, VALUE transaction) {
|
|
440
506
|
*
|
441
507
|
*/
|
442
508
|
VALUE rescueLocalTransaction(VALUE transaction, VALUE error) {
|
443
|
-
rb_funcall(transaction,
|
509
|
+
rb_funcall(transaction, RB_INTERN_ROLLBACK, 0);
|
444
510
|
rb_exc_raise(error);
|
445
511
|
return(Qnil);
|
446
512
|
}
|
@@ -456,7 +522,7 @@ VALUE rescueLocalTransaction(VALUE transaction, VALUE error) {
|
|
456
522
|
*
|
457
523
|
*/
|
458
524
|
VALUE rescueStatement(VALUE statement, VALUE error) {
|
459
|
-
rb_funcall(statement,
|
525
|
+
rb_funcall(statement, RB_INTERN_CLOSE, 0);
|
460
526
|
rb_exc_raise(error);
|
461
527
|
return(Qnil);
|
462
528
|
}
|
@@ -494,6 +560,10 @@ short isCursorStatement(StatementHandle *hStatement) {
|
|
494
560
|
}
|
495
561
|
}
|
496
562
|
|
563
|
+
static VALUE resultSetEach(VALUE resultSet) {
|
564
|
+
return rb_funcall(resultSet, RB_INTERN_EACH, 0);
|
565
|
+
}
|
566
|
+
|
497
567
|
/**
|
498
568
|
* Execute a statement within a transaction context
|
499
569
|
*
|
@@ -526,7 +596,7 @@ VALUE execInTransaction(VALUE self, VALUE transaction, VALUE parameters) {
|
|
526
596
|
"Empty parameter list specified for statement.");
|
527
597
|
}
|
528
598
|
|
529
|
-
value = rb_funcall(parameters,
|
599
|
+
value = rb_funcall(parameters, RB_INTERN_SIZE, 0);
|
530
600
|
size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
|
531
601
|
if(size < hStatement->inputs) {
|
532
602
|
rb_fireruby_raise(NULL,
|
@@ -554,9 +624,9 @@ VALUE execInTransaction(VALUE self, VALUE transaction, VALUE parameters) {
|
|
554
624
|
rb_fireruby_raise(status, "Error executing SQL statement.");
|
555
625
|
}
|
556
626
|
if (hStatement->output) {
|
557
|
-
result =
|
627
|
+
result = rb_funcall(cResultSet, RB_INTERN_NEW, 2, self, transaction);
|
558
628
|
if(rb_block_given_p()) {
|
559
|
-
result =
|
629
|
+
result = rb_iterate(resultSetEach, result, rb_yield, 0);
|
560
630
|
}
|
561
631
|
} else {
|
562
632
|
result = INT2NUM(fb_query_affected(hStatement));
|
@@ -717,7 +787,7 @@ VALUE getStatementPlan(VALUE self) {
|
|
717
787
|
case isc_info_sql_get_plan:
|
718
788
|
dataLength = isc_vax_integer(&buffer[1], 2);
|
719
789
|
result = rb_str_new(&buffer[3], dataLength);
|
720
|
-
rb_funcall(result,
|
790
|
+
rb_funcall(result, RB_INTERN_STRIP, 0);
|
721
791
|
default:
|
722
792
|
retry = 0;
|
723
793
|
}
|
@@ -798,7 +868,7 @@ StatementHandle* getPreparedHandle(VALUE self) {
|
|
798
868
|
rb_ary_push(args, transaction);
|
799
869
|
|
800
870
|
rb_rescue(prepareFromArray, args, rescueLocalTransaction, transaction);
|
801
|
-
rb_funcall(transaction,
|
871
|
+
rb_funcall(transaction, RB_INTERN_COMMIT, 0);
|
802
872
|
}
|
803
873
|
return (hStatement);
|
804
874
|
}
|
@@ -818,6 +888,64 @@ void statementFree(void *handle) {
|
|
818
888
|
}
|
819
889
|
}
|
820
890
|
|
891
|
+
static VALUE fetch(VALUE self) {
|
892
|
+
StatementHandle *hStatement;
|
893
|
+
ISC_STATUS status[ISC_STATUS_LENGTH],
|
894
|
+
fetch_result;
|
895
|
+
|
896
|
+
Data_Get_Struct(self, StatementHandle, hStatement);
|
897
|
+
if (hStatement->outputs == 0) {
|
898
|
+
return Qnil;
|
899
|
+
}
|
900
|
+
|
901
|
+
if (isCursorStatement(hStatement)) {
|
902
|
+
fetch_result = isc_dsql_fetch(status, &hStatement->handle, hStatement->dialect,
|
903
|
+
hStatement->output);
|
904
|
+
if(fetch_result != FETCH_MORE && fetch_result != FETCH_COMPLETED) {
|
905
|
+
rb_fireruby_raise(status, "Error fetching query row.");
|
906
|
+
}
|
907
|
+
} else {
|
908
|
+
fetch_result = FETCH_ONE;
|
909
|
+
}
|
910
|
+
|
911
|
+
return INT2FIX(fetch_result);
|
912
|
+
}
|
913
|
+
|
914
|
+
static VALUE closeCursor(VALUE self) {
|
915
|
+
StatementHandle *hStatement;
|
916
|
+
ISC_STATUS status[ISC_STATUS_LENGTH],
|
917
|
+
close_result;
|
918
|
+
|
919
|
+
Data_Get_Struct(self, StatementHandle, hStatement);
|
920
|
+
if (hStatement->outputs == 0) {
|
921
|
+
rb_fireruby_raise(status, "Not a cursor statement.");
|
922
|
+
}
|
923
|
+
if(close_result = isc_dsql_free_statement(status, &hStatement->handle, DSQL_close)) {
|
924
|
+
rb_fireruby_raise(status, "Error closing cursor.");
|
925
|
+
}
|
926
|
+
return INT2FIX(close_result);
|
927
|
+
}
|
928
|
+
|
929
|
+
static VALUE currentRow(VALUE self, VALUE transaction) {
|
930
|
+
int i;
|
931
|
+
XSQLVAR *entry;
|
932
|
+
StatementHandle *hStatement;
|
933
|
+
VALUE array, connection;
|
934
|
+
|
935
|
+
Data_Get_Struct(self, StatementHandle, hStatement);
|
936
|
+
if (hStatement->outputs == 0) {
|
937
|
+
rb_fireruby_raise(NULL, "Statement has no output.");
|
938
|
+
}
|
939
|
+
|
940
|
+
connection = getStatementConnection(self);
|
941
|
+
array = rb_ary_new2(hStatement->output->sqln);
|
942
|
+
entry = hStatement->output->sqlvar;
|
943
|
+
for(i = 0; i < hStatement->output->sqln; i++, entry++) {
|
944
|
+
rb_ary_store(array, i, toValue(entry, connection, transaction));
|
945
|
+
}
|
946
|
+
return(array);
|
947
|
+
}
|
948
|
+
|
821
949
|
/**
|
822
950
|
* This function initializes the Statement class within the Ruby environment.
|
823
951
|
* The class is established under the module specified to the function.
|
@@ -826,7 +954,30 @@ void statementFree(void *handle) {
|
|
826
954
|
*
|
827
955
|
*/
|
828
956
|
void Init_Statement(VALUE module) {
|
957
|
+
RB_INTERN_CREATE_COLUMN_METADATA = rb_intern("create_column_metadata");
|
958
|
+
RB_INTERN_AT_NAME = rb_intern("@name");
|
959
|
+
RB_INTERN_AT_ALIAS = rb_intern("@alias");
|
960
|
+
RB_INTERN_AT_KEY = rb_intern("@key");
|
961
|
+
RB_INTERN_AT_TYPE = rb_intern("@type");
|
962
|
+
RB_INTERN_AT_SCALE = rb_intern("@scale");
|
963
|
+
RB_INTERN_AT_RELATION = rb_intern("@relation");
|
964
|
+
RB_INTERN_AT_METADATA = rb_intern("@metadata");
|
965
|
+
RB_INTERN_AT_MANAGE_STATEMENT = rb_intern("@manage_statement");
|
966
|
+
RB_INTERN_AT_MANAGE_TRANSACTION = rb_intern("@manage_transaction");
|
967
|
+
RB_INTERN_ACTIVE = rb_intern("active?");
|
968
|
+
RB_INTERN_EACH = rb_intern("each");
|
969
|
+
RB_INTERN_COMMIT = rb_intern("commit");
|
970
|
+
RB_INTERN_ROLLBACK = rb_intern("rollback");
|
971
|
+
RB_INTERN_SIZE = rb_intern("size");
|
972
|
+
RB_INTERN_CLOSE = rb_intern("close");
|
973
|
+
RB_INTERN_NEW = rb_intern("new");
|
974
|
+
RB_INTERN_TO_S = rb_intern("to_s");
|
975
|
+
RB_INTERN_OPEN = rb_intern("open?");
|
976
|
+
RB_INTERN_STRIP = rb_intern("strip!");
|
977
|
+
|
978
|
+
cResultSet = getClassInModule("ResultSet", module);
|
829
979
|
cStatement = rb_define_class_under(module, "Statement", rb_cObject);
|
980
|
+
|
830
981
|
rb_define_alloc_func(cStatement, allocateStatement);
|
831
982
|
rb_define_method(cStatement, "initialize", initializeStatement, 2);
|
832
983
|
rb_define_method(cStatement, "initialize_copy", forbidObjectCopy, 1);
|
@@ -841,6 +992,9 @@ void Init_Statement(VALUE module) {
|
|
841
992
|
rb_define_method(cStatement, "prepare", prepareStatement, -1);
|
842
993
|
rb_define_method(cStatement, "prepared?", getStatementPrepared, 0);
|
843
994
|
rb_define_method(cStatement, "plan", getStatementPlan, 0);
|
995
|
+
rb_define_method(cStatement, "fetch", fetch, 0);
|
996
|
+
rb_define_method(cStatement, "close_cursor", closeCursor, 0);
|
997
|
+
rb_define_method(cStatement, "current_row", currentRow, 1);
|
844
998
|
|
845
999
|
rb_define_const(cStatement, "SELECT_STATEMENT",
|
846
1000
|
INT2FIX(isc_info_sql_stmt_select));
|
@@ -870,4 +1024,10 @@ void Init_Statement(VALUE module) {
|
|
870
1024
|
INT2FIX(isc_info_sql_stmt_set_generator));
|
871
1025
|
rb_define_const(cStatement, "SAVE_POINT_STATEMENT",
|
872
1026
|
INT2FIX(isc_info_sql_stmt_savepoint));
|
1027
|
+
rb_define_const(cStatement, "FETCH_MORE",
|
1028
|
+
INT2FIX(FETCH_MORE));
|
1029
|
+
rb_define_const(cStatement, "FETCH_COMPLETED",
|
1030
|
+
INT2FIX(FETCH_COMPLETED));
|
1031
|
+
rb_define_const(cStatement, "FETCH_ONE",
|
1032
|
+
INT2FIX(FETCH_ONE));
|
873
1033
|
}
|