rubyfb 0.6.4 → 0.6.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|