fb 0.6.7 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/extconf.rb +20 -4
- data/fb.c +196 -140
- data/test/ConnectionTestCases.rb +2 -2
- data/test/EncodingTestCases.rb +40 -0
- data/test/FbTestSuite.rb +3 -0
- metadata +27 -38
data/extconf.rb
CHANGED
@@ -14,13 +14,29 @@
|
|
14
14
|
# = Mac OS X (Intel)
|
15
15
|
# * Works
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def unquote(string)
|
18
|
+
string.sub(/\A(['"])?(.*?)\1?\z/m, '\2') unless string.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_firebird_registry
|
22
|
+
require 'win32/registry'
|
23
|
+
Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Firebird Project\Firebird Server\Instances', Win32::Registry::Constants::KEY_READ) do |reg|
|
24
|
+
return reg.read_s('DefaultInstance') rescue nil
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
28
|
+
def search_firebird_path
|
29
|
+
program_files = ENV['ProgramFiles'].gsub('\\', '/').gsub(/(\w+\s+[\w\s]+)/) { |s| s.size > 8 ? s[0,6] + '~1' : s }
|
30
|
+
Dir["#{program_files}/Firebird/Firebird_*"].sort.last
|
31
|
+
end
|
32
|
+
|
33
|
+
if RUBY_PLATFORM =~ /(mingw32|mswin32)/ and ARGV.grep(/^--with-opt-dir=/).empty?
|
34
|
+
opt = unquote(ENV['FIREBIRD'])
|
35
|
+
opt = opt || read_firebird_registry
|
36
|
+
opt = opt || search_firebird_path
|
37
|
+
ARGV << "--with-opt-dir=#{opt}" if opt
|
38
|
+
end
|
39
|
+
|
24
40
|
require 'mkmf'
|
25
41
|
|
26
42
|
libs = %w/ fbclient gds /
|
data/fb.c
CHANGED
@@ -21,7 +21,47 @@
|
|
21
21
|
*/
|
22
22
|
|
23
23
|
#include "ruby.h"
|
24
|
-
|
24
|
+
|
25
|
+
/* Ensure compatibility with early releases of Ruby 1.8.5 */
|
26
|
+
#ifndef RSTRING_PTR
|
27
|
+
# define RSTRING_PTR(v) RSTRING(v)->ptr
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#ifndef RSTRING_LEN
|
31
|
+
# define RSTRING_LEN(v) RSTRING(v)->len
|
32
|
+
#endif
|
33
|
+
|
34
|
+
#ifndef RARRAY_PTR
|
35
|
+
# define RARRAY_PTR(v) RARRAY(v)->ptr
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#ifndef RARRAY_LEN
|
39
|
+
# define RARRAY_LEN(v) RARRAY(v)->len
|
40
|
+
#endif
|
41
|
+
|
42
|
+
#ifdef HAVE_RUBY_REGEX_H
|
43
|
+
# include "ruby/re.h"
|
44
|
+
#else
|
45
|
+
# include "re.h"
|
46
|
+
#endif
|
47
|
+
|
48
|
+
// this sucks. but for some reason these moved around between 1.8 and 1.9
|
49
|
+
#ifdef ONIGURUMA_H
|
50
|
+
#define IGNORECASE ONIG_OPTION_IGNORECASE
|
51
|
+
#define MULTILINE ONIG_OPTION_MULTILINE
|
52
|
+
#define EXTENDED ONIG_OPTION_EXTEND
|
53
|
+
#else
|
54
|
+
#define IGNORECASE RE_OPTION_IGNORECASE
|
55
|
+
#define MULTILINE RE_OPTION_MULTILINE
|
56
|
+
#define EXTENDED RE_OPTION_EXTENDED
|
57
|
+
#endif
|
58
|
+
|
59
|
+
// this sucks too.
|
60
|
+
#ifndef RREGEXP_SRC_PTR
|
61
|
+
#define RREGEXP_SRC_PTR(r) RREGEXP(r)->str
|
62
|
+
#define RREGEXP_SRC_LEN(r) RREGEXP(r)->len
|
63
|
+
#endif
|
64
|
+
|
25
65
|
#include <stdio.h>
|
26
66
|
#include <string.h>
|
27
67
|
#include <limits.h>
|
@@ -29,6 +69,7 @@
|
|
29
69
|
#include <float.h>
|
30
70
|
#include <time.h>
|
31
71
|
|
72
|
+
|
32
73
|
#define SQLDA_COLSINIT 50
|
33
74
|
#define SQLCODE_NOMORE 100
|
34
75
|
#define TPBBUFF_ALLOC 64
|
@@ -61,6 +102,7 @@ static ID id_downcase_bang;
|
|
61
102
|
static VALUE re_lowercase;
|
62
103
|
static ID id_rstrip_bang;
|
63
104
|
static ID id_sub_bang;
|
105
|
+
static ID id_force_encoding;
|
64
106
|
|
65
107
|
/* static char isc_info_stmt[] = { isc_info_sql_stmt_type }; */
|
66
108
|
/* static char isc_info_buff[16]; */
|
@@ -93,6 +135,7 @@ struct FbConnection {
|
|
93
135
|
unsigned short dialect;
|
94
136
|
unsigned short db_dialect;
|
95
137
|
short downcase_names;
|
138
|
+
VALUE encoding;
|
96
139
|
int dropped;
|
97
140
|
ISC_STATUS isc_status[20];
|
98
141
|
/* struct FbConnection *next; */
|
@@ -118,8 +161,8 @@ struct FbCursor {
|
|
118
161
|
|
119
162
|
typedef struct trans_opts
|
120
163
|
{
|
121
|
-
char *option1;
|
122
|
-
char *option2;
|
164
|
+
const char *option1;
|
165
|
+
const char *option2;
|
123
166
|
char optval;
|
124
167
|
short position;
|
125
168
|
struct trans_opts *sub_opts;
|
@@ -208,7 +251,7 @@ struct time_object {
|
|
208
251
|
#define GetTimeval(obj, tobj) \
|
209
252
|
Data_Get_Struct(obj, struct time_object, tobj)
|
210
253
|
|
211
|
-
static VALUE fb_mktime(struct tm *tm, char *which)
|
254
|
+
static VALUE fb_mktime(struct tm *tm, const char *which)
|
212
255
|
{
|
213
256
|
#if defined(_WIN32)
|
214
257
|
if (tm->tm_year + 1900 < 1970)
|
@@ -272,16 +315,42 @@ static void tm_from_date(struct tm *tm, VALUE date)
|
|
272
315
|
|
273
316
|
static void tm_from_timestamp(struct tm *tm, VALUE obj)
|
274
317
|
{
|
318
|
+
#ifdef TypedData_Get_Struct
|
319
|
+
VALUE year, month, day, hour, min, sec;
|
320
|
+
#endif
|
275
321
|
struct time_object *tobj;
|
276
322
|
|
277
|
-
if (!rb_obj_is_kind_of(obj, rb_cTime)
|
323
|
+
if (!rb_obj_is_kind_of(obj, rb_cTime))
|
278
324
|
{
|
279
|
-
|
280
|
-
|
325
|
+
if (rb_respond_to(obj, rb_intern("to_str")))
|
326
|
+
{
|
327
|
+
VALUE s = rb_funcall(obj, rb_intern("to_str"), 0);
|
328
|
+
obj = rb_funcall(rb_cTime, rb_intern("parse"), 1, s);
|
329
|
+
}
|
330
|
+
else
|
331
|
+
{
|
332
|
+
rb_raise(rb_eTypeError, "Expecting Time object or string.");
|
333
|
+
}
|
281
334
|
}
|
282
335
|
|
336
|
+
#ifdef TypedData_Get_Struct
|
337
|
+
year = rb_funcall(obj, rb_intern("year"), 0);
|
338
|
+
month = rb_funcall(obj, rb_intern("month"), 0);
|
339
|
+
day = rb_funcall(obj, rb_intern("day"), 0);
|
340
|
+
hour = rb_funcall(obj, rb_intern("hour"), 0);
|
341
|
+
min = rb_funcall(obj, rb_intern("min"), 0);
|
342
|
+
sec = rb_funcall(obj, rb_intern("sec"), 0);
|
343
|
+
memset(tm, 0, sizeof(struct tm));
|
344
|
+
tm->tm_year = FIX2INT(year) - 1900;
|
345
|
+
tm->tm_mon = FIX2INT(month) - 1;
|
346
|
+
tm->tm_mday = FIX2INT(day);
|
347
|
+
tm->tm_hour = FIX2INT(hour);
|
348
|
+
tm->tm_min = FIX2INT(min);
|
349
|
+
tm->tm_sec = FIX2INT(sec);
|
350
|
+
#else
|
283
351
|
GetTimeval(obj, tobj);
|
284
352
|
*tm = tobj->tm;
|
353
|
+
#endif
|
285
354
|
}
|
286
355
|
|
287
356
|
static VALUE long_from_obj(VALUE obj)
|
@@ -315,7 +384,7 @@ static VALUE double_from_obj(VALUE obj)
|
|
315
384
|
|
316
385
|
static VALUE fb_sql_type_from_code(int code, int subtype)
|
317
386
|
{
|
318
|
-
char *sql_type = NULL;
|
387
|
+
const char *sql_type = NULL;
|
319
388
|
switch(code) {
|
320
389
|
case SQL_TEXT:
|
321
390
|
case blr_text:
|
@@ -408,7 +477,6 @@ static VALUE sql_type_from_code(VALUE self, VALUE code, VALUE subtype)
|
|
408
477
|
|
409
478
|
static void fb_error_check(ISC_STATUS *isc_status)
|
410
479
|
{
|
411
|
-
HERE("fb_error_check");
|
412
480
|
if (isc_status[0] == 1 && isc_status[1]) {
|
413
481
|
char buf[1024];
|
414
482
|
VALUE exc, msg, msg1, msg2;
|
@@ -422,10 +490,8 @@ static void fb_error_check(ISC_STATUS *isc_status)
|
|
422
490
|
|
423
491
|
exc = rb_exc_new3(rb_eFbError, msg);
|
424
492
|
rb_iv_set(exc, "error_code", INT2FIX(code));
|
425
|
-
HERE("fb_error_check 1");
|
426
493
|
rb_exc_raise(exc);
|
427
494
|
}
|
428
|
-
HERE("fb_error_check 2");
|
429
495
|
}
|
430
496
|
|
431
497
|
static void fb_error_check_warn(ISC_STATUS *isc_status)
|
@@ -464,7 +530,6 @@ static void fb_cursor_free();
|
|
464
530
|
/* connection utilities */
|
465
531
|
static void fb_connection_check(struct FbConnection *fb_connection)
|
466
532
|
{
|
467
|
-
HERE("fb_connection_check");
|
468
533
|
if (fb_connection->db == 0) {
|
469
534
|
rb_raise(rb_eFbError, "closed db connection");
|
470
535
|
}
|
@@ -488,20 +553,20 @@ static void global_close_cursors()
|
|
488
553
|
static void fb_connection_close_cursors(struct FbConnection *fb_connection)
|
489
554
|
{
|
490
555
|
int i;
|
491
|
-
|
492
|
-
for (i = 0; i <
|
493
|
-
cursor_close(
|
556
|
+
long len = RARRAY_LEN(fb_connection->cursor);
|
557
|
+
for (i = 0; i < len; i++) {
|
558
|
+
cursor_close(RARRAY_PTR(fb_connection->cursor)[i]);
|
494
559
|
}
|
495
560
|
}
|
496
561
|
|
497
562
|
static void fb_connection_drop_cursors(struct FbConnection *fb_connection)
|
498
563
|
{
|
499
564
|
int i;
|
500
|
-
|
501
|
-
for (i = 0; i <
|
502
|
-
cursor_drop(
|
565
|
+
long len = RARRAY_LEN(fb_connection->cursor);
|
566
|
+
for (i = 0; i < len; i++) {
|
567
|
+
cursor_drop(RARRAY_PTR(fb_connection->cursor)[i]);
|
503
568
|
}
|
504
|
-
|
569
|
+
rb_ary_clear(fb_connection->cursor);
|
505
570
|
}
|
506
571
|
|
507
572
|
/*
|
@@ -667,7 +732,7 @@ static trans_opts trans_opt_S[] =
|
|
667
732
|
#define RESV_WRITE "WRITE"
|
668
733
|
#define RESV_CONTINUE ','
|
669
734
|
|
670
|
-
static char* trans_parseopts(VALUE opt,
|
735
|
+
static char* trans_parseopts(VALUE opt, long *tpb_len)
|
671
736
|
{
|
672
737
|
char *s, *trans;
|
673
738
|
long used;
|
@@ -683,17 +748,17 @@ static char* trans_parseopts(VALUE opt, int *tpb_len)
|
|
683
748
|
char *resv_p;
|
684
749
|
char *resend_p;
|
685
750
|
char *tblend_p = 0;
|
686
|
-
|
687
|
-
|
751
|
+
long tbl_len;
|
752
|
+
long res_first;
|
688
753
|
int res_count;
|
689
|
-
|
754
|
+
long ofs;
|
690
755
|
char sp_prm;
|
691
756
|
char rw_prm;
|
692
757
|
int cont_f;
|
693
|
-
char *desc = 0;
|
758
|
+
const char *desc = 0;
|
694
759
|
|
695
760
|
/* Initialize */
|
696
|
-
s =
|
761
|
+
s = StringValuePtr(opt);
|
697
762
|
trans = ALLOCA_N(char, strlen(s)+1);
|
698
763
|
strcpy(trans, s);
|
699
764
|
s = trans;
|
@@ -917,7 +982,7 @@ static char* trans_parseopts(VALUE opt, int *tpb_len)
|
|
917
982
|
|
918
983
|
error:
|
919
984
|
xfree(tpb);
|
920
|
-
rb_raise(rb_eFbError, desc);
|
985
|
+
rb_raise(rb_eFbError, "%s", desc);
|
921
986
|
}
|
922
987
|
|
923
988
|
/*
|
@@ -1062,9 +1127,8 @@ static VALUE global_transaction_started()
|
|
1062
1127
|
static void fb_connection_transaction_start(struct FbConnection *fb_connection, VALUE opt)
|
1063
1128
|
{
|
1064
1129
|
char *tpb = 0;
|
1065
|
-
|
1130
|
+
long tpb_len;
|
1066
1131
|
|
1067
|
-
HERE("fb_connection_transaction_start");
|
1068
1132
|
if (fb_connection->transact) {
|
1069
1133
|
rb_raise(rb_eFbError, "A transaction has been already started");
|
1070
1134
|
}
|
@@ -1079,31 +1143,24 @@ static void fb_connection_transaction_start(struct FbConnection *fb_connection,
|
|
1079
1143
|
isc_start_transaction(fb_connection->isc_status, &fb_connection->transact, 1, &fb_connection->db, tpb_len, tpb);
|
1080
1144
|
xfree(tpb);
|
1081
1145
|
fb_error_check(fb_connection->isc_status);
|
1082
|
-
HERE("fb_connection_transaction_start Z");
|
1083
1146
|
}
|
1084
1147
|
|
1085
1148
|
static void fb_connection_commit(struct FbConnection *fb_connection)
|
1086
1149
|
{
|
1087
|
-
HERE("fb_connection_commit");
|
1088
|
-
|
1089
1150
|
if (fb_connection->transact) {
|
1090
1151
|
fb_connection_close_cursors(fb_connection);
|
1091
1152
|
isc_commit_transaction(fb_connection->isc_status, &fb_connection->transact);
|
1092
1153
|
fb_error_check(fb_connection->isc_status);
|
1093
1154
|
}
|
1094
|
-
HERE("fb_connection_commit Z");
|
1095
1155
|
}
|
1096
1156
|
|
1097
1157
|
static void fb_connection_rollback(struct FbConnection *fb_connection)
|
1098
1158
|
{
|
1099
|
-
HERE("fb_connection_rollback");
|
1100
|
-
|
1101
1159
|
if (fb_connection->transact) {
|
1102
1160
|
fb_connection_close_cursors(fb_connection);
|
1103
1161
|
isc_rollback_transaction(fb_connection->isc_status, &fb_connection->transact);
|
1104
1162
|
fb_error_check(fb_connection->isc_status);
|
1105
1163
|
}
|
1106
|
-
HERE("fb_connection_rollback Z");
|
1107
1164
|
}
|
1108
1165
|
|
1109
1166
|
/* call-seq:
|
@@ -1219,7 +1276,6 @@ static VALUE connection_cursor(VALUE self)
|
|
1219
1276
|
struct FbConnection *fb_connection;
|
1220
1277
|
struct FbCursor *fb_cursor;
|
1221
1278
|
|
1222
|
-
HERE("connection_cursor");
|
1223
1279
|
Data_Get_Struct(self, struct FbConnection, fb_connection);
|
1224
1280
|
fb_connection_check(fb_connection);
|
1225
1281
|
|
@@ -1238,7 +1294,6 @@ static VALUE connection_cursor(VALUE self)
|
|
1238
1294
|
fb_cursor->o_buffer_size = 0;
|
1239
1295
|
isc_dsql_alloc_statement2(fb_connection->isc_status, &fb_connection->db, &fb_cursor->stmt);
|
1240
1296
|
fb_error_check(fb_connection->isc_status);
|
1241
|
-
HERE("connection_cursor Z");
|
1242
1297
|
|
1243
1298
|
return c;
|
1244
1299
|
}
|
@@ -1269,7 +1324,6 @@ static VALUE connection_cursor(VALUE self)
|
|
1269
1324
|
*/
|
1270
1325
|
static VALUE connection_execute(int argc, VALUE *argv, VALUE self)
|
1271
1326
|
{
|
1272
|
-
HERE("connection_execute");
|
1273
1327
|
VALUE cursor = connection_cursor(self);
|
1274
1328
|
VALUE val = cursor_execute(argc, argv, cursor);
|
1275
1329
|
|
@@ -1283,7 +1337,6 @@ static VALUE connection_execute(int argc, VALUE *argv, VALUE self)
|
|
1283
1337
|
} else {
|
1284
1338
|
cursor_drop(cursor);
|
1285
1339
|
}
|
1286
|
-
HERE("connection_execute Z");
|
1287
1340
|
return val;
|
1288
1341
|
}
|
1289
1342
|
|
@@ -1308,7 +1361,6 @@ static VALUE connection_query(int argc, VALUE *argv, VALUE self)
|
|
1308
1361
|
VALUE cursor;
|
1309
1362
|
VALUE result;
|
1310
1363
|
|
1311
|
-
HERE("connection_query");
|
1312
1364
|
if (argc >= 1 && TYPE(argv[0]) == T_SYMBOL) {
|
1313
1365
|
format = argv[0];
|
1314
1366
|
argc--; argv++;
|
@@ -1321,7 +1373,6 @@ static VALUE connection_query(int argc, VALUE *argv, VALUE self)
|
|
1321
1373
|
result = cursor_fetchall(1, &format, cursor);
|
1322
1374
|
cursor_close(cursor);
|
1323
1375
|
}
|
1324
|
-
HERE("connection_query Z");
|
1325
1376
|
|
1326
1377
|
return result;
|
1327
1378
|
}
|
@@ -1444,7 +1495,7 @@ static void fb_cursor_free(struct FbCursor *fb_cursor)
|
|
1444
1495
|
xfree(fb_cursor);
|
1445
1496
|
}
|
1446
1497
|
|
1447
|
-
static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor,
|
1498
|
+
static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, long argc, VALUE *argv)
|
1448
1499
|
{
|
1449
1500
|
struct FbConnection *fb_connection;
|
1450
1501
|
long count;
|
@@ -1475,7 +1526,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1475
1526
|
|
1476
1527
|
/* Check the number of parameters */
|
1477
1528
|
if (fb_cursor->i_sqlda->sqld != argc) {
|
1478
|
-
rb_raise(rb_eFbError, "statement requires %d items; %
|
1529
|
+
rb_raise(rb_eFbError, "statement requires %d items; %ld given", fb_cursor->i_sqlda->sqld, argc);
|
1479
1530
|
}
|
1480
1531
|
|
1481
1532
|
/* Get the parameters */
|
@@ -1496,12 +1547,12 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1496
1547
|
offset = FB_ALIGN(offset, alignment);
|
1497
1548
|
var->sqldata = (char *)(fb_cursor->i_buffer + offset);
|
1498
1549
|
obj = rb_obj_as_string(obj);
|
1499
|
-
if (
|
1500
|
-
rb_raise(rb_eRangeError, "CHAR overflow: %
|
1501
|
-
|
1550
|
+
if (RSTRING_LEN(obj) > var->sqllen) {
|
1551
|
+
rb_raise(rb_eRangeError, "CHAR overflow: %ld bytes exceeds %d byte(s) allowed.",
|
1552
|
+
RSTRING_LEN(obj), var->sqllen);
|
1502
1553
|
}
|
1503
|
-
memcpy(var->sqldata,
|
1504
|
-
var->sqllen =
|
1554
|
+
memcpy(var->sqldata, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
1555
|
+
var->sqllen = RSTRING_LEN(obj);
|
1505
1556
|
offset += var->sqllen + 1;
|
1506
1557
|
break;
|
1507
1558
|
|
@@ -1511,12 +1562,12 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1511
1562
|
var->sqldata = (char *)(fb_cursor->i_buffer + offset);
|
1512
1563
|
vary = (VARY *)var->sqldata;
|
1513
1564
|
obj = rb_obj_as_string(obj);
|
1514
|
-
if (
|
1515
|
-
rb_raise(rb_eRangeError, "VARCHAR overflow: %
|
1516
|
-
|
1565
|
+
if (RSTRING_LEN(obj) > var->sqllen) {
|
1566
|
+
rb_raise(rb_eRangeError, "VARCHAR overflow: %ld bytes exceeds %d byte(s) allowed.",
|
1567
|
+
RSTRING_LEN(obj), var->sqllen);
|
1517
1568
|
}
|
1518
|
-
memcpy(vary->vary_string,
|
1519
|
-
vary->vary_length =
|
1569
|
+
memcpy(vary->vary_string, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
1570
|
+
vary->vary_length = RSTRING_LEN(obj);
|
1520
1571
|
offset += vary->vary_length + sizeof(short);
|
1521
1572
|
break;
|
1522
1573
|
|
@@ -1558,7 +1609,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1558
1609
|
if (lvalue < -2147483647 || lvalue > 2147483647) {
|
1559
1610
|
rb_raise(rb_eRangeError, "integer overflow");
|
1560
1611
|
}
|
1561
|
-
*(ISC_LONG *)var->sqldata = lvalue;
|
1612
|
+
*(ISC_LONG *)var->sqldata = (ISC_LONG)lvalue;
|
1562
1613
|
offset += alignment;
|
1563
1614
|
break;
|
1564
1615
|
|
@@ -1575,7 +1626,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1575
1626
|
if (dcheck != 0.0 && (dcheck < FLT_MIN || dcheck > FLT_MAX)) {
|
1576
1627
|
rb_raise(rb_eRangeError, "float overflow");
|
1577
1628
|
}
|
1578
|
-
*(float *)var->sqldata = dvalue;
|
1629
|
+
*(float *)var->sqldata = (float)dvalue;
|
1579
1630
|
offset += alignment;
|
1580
1631
|
break;
|
1581
1632
|
|
@@ -1618,8 +1669,8 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1618
1669
|
fb_connection->isc_status,&fb_connection->db,&fb_connection->transact,
|
1619
1670
|
&blob_handle,&blob_id,0,NULL);
|
1620
1671
|
fb_error_check(fb_connection->isc_status);
|
1621
|
-
length =
|
1622
|
-
p =
|
1672
|
+
length = RSTRING_LEN(obj);
|
1673
|
+
p = RSTRING_PTR(obj);
|
1623
1674
|
while (length >= 4096) {
|
1624
1675
|
isc_put_segment(fb_connection->isc_status,&blob_handle,4096,p);
|
1625
1676
|
fb_error_check(fb_connection->isc_status);
|
@@ -1697,7 +1748,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
|
|
1697
1748
|
}
|
1698
1749
|
}
|
1699
1750
|
|
1700
|
-
static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor,
|
1751
|
+
static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, long argc, VALUE *argv)
|
1701
1752
|
{
|
1702
1753
|
struct FbConnection *fb_connection;
|
1703
1754
|
|
@@ -1707,8 +1758,8 @@ static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, int argc, V
|
|
1707
1758
|
int i;
|
1708
1759
|
VALUE obj;
|
1709
1760
|
VALUE ary = argv[0];
|
1710
|
-
if (
|
1711
|
-
for (i = 0; i <
|
1761
|
+
if (RARRAY_LEN(ary) > 0 && TYPE(RARRAY_PTR(ary)[0]) == T_ARRAY) {
|
1762
|
+
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
1712
1763
|
obj = rb_ary_entry(ary, i);
|
1713
1764
|
fb_cursor_execute_withparams(fb_cursor, 1, &obj);
|
1714
1765
|
}
|
@@ -1718,7 +1769,7 @@ static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, int argc, V
|
|
1718
1769
|
|
1719
1770
|
/* Set the input parameters */
|
1720
1771
|
Check_Type(obj, T_ARRAY);
|
1721
|
-
fb_cursor_set_inputparams(fb_cursor,
|
1772
|
+
fb_cursor_set_inputparams(fb_cursor, RARRAY_LEN(obj), RARRAY_PTR(obj));
|
1722
1773
|
|
1723
1774
|
/* Execute SQL statement */
|
1724
1775
|
isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, fb_cursor->i_sqlda, NULL);
|
@@ -1782,16 +1833,13 @@ static VALUE precision_from_sqlvar(XSQLVAR *sqlvar)
|
|
1782
1833
|
|
1783
1834
|
static int no_lowercase(VALUE value)
|
1784
1835
|
{
|
1785
|
-
|
1786
|
-
|
1787
|
-
int result = rb_funcall(re_lowercase, id_matches, 1, value) == Qnil;
|
1788
|
-
HERE("no_lowercase Z");
|
1836
|
+
VALUE local_value = StringValue(value);
|
1837
|
+
int result = rb_funcall(re_lowercase, id_matches, 1, local_value) == Qnil;
|
1789
1838
|
return result;
|
1790
1839
|
}
|
1791
1840
|
|
1792
1841
|
static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
|
1793
1842
|
{
|
1794
|
-
HERE("fb_cursor_fields_ary");
|
1795
1843
|
long cols;
|
1796
1844
|
long count;
|
1797
1845
|
XSQLVAR *var;
|
@@ -1837,23 +1885,20 @@ static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
|
|
1837
1885
|
rb_ary_push(ary, field);
|
1838
1886
|
}
|
1839
1887
|
rb_ary_freeze(ary);
|
1840
|
-
HERE("fb_cursor_fields_ary Z");
|
1841
1888
|
return ary;
|
1842
1889
|
}
|
1843
1890
|
|
1844
1891
|
static VALUE fb_cursor_fields_hash(VALUE fields_ary)
|
1845
1892
|
{
|
1846
|
-
HERE("fb_cursor_fields_hash");
|
1847
1893
|
int i;
|
1848
1894
|
VALUE hash = rb_hash_new();
|
1849
1895
|
|
1850
|
-
for (i = 0; i <
|
1896
|
+
for (i = 0; i < RARRAY_LEN(fields_ary); i++) {
|
1851
1897
|
VALUE field = rb_ary_entry(fields_ary, i);
|
1852
1898
|
VALUE name = rb_struct_aref(field, LONG2NUM(0));
|
1853
1899
|
rb_hash_aset(hash, name, field);
|
1854
1900
|
}
|
1855
1901
|
|
1856
|
-
HERE("fb_cursor_fields_hash Z");
|
1857
1902
|
return hash;
|
1858
1903
|
}
|
1859
1904
|
|
@@ -1964,11 +2009,17 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
1964
2009
|
switch (dtp) {
|
1965
2010
|
case SQL_TEXT:
|
1966
2011
|
val = rb_tainted_str_new(var->sqldata, var->sqllen);
|
2012
|
+
#if HAVE_RUBY_ENCODING_H
|
2013
|
+
rb_funcall(val, id_force_encoding, 1, fb_connection->encoding);
|
2014
|
+
#endif
|
1967
2015
|
break;
|
1968
2016
|
|
1969
2017
|
case SQL_VARYING:
|
1970
2018
|
vary = (VARY*)var->sqldata;
|
1971
2019
|
val = rb_tainted_str_new(vary->vary_string, vary->vary_length);
|
2020
|
+
#if HAVE_RUBY_ENCODING_H
|
2021
|
+
rb_funcall(val, id_force_encoding, 1, fb_connection->encoding);
|
2022
|
+
#endif
|
1972
2023
|
break;
|
1973
2024
|
|
1974
2025
|
case SQL_SHORT:
|
@@ -2057,10 +2108,13 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
2057
2108
|
}
|
2058
2109
|
}
|
2059
2110
|
val = rb_tainted_str_new(NULL,total_length);
|
2060
|
-
for (p =
|
2111
|
+
for (p = RSTRING_PTR(val); num_segments > 0; num_segments--, p += actual_seg_len) {
|
2061
2112
|
isc_get_segment(fb_connection->isc_status, &blob_handle, &actual_seg_len, max_segment, p);
|
2062
2113
|
fb_error_check(fb_connection->isc_status);
|
2063
2114
|
}
|
2115
|
+
#if HAVE_RUBY_ENCODING_H
|
2116
|
+
rb_funcall(val, id_force_encoding, 1, fb_connection->encoding);
|
2117
|
+
#endif
|
2064
2118
|
isc_close_blob(fb_connection->isc_status, &blob_handle);
|
2065
2119
|
fb_error_check(fb_connection->isc_status);
|
2066
2120
|
break;
|
@@ -2071,7 +2125,7 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
|
|
2071
2125
|
break;
|
2072
2126
|
|
2073
2127
|
default:
|
2074
|
-
rb_raise(rb_eFbError, "Specified table includes unsupported datatype (%
|
2128
|
+
rb_raise(rb_eFbError, "Specified table includes unsupported datatype (%ld)", dtp);
|
2075
2129
|
break;
|
2076
2130
|
}
|
2077
2131
|
}
|
@@ -2129,10 +2183,10 @@ static long cursor_rows_affected(struct FbCursor *fb_cursor, long statement_type
|
|
2129
2183
|
*/
|
2130
2184
|
static VALUE cursor_execute2(VALUE args)
|
2131
2185
|
{
|
2132
|
-
HERE("cursor_execute2");
|
2133
2186
|
struct FbCursor *fb_cursor;
|
2134
2187
|
struct FbConnection *fb_connection;
|
2135
2188
|
char *sql;
|
2189
|
+
VALUE rb_sql;
|
2136
2190
|
long statement;
|
2137
2191
|
long length;
|
2138
2192
|
long in_params;
|
@@ -2146,7 +2200,8 @@ static VALUE cursor_execute2(VALUE args)
|
|
2146
2200
|
Data_Get_Struct(self, struct FbCursor, fb_cursor);
|
2147
2201
|
Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
|
2148
2202
|
|
2149
|
-
|
2203
|
+
rb_sql = rb_ary_shift(args);
|
2204
|
+
sql = StringValuePtr(rb_sql);
|
2150
2205
|
|
2151
2206
|
/* Prepare query */
|
2152
2207
|
isc_dsql_prepare(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, 0, sql, fb_connection_dialect(fb_connection), fb_cursor->o_sqlda);
|
@@ -2199,7 +2254,7 @@ static VALUE cursor_execute2(VALUE args)
|
|
2199
2254
|
} else if (statement == isc_info_sql_stmt_rollback) {
|
2200
2255
|
rb_raise(rb_eFbError, "use Fb::Connection#rollback()");
|
2201
2256
|
} else if (in_params) {
|
2202
|
-
fb_cursor_execute_withparams(fb_cursor,
|
2257
|
+
fb_cursor_execute_withparams(fb_cursor, RARRAY_LEN(args), RARRAY_PTR(args));
|
2203
2258
|
} else {
|
2204
2259
|
isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, NULL, NULL);
|
2205
2260
|
fb_error_check(fb_connection->isc_status);
|
@@ -2219,7 +2274,7 @@ static VALUE cursor_execute2(VALUE args)
|
|
2219
2274
|
}
|
2220
2275
|
|
2221
2276
|
if (in_params) {
|
2222
|
-
fb_cursor_set_inputparams(fb_cursor,
|
2277
|
+
fb_cursor_set_inputparams(fb_cursor, RARRAY_LEN(args), RARRAY_PTR(args));
|
2223
2278
|
}
|
2224
2279
|
|
2225
2280
|
/* Open cursor */
|
@@ -2237,9 +2292,7 @@ static VALUE cursor_execute2(VALUE args)
|
|
2237
2292
|
/* Set the description attributes */
|
2238
2293
|
fb_cursor->fields_ary = fb_cursor_fields_ary(fb_cursor->o_sqlda, fb_connection->downcase_names);
|
2239
2294
|
fb_cursor->fields_hash = fb_cursor_fields_hash(fb_cursor->fields_ary);
|
2240
|
-
HERE("cursor_execute2 Z");
|
2241
2295
|
}
|
2242
|
-
HERE("cursor_execute2 Z");
|
2243
2296
|
return result;
|
2244
2297
|
}
|
2245
2298
|
|
@@ -2250,7 +2303,6 @@ static VALUE cursor_execute2(VALUE args)
|
|
2250
2303
|
*/
|
2251
2304
|
static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
|
2252
2305
|
{
|
2253
|
-
HERE("cursor_execute");
|
2254
2306
|
struct FbCursor *fb_cursor;
|
2255
2307
|
struct FbConnection *fb_connection;
|
2256
2308
|
VALUE args;
|
@@ -2285,14 +2337,11 @@ static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
|
|
2285
2337
|
return rb_funcall(rb_mKernel, rb_intern("raise"), 0);
|
2286
2338
|
} else if (result != Qnil) {
|
2287
2339
|
fb_connection_commit(fb_connection);
|
2288
|
-
HERE("cursor_execute X");
|
2289
2340
|
return result;
|
2290
2341
|
} else {
|
2291
|
-
HERE("cursor_execute Y");
|
2292
2342
|
return result;
|
2293
2343
|
}
|
2294
2344
|
} else {
|
2295
|
-
HERE("cursor_execute Z");
|
2296
2345
|
return cursor_execute2(args);
|
2297
2346
|
}
|
2298
2347
|
}
|
@@ -2301,7 +2350,7 @@ static VALUE fb_hash_from_ary(VALUE fields, VALUE row)
|
|
2301
2350
|
{
|
2302
2351
|
VALUE hash = rb_hash_new();
|
2303
2352
|
int i;
|
2304
|
-
for (i = 0; i <
|
2353
|
+
for (i = 0; i < RARRAY_LEN(fields); i++) {
|
2305
2354
|
VALUE field = rb_ary_entry(fields, i);
|
2306
2355
|
VALUE name = rb_struct_aref(field, LONG2NUM(0));
|
2307
2356
|
VALUE v = rb_ary_entry(row, i);
|
@@ -2464,9 +2513,9 @@ static VALUE cursor_drop(VALUE self)
|
|
2464
2513
|
|
2465
2514
|
/* reset the reference from connection */
|
2466
2515
|
Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
|
2467
|
-
for (i = 0; i <
|
2468
|
-
if (
|
2469
|
-
|
2516
|
+
for (i = 0; i < RARRAY_LEN(fb_connection->cursor); i++) {
|
2517
|
+
if (RARRAY_PTR(fb_connection->cursor)[i] == self) {
|
2518
|
+
RARRAY_PTR(fb_connection->cursor)[i] = Qnil;
|
2470
2519
|
}
|
2471
2520
|
}
|
2472
2521
|
|
@@ -2507,7 +2556,7 @@ static VALUE error_error_code(VALUE error)
|
|
2507
2556
|
return rb_iv_get(error, "error_code");
|
2508
2557
|
}
|
2509
2558
|
|
2510
|
-
static char* dbp_create(
|
2559
|
+
static char* dbp_create(long *length)
|
2511
2560
|
{
|
2512
2561
|
char *dbp = ALLOC_N(char, 1);
|
2513
2562
|
*dbp = isc_dpb_version1;
|
@@ -2515,11 +2564,11 @@ static char* dbp_create(int *length)
|
|
2515
2564
|
return dbp;
|
2516
2565
|
}
|
2517
2566
|
|
2518
|
-
static char* dbp_add_string(char *dbp, char isc_dbp_code, char *s,
|
2567
|
+
static char* dbp_add_string(char *dbp, char isc_dbp_code, char *s, long *length)
|
2519
2568
|
{
|
2520
2569
|
char *buf;
|
2521
|
-
|
2522
|
-
|
2570
|
+
long old_length = *length;
|
2571
|
+
long s_len = strlen(s);
|
2523
2572
|
*length += 2 + s_len;
|
2524
2573
|
REALLOC_N(dbp, char, *length);
|
2525
2574
|
buf = dbp + old_length;
|
@@ -2529,7 +2578,7 @@ static char* dbp_add_string(char *dbp, char isc_dbp_code, char *s, int *length)
|
|
2529
2578
|
return dbp;
|
2530
2579
|
}
|
2531
2580
|
|
2532
|
-
static char* connection_create_dbp(VALUE self,
|
2581
|
+
static char* connection_create_dbp(VALUE self, long *length)
|
2533
2582
|
{
|
2534
2583
|
char *dbp;
|
2535
2584
|
VALUE username, password, charset, role;
|
@@ -2542,24 +2591,25 @@ static char* connection_create_dbp(VALUE self, int *length)
|
|
2542
2591
|
charset = rb_iv_get(self, "@charset");
|
2543
2592
|
|
2544
2593
|
dbp = dbp_create(length);
|
2545
|
-
dbp = dbp_add_string(dbp, isc_dpb_user_name,
|
2546
|
-
dbp = dbp_add_string(dbp, isc_dpb_password,
|
2594
|
+
dbp = dbp_add_string(dbp, isc_dpb_user_name, StringValuePtr(username), length);
|
2595
|
+
dbp = dbp_add_string(dbp, isc_dpb_password, StringValuePtr(password), length);
|
2547
2596
|
if (!NIL_P(charset)) {
|
2548
|
-
dbp = dbp_add_string(dbp, isc_dpb_lc_ctype,
|
2597
|
+
dbp = dbp_add_string(dbp, isc_dpb_lc_ctype, StringValuePtr(charset), length);
|
2549
2598
|
}
|
2550
2599
|
if (!NIL_P(role)) {
|
2551
|
-
dbp = dbp_add_string(dbp, isc_dpb_sql_role_name,
|
2600
|
+
dbp = dbp_add_string(dbp, isc_dpb_sql_role_name, StringValuePtr(role), length);
|
2552
2601
|
}
|
2553
2602
|
return dbp;
|
2554
2603
|
}
|
2555
2604
|
|
2556
|
-
static char* CONNECTION_PARMS[] = {
|
2605
|
+
static const char* CONNECTION_PARMS[] = {
|
2557
2606
|
"@database",
|
2558
2607
|
"@username",
|
2559
2608
|
"@password",
|
2560
2609
|
"@charset",
|
2561
2610
|
"@role",
|
2562
2611
|
"@downcase_names",
|
2612
|
+
"@encoding",
|
2563
2613
|
(char *)0
|
2564
2614
|
};
|
2565
2615
|
|
@@ -2568,7 +2618,7 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
|
|
2568
2618
|
unsigned short dialect;
|
2569
2619
|
unsigned short db_dialect;
|
2570
2620
|
VALUE downcase_names;
|
2571
|
-
char *parm;
|
2621
|
+
const char *parm;
|
2572
2622
|
int i;
|
2573
2623
|
struct FbConnection *fb_connection;
|
2574
2624
|
VALUE connection = Data_Make_Struct(rb_cFbConnection, struct FbConnection, fb_connection_mark, fb_connection_free, fb_connection);
|
@@ -2592,6 +2642,7 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
|
|
2592
2642
|
fb_connection->db_dialect = db_dialect;
|
2593
2643
|
downcase_names = rb_iv_get(db, "@downcase_names");
|
2594
2644
|
fb_connection->downcase_names = RTEST(downcase_names);
|
2645
|
+
fb_connection->encoding = rb_iv_get(db, "@encoding");
|
2595
2646
|
|
2596
2647
|
for (i = 0; (parm = CONNECTION_PARMS[i]); i++) {
|
2597
2648
|
rb_iv_set(connection, parm, rb_iv_get(db, parm));
|
@@ -2600,7 +2651,7 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
|
|
2600
2651
|
return connection;
|
2601
2652
|
}
|
2602
2653
|
|
2603
|
-
static VALUE connection_names(VALUE self, char *sql)
|
2654
|
+
static VALUE connection_names(VALUE self, const char *sql)
|
2604
2655
|
{
|
2605
2656
|
VALUE row;
|
2606
2657
|
VALUE query = rb_str_new2(sql);
|
@@ -2629,7 +2680,7 @@ static VALUE connection_names(VALUE self, char *sql)
|
|
2629
2680
|
*/
|
2630
2681
|
static VALUE connection_table_names(VALUE self)
|
2631
2682
|
{
|
2632
|
-
char *sql = "SELECT RDB$RELATION_NAME FROM RDB$RELATIONS "
|
2683
|
+
const char *sql = "SELECT RDB$RELATION_NAME FROM RDB$RELATIONS "
|
2633
2684
|
"WHERE (RDB$SYSTEM_FLAG <> 1 OR RDB$SYSTEM_FLAG IS NULL) AND RDB$VIEW_BLR IS NULL "
|
2634
2685
|
"ORDER BY RDB$RELATION_NAME";
|
2635
2686
|
return connection_names(self, sql);
|
@@ -2642,7 +2693,7 @@ static VALUE connection_table_names(VALUE self)
|
|
2642
2693
|
*/
|
2643
2694
|
static VALUE connection_generator_names(VALUE self)
|
2644
2695
|
{
|
2645
|
-
char *sql = "SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS "
|
2696
|
+
const char *sql = "SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS "
|
2646
2697
|
"WHERE (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG <> 1) "
|
2647
2698
|
"ORDER BY RDB$GENERATOR_NAME";
|
2648
2699
|
return connection_names(self, sql);
|
@@ -2655,7 +2706,7 @@ static VALUE connection_generator_names(VALUE self)
|
|
2655
2706
|
*/
|
2656
2707
|
static VALUE connection_view_names(VALUE self)
|
2657
2708
|
{
|
2658
|
-
char *sql = "SELECT RDB$RELATION_NAME, RDB$OWNER_NAME, RDB$VIEW_SOURCE FROM RDB$RELATIONS "
|
2709
|
+
const char *sql = "SELECT RDB$RELATION_NAME, RDB$OWNER_NAME, RDB$VIEW_SOURCE FROM RDB$RELATIONS "
|
2659
2710
|
"WHERE (RDB$SYSTEM_FLAG <> 1 OR RDB$SYSTEM_FLAG IS NULL) AND NOT RDB$VIEW_BLR IS NULL AND RDB$FLAGS = 1 "
|
2660
2711
|
"ORDER BY RDB$RELATION_ID";
|
2661
2712
|
return connection_names(self, sql);
|
@@ -2668,7 +2719,7 @@ static VALUE connection_view_names(VALUE self)
|
|
2668
2719
|
*/
|
2669
2720
|
static VALUE connection_role_names(VALUE self)
|
2670
2721
|
{
|
2671
|
-
char *sql = "SELECT * FROM RDB$ROLES ORDER BY RDB$ROLE_NAME";
|
2722
|
+
const char *sql = "SELECT * FROM RDB$ROLES WHERE RDB$SYSTEM_FLAG = 0 ORDER BY RDB$ROLE_NAME";
|
2672
2723
|
return connection_names(self, sql);
|
2673
2724
|
}
|
2674
2725
|
|
@@ -2679,7 +2730,7 @@ static VALUE connection_role_names(VALUE self)
|
|
2679
2730
|
*/
|
2680
2731
|
static VALUE connection_procedure_names(VALUE self)
|
2681
2732
|
{
|
2682
|
-
char *sql = "SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES "
|
2733
|
+
const char *sql = "SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES "
|
2683
2734
|
"ORDER BY RDB$PROCEDURE_NAME";
|
2684
2735
|
return connection_names(self, sql);
|
2685
2736
|
}
|
@@ -2691,7 +2742,7 @@ static VALUE connection_procedure_names(VALUE self)
|
|
2691
2742
|
*/
|
2692
2743
|
static VALUE connection_trigger_names(VALUE self)
|
2693
2744
|
{
|
2694
|
-
char *sql = "SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS "
|
2745
|
+
const char *sql = "SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS "
|
2695
2746
|
"ORDER BY RDB$TRIGGER_NAME";
|
2696
2747
|
return connection_names(self, sql);
|
2697
2748
|
}
|
@@ -2705,12 +2756,12 @@ static VALUE connection_trigger_names(VALUE self)
|
|
2705
2756
|
static VALUE connection_columns(VALUE self, VALUE table_name)
|
2706
2757
|
{
|
2707
2758
|
int i;
|
2708
|
-
|
2709
|
-
VALUE re_default = rb_reg_new("^\\s*DEFAULT\\s+", strlen("^\\s*DEFAULT\\s+"),
|
2759
|
+
struct FbConnection *fb_connection;
|
2760
|
+
VALUE re_default = rb_reg_new("^\\s*DEFAULT\\s+", strlen("^\\s*DEFAULT\\s+"), IGNORECASE);
|
2710
2761
|
VALUE re_rdb = rb_reg_new("^RDB\\$", strlen("^RDB\\$"), 0);
|
2711
2762
|
VALUE empty = rb_str_new(NULL, 0);
|
2712
2763
|
VALUE columns = rb_ary_new();
|
2713
|
-
char *sql = "SELECT r.rdb$field_name NAME, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type, "
|
2764
|
+
const char *sql = "SELECT r.rdb$field_name NAME, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type, "
|
2714
2765
|
"f.rdb$field_length, f.rdb$field_precision, f.rdb$field_scale SCALE, "
|
2715
2766
|
"COALESCE(r.rdb$default_source, f.rdb$default_source), "
|
2716
2767
|
"COALESCE(r.rdb$null_flag, f.rdb$null_flag) "
|
@@ -2719,11 +2770,11 @@ static VALUE connection_columns(VALUE self, VALUE table_name)
|
|
2719
2770
|
"WHERE UPPER(r.rdb$relation_name) = ? "
|
2720
2771
|
"ORDER BY r.rdb$field_position";
|
2721
2772
|
VALUE query = rb_str_new2(sql);
|
2722
|
-
|
2723
|
-
VALUE query_parms[] = { query,
|
2773
|
+
VALUE upcase_table_name = rb_funcall(table_name, rb_intern("upcase"), 0);
|
2774
|
+
VALUE query_parms[] = { query, upcase_table_name };
|
2724
2775
|
VALUE rs = connection_query(2, query_parms, self);
|
2725
|
-
|
2726
|
-
for (i = 0; i <
|
2776
|
+
Data_Get_Struct(self, struct FbConnection, fb_connection);
|
2777
|
+
for (i = 0; i < RARRAY_LEN(rs); i++) {
|
2727
2778
|
VALUE row = rb_ary_entry(rs, i);
|
2728
2779
|
VALUE name = rb_ary_entry(row, 0);
|
2729
2780
|
VALUE domain = rb_ary_entry(row, 1);
|
@@ -2734,23 +2785,25 @@ static VALUE connection_columns(VALUE self, VALUE table_name)
|
|
2734
2785
|
VALUE scale = rb_ary_entry(row, 6);
|
2735
2786
|
VALUE dflt = rb_ary_entry(row, 7);
|
2736
2787
|
VALUE not_null = rb_ary_entry(row, 8);
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2788
|
+
VALUE nullable;
|
2789
|
+
VALUE column;
|
2790
|
+
rb_funcall(name, id_rstrip_bang, 0);
|
2791
|
+
rb_funcall(domain, id_rstrip_bang, 0);
|
2792
|
+
if (fb_connection->downcase_names && no_lowercase(name)) {
|
2793
|
+
rb_funcall(name, id_downcase_bang, 0);
|
2794
|
+
}
|
2795
|
+
if (rb_funcall(re_rdb, rb_intern("match"), 1, domain) != Qnil) {
|
2743
2796
|
domain = Qnil;
|
2744
2797
|
}
|
2745
|
-
|
2798
|
+
if (sql_subtype == Qnil) {
|
2746
2799
|
sql_subtype = INT2NUM(0);
|
2747
|
-
|
2800
|
+
}
|
2748
2801
|
sql_type = sql_type_from_code(self, sql_type, sql_subtype);
|
2749
2802
|
if (dflt != Qnil) {
|
2750
2803
|
rb_funcall(dflt, id_sub_bang, 2, re_default, empty);
|
2751
2804
|
}
|
2752
|
-
|
2753
|
-
|
2805
|
+
nullable = RTEST(not_null) ? Qfalse : Qtrue;
|
2806
|
+
column = rb_struct_new(rb_sFbColumn, name, domain, sql_type, sql_subtype, length, precision, scale, dflt, nullable);
|
2754
2807
|
rb_ary_push(columns, column);
|
2755
2808
|
}
|
2756
2809
|
rb_ary_freeze(columns);
|
@@ -2770,7 +2823,7 @@ char *p(char *prompt, VALUE s)
|
|
2770
2823
|
|
2771
2824
|
static VALUE connection_index_columns(VALUE self, VALUE index_name)
|
2772
2825
|
{
|
2773
|
-
char *sql_columns = "SELECT * "
|
2826
|
+
const char *sql_columns = "SELECT * "
|
2774
2827
|
"FROM RDB$INDEX_SEGMENTS "
|
2775
2828
|
"WHERE RDB$INDEX_SEGMENTS.RDB$INDEX_NAME = ? "
|
2776
2829
|
"ORDER BY RDB$INDEX_SEGMENTS.RDB$FIELD_POSITION";
|
@@ -2782,7 +2835,7 @@ static VALUE connection_index_columns(VALUE self, VALUE index_name)
|
|
2782
2835
|
struct FbConnection *fb_connection;
|
2783
2836
|
Data_Get_Struct(self, struct FbConnection, fb_connection);
|
2784
2837
|
|
2785
|
-
for (i = 0; i <
|
2838
|
+
for (i = 0; i < RARRAY_LEN(result); i++) {
|
2786
2839
|
VALUE row = rb_ary_entry(result, i);
|
2787
2840
|
VALUE name = rb_ary_entry(row, 1);
|
2788
2841
|
rb_funcall(name, id_rstrip_bang, 0);
|
@@ -2801,7 +2854,7 @@ static VALUE connection_index_columns(VALUE self, VALUE index_name)
|
|
2801
2854
|
*/
|
2802
2855
|
static VALUE connection_indexes(VALUE self)
|
2803
2856
|
{
|
2804
|
-
char *sql_indexes = "SELECT RDB$INDICES.RDB$RELATION_NAME, RDB$INDICES.RDB$INDEX_NAME, RDB$INDICES.RDB$UNIQUE_FLAG, RDB$INDICES.RDB$INDEX_TYPE "
|
2857
|
+
const char *sql_indexes = "SELECT RDB$INDICES.RDB$RELATION_NAME, RDB$INDICES.RDB$INDEX_NAME, RDB$INDICES.RDB$UNIQUE_FLAG, RDB$INDICES.RDB$INDEX_TYPE "
|
2805
2858
|
"FROM RDB$INDICES "
|
2806
2859
|
" JOIN RDB$RELATIONS ON RDB$INDICES.RDB$RELATION_NAME = RDB$RELATIONS.RDB$RELATION_NAME "
|
2807
2860
|
"WHERE (RDB$RELATIONS.RDB$SYSTEM_FLAG <> 1 OR RDB$RELATIONS.RDB$SYSTEM_FLAG IS NULL) ";
|
@@ -2812,7 +2865,7 @@ static VALUE connection_indexes(VALUE self)
|
|
2812
2865
|
struct FbConnection *fb_connection;
|
2813
2866
|
Data_Get_Struct(self, struct FbConnection, fb_connection);
|
2814
2867
|
|
2815
|
-
for (i = 0; i <
|
2868
|
+
for (i = 0; i < RARRAY_LEN(ary_indexes); i++) {
|
2816
2869
|
VALUE index_struct;
|
2817
2870
|
VALUE row = rb_ary_entry(ary_indexes, i);
|
2818
2871
|
VALUE table_name = rb_ary_entry(row, 0);
|
@@ -2857,14 +2910,14 @@ static void define_attrs(VALUE klass, char **attrs)
|
|
2857
2910
|
}
|
2858
2911
|
*/
|
2859
2912
|
|
2860
|
-
static VALUE default_string(VALUE hash, char *key, char *def)
|
2913
|
+
static VALUE default_string(VALUE hash, const char *key, const char *def)
|
2861
2914
|
{
|
2862
2915
|
VALUE sym = ID2SYM(rb_intern(key));
|
2863
2916
|
VALUE val = rb_hash_aref(hash, sym);
|
2864
2917
|
return NIL_P(val) ? rb_str_new2(def) : StringValue(val);
|
2865
2918
|
}
|
2866
2919
|
|
2867
|
-
static VALUE default_int(VALUE hash, char *key, int def)
|
2920
|
+
static VALUE default_int(VALUE hash, const char *key, int def)
|
2868
2921
|
{
|
2869
2922
|
VALUE sym = ID2SYM(rb_intern(key));
|
2870
2923
|
VALUE val = rb_hash_aref(hash, sym);
|
@@ -2873,9 +2926,9 @@ static VALUE default_int(VALUE hash, char *key, int def)
|
|
2873
2926
|
|
2874
2927
|
static VALUE database_allocate_instance(VALUE klass)
|
2875
2928
|
{
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2929
|
+
NEWOBJ(obj, struct RObject);
|
2930
|
+
OBJSETUP(obj, klass, T_OBJECT);
|
2931
|
+
return (VALUE)obj;
|
2879
2932
|
}
|
2880
2933
|
|
2881
2934
|
static VALUE hash_from_connection_string(VALUE cs)
|
@@ -2886,10 +2939,10 @@ static VALUE hash_from_connection_string(VALUE cs)
|
|
2886
2939
|
ID id_split = rb_intern("split");
|
2887
2940
|
VALUE pairs = rb_funcall(cs, id_split, 1, re_SemiColon);
|
2888
2941
|
int i;
|
2889
|
-
for (i = 0; i <
|
2942
|
+
for (i = 0; i < RARRAY_LEN(pairs); i++) {
|
2890
2943
|
VALUE pair = rb_ary_entry(pairs, i);
|
2891
2944
|
VALUE keyValue = rb_funcall(pair, id_split, 1, re_Equal);
|
2892
|
-
if (
|
2945
|
+
if (RARRAY_LEN(keyValue) == 2) {
|
2893
2946
|
VALUE key = rb_ary_entry(keyValue, 0);
|
2894
2947
|
VALUE val = rb_ary_entry(keyValue, 1);
|
2895
2948
|
rb_hash_aset(hash, rb_str_intern(key), val);
|
@@ -2936,6 +2989,7 @@ static VALUE database_initialize(int argc, VALUE *argv, VALUE self)
|
|
2936
2989
|
rb_iv_set(self, "@charset", default_string(parms, "charset", "NONE"));
|
2937
2990
|
rb_iv_set(self, "@role", rb_hash_aref(parms, ID2SYM(rb_intern("role"))));
|
2938
2991
|
rb_iv_set(self, "@downcase_names", rb_hash_aref(parms, ID2SYM(rb_intern("downcase_names"))));
|
2992
|
+
rb_iv_set(self, "@encoding", default_string(parms, "encoding", "ASCII-8BIT"));
|
2939
2993
|
rb_iv_set(self, "@page_size", default_int(parms, "page_size", 1024));
|
2940
2994
|
}
|
2941
2995
|
return self;
|
@@ -3015,13 +3069,13 @@ static VALUE database_connect(VALUE self)
|
|
3015
3069
|
{
|
3016
3070
|
ISC_STATUS isc_status[20];
|
3017
3071
|
char *dbp;
|
3018
|
-
|
3072
|
+
long length;
|
3019
3073
|
isc_db_handle handle = 0;
|
3020
3074
|
VALUE database = rb_iv_get(self, "@database");
|
3021
3075
|
|
3022
3076
|
Check_Type(database, T_STRING);
|
3023
3077
|
dbp = connection_create_dbp(self, &length);
|
3024
|
-
isc_attach_database(isc_status, 0,
|
3078
|
+
isc_attach_database(isc_status, 0, StringValuePtr(database), &handle, length, dbp);
|
3025
3079
|
xfree(dbp);
|
3026
3080
|
fb_error_check(isc_status);
|
3027
3081
|
{
|
@@ -3082,7 +3136,6 @@ static VALUE database_s_drop(int argc, VALUE *argv, VALUE klass)
|
|
3082
3136
|
|
3083
3137
|
void Init_fb()
|
3084
3138
|
{
|
3085
|
-
HERE("Init_fb");
|
3086
3139
|
rb_mFb = rb_define_module("Fb");
|
3087
3140
|
|
3088
3141
|
rb_cFbDatabase = rb_define_class_under(rb_mFb, "Database", rb_cData);
|
@@ -3094,6 +3147,7 @@ void Init_fb()
|
|
3094
3147
|
rb_define_attr(rb_cFbDatabase, "charset", 1, 1);
|
3095
3148
|
rb_define_attr(rb_cFbDatabase, "role", 1, 1);
|
3096
3149
|
rb_define_attr(rb_cFbDatabase, "downcase_names", 1, 1);
|
3150
|
+
rb_define_attr(rb_cFbDatabase, "encoding", 1, 1);
|
3097
3151
|
rb_define_attr(rb_cFbDatabase, "page_size", 1, 1);
|
3098
3152
|
rb_define_method(rb_cFbDatabase, "create", database_create, 0);
|
3099
3153
|
rb_define_singleton_method(rb_cFbDatabase, "create", database_s_create, -1);
|
@@ -3109,6 +3163,7 @@ void Init_fb()
|
|
3109
3163
|
rb_define_attr(rb_cFbConnection, "charset", 1, 1);
|
3110
3164
|
rb_define_attr(rb_cFbConnection, "role", 1, 1);
|
3111
3165
|
rb_define_attr(rb_cFbConnection, "downcase_names", 1, 1);
|
3166
|
+
rb_define_attr(rb_cFbConnection, "encoding", 1, 1);
|
3112
3167
|
rb_define_method(rb_cFbConnection, "to_s", connection_to_s, 0);
|
3113
3168
|
rb_define_method(rb_cFbConnection, "execute", connection_execute, -1);
|
3114
3169
|
rb_define_method(rb_cFbConnection, "query", connection_query, -1);
|
@@ -3144,11 +3199,11 @@ void Init_fb()
|
|
3144
3199
|
rb_define_singleton_method(rb_cFbSqlType, "from_code", sql_type_from_code, 2);
|
3145
3200
|
|
3146
3201
|
/*
|
3147
|
-
|
3148
|
-
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3202
|
+
rb_cFbGlobal = rb_define_class_under(rb_mFb, "Global", rb_cData);
|
3203
|
+
rb_define_singleton_method(rb_cFbGlobal, "transaction", global_transaction, -1);
|
3204
|
+
rb_define_singleton_method(rb_cFbGlobal, "transaction_started", global_transaction_started, 0);
|
3205
|
+
rb_define_singleton_method(rb_cFbGlobal, "commit", global_commit, 0);
|
3206
|
+
rb_define_singleton_method(rb_cFbGlobal, "rollback", global_rollback, 0);
|
3152
3207
|
*/
|
3153
3208
|
|
3154
3209
|
rb_eFbError = rb_define_class_under(rb_mFb, "Error", rb_eStandardError);
|
@@ -3168,4 +3223,5 @@ void Init_fb()
|
|
3168
3223
|
rb_global_variable(&re_lowercase);
|
3169
3224
|
id_rstrip_bang = rb_intern("rstrip!");
|
3170
3225
|
id_sub_bang = rb_intern("sub!");
|
3226
|
+
id_force_encoding = rb_intern("force_encoding");
|
3171
3227
|
}
|
data/test/ConnectionTestCases.rb
CHANGED
@@ -144,9 +144,9 @@ class ConnectionTestCases < Test::Unit::TestCase
|
|
144
144
|
affected = connection.execute(sql_update, 5)
|
145
145
|
assert_equal 5, affected
|
146
146
|
affected = connection.execute(sql_delete, 5)
|
147
|
-
|
147
|
+
assert_equal 4, affected
|
148
148
|
rows = connection.execute(sql_select) do |cursor| cursor.fetchall end
|
149
|
-
|
149
|
+
assert_equal 6, rows.size
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#coding:utf-8
|
2
|
+
require 'test/unit'
|
3
|
+
require 'test/FbTestCases'
|
4
|
+
|
5
|
+
class EncodingTestCases < Test::Unit::TestCase
|
6
|
+
include FbTestCases
|
7
|
+
|
8
|
+
def test_encoding
|
9
|
+
sql_schema = <<-END
|
10
|
+
create table TEST (
|
11
|
+
ID INTEGER,
|
12
|
+
C10 CHAR(10),
|
13
|
+
VC10 VARCHAR(10),
|
14
|
+
MEMO BLOB SUB_TYPE TEXT)
|
15
|
+
END
|
16
|
+
sql_insert = <<-END
|
17
|
+
insert into test
|
18
|
+
(ID, C10, VC10, MEMO)
|
19
|
+
values
|
20
|
+
(?, ?, ?, ?);
|
21
|
+
END
|
22
|
+
sql_select = "select * from TEST order by ID"
|
23
|
+
lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
24
|
+
|
25
|
+
Database.create(@parms.update(:encoding => "UTF-8")) do |connection|
|
26
|
+
connection.execute(sql_schema);
|
27
|
+
|
28
|
+
connection.execute(sql_insert, 1, "abcdef", "한글", lorem)
|
29
|
+
|
30
|
+
row = connection.query(sql_select).first
|
31
|
+
assert_equal 1, row[0]
|
32
|
+
assert_equal Encoding::UTF_8, row[1].encoding
|
33
|
+
assert_equal "abcdef ", row[1]
|
34
|
+
assert_equal Encoding::UTF_8, row[2].encoding
|
35
|
+
assert_equal "한글", row[2]
|
36
|
+
assert_equal Encoding::UTF_8, row[3].encoding
|
37
|
+
assert_equal lorem, row[3]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/test/FbTestSuite.rb
CHANGED
metadata
CHANGED
@@ -1,32 +1,24 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: fb
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 6
|
8
|
-
- 7
|
9
|
-
version: 0.6.7
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Brent Rowland
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
date: 2010-03-27 00:00:00 -07:00
|
18
|
-
default_executable:
|
12
|
+
date: 2012-05-15 00:00:00.000000000 Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
14
|
description:
|
22
15
|
email: rowland@rowlandresearch.com
|
23
16
|
executables: []
|
24
|
-
|
25
|
-
extensions:
|
17
|
+
extensions:
|
26
18
|
- extconf.rb
|
27
|
-
extra_rdoc_files:
|
19
|
+
extra_rdoc_files:
|
28
20
|
- README
|
29
|
-
files:
|
21
|
+
files:
|
30
22
|
- extconf.rb
|
31
23
|
- fb.c
|
32
24
|
- README
|
@@ -35,43 +27,40 @@ files:
|
|
35
27
|
- test/CursorTestCases.rb
|
36
28
|
- test/DatabaseTestCases.rb
|
37
29
|
- test/DataTypesTestCases.rb
|
30
|
+
- test/EncodingTestCases.rb
|
38
31
|
- test/FbTestCases.rb
|
39
32
|
- test/FbTestSuite.rb
|
40
33
|
- test/TransactionTestCases.rb
|
41
|
-
has_rdoc: true
|
42
34
|
homepage: http://github.com/rowland/fb
|
43
35
|
licenses: []
|
44
|
-
|
45
36
|
post_install_message:
|
46
|
-
rdoc_options:
|
37
|
+
rdoc_options:
|
47
38
|
- --title
|
48
39
|
- Fb -- Ruby Firebird Extension
|
49
40
|
- --main
|
50
41
|
- README
|
51
42
|
- -x
|
52
43
|
- test
|
53
|
-
require_paths:
|
44
|
+
require_paths:
|
54
45
|
- .
|
55
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
|
67
|
-
|
68
|
-
version: "0"
|
69
|
-
requirements:
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements:
|
70
59
|
- Firebird client library fbclient.dll, libfbclient.so or Firebird.framework.
|
71
60
|
rubyforge_project: fblib
|
72
|
-
rubygems_version: 1.
|
61
|
+
rubygems_version: 1.8.23
|
73
62
|
signing_key:
|
74
63
|
specification_version: 3
|
75
64
|
summary: Firebird and Interbase driver
|
76
|
-
test_files:
|
65
|
+
test_files:
|
77
66
|
- test/FbTestSuite.rb
|