fb 0.9.3 → 0.10.0
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.
- checksums.yaml +4 -4
- data/extconf.rb +2 -1
- data/fb.c +193 -63
- data/test/ConnectionTestCases.rb +41 -53
- data/test/CursorTestCases.rb +14 -62
- data/test/DataTypesTestCases.rb +22 -6
- data/test/DatabaseTestCases.rb +11 -11
- data/test/FbTestCases.rb +10 -3
- data/test/FbTestSuite.rb +1 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1415cff2f9f2c6be0873c14498b0371608c71e43656539aa671b1ba980771748
|
4
|
+
data.tar.gz: f556b1a03eb33b21b12fe8ab28ffd677d6738c5848ff1d2da1aed3a3ed0df684
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83d5395e6951329567df2da7b4b98e87cc933c40a1b6afa53385da86a3bd632dd4be082b4e04190c3ad25a36284afc83183f4ecd8c13cf620dbeaca8265f5d8b
|
7
|
+
data.tar.gz: 79f5db3854e727db141e6aee96284703bbfbc181ae18de57f7ef45f780c09ab329e19f01aa337414e2532fca6d6bf965cc19b4702105edd744b31f4d2de5759c
|
data/extconf.rb
CHANGED
@@ -74,7 +74,8 @@ case RUBY_PLATFORM
|
|
74
74
|
# $LDFLAGS.gsub!(/-arch (\w+)/) { |m| $1 == hosttype ? m : '' }
|
75
75
|
# CONFIG['LDSHARED'].gsub!(/-arch (\w+)/) { |m| $1 == hosttype ? m : '' }
|
76
76
|
$CPPFLAGS += " -I/Library/Frameworks/Firebird.framework/Headers"
|
77
|
-
$LDFLAGS += " -framework Firebird"
|
77
|
+
# $LDFLAGS += " -framework Firebird"
|
78
|
+
$LDFLAGS += " -L/Library/Frameworks/Firebird.framework/Resources/lib -Wl,-rpath,/Library/Frameworks/Firebird.framework/Resources/lib"
|
78
79
|
when /linux/
|
79
80
|
$CFLAGS = $CFLAGS + " -DOS_UNIX"
|
80
81
|
end
|
data/fb.c
CHANGED
@@ -430,6 +430,11 @@ static VALUE fb_sql_type_from_code(int code, int subtype)
|
|
430
430
|
case 2: sql_type = "DECIMAL"; break;
|
431
431
|
}
|
432
432
|
break;
|
433
|
+
#if (FB_API_VER >= 40)
|
434
|
+
case SQL_INT128:
|
435
|
+
sql_type = "INT128";
|
436
|
+
break;
|
437
|
+
#endif
|
433
438
|
default:
|
434
439
|
printf("Unknown: %d, %d\n", code, subtype);
|
435
440
|
sql_type = "UNKNOWN";
|
@@ -497,8 +502,43 @@ static VALUE cursor_drop _((VALUE));
|
|
497
502
|
static VALUE cursor_execute _((int, VALUE*, VALUE));
|
498
503
|
static VALUE cursor_fetchall _((int, VALUE*, VALUE));
|
499
504
|
|
500
|
-
static void fb_cursor_mark();
|
501
|
-
static void fb_cursor_free();
|
505
|
+
static void fb_cursor_mark(struct FbCursor *fb_cursor);
|
506
|
+
static void fb_cursor_free(struct FbCursor *fb_cursor);
|
507
|
+
static void fb_connection_mark(struct FbConnection *fb_connection);
|
508
|
+
static void fb_connection_free(struct FbConnection *fb_connection);
|
509
|
+
|
510
|
+
/* ruby data types */
|
511
|
+
|
512
|
+
static const rb_data_type_t fbdatabase_data_type = {
|
513
|
+
"FBDB",
|
514
|
+
{
|
515
|
+
NULL,
|
516
|
+
NULL,
|
517
|
+
NULL,
|
518
|
+
NULL,
|
519
|
+
},
|
520
|
+
0, 0, 0
|
521
|
+
};
|
522
|
+
|
523
|
+
static const rb_data_type_t fbconnection_data_type = {
|
524
|
+
"fbdb/connection",
|
525
|
+
{
|
526
|
+
(void (*)(void *))fb_connection_mark,
|
527
|
+
(void (*)(void *))fb_connection_free,
|
528
|
+
NULL,
|
529
|
+
},
|
530
|
+
0, 0, 0
|
531
|
+
};
|
532
|
+
|
533
|
+
static const rb_data_type_t fbcursor_data_type = {
|
534
|
+
"fbdb/cursor",
|
535
|
+
{
|
536
|
+
(void (*)(void *))fb_cursor_mark,
|
537
|
+
(void (*)(void *))fb_cursor_free,
|
538
|
+
NULL,
|
539
|
+
},
|
540
|
+
0, 0, 0
|
541
|
+
};
|
502
542
|
|
503
543
|
/* connection utilities */
|
504
544
|
static void fb_connection_check(struct FbConnection *fb_connection)
|
@@ -970,7 +1010,7 @@ static VALUE connection_transaction(int argc, VALUE *argv, VALUE self)
|
|
970
1010
|
VALUE opt = Qnil;
|
971
1011
|
|
972
1012
|
rb_scan_args(argc, argv, "01", &opt);
|
973
|
-
|
1013
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
974
1014
|
|
975
1015
|
fb_connection_transaction_start(fb_connection, opt);
|
976
1016
|
|
@@ -997,7 +1037,7 @@ static VALUE connection_transaction(int argc, VALUE *argv, VALUE self)
|
|
997
1037
|
static VALUE connection_transaction_started(VALUE self)
|
998
1038
|
{
|
999
1039
|
struct FbConnection *fb_connection;
|
1000
|
-
|
1040
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1001
1041
|
|
1002
1042
|
return fb_connection->transact ? Qtrue : Qfalse;
|
1003
1043
|
}
|
@@ -1010,7 +1050,7 @@ static VALUE connection_transaction_started(VALUE self)
|
|
1010
1050
|
static VALUE connection_commit(VALUE self)
|
1011
1051
|
{
|
1012
1052
|
struct FbConnection *fb_connection;
|
1013
|
-
|
1053
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1014
1054
|
|
1015
1055
|
fb_connection_commit(fb_connection);
|
1016
1056
|
return Qnil;
|
@@ -1024,7 +1064,7 @@ static VALUE connection_commit(VALUE self)
|
|
1024
1064
|
static VALUE connection_rollback(VALUE self)
|
1025
1065
|
{
|
1026
1066
|
struct FbConnection *fb_connection;
|
1027
|
-
|
1067
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1028
1068
|
|
1029
1069
|
fb_connection_rollback(fb_connection);
|
1030
1070
|
return Qnil;
|
@@ -1041,7 +1081,7 @@ static VALUE connection_is_open(VALUE self)
|
|
1041
1081
|
{
|
1042
1082
|
struct FbConnection *fb_connection;
|
1043
1083
|
|
1044
|
-
|
1084
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1045
1085
|
return (fb_connection->db == 0) ? Qfalse : Qtrue;
|
1046
1086
|
}
|
1047
1087
|
|
@@ -1071,10 +1111,10 @@ static VALUE connection_cursor(VALUE self)
|
|
1071
1111
|
struct FbConnection *fb_connection;
|
1072
1112
|
struct FbCursor *fb_cursor;
|
1073
1113
|
|
1074
|
-
|
1114
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1075
1115
|
fb_connection_check(fb_connection);
|
1076
1116
|
|
1077
|
-
c =
|
1117
|
+
c = TypedData_Make_Struct(rb_cFbCursor, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
1078
1118
|
fb_cursor->connection = self;
|
1079
1119
|
fb_cursor->fields_ary = Qnil;
|
1080
1120
|
fb_cursor->fields_hash = Qnil;
|
@@ -1181,7 +1221,7 @@ static VALUE connection_close(VALUE self)
|
|
1181
1221
|
{
|
1182
1222
|
struct FbConnection *fb_connection;
|
1183
1223
|
|
1184
|
-
|
1224
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1185
1225
|
|
1186
1226
|
if (fb_connection->dropped) return Qnil;
|
1187
1227
|
|
@@ -1201,7 +1241,7 @@ static VALUE connection_drop(VALUE self)
|
|
1201
1241
|
{
|
1202
1242
|
struct FbConnection *fb_connection;
|
1203
1243
|
|
1204
|
-
|
1244
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1205
1245
|
fb_connection->dropped = 1;
|
1206
1246
|
fb_connection_disconnect(fb_connection);
|
1207
1247
|
fb_connection_drop_cursors(fb_connection);
|
@@ -1218,7 +1258,7 @@ static VALUE connection_dialect(VALUE self)
|
|
1218
1258
|
{
|
1219
1259
|
struct FbConnection *fb_connection;
|
1220
1260
|
|
1221
|
-
|
1261
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1222
1262
|
fb_connection_check(fb_connection);
|
1223
1263
|
|
1224
1264
|
return INT2FIX(fb_connection->dialect);
|
@@ -1233,7 +1273,7 @@ static VALUE connection_db_dialect(VALUE self)
|
|
1233
1273
|
{
|
1234
1274
|
struct FbConnection *fb_connection;
|
1235
1275
|
|
1236
|
-
|
1276
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1237
1277
|
fb_connection_check(fb_connection);
|
1238
1278
|
|
1239
1279
|
return INT2FIX(fb_connection->db_dialect);
|
@@ -1292,14 +1332,72 @@ static void fb_cursor_free(struct FbCursor *fb_cursor)
|
|
1292
1332
|
|
1293
1333
|
static VALUE sql_decimal_to_bigdecimal(long long sql_data, int scale)
|
1294
1334
|
{
|
1295
|
-
|
1296
|
-
|
1297
|
-
unsigned long
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1335
|
+
char bigdecimal_buffer[128]; /* Increased buffer size */
|
1336
|
+
int is_negative = 0;
|
1337
|
+
unsigned long long abs_data;
|
1338
|
+
int len, decimal_places, dot_pos;
|
1339
|
+
|
1340
|
+
/* Handle negative numbers */
|
1341
|
+
if (sql_data < 0) {
|
1342
|
+
is_negative = 1;
|
1343
|
+
/* Use unsigned arithmetic to avoid overflow with minimum integer value */
|
1344
|
+
abs_data = (unsigned long long)(-sql_data);
|
1345
|
+
} else {
|
1346
|
+
abs_data = (unsigned long long)sql_data;
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
/* Convert to string */
|
1350
|
+
int wrote = snprintf(bigdecimal_buffer, sizeof(bigdecimal_buffer), "%llu", abs_data);
|
1351
|
+
if (wrote < 0 || wrote >= (int)sizeof(bigdecimal_buffer)) {
|
1352
|
+
rb_raise(rb_eRuntimeError, "Buffer overflow in decimal conversion");
|
1353
|
+
}
|
1354
|
+
len = wrote;
|
1355
|
+
|
1356
|
+
/* Add decimal point if scale != 0 */
|
1357
|
+
if (scale != 0) {
|
1358
|
+
decimal_places = (scale < 0) ? -scale : scale;
|
1359
|
+
dot_pos = len - decimal_places;
|
1360
|
+
|
1361
|
+
/* If we need leading zeros before the decimal point */
|
1362
|
+
if (dot_pos <= 0) {
|
1363
|
+
/* Need to add leading zeros to ensure at least one digit before decimal point */
|
1364
|
+
int leading_zeros = 1 - dot_pos;
|
1365
|
+
|
1366
|
+
/* Check buffer bounds */
|
1367
|
+
if (len + leading_zeros + 1 >= (int)sizeof(bigdecimal_buffer)) {
|
1368
|
+
rb_raise(rb_eRuntimeError, "Buffer overflow in decimal conversion");
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
/* Shift the string to make room for leading zeros */
|
1372
|
+
memmove(bigdecimal_buffer + leading_zeros, bigdecimal_buffer, len + 1);
|
1373
|
+
|
1374
|
+
/* Add leading zeros */
|
1375
|
+
memset(bigdecimal_buffer, '0', leading_zeros);
|
1376
|
+
|
1377
|
+
len += leading_zeros;
|
1378
|
+
dot_pos = len - decimal_places;
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
/* Check buffer bounds before inserting decimal point */
|
1382
|
+
if (len + 1 >= (int)sizeof(bigdecimal_buffer)) {
|
1383
|
+
rb_raise(rb_eRuntimeError, "Buffer overflow in decimal conversion");
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
/* Insert decimal point */
|
1387
|
+
memmove(bigdecimal_buffer + dot_pos + 1, bigdecimal_buffer + dot_pos, len - dot_pos);
|
1388
|
+
bigdecimal_buffer[dot_pos] = '.';
|
1389
|
+
bigdecimal_buffer[len + 1] = '\0';
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
/* Add minus sign if needed - do this AFTER decimal point placement */
|
1393
|
+
if (is_negative) {
|
1394
|
+
/* Shift string to make room for minus sign */
|
1395
|
+
len = (int)strlen(bigdecimal_buffer);
|
1396
|
+
memmove(bigdecimal_buffer + 1, bigdecimal_buffer, len + 1);
|
1397
|
+
bigdecimal_buffer[0] = '-';
|
1398
|
+
bigdecimal_buffer[len + 1] = '\0'; /* Ensure proper null termination */
|
1399
|
+
}
|
1400
|
+
|
1303
1401
|
return rb_funcall(rb_cObject, rb_intern("BigDecimal"), 1, rb_str_new2(bigdecimal_buffer));
|
1304
1402
|
}
|
1305
1403
|
|
@@ -1341,7 +1439,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, long argc, VAL
|
|
1341
1439
|
/* struct time_object *tobj; */
|
1342
1440
|
struct tm tms;
|
1343
1441
|
|
1344
|
-
|
1442
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1345
1443
|
|
1346
1444
|
/* Check the number of parameters */
|
1347
1445
|
if (fb_cursor->i_sqlda->sqld != argc) {
|
@@ -1535,7 +1633,22 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, long argc, VAL
|
|
1535
1633
|
offset += alignment;
|
1536
1634
|
break;
|
1537
1635
|
#endif
|
1538
|
-
|
1636
|
+
|
1637
|
+
#if (FB_API_VER >= 40)
|
1638
|
+
case SQL_INT128:
|
1639
|
+
offset = FB_ALIGN(offset, alignment);
|
1640
|
+
var->sqldata = (char *)(fb_cursor->i_buffer + offset);
|
1641
|
+
if (var->sqlscale < 0) {
|
1642
|
+
llvalue = NUM2LL(object_to_unscaled_bigdecimal(obj, var->sqlscale));
|
1643
|
+
} else {
|
1644
|
+
llvalue = NUM2LL(object_to_fixnum(obj));
|
1645
|
+
}
|
1646
|
+
*(ISC_INT64 *)var->sqldata = llvalue;
|
1647
|
+
offset += alignment;
|
1648
|
+
break;
|
1649
|
+
#endif
|
1650
|
+
|
1651
|
+
default:
|
1539
1652
|
rb_raise(rb_eFbError, "Specified table includes unsupported datatype (%d)", dtp);
|
1540
1653
|
}
|
1541
1654
|
|
@@ -1561,7 +1674,7 @@ static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, long argc,
|
|
1561
1674
|
{
|
1562
1675
|
struct FbConnection *fb_connection;
|
1563
1676
|
|
1564
|
-
|
1677
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1565
1678
|
/* Check the first object type of the parameters */
|
1566
1679
|
if (argc >= 1 && TYPE(argv[0]) == T_ARRAY) {
|
1567
1680
|
int i;
|
@@ -1672,25 +1785,25 @@ static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
|
|
1672
1785
|
dtp = var->sqltype & ~1;
|
1673
1786
|
|
1674
1787
|
if (var->aliasname_length) { /* aliasname always present? */
|
1675
|
-
name =
|
1788
|
+
name = rb_str_new(var->aliasname, var->aliasname_length);
|
1676
1789
|
} else {
|
1677
|
-
name =
|
1790
|
+
name = rb_str_new(var->sqlname, var->sqlname_length);
|
1678
1791
|
}
|
1679
1792
|
if (downcase_names && no_lowercase(name)) {
|
1680
1793
|
rb_funcall(name, id_downcase_bang, 0);
|
1681
1794
|
}
|
1682
1795
|
rb_str_freeze(name);
|
1683
|
-
type_code = INT2NUM((
|
1796
|
+
type_code = INT2NUM((int)(var->sqltype & ~1));
|
1684
1797
|
sql_type = fb_sql_type_from_code(dtp, var->sqlsubtype);
|
1685
1798
|
sql_subtype = INT2FIX(var->sqlsubtype);
|
1686
|
-
display_size = INT2NUM((
|
1799
|
+
display_size = INT2NUM((int)var->sqllen);
|
1687
1800
|
if (dtp == SQL_VARYING) {
|
1688
|
-
internal_size = INT2NUM((
|
1801
|
+
internal_size = INT2NUM((int)(var->sqllen + sizeof(short)));
|
1689
1802
|
} else {
|
1690
|
-
internal_size = INT2NUM((
|
1803
|
+
internal_size = INT2NUM((int)var->sqllen);
|
1691
1804
|
}
|
1692
1805
|
precision = precision_from_sqlvar(var);
|
1693
|
-
scale = INT2NUM((
|
1806
|
+
scale = INT2NUM((int)var->sqlscale);
|
1694
1807
|
nullable = (var->sqltype & 1) ? Qtrue : Qfalse;
|
1695
1808
|
|
1696
1809
|
field = rb_struct_new(rb_sFbField, name, sql_type, sql_subtype, display_size, internal_size, precision, scale, nullable, type_code);
|
@@ -1727,7 +1840,7 @@ static void fb_cursor_fetch_prep(struct FbCursor *fb_cursor)
|
|
1727
1840
|
|
1728
1841
|
fb_cursor_check(fb_cursor);
|
1729
1842
|
|
1730
|
-
|
1843
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1731
1844
|
fb_connection_check(fb_connection);
|
1732
1845
|
|
1733
1846
|
/* Check if open cursor */
|
@@ -1786,7 +1899,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1786
1899
|
ISC_LONG num_segments = 0;
|
1787
1900
|
ISC_LONG total_length = 0;
|
1788
1901
|
|
1789
|
-
|
1902
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
1790
1903
|
fb_connection_check(fb_connection);
|
1791
1904
|
|
1792
1905
|
if (fb_cursor->eof) {
|
@@ -1816,7 +1929,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1816
1929
|
|
1817
1930
|
switch (dtp) {
|
1818
1931
|
case SQL_TEXT:
|
1819
|
-
val =
|
1932
|
+
val = rb_str_new(var->sqldata, var->sqllen);
|
1820
1933
|
#if HAVE_RUBY_ENCODING_H
|
1821
1934
|
rb_funcall(val, id_force_encoding, 1, fb_connection->encoding);
|
1822
1935
|
#endif
|
@@ -1824,7 +1937,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1824
1937
|
|
1825
1938
|
case SQL_VARYING:
|
1826
1939
|
vary = (VARY*)var->sqldata;
|
1827
|
-
val =
|
1940
|
+
val = rb_str_new(vary->vary_string, vary->vary_length);
|
1828
1941
|
#if HAVE_RUBY_ENCODING_H
|
1829
1942
|
rb_funcall(val, id_force_encoding, 1, fb_connection->encoding);
|
1830
1943
|
#endif
|
@@ -1834,7 +1947,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1834
1947
|
if (var->sqlscale < 0) {
|
1835
1948
|
val = sql_decimal_to_bigdecimal((long long)*(ISC_SHORT*)var->sqldata, var->sqlscale);
|
1836
1949
|
} else {
|
1837
|
-
val = INT2NUM((
|
1950
|
+
val = INT2NUM((int)*(short*)var->sqldata);
|
1838
1951
|
}
|
1839
1952
|
break;
|
1840
1953
|
|
@@ -1906,7 +2019,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1906
2019
|
break;
|
1907
2020
|
}
|
1908
2021
|
}
|
1909
|
-
val =
|
2022
|
+
val = rb_str_new(NULL,total_length);
|
1910
2023
|
for (p = RSTRING_PTR(val); num_segments > 0; num_segments--, p += actual_seg_len) {
|
1911
2024
|
isc_get_segment(fb_connection->isc_status, &blob_handle, &actual_seg_len, max_segment, p);
|
1912
2025
|
fb_error_check(fb_connection->isc_status);
|
@@ -1923,6 +2036,17 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1923
2036
|
val = Qnil;
|
1924
2037
|
break;
|
1925
2038
|
|
2039
|
+
#if (FB_API_VER >= 40)
|
2040
|
+
case SQL_INT128:
|
2041
|
+
/* Treat as 64-bit integer for now */
|
2042
|
+
if (var->sqlscale < 0) {
|
2043
|
+
val = sql_decimal_to_bigdecimal(*(ISC_INT64*)var->sqldata, var->sqlscale);
|
2044
|
+
} else {
|
2045
|
+
val = LL2NUM(*(ISC_INT64*)var->sqldata);
|
2046
|
+
}
|
2047
|
+
break;
|
2048
|
+
#endif
|
2049
|
+
|
1926
2050
|
#if (FB_API_VER >= 30)
|
1927
2051
|
case SQL_BOOLEAN:
|
1928
2052
|
val = (*(bool*)var->sqldata) ? Qtrue : Qfalse;
|
@@ -2002,8 +2126,8 @@ static VALUE cursor_execute2(VALUE args)
|
|
2002
2126
|
char isc_info_stmt[] = { isc_info_sql_stmt_type };
|
2003
2127
|
|
2004
2128
|
VALUE self = rb_ary_pop(args);
|
2005
|
-
|
2006
|
-
|
2129
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2130
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2007
2131
|
|
2008
2132
|
rb_sql = rb_ary_shift(args);
|
2009
2133
|
sql = StringValuePtr(rb_sql);
|
@@ -2046,6 +2170,7 @@ static VALUE cursor_execute2(VALUE args)
|
|
2046
2170
|
length = calculate_buffsize(fb_cursor->i_sqlda);
|
2047
2171
|
if (length > fb_cursor->i_buffer_size) {
|
2048
2172
|
fb_cursor->i_buffer = xrealloc(fb_cursor->i_buffer, length);
|
2173
|
+
memset(fb_cursor->i_buffer, 0, length);
|
2049
2174
|
fb_cursor->i_buffer_size = length;
|
2050
2175
|
}
|
2051
2176
|
}
|
@@ -2065,7 +2190,7 @@ static VALUE cursor_execute2(VALUE args)
|
|
2065
2190
|
fb_error_check(fb_connection->isc_status);
|
2066
2191
|
}
|
2067
2192
|
rows_affected = cursor_rows_affected(fb_cursor, statement);
|
2068
|
-
result = INT2NUM(rows_affected);
|
2193
|
+
result = INT2NUM((int)rows_affected);
|
2069
2194
|
} else {
|
2070
2195
|
/* Open cursor if the SQL statement is query */
|
2071
2196
|
/* Get the number of columns and reallocate the SQLDA */
|
@@ -2119,8 +2244,8 @@ static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
|
|
2119
2244
|
args = rb_ary_new4(argc, argv);
|
2120
2245
|
rb_ary_push(args, self);
|
2121
2246
|
|
2122
|
-
|
2123
|
-
|
2247
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2248
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2124
2249
|
fb_connection_check(fb_connection);
|
2125
2250
|
|
2126
2251
|
if (fb_cursor->open) {
|
@@ -2192,7 +2317,7 @@ static VALUE cursor_fetch(int argc, VALUE* argv, VALUE self)
|
|
2192
2317
|
|
2193
2318
|
int hash_row = hash_format(argc, argv);
|
2194
2319
|
|
2195
|
-
|
2320
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2196
2321
|
fb_cursor_fetch_prep(fb_cursor);
|
2197
2322
|
|
2198
2323
|
ary = fb_cursor_fetch(fb_cursor);
|
@@ -2217,7 +2342,7 @@ static VALUE cursor_fetchall(int argc, VALUE* argv, VALUE self)
|
|
2217
2342
|
|
2218
2343
|
int hash_rows = hash_format(argc, argv);
|
2219
2344
|
|
2220
|
-
|
2345
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2221
2346
|
fb_cursor_fetch_prep(fb_cursor);
|
2222
2347
|
|
2223
2348
|
ary = rb_ary_new();
|
@@ -2251,7 +2376,7 @@ static VALUE cursor_each(int argc, VALUE* argv, VALUE self)
|
|
2251
2376
|
|
2252
2377
|
int hash_rows = hash_format(argc, argv);
|
2253
2378
|
|
2254
|
-
|
2379
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2255
2380
|
fb_cursor_fetch_prep(fb_cursor);
|
2256
2381
|
|
2257
2382
|
for (;;) {
|
@@ -2277,8 +2402,8 @@ static VALUE cursor_close(VALUE self)
|
|
2277
2402
|
struct FbCursor *fb_cursor;
|
2278
2403
|
struct FbConnection *fb_connection;
|
2279
2404
|
|
2280
|
-
|
2281
|
-
|
2405
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2406
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2282
2407
|
fb_cursor_check(fb_cursor);
|
2283
2408
|
|
2284
2409
|
/* Close the cursor */
|
@@ -2312,13 +2437,13 @@ static VALUE cursor_drop(VALUE self)
|
|
2312
2437
|
struct FbConnection *fb_connection;
|
2313
2438
|
int i;
|
2314
2439
|
|
2315
|
-
|
2440
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2316
2441
|
fb_cursor_drop(fb_cursor);
|
2317
2442
|
fb_cursor->fields_ary = Qnil;
|
2318
2443
|
fb_cursor->fields_hash = Qnil;
|
2319
2444
|
|
2320
2445
|
/* reset the reference from connection */
|
2321
|
-
|
2446
|
+
TypedData_Get_Struct(fb_cursor->connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2322
2447
|
for (i = 0; i < RARRAY_LEN(fb_connection->cursor); i++) {
|
2323
2448
|
if (RARRAY_PTR(fb_connection->cursor)[i] == self) {
|
2324
2449
|
RARRAY_PTR(fb_connection->cursor)[i] = Qnil;
|
@@ -2341,7 +2466,7 @@ static VALUE cursor_fields(int argc, VALUE* argv, VALUE self)
|
|
2341
2466
|
{
|
2342
2467
|
struct FbCursor *fb_cursor;
|
2343
2468
|
|
2344
|
-
|
2469
|
+
TypedData_Get_Struct(self, struct FbCursor, &fbcursor_data_type, fb_cursor);
|
2345
2470
|
if (argc == 0 || argv[0] == ID2SYM(rb_intern("array"))) {
|
2346
2471
|
return fb_cursor->fields_ary;
|
2347
2472
|
} else if (argv[0] == ID2SYM(rb_intern("hash"))) {
|
@@ -2427,7 +2552,7 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
|
|
2427
2552
|
const char *parm;
|
2428
2553
|
int i;
|
2429
2554
|
struct FbConnection *fb_connection;
|
2430
|
-
|
2555
|
+
VALUE connection = TypedData_Make_Struct(rb_cFbConnection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2431
2556
|
fb_connection->db = handle;
|
2432
2557
|
fb_connection->transact = 0;
|
2433
2558
|
fb_connection->cursor = rb_ary_new();
|
@@ -2459,7 +2584,7 @@ static VALUE connection_names(VALUE self, const char *sql)
|
|
2459
2584
|
VALUE cursor = connection_execute(1, &query, self);
|
2460
2585
|
VALUE names = rb_ary_new();
|
2461
2586
|
struct FbConnection *fb_connection;
|
2462
|
-
|
2587
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2463
2588
|
|
2464
2589
|
while ((row = cursor_fetch(0, NULL, cursor)) != Qnil) {
|
2465
2590
|
VALUE name = rb_ary_entry(row, 0);
|
@@ -2574,7 +2699,7 @@ static VALUE connection_columns(VALUE self, VALUE table_name)
|
|
2574
2699
|
VALUE upcase_table_name = rb_funcall(table_name, rb_intern("upcase"), 0);
|
2575
2700
|
VALUE query_parms[] = { query, upcase_table_name };
|
2576
2701
|
VALUE rs = connection_query(2, query_parms, self);
|
2577
|
-
|
2702
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2578
2703
|
for (i = 0; i < RARRAY_LEN(rs); i++) {
|
2579
2704
|
VALUE row = rb_ary_entry(rs, i);
|
2580
2705
|
VALUE name = rb_ary_entry(row, 0);
|
@@ -2634,7 +2759,7 @@ static VALUE connection_index_columns(VALUE self, VALUE index_name)
|
|
2634
2759
|
VALUE columns = rb_ary_new();
|
2635
2760
|
int i;
|
2636
2761
|
struct FbConnection *fb_connection;
|
2637
|
-
|
2762
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2638
2763
|
|
2639
2764
|
for (i = 0; i < RARRAY_LEN(result); i++) {
|
2640
2765
|
VALUE row = rb_ary_entry(result, i);
|
@@ -2664,7 +2789,7 @@ static VALUE connection_indexes(VALUE self)
|
|
2664
2789
|
VALUE indexes = rb_hash_new();
|
2665
2790
|
int i;
|
2666
2791
|
struct FbConnection *fb_connection;
|
2667
|
-
|
2792
|
+
TypedData_Get_Struct(self, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2668
2793
|
|
2669
2794
|
for (i = 0; i < RARRAY_LEN(ary_indexes); i++) {
|
2670
2795
|
VALUE index_struct;
|
@@ -2727,9 +2852,7 @@ static VALUE default_int(VALUE hash, const char *key, int def)
|
|
2727
2852
|
|
2728
2853
|
static VALUE database_allocate_instance(VALUE klass)
|
2729
2854
|
{
|
2730
|
-
|
2731
|
-
OBJSETUP((VALUE)obj, klass, T_OBJECT);
|
2732
|
-
return (VALUE)obj;
|
2855
|
+
return TypedData_Wrap_Struct(klass, &fbdatabase_data_type, NULL);
|
2733
2856
|
}
|
2734
2857
|
|
2735
2858
|
static VALUE hash_from_connection_string(VALUE cs)
|
@@ -2916,7 +3039,7 @@ static VALUE database_drop(VALUE self)
|
|
2916
3039
|
struct FbConnection *fb_connection;
|
2917
3040
|
|
2918
3041
|
VALUE connection = database_connect(self);
|
2919
|
-
|
3042
|
+
TypedData_Get_Struct(connection, struct FbConnection, &fbconnection_data_type, fb_connection);
|
2920
3043
|
isc_drop_database(fb_connection->isc_status, &fb_connection->db);
|
2921
3044
|
fb_error_check(fb_connection->isc_status);
|
2922
3045
|
/* fb_connection_remove(fb_connection); */
|
@@ -2941,7 +3064,8 @@ void Init_fb()
|
|
2941
3064
|
|
2942
3065
|
rb_mFb = rb_define_module("Fb");
|
2943
3066
|
|
2944
|
-
rb_cFbDatabase = rb_define_class_under(rb_mFb, "Database",
|
3067
|
+
rb_cFbDatabase = rb_define_class_under(rb_mFb, "Database", rb_cObject);
|
3068
|
+
rb_undef_alloc_func(rb_cFbDatabase);
|
2945
3069
|
rb_define_alloc_func(rb_cFbDatabase, database_allocate_instance);
|
2946
3070
|
rb_define_method(rb_cFbDatabase, "initialize", database_initialize, -1);
|
2947
3071
|
rb_define_attr(rb_cFbDatabase, "database", 1, 1);
|
@@ -2959,7 +3083,9 @@ void Init_fb()
|
|
2959
3083
|
rb_define_method(rb_cFbDatabase, "drop", database_drop, 0);
|
2960
3084
|
rb_define_singleton_method(rb_cFbDatabase, "drop", database_s_drop, -1);
|
2961
3085
|
|
2962
|
-
rb_cFbConnection = rb_define_class_under(rb_mFb, "Connection",
|
3086
|
+
rb_cFbConnection = rb_define_class_under(rb_mFb, "Connection", rb_cObject);
|
3087
|
+
rb_undef_alloc_func(rb_cFbConnection);
|
3088
|
+
rb_undef_method(CLASS_OF(rb_cFbConnection), "new");
|
2963
3089
|
rb_define_attr(rb_cFbConnection, "database", 1, 1);
|
2964
3090
|
rb_define_attr(rb_cFbConnection, "username", 1, 1);
|
2965
3091
|
rb_define_attr(rb_cFbConnection, "password", 1, 1);
|
@@ -2989,7 +3115,9 @@ void Init_fb()
|
|
2989
3115
|
rb_define_method(rb_cFbConnection, "columns", connection_columns, 1);
|
2990
3116
|
/* rb_define_method(rb_cFbConnection, "cursor", connection_cursor, 0); */
|
2991
3117
|
|
2992
|
-
rb_cFbCursor = rb_define_class_under(rb_mFb, "Cursor",
|
3118
|
+
rb_cFbCursor = rb_define_class_under(rb_mFb, "Cursor", rb_cObject);
|
3119
|
+
rb_undef_alloc_func(rb_cFbCursor);
|
3120
|
+
rb_undef_method(CLASS_OF(rb_cFbCursor), "new");
|
2993
3121
|
/* rb_define_method(rb_cFbCursor, "execute", cursor_execute, -1); */
|
2994
3122
|
rb_define_method(rb_cFbCursor, "fields", cursor_fields, -1);
|
2995
3123
|
rb_define_method(rb_cFbCursor, "fetch", cursor_fetch, -1);
|
@@ -2998,7 +3126,9 @@ void Init_fb()
|
|
2998
3126
|
rb_define_method(rb_cFbCursor, "close", cursor_close, 0);
|
2999
3127
|
rb_define_method(rb_cFbCursor, "drop", cursor_drop, 0);
|
3000
3128
|
|
3001
|
-
rb_cFbSqlType = rb_define_class_under(rb_mFb, "SqlType",
|
3129
|
+
rb_cFbSqlType = rb_define_class_under(rb_mFb, "SqlType", rb_cObject);
|
3130
|
+
rb_undef_alloc_func(rb_cFbSqlType);
|
3131
|
+
rb_undef_method(CLASS_OF(rb_cFbSqlType), "new");
|
3002
3132
|
rb_define_singleton_method(rb_cFbSqlType, "from_code", sql_type_from_code, 2);
|
3003
3133
|
|
3004
3134
|
rb_eFbError = rb_define_class_under(rb_mFb, "Error", rb_eStandardError);
|
data/test/ConnectionTestCases.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test/FbTestCases'
|
|
2
2
|
|
3
3
|
class ConnectionTestCases < FbTestCase
|
4
4
|
include FbTestCases
|
5
|
-
|
5
|
+
|
6
6
|
def test_execute
|
7
7
|
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
8
8
|
sql_select = "SELECT * FROM RDB$DATABASE"
|
@@ -16,50 +16,38 @@ class ConnectionTestCases < FbTestCase
|
|
16
16
|
connection.drop
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def test_query_select
|
21
21
|
sql_select = "SELECT * FROM RDB$DATABASE"
|
22
22
|
Database.create(@parms) do |connection|
|
23
|
-
|
24
23
|
d = connection.query(sql_select)
|
25
24
|
assert_instance_of Array, d
|
26
25
|
assert_equal 1, d.size
|
27
26
|
assert_instance_of Array, d.first
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
assert_equal 4, d.first.size
|
32
|
-
end
|
33
|
-
|
27
|
+
|
28
|
+
assert_equal expected_columns, d.first.size
|
29
|
+
|
34
30
|
a = connection.query(:array, sql_select)
|
35
31
|
assert_instance_of Array, a
|
36
32
|
assert_equal 1, a.size
|
37
33
|
assert_instance_of Array, a.first
|
38
|
-
|
39
|
-
assert_equal 5, a.first.size
|
40
|
-
else
|
41
|
-
assert_equal 4, a.first.size
|
42
|
-
end
|
34
|
+
assert_equal expected_columns, a.first.size
|
43
35
|
|
44
36
|
h = connection.query(:hash, sql_select)
|
45
37
|
assert_instance_of Array, h
|
46
38
|
assert_equal 1, h.size
|
47
39
|
assert_instance_of Hash, h.first
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
assert_equal 4, h.first.keys.size
|
52
|
-
end
|
40
|
+
|
41
|
+
assert_equal expected_columns, h.first.keys.size
|
42
|
+
|
53
43
|
assert h.first.keys.include?("RDB$DESCRIPTION")
|
54
44
|
assert h.first.keys.include?("RDB$RELATION_ID")
|
55
45
|
assert h.first.keys.include?("RDB$SECURITY_CLASS")
|
56
46
|
assert h.first.keys.include?("RDB$CHARACTER_SET_NAME")
|
57
|
-
if @fb_version
|
58
|
-
assert h.first.keys.include?("RDB$LINGER")
|
59
|
-
end
|
47
|
+
assert h.first.keys.include?("RDB$LINGER") if @fb_version >= 3
|
60
48
|
end
|
61
49
|
end
|
62
|
-
|
50
|
+
|
63
51
|
def test_query_update
|
64
52
|
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
65
53
|
sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)"
|
@@ -69,22 +57,22 @@ class ConnectionTestCases < FbTestCase
|
|
69
57
|
Database.create(@parms) do |connection|
|
70
58
|
su = connection.query(sql_schema)
|
71
59
|
assert_equal -1, su
|
72
|
-
|
60
|
+
|
73
61
|
i = connection.query(sql_insert, 1, "NAME")
|
74
62
|
assert_equal 1, i
|
75
|
-
|
63
|
+
|
76
64
|
u = connection.query(sql_update, 1, "NAME2", 1)
|
77
65
|
assert_equal 1, u
|
78
|
-
|
66
|
+
|
79
67
|
d = connection.query(sql_delete, 1)
|
80
68
|
assert_equal 1, d
|
81
|
-
|
69
|
+
|
82
70
|
q = connection.query(sql_select)
|
83
71
|
assert_instance_of Array, q
|
84
72
|
assert_equal 0, q.size
|
85
73
|
end
|
86
74
|
end
|
87
|
-
|
75
|
+
|
88
76
|
def test_insert_blobs_text
|
89
77
|
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20), MEMO BLOB SUB_TYPE TEXT)"
|
90
78
|
sql_insert = "INSERT INTO TEST (ID, NAME, MEMO) VALUES (?, ?, ?)"
|
@@ -193,7 +181,7 @@ class ConnectionTestCases < FbTestCase
|
|
193
181
|
connection.drop
|
194
182
|
end
|
195
183
|
end
|
196
|
-
|
184
|
+
|
197
185
|
def test_open?
|
198
186
|
db = Database.create(@parms);
|
199
187
|
connection = db.connect
|
@@ -202,7 +190,7 @@ class ConnectionTestCases < FbTestCase
|
|
202
190
|
assert !connection.open?
|
203
191
|
db.drop
|
204
192
|
end
|
205
|
-
|
193
|
+
|
206
194
|
def test_properties_instance
|
207
195
|
db = Database.new(@parms)
|
208
196
|
db.create
|
@@ -215,7 +203,7 @@ class ConnectionTestCases < FbTestCase
|
|
215
203
|
connection.drop
|
216
204
|
end
|
217
205
|
end
|
218
|
-
|
206
|
+
|
219
207
|
def test_properties_singleton
|
220
208
|
Database.create(@parms) do |connection|
|
221
209
|
assert_equal @parms[:database], connection.database
|
@@ -226,25 +214,25 @@ class ConnectionTestCases < FbTestCase
|
|
226
214
|
connection.drop
|
227
215
|
end
|
228
216
|
end
|
229
|
-
|
217
|
+
|
230
218
|
def test_drop_instance
|
231
219
|
db = Database.create(@parms)
|
232
|
-
assert File.
|
220
|
+
assert File.exist?(@db_file)
|
233
221
|
connection = db.connect
|
234
|
-
assert connection.open?
|
222
|
+
assert connection.open?
|
235
223
|
connection.drop
|
236
224
|
assert !connection.open?
|
237
|
-
assert !File.
|
225
|
+
assert !File.exist?(@db_file)
|
238
226
|
end
|
239
|
-
|
227
|
+
|
240
228
|
def test_drop_singleton
|
241
229
|
Database.create(@parms) do |connection|
|
242
|
-
assert File.
|
230
|
+
assert File.exist?(@db_file)
|
243
231
|
connection.drop
|
244
|
-
assert !File.
|
232
|
+
assert !File.exist?(@db_file)
|
245
233
|
end
|
246
234
|
end
|
247
|
-
|
235
|
+
|
248
236
|
def test_to_s
|
249
237
|
db = Database.new(@parms)
|
250
238
|
db.create
|
@@ -256,7 +244,7 @@ class ConnectionTestCases < FbTestCase
|
|
256
244
|
assert_equal "#{@parms[:database]} (CLOSED)", connection.to_s
|
257
245
|
end
|
258
246
|
end
|
259
|
-
|
247
|
+
|
260
248
|
def test_table_names
|
261
249
|
sql_schema = <<-END
|
262
250
|
CREATE TABLE TEST1 (ID INT);
|
@@ -351,7 +339,7 @@ class ConnectionTestCases < FbTestCase
|
|
351
339
|
assert_equal 'WRITER', names[1]
|
352
340
|
end
|
353
341
|
end
|
354
|
-
|
342
|
+
|
355
343
|
def test_role_names_downcased
|
356
344
|
sql_schema = <<-END
|
357
345
|
create role reader;
|
@@ -364,7 +352,7 @@ class ConnectionTestCases < FbTestCase
|
|
364
352
|
assert_equal 'writer', names[1]
|
365
353
|
end
|
366
354
|
end
|
367
|
-
|
355
|
+
|
368
356
|
def test_procedure_names
|
369
357
|
sql_schema = <<-END_SQL
|
370
358
|
CREATE PROCEDURE PLUSONE(NUM1 INTEGER) RETURNS (NUM2 INTEGER) AS
|
@@ -376,7 +364,7 @@ class ConnectionTestCases < FbTestCase
|
|
376
364
|
Database.create(@parms) do |connection|
|
377
365
|
connection.execute(sql_schema)
|
378
366
|
names = connection.procedure_names
|
379
|
-
|
367
|
+
assert names.include?('PLUSONE'), "PLUSONE procedure not found in: #{names.inspect}"
|
380
368
|
end
|
381
369
|
end
|
382
370
|
|
@@ -391,10 +379,10 @@ class ConnectionTestCases < FbTestCase
|
|
391
379
|
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
392
380
|
connection.execute(sql_schema)
|
393
381
|
names = connection.procedure_names
|
394
|
-
|
382
|
+
assert names.include?('plusone'), "plusone procedure not found in: #{names.inspect}"
|
395
383
|
end
|
396
384
|
end
|
397
|
-
|
385
|
+
|
398
386
|
def test_trigger_names
|
399
387
|
table_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20)); CREATE GENERATOR TEST_SEQ;"
|
400
388
|
trigger_schema = <<-END_SQL
|
@@ -448,16 +436,16 @@ class ConnectionTestCases < FbTestCase
|
|
448
436
|
assert indexes.keys.include?('FK_DETAIL_MASTER_ID')
|
449
437
|
assert indexes.keys.include?('IX_MASTER_NAME1')
|
450
438
|
assert indexes.keys.include?('IX_DETAIL_ID_DESC')
|
451
|
-
|
439
|
+
|
452
440
|
assert indexes['PK_MASTER'].columns.include?('ID')
|
453
441
|
assert indexes['PK_DETAIL'].columns.include?('ID')
|
454
442
|
|
455
443
|
master_indexes = indexes.values.select {|ix| ix.table_name == 'MASTER' }
|
456
444
|
assert_equal 2, master_indexes.size
|
457
|
-
|
445
|
+
|
458
446
|
detail_indexes = indexes.values.select {|ix| ix.table_name == 'DETAIL' }
|
459
447
|
assert_equal 3, detail_indexes.size
|
460
|
-
|
448
|
+
|
461
449
|
assert_equal 'MASTER', indexes['PK_MASTER'].table_name
|
462
450
|
assert indexes['PK_MASTER'].unique
|
463
451
|
assert !indexes['PK_MASTER'].descending
|
@@ -465,7 +453,7 @@ class ConnectionTestCases < FbTestCase
|
|
465
453
|
assert_equal 'MASTER', indexes['IX_MASTER_NAME1'].table_name
|
466
454
|
assert indexes['IX_MASTER_NAME1'].unique
|
467
455
|
assert !indexes['IX_MASTER_NAME1'].descending
|
468
|
-
|
456
|
+
|
469
457
|
assert_equal 'DETAIL', indexes['PK_DETAIL'].table_name
|
470
458
|
assert indexes['PK_DETAIL'].unique
|
471
459
|
assert !indexes['PK_DETAIL'].descending
|
@@ -476,8 +464,8 @@ class ConnectionTestCases < FbTestCase
|
|
476
464
|
|
477
465
|
assert_equal 'DETAIL', indexes['IX_DETAIL_ID_DESC'].table_name
|
478
466
|
assert !indexes['IX_DETAIL_ID_DESC'].unique
|
479
|
-
assert indexes['IX_DETAIL_ID_DESC'].descending
|
480
|
-
|
467
|
+
assert indexes['IX_DETAIL_ID_DESC'].descending
|
468
|
+
|
481
469
|
connection.drop
|
482
470
|
end
|
483
471
|
end
|
@@ -514,7 +502,7 @@ class ConnectionTestCases < FbTestCase
|
|
514
502
|
I INTEGER,
|
515
503
|
SI SMALLINT,
|
516
504
|
BI BIGINT,
|
517
|
-
F FLOAT,
|
505
|
+
F FLOAT,
|
518
506
|
D DOUBLE PRECISION,
|
519
507
|
C CHAR,
|
520
508
|
C10 CHAR(10),
|
@@ -552,5 +540,5 @@ class ConnectionTestCases < FbTestCase
|
|
552
540
|
assert_equal column, columns[i]
|
553
541
|
end
|
554
542
|
end
|
555
|
-
end
|
543
|
+
end
|
556
544
|
end
|
data/test/CursorTestCases.rb
CHANGED
@@ -9,11 +9,7 @@ class CursorTestCases < FbTestCase
|
|
9
9
|
assert_instance_of Cursor, cursor
|
10
10
|
row = cursor.fetch :array
|
11
11
|
assert_instance_of Array, row
|
12
|
-
|
13
|
-
assert_equal 5, row.size
|
14
|
-
else
|
15
|
-
assert_equal 4, row.size
|
16
|
-
end
|
12
|
+
assert_equal expected_columns, row.size
|
17
13
|
end
|
18
14
|
connection.execute("select * from rdb$database where rdb$description = 'bogus'") do |cursor|
|
19
15
|
assert_instance_of Cursor, cursor
|
@@ -31,11 +27,7 @@ class CursorTestCases < FbTestCase
|
|
31
27
|
assert_instance_of Cursor, cursor
|
32
28
|
row = cursor.fetch :hash
|
33
29
|
assert_instance_of Hash, row
|
34
|
-
|
35
|
-
assert_equal 5, row.size
|
36
|
-
else
|
37
|
-
assert_equal 4, row.size
|
38
|
-
end
|
30
|
+
assert_equal expected_columns, row.size
|
39
31
|
end
|
40
32
|
connection.execute("select * from rdb$database where rdb$description = 'bogus'") do |cursor|
|
41
33
|
assert_instance_of Cursor, cursor
|
@@ -55,11 +47,7 @@ class CursorTestCases < FbTestCase
|
|
55
47
|
assert_instance_of Array, rows
|
56
48
|
assert_equal 1, rows.size
|
57
49
|
assert_instance_of Array, rows[0]
|
58
|
-
|
59
|
-
assert_equal 5, rows[0].size
|
60
|
-
else
|
61
|
-
assert_equal 4, rows[0].size
|
62
|
-
end
|
50
|
+
assert_equal expected_columns, rows[0].size
|
63
51
|
end
|
64
52
|
connection.drop
|
65
53
|
end
|
@@ -73,11 +61,7 @@ class CursorTestCases < FbTestCase
|
|
73
61
|
assert_instance_of Array, rows
|
74
62
|
assert_equal 1, rows.size
|
75
63
|
assert_instance_of Hash, rows[0]
|
76
|
-
|
77
|
-
assert_equal 5, rows[0].size
|
78
|
-
else
|
79
|
-
assert_equal 4, rows[0].size
|
80
|
-
end
|
64
|
+
assert_equal expected_columns, rows[0].size
|
81
65
|
end
|
82
66
|
connection.drop
|
83
67
|
end
|
@@ -89,18 +73,12 @@ class CursorTestCases < FbTestCase
|
|
89
73
|
fields = cursor.fields
|
90
74
|
fields_ary = cursor.fields :array
|
91
75
|
assert_equal fields, fields_ary
|
92
|
-
|
93
|
-
assert_equal 5, fields.size
|
94
|
-
else
|
95
|
-
assert_equal 4, fields.size
|
96
|
-
end
|
76
|
+
assert_equal expected_columns, fields.size
|
97
77
|
assert_equal "RDB$DESCRIPTION", fields[0].name;
|
98
78
|
assert_equal "RDB$RELATION_ID", fields[1].name;
|
99
79
|
assert_equal "RDB$SECURITY_CLASS", fields[2].name;
|
100
80
|
assert_equal "RDB$CHARACTER_SET_NAME", fields[3].name;
|
101
|
-
if @fb_version
|
102
|
-
assert_equal "RDB$LINGER", fields[4].name;
|
103
|
-
end
|
81
|
+
assert_equal "RDB$LINGER", fields[4].name if @fb_version >= 3
|
104
82
|
end
|
105
83
|
connection.drop
|
106
84
|
end
|
@@ -112,18 +90,12 @@ class CursorTestCases < FbTestCase
|
|
112
90
|
fields = cursor.fields
|
113
91
|
fields_ary = cursor.fields :array
|
114
92
|
assert_equal fields, fields_ary
|
115
|
-
|
116
|
-
assert_equal 5, fields.size
|
117
|
-
else
|
118
|
-
assert_equal 4, fields.size
|
119
|
-
end
|
93
|
+
assert_equal expected_columns, fields.size
|
120
94
|
assert_equal "rdb$description", fields[0].name;
|
121
95
|
assert_equal "rdb$relation_id", fields[1].name;
|
122
96
|
assert_equal "rdb$security_class", fields[2].name;
|
123
97
|
assert_equal "rdb$character_set_name", fields[3].name;
|
124
|
-
if @fb_version
|
125
|
-
assert_equal "rdb$linger", fields[4].name;
|
126
|
-
end
|
98
|
+
assert_equal "rdb$linger", fields[4].name if @fb_version >= 3
|
127
99
|
end
|
128
100
|
connection.drop
|
129
101
|
end
|
@@ -133,18 +105,12 @@ class CursorTestCases < FbTestCase
|
|
133
105
|
Database.create(@parms) do |connection|
|
134
106
|
connection.execute("select * from rdb$database") do |cursor|
|
135
107
|
fields = cursor.fields :hash
|
136
|
-
|
137
|
-
assert_equal 5, fields.size
|
138
|
-
else
|
139
|
-
assert_equal 4, fields.size
|
140
|
-
end
|
108
|
+
assert_equal expected_columns, fields.size
|
141
109
|
assert_equal 520, fields["RDB$DESCRIPTION"].type_code
|
142
110
|
assert_equal 500, fields["RDB$RELATION_ID"].type_code
|
143
111
|
assert_equal 452, fields["RDB$SECURITY_CLASS"].type_code
|
144
112
|
assert_equal 452, fields["RDB$CHARACTER_SET_NAME"].type_code
|
145
|
-
if @fb_version
|
146
|
-
assert_equal 496, fields["RDB$LINGER"].type_code
|
147
|
-
end
|
113
|
+
assert_equal 496, fields["RDB$LINGER"].type_code if @fb_version >= 3
|
148
114
|
end
|
149
115
|
connection.drop
|
150
116
|
end
|
@@ -154,18 +120,12 @@ class CursorTestCases < FbTestCase
|
|
154
120
|
Database.create(@parms.merge(:downcase_names => true)) do |connection| # xxx true
|
155
121
|
connection.execute("select * from rdb$database") do |cursor|
|
156
122
|
fields = cursor.fields :hash
|
157
|
-
|
158
|
-
assert_equal 5, fields.size
|
159
|
-
else
|
160
|
-
assert_equal 4, fields.size
|
161
|
-
end
|
123
|
+
assert_equal expected_columns, fields.size
|
162
124
|
assert_equal 520, fields["rdb$description"].type_code
|
163
125
|
assert_equal 500, fields["rdb$relation_id"].type_code
|
164
126
|
assert_equal 452, fields["rdb$security_class"].type_code
|
165
127
|
assert_equal 452, fields["rdb$character_set_name"].type_code
|
166
|
-
if @fb_version
|
167
|
-
assert_equal 496, fields["rdb$linger"].type_code
|
168
|
-
end
|
128
|
+
assert_equal 496, fields["rdb$linger"].type_code if @fb_version >= 3
|
169
129
|
end
|
170
130
|
connection.drop
|
171
131
|
end
|
@@ -178,11 +138,7 @@ class CursorTestCases < FbTestCase
|
|
178
138
|
cursor.each :array do |row|
|
179
139
|
count += 1
|
180
140
|
assert_instance_of Array, row
|
181
|
-
|
182
|
-
assert_equal 5, row.size
|
183
|
-
else
|
184
|
-
assert_equal 4, row.size
|
185
|
-
end
|
141
|
+
assert_equal expected_columns, row.size
|
186
142
|
end
|
187
143
|
assert_equal 1, count
|
188
144
|
end
|
@@ -197,11 +153,7 @@ class CursorTestCases < FbTestCase
|
|
197
153
|
cursor.each :hash do |row|
|
198
154
|
count += 1
|
199
155
|
assert_instance_of Hash, row
|
200
|
-
|
201
|
-
assert_equal 5, row.size
|
202
|
-
else
|
203
|
-
assert_equal 4, row.size
|
204
|
-
end
|
156
|
+
assert_equal expected_columns, row.size
|
205
157
|
end
|
206
158
|
assert_equal 1, count
|
207
159
|
end
|
data/test/DataTypesTestCases.rb
CHANGED
@@ -98,7 +98,7 @@ class DataTypesTestCases < FbTestCase
|
|
98
98
|
I INTEGER,
|
99
99
|
SI SMALLINT,
|
100
100
|
BI BIGINT,
|
101
|
-
F FLOAT,
|
101
|
+
F FLOAT,
|
102
102
|
D DOUBLE PRECISION,
|
103
103
|
C CHAR,
|
104
104
|
C10 CHAR(10),
|
@@ -337,11 +337,25 @@ class DataTypesTestCases < FbTestCase
|
|
337
337
|
connection.execute(sql_insert, Time.now)
|
338
338
|
end
|
339
339
|
elsif cols[i] == 'DT'
|
340
|
-
|
341
|
-
|
340
|
+
# Ruby 3.0.3+ raises Date::Error instead of ArgumentError for Date class
|
341
|
+
if RUBY_VERSION >= "3.0"
|
342
|
+
assert_raises Date::Error do
|
343
|
+
connection.execute(sql_insert, Date)
|
344
|
+
end
|
345
|
+
else
|
346
|
+
assert_raises ArgumentError do
|
347
|
+
connection.execute(sql_insert, Date)
|
348
|
+
end
|
342
349
|
end
|
343
|
-
|
344
|
-
|
350
|
+
# Ruby 3.0.3+ raises Date::Error instead of ArgumentError for integer
|
351
|
+
if RUBY_VERSION >= "3.0"
|
352
|
+
assert_raises Date::Error do
|
353
|
+
connection.execute(sql_insert, 2006)
|
354
|
+
end
|
355
|
+
else
|
356
|
+
assert_raises ArgumentError do
|
357
|
+
connection.execute(sql_insert, 2006)
|
358
|
+
end
|
345
359
|
end
|
346
360
|
elsif cols[i] == 'TM'
|
347
361
|
assert_raises TypeError do
|
@@ -502,7 +516,9 @@ class DataTypesTestCases < FbTestCase
|
|
502
516
|
connection.execute(sql_insert, -91520.65)
|
503
517
|
vals = connection.query(sql_select)
|
504
518
|
assert vals[0][0].is_a?(BigDecimal), "Numeric(15,4) must return BigDecimal"
|
505
|
-
|
519
|
+
# In Ruby 3.2+, BigDecimal and Float comparisons may be equal due to improved precision
|
520
|
+
# So we check that the types are different instead of the values
|
521
|
+
assert vals[0][0].class != Float(91520.65).class, "BigDecimal and Float should be different types"
|
506
522
|
assert_equal BigDecimal('91520.65'), vals[0][0]
|
507
523
|
assert_equal BigDecimal('91520.65'), vals[1][0]
|
508
524
|
assert_equal BigDecimal('-91520.65'), vals[2][0]
|
data/test/DatabaseTestCases.rb
CHANGED
@@ -69,7 +69,7 @@ class DatabaseTestCases < FbTestCase
|
|
69
69
|
def test_create_instance
|
70
70
|
db = Database.new(@parms)
|
71
71
|
db.create
|
72
|
-
assert File.
|
72
|
+
assert File.exist?(@db_file)
|
73
73
|
end
|
74
74
|
|
75
75
|
def test_create_instance_block
|
@@ -82,17 +82,17 @@ class DatabaseTestCases < FbTestCase
|
|
82
82
|
assert_equal 3, connection.dialect
|
83
83
|
assert_equal 3, connection.db_dialect
|
84
84
|
end
|
85
|
-
assert File.
|
85
|
+
assert File.exist?(@db_file)
|
86
86
|
end
|
87
87
|
|
88
88
|
def test_create_singleton
|
89
89
|
db = Database.create(@parms);
|
90
|
-
assert File.
|
90
|
+
assert File.exist?(@db_file)
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_create_singleton_with_defaults
|
94
94
|
db = Database.create(:database => "localhost:#{@db_file}");
|
95
|
-
assert File.
|
95
|
+
assert File.exist?(@db_file)
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_create_singleton_block
|
@@ -103,7 +103,7 @@ class DatabaseTestCases < FbTestCase
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
assert_instance_of Database, db
|
106
|
-
assert File.
|
106
|
+
assert File.exist?(@db_file)
|
107
107
|
end
|
108
108
|
|
109
109
|
def test_create_bad_param
|
@@ -133,19 +133,19 @@ class DatabaseTestCases < FbTestCase
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def test_drop_instance
|
136
|
-
assert !File.
|
136
|
+
assert !File.exist?(@db_file)
|
137
137
|
db = Database.create(@parms)
|
138
|
-
assert File.
|
138
|
+
assert File.exist?(@db_file)
|
139
139
|
db.drop
|
140
|
-
assert !File.
|
140
|
+
assert !File.exist?(@db_file)
|
141
141
|
end
|
142
142
|
|
143
143
|
def test_drop_singleton
|
144
|
-
assert !File.
|
144
|
+
assert !File.exist?(@db_file)
|
145
145
|
Database.create(@parms)
|
146
|
-
assert File.
|
146
|
+
assert File.exist?(@db_file)
|
147
147
|
Database.drop(@parms)
|
148
|
-
assert !File.
|
148
|
+
assert !File.exist?(@db_file)
|
149
149
|
end
|
150
150
|
|
151
151
|
def test_role_support
|
data/test/FbTestCases.rb
CHANGED
@@ -44,17 +44,24 @@ module FbTestCases
|
|
44
44
|
rm_rf @db_file
|
45
45
|
|
46
46
|
Database.create(@parms) do |connection|
|
47
|
-
|
48
47
|
d = connection.query("SELECT substring(rdb$get_context('SYSTEM', 'ENGINE_VERSION') from 1 for 1) from rdb$database")
|
49
|
-
|
50
48
|
@fb_version = Integer(d.first[0])
|
51
|
-
|
52
49
|
connection.drop
|
53
50
|
end
|
54
51
|
|
55
52
|
rm_rf @db_file
|
56
53
|
end
|
57
54
|
|
55
|
+
def expected_columns
|
56
|
+
case @fb_version
|
57
|
+
when 5, 4
|
58
|
+
6
|
59
|
+
when 3
|
60
|
+
5
|
61
|
+
else
|
62
|
+
4
|
63
|
+
end
|
64
|
+
end
|
58
65
|
end
|
59
66
|
|
60
67
|
class Fb::Connection
|
data/test/FbTestSuite.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brent Rowland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby Firebird Extension Library
|
14
14
|
email: rowland@rowlandresearch.com
|
@@ -57,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
57
|
version: '0'
|
58
58
|
requirements:
|
59
59
|
- Firebird client library fbclient.dll, libfbclient.so or Firebird.framework.
|
60
|
-
rubygems_version: 3.
|
60
|
+
rubygems_version: 3.1.6
|
61
61
|
signing_key:
|
62
62
|
specification_version: 4
|
63
63
|
summary: Firebird database driver
|