rubyfb 0.5.9 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +36 -0
- data/Manifest +1 -0
- data/README +75 -175
- data/Rakefile +1 -1
- data/ext/Blob.c +1 -1
- data/ext/Connection.c +40 -126
- data/ext/FireRubyException.c +27 -41
- data/ext/Generator.c +61 -339
- data/ext/Generator.h +0 -5
- data/ext/ResultSet.c +201 -381
- data/ext/ResultSet.h +8 -9
- data/ext/Statement.c +495 -426
- data/ext/Statement.h +8 -11
- data/ext/Transaction.c +3 -2
- data/ext/TypeMap.c +44 -43
- data/ext/TypeMap.h +1 -1
- data/lib/active_record/connection_adapters/rubyfb_adapter.rb +370 -120
- data/lib/arel/visitors/rubyfb.rb +7 -3
- data/lib/arel/visitors/rubyfb_15compat.rb +8 -4
- data/lib/rubyfb_lib.so +0 -0
- data/lib/src.rb +76 -39
- data/rubyfb.gemspec +3 -3
- data/test/AddRemoveUserTest.rb +7 -0
- data/test/BackupRestoreTest.rb +1 -1
- data/test/BlobTest.rb +5 -5
- data/test/GeneratorTest.rb +8 -8
- data/test/KeyTest.rb +1 -2
- data/test/ResultSetTest.rb +14 -16
- data/test/RoleTest.rb +2 -2
- data/test/RowCountTest.rb +19 -19
- data/test/RowTest.rb +7 -8
- data/test/SQLTest.rb +7 -8
- data/test/StatementTest.rb +18 -24
- data/test/StoredProcedureTest.rb +80 -0
- data/test/TransactionTest.rb +1 -1
- data/test/TypeTest.rb +4 -5
- metadata +5 -5
data/ext/Statement.h
CHANGED
@@ -40,23 +40,20 @@
|
|
40
40
|
typedef struct {
|
41
41
|
isc_stmt_handle handle;
|
42
42
|
int type,
|
43
|
-
inputs
|
43
|
+
inputs,
|
44
|
+
outputs;
|
44
45
|
short dialect;
|
45
|
-
XSQLDA *
|
46
|
+
XSQLDA *output;
|
46
47
|
} StatementHandle;
|
47
48
|
|
48
49
|
/* Function prototypes. */
|
49
|
-
void prepare(isc_db_handle *, isc_tr_handle *, char *, isc_stmt_handle *,
|
50
|
+
/*void prepare(isc_db_handle *, isc_tr_handle *, char *, isc_stmt_handle *,
|
50
51
|
short, int *, int *, int *);
|
51
52
|
void execute(isc_tr_handle *, isc_stmt_handle *, short, XSQLDA *,
|
52
|
-
int, long *)
|
53
|
-
VALUE rb_statement_new(VALUE, VALUE
|
54
|
-
VALUE
|
55
|
-
VALUE rb_execute_statement_for(VALUE, VALUE);
|
56
|
-
VALUE rb_execute_sql(VALUE, VALUE, VALUE);
|
57
|
-
VALUE rb_get_statement_type(VALUE);
|
58
|
-
void rb_statement_close(VALUE);
|
59
|
-
void statementFree(void *);
|
53
|
+
int, long *);*/
|
54
|
+
VALUE rb_statement_new(VALUE, VALUE);
|
55
|
+
VALUE rb_execute_sql(VALUE, VALUE, VALUE, VALUE);
|
60
56
|
void Init_Statement(VALUE);
|
57
|
+
short isCursorStatement(StatementHandle*);
|
61
58
|
|
62
59
|
#endif /* FIRERUBY_STATEMENT_H */
|
data/ext/Transaction.c
CHANGED
@@ -133,7 +133,7 @@ static VALUE commitTransaction(VALUE self) {
|
|
133
133
|
TransactionHandle *transaction = NULL;
|
134
134
|
|
135
135
|
Data_Get_Struct(self, TransactionHandle, transaction);
|
136
|
-
|
136
|
+
|
137
137
|
/* Commit the transaction. */
|
138
138
|
if(transaction->handle != 0) {
|
139
139
|
ISC_STATUS status[ISC_STATUS_LENGTH];
|
@@ -306,7 +306,7 @@ static VALUE executeOnTransaction(VALUE self, VALUE sql) {
|
|
306
306
|
}
|
307
307
|
|
308
308
|
connection = rb_ary_entry(list, 0);
|
309
|
-
return rb_execute_sql(connection,
|
309
|
+
return rb_execute_sql(connection, sql, rb_ary_new(), self);
|
310
310
|
}
|
311
311
|
|
312
312
|
|
@@ -480,6 +480,7 @@ void startTransaction(TransactionHandle *transaction,
|
|
480
480
|
if(teb != NULL) {
|
481
481
|
free(teb);
|
482
482
|
}
|
483
|
+
|
483
484
|
}
|
484
485
|
|
485
486
|
|
data/ext/TypeMap.c
CHANGED
@@ -46,7 +46,7 @@ VALUE getConstant(const char *, VALUE);
|
|
46
46
|
VALUE toDateTime(VALUE);
|
47
47
|
VALUE rescueConvert(VALUE, VALUE);
|
48
48
|
void storeBlob(VALUE, XSQLVAR *, ConnectionHandle *, TransactionHandle *);
|
49
|
-
void populateBlobField(VALUE, XSQLVAR *, VALUE);
|
49
|
+
void populateBlobField(VALUE, XSQLVAR *, VALUE, VALUE);
|
50
50
|
void populateDoubleField(VALUE, XSQLVAR *);
|
51
51
|
void populateFloatField(VALUE, XSQLVAR *);
|
52
52
|
void populateInt64Field(VALUE, XSQLVAR *);
|
@@ -215,15 +215,15 @@ VALUE toValue(XSQLVAR *entry,
|
|
215
215
|
*/
|
216
216
|
VALUE toArray(VALUE results) {
|
217
217
|
VALUE array = rb_ary_new(),
|
218
|
-
transaction =
|
219
|
-
connection =
|
218
|
+
transaction = rb_funcall(results, rb_intern("transaction"), 0),
|
219
|
+
connection = rb_funcall(results, rb_intern("connection"), 0);
|
220
220
|
XSQLVAR *entry = NULL;
|
221
|
-
|
221
|
+
StatementHandle *hStatement = NULL;
|
222
222
|
int i;
|
223
223
|
|
224
|
-
Data_Get_Struct(results,
|
225
|
-
entry =
|
226
|
-
for(i = 0; i <
|
224
|
+
Data_Get_Struct(rb_funcall(results, rb_intern("statement"), 0), StatementHandle, hStatement);
|
225
|
+
entry = hStatement->output->sqlvar;
|
226
|
+
for(i = 0; i < hStatement->output->sqln; i++, entry++) {
|
227
227
|
VALUE value = toValue(entry, connection, transaction);
|
228
228
|
|
229
229
|
rb_ary_push(array, value);
|
@@ -247,7 +247,7 @@ VALUE toArray(VALUE results) {
|
|
247
247
|
* to get connection and transaction details.
|
248
248
|
*
|
249
249
|
*/
|
250
|
-
void setParameters(XSQLDA *parameters, VALUE array, VALUE
|
250
|
+
void setParameters(XSQLDA *parameters, VALUE array, VALUE transaction, VALUE connection) {
|
251
251
|
VALUE value;
|
252
252
|
int index,
|
253
253
|
size;
|
@@ -274,7 +274,7 @@ void setParameters(XSQLDA *parameters, VALUE array, VALUE source) {
|
|
274
274
|
if(value != Qnil) {
|
275
275
|
VALUE name = rb_funcall(value, rb_intern("class"), 0);
|
276
276
|
|
277
|
-
parameter->sqlind = 0;
|
277
|
+
*parameter->sqlind = 0;
|
278
278
|
name = rb_funcall(name, rb_intern("name"), 0);
|
279
279
|
switch(type) {
|
280
280
|
case SQL_ARRAY: /* Type: ARRAY */
|
@@ -282,7 +282,7 @@ void setParameters(XSQLDA *parameters, VALUE array, VALUE source) {
|
|
282
282
|
break;
|
283
283
|
|
284
284
|
case SQL_BLOB: /* Type: BLOB */
|
285
|
-
populateBlobField(value, parameter,
|
285
|
+
populateBlobField(value, parameter, transaction, connection);
|
286
286
|
break;
|
287
287
|
|
288
288
|
case SQL_DOUBLE: /* Type: DOUBLE PRECISION, DECIMAL, NUMERIC */
|
@@ -619,11 +619,15 @@ VALUE getClassInModule(const char *name, VALUE owner) {
|
|
619
619
|
*/
|
620
620
|
VALUE toDateTime(VALUE value) {
|
621
621
|
VALUE result,
|
622
|
-
klass = rb_funcall(value, rb_intern("class"), 0)
|
622
|
+
klass = rb_funcall(value, rb_intern("class"), 0),
|
623
|
+
date_time_class = getClass("DateTime");
|
623
624
|
|
624
|
-
if(klass == rb_cTime) {
|
625
|
+
if((klass == rb_cTime) || (klass == date_time_class)) {
|
625
626
|
VALUE data;
|
626
627
|
|
628
|
+
if (klass == date_time_class) {
|
629
|
+
value = rb_funcall(value, rb_intern("to_time"), 0);
|
630
|
+
}
|
627
631
|
result = rb_ary_new();
|
628
632
|
|
629
633
|
data = rb_funcall(value, rb_intern("year"), 0);
|
@@ -684,6 +688,10 @@ VALUE rescueConvert(VALUE arguments, VALUE error) {
|
|
684
688
|
return(rb_funcall(rb_eException, rb_intern("exception"), 1, &message));
|
685
689
|
}
|
686
690
|
|
691
|
+
long getLongProperty(VALUE obj, const char* name) {
|
692
|
+
VALUE number = rb_funcall(obj, rb_intern(name), 0);
|
693
|
+
return TYPE(number) == T_FIXNUM ? FIX2INT(number) : NUM2INT(number);
|
694
|
+
}
|
687
695
|
|
688
696
|
/**
|
689
697
|
* This function creates a new blob and returns the identifier for it.
|
@@ -707,10 +715,13 @@ void storeBlob(VALUE info,
|
|
707
715
|
isc_blob_handle handle = 0;
|
708
716
|
ISC_QUAD *blobId = (ISC_QUAD *)field->sqldata;
|
709
717
|
char *data = StringValuePtr(info);
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
718
|
+
long dataLength = getLongProperty(info, "length");
|
719
|
+
|
720
|
+
if(Qtrue == rb_funcall(info, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("bytesize")))) {
|
721
|
+
/* 1.9 strings */
|
722
|
+
dataLength = getLongProperty(info, "bytesize");
|
723
|
+
}
|
724
|
+
|
714
725
|
field->sqltype = SQL_BLOB;
|
715
726
|
|
716
727
|
if(isc_create_blob(status, &connection->handle, &transaction->handle,
|
@@ -718,11 +729,10 @@ void storeBlob(VALUE info,
|
|
718
729
|
long offset = 0;
|
719
730
|
unsigned short size = 0;
|
720
731
|
|
721
|
-
while(offset <
|
732
|
+
while(offset < dataLength) {
|
722
733
|
char *buffer = &data[offset];
|
723
734
|
|
724
|
-
size = (
|
725
|
-
size = (size/charSize)*charSize; // align
|
735
|
+
size = (dataLength - offset) > USHRT_MAX ? USHRT_MAX : dataLength - offset;
|
726
736
|
if(isc_put_segment(status, &handle, size, buffer) != 0) {
|
727
737
|
ISC_STATUS other[20];
|
728
738
|
|
@@ -751,21 +761,18 @@ void storeBlob(VALUE info,
|
|
751
761
|
* contains the connection and transaction details.
|
752
762
|
*
|
753
763
|
*/
|
754
|
-
void populateBlobField(VALUE value, XSQLVAR *field, VALUE
|
755
|
-
|
756
|
-
|
757
|
-
TransactionHandle *transaction = NULL;
|
764
|
+
void populateBlobField(VALUE value, XSQLVAR *field, VALUE transaction, VALUE connection) {
|
765
|
+
ConnectionHandle *hConnection = NULL;
|
766
|
+
TransactionHandle *hTransaction = NULL;
|
758
767
|
|
759
768
|
if(TYPE(value) != T_STRING) {
|
760
769
|
rb_fireruby_raise(NULL, "Error converting input parameter to blob.");
|
761
770
|
}
|
762
771
|
|
763
772
|
/* Fetch the connection and transaction details. */
|
764
|
-
|
765
|
-
Data_Get_Struct(
|
766
|
-
|
767
|
-
Data_Get_Struct(attribute, TransactionHandle, transaction);
|
768
|
-
storeBlob(value, field, connection, transaction);
|
773
|
+
Data_Get_Struct(connection, ConnectionHandle, hConnection);
|
774
|
+
Data_Get_Struct(transaction, TransactionHandle, hTransaction);
|
775
|
+
storeBlob(value, field, hConnection, hTransaction);
|
769
776
|
field->sqltype = SQL_BLOB;
|
770
777
|
}
|
771
778
|
|
@@ -858,26 +865,20 @@ void populateFloatField(VALUE value, XSQLVAR *field) {
|
|
858
865
|
*
|
859
866
|
*/
|
860
867
|
void populateInt64Field(VALUE value, XSQLVAR *field) {
|
861
|
-
VALUE actual =
|
868
|
+
VALUE actual = value;
|
862
869
|
long long store = 0;
|
863
870
|
|
864
|
-
if(
|
865
|
-
actual = value;
|
866
|
-
} else if(TYPE(value) == T_FLOAT) {
|
867
|
-
double number = NUM2DBL(value);
|
868
|
-
|
871
|
+
if(TYPE(value) == T_STRING) {
|
869
872
|
if(field->sqlscale != 0) {
|
870
|
-
|
871
|
-
|
873
|
+
actual = rb_funcall(value, rb_intern("to_f"), 0);
|
874
|
+
} else {
|
875
|
+
actual = rb_funcall(value, rb_intern("to_i"), 0);
|
872
876
|
}
|
873
|
-
} else if(TYPE(value) == T_STRING) {
|
874
|
-
actual = rb_funcall(value, rb_intern("to_i"), 0);
|
875
|
-
} else {
|
876
|
-
rb_fireruby_raise(NULL,
|
877
|
-
"Error converting input parameter to 64 bit integer.");
|
878
877
|
}
|
879
|
-
|
880
|
-
|
878
|
+
if(field->sqlscale != 0) {
|
879
|
+
actual = rb_funcall(actual, rb_intern("*"), 1, INT2NUM((long)pow(10, abs(field->sqlscale))));
|
880
|
+
}
|
881
|
+
store = NUM2LL(actual);
|
881
882
|
memcpy(field->sqldata, &store, field->sqllen);
|
882
883
|
field->sqltype = SQL_INT64;
|
883
884
|
}
|
data/ext/TypeMap.h
CHANGED
@@ -41,7 +41,7 @@
|
|
41
41
|
|
42
42
|
/* Function prototypes. */
|
43
43
|
VALUE toArray(VALUE);
|
44
|
-
void setParameters(XSQLDA *, VALUE, VALUE);
|
44
|
+
void setParameters(XSQLDA *, VALUE, VALUE, VALUE);
|
45
45
|
VALUE getModule(const char *);
|
46
46
|
VALUE getClass(const char *);
|
47
47
|
VALUE getClassInModule(const char *, VALUE);
|