firebird 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 +7 -0
- data/.gitignore +8 -0
- data/.gitlab-ci.yml +27 -0
- data/.travis.yml +20 -0
- data/Gemfile +2 -0
- data/README.md +15 -0
- data/Rakefile +13 -0
- data/USAGE.txt +180 -0
- data/ext/fb/extconf.rb +93 -0
- data/ext/fb/fb_ext.c +3022 -0
- data/fb.gemspec +34 -0
- data/lib/fb.rb +23 -0
- data/lib/fb/version.rb +3 -0
- data/mkmf.cmd +1 -0
- data/test/ConnectionTestCases.rb +550 -0
- data/test/CursorTestCases.rb +294 -0
- data/test/DataTypesTestCases.rb +556 -0
- data/test/DatabaseTestCases.rb +183 -0
- data/test/EncodingTestCases.rb +39 -0
- data/test/NumericDataTypesTestCases.rb +588 -0
- data/test/TransactionTestCases.rb +270 -0
- data/test/test_helper.rb +91 -0
- metadata +108 -0
data/fb.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "firebird"
|
8
|
+
s.version = Fb::VERSION
|
9
|
+
s.date = "2019-06-08"
|
10
|
+
s.summary = "Firebird database driver"
|
11
|
+
s.description = "Ruby Firebird Extension Library"
|
12
|
+
s.licenses = ["MIT"]
|
13
|
+
s.requirements = "Firebird client library fbclient.dll, libfbclient.so or Firebird.framework."
|
14
|
+
s.require_paths = ["lib", "ext"]
|
15
|
+
s.author = "Popa Adrian Marius"
|
16
|
+
s.email = "mapopa@gmail.com"
|
17
|
+
s.homepage = "http://github.com/mariuz/fb"
|
18
|
+
# s.has_rdoc = true
|
19
|
+
# s.extra_rdoc_files = ['README']
|
20
|
+
# s.rdoc_options << '--title' << 'Fb -- Ruby Firebird Extension' << '--main' << 'README' << '-x' << 'test'
|
21
|
+
# s.files = ['ext/fb/extconf.rb', 'ext/fb/fb.c', 'README', 'lib/fb.rb'] + Dir.glob("test/*.rb")
|
22
|
+
s.files = `git ls-files`.split($/)
|
23
|
+
s.platform = case RUBY_PLATFORM
|
24
|
+
when /win32/ then Gem::Platform::WIN32
|
25
|
+
else
|
26
|
+
Gem::Platform::RUBY
|
27
|
+
end
|
28
|
+
s.extensions = ['ext/fb/extconf.rb'] if s.platform == Gem::Platform::RUBY
|
29
|
+
s.add_development_dependency "rake", ">= 0"
|
30
|
+
s.add_development_dependency "rake-compiler", ">= 0"
|
31
|
+
if RUBY_VERSION =~ /^2/
|
32
|
+
s.add_development_dependency "minitest", ">= 0"
|
33
|
+
end
|
34
|
+
end
|
data/lib/fb.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'fb/fb_ext'
|
2
|
+
|
3
|
+
module Fb
|
4
|
+
class Connection
|
5
|
+
def execute_script(sql)
|
6
|
+
stmts = []
|
7
|
+
delim = ';'
|
8
|
+
while sql =~ /\S/
|
9
|
+
stmt, sql = sql.split(delim, 2)
|
10
|
+
if stmt =~ /^\s*set\s+term\s+(\S+)/i
|
11
|
+
delim = $1
|
12
|
+
elsif stmt =~ /\S/
|
13
|
+
stmts << stmt
|
14
|
+
end
|
15
|
+
end
|
16
|
+
self.transaction do
|
17
|
+
stmts.each do |stmt|
|
18
|
+
self.execute(stmt)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/fb/version.rb
ADDED
data/mkmf.cmd
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby extconf.rb --with-opt-dir=c:/Firebird --with-dotnet-dir=C:\PROGRA~1\MICROS~2.NET\Vc7 --with-win32-dir=C:\PROGRA~1\MI9547~1
|
@@ -0,0 +1,550 @@
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
|
+
|
3
|
+
class ConnectionTestCases < FbTestCase
|
4
|
+
def test_execute
|
5
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
6
|
+
sql_select = "SELECT * FROM RDB$DATABASE"
|
7
|
+
Database.create(@parms) do |connection|
|
8
|
+
assert !connection.transaction_started
|
9
|
+
connection.execute(sql_schema)
|
10
|
+
connection.execute(sql_select)
|
11
|
+
assert connection.transaction_started
|
12
|
+
connection.commit
|
13
|
+
assert !connection.transaction_started
|
14
|
+
connection.drop
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_query_select
|
19
|
+
sql_select = "SELECT * FROM RDB$DATABASE"
|
20
|
+
Database.create(@parms) do |connection|
|
21
|
+
|
22
|
+
d = connection.query(sql_select)
|
23
|
+
assert_instance_of Array, d
|
24
|
+
assert_equal 1, d.size
|
25
|
+
assert_instance_of Array, d.first
|
26
|
+
if @fb_version == 3
|
27
|
+
assert_equal 5, d.first.size
|
28
|
+
else
|
29
|
+
assert_equal 4, d.first.size
|
30
|
+
end
|
31
|
+
|
32
|
+
a = connection.query(:array, sql_select)
|
33
|
+
assert_instance_of Array, a
|
34
|
+
assert_equal 1, a.size
|
35
|
+
assert_instance_of Array, a.first
|
36
|
+
if @fb_version == 3
|
37
|
+
assert_equal 5, a.first.size
|
38
|
+
else
|
39
|
+
assert_equal 4, a.first.size
|
40
|
+
end
|
41
|
+
|
42
|
+
h = connection.query(:hash, sql_select)
|
43
|
+
assert_instance_of Array, h
|
44
|
+
assert_equal 1, h.size
|
45
|
+
assert_instance_of Hash, h.first
|
46
|
+
if @fb_version == 3
|
47
|
+
assert_equal 5, h.first.keys.size
|
48
|
+
else
|
49
|
+
assert_equal 4, h.first.keys.size
|
50
|
+
end
|
51
|
+
assert h.first.keys.include?("RDB$DESCRIPTION")
|
52
|
+
assert h.first.keys.include?("RDB$RELATION_ID")
|
53
|
+
assert h.first.keys.include?("RDB$SECURITY_CLASS")
|
54
|
+
assert h.first.keys.include?("RDB$CHARACTER_SET_NAME")
|
55
|
+
if @fb_version == 3
|
56
|
+
assert h.first.keys.include?("RDB$LINGER")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_query_update
|
62
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
63
|
+
sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)"
|
64
|
+
sql_update = "UPDATE TEST SET ID = ?, NAME = ? WHERE ID = ?"
|
65
|
+
sql_delete = "DELETE FROM TEST WHERE ID = ?"
|
66
|
+
sql_select = "SELECT * FROM TEST"
|
67
|
+
Database.create(@parms) do |connection|
|
68
|
+
su = connection.query(sql_schema)
|
69
|
+
assert_equal(-1, su)
|
70
|
+
|
71
|
+
i = connection.query(sql_insert, 1, "NAME")
|
72
|
+
assert_equal 1, i
|
73
|
+
|
74
|
+
u = connection.query(sql_update, 1, "NAME2", 1)
|
75
|
+
assert_equal 1, u
|
76
|
+
|
77
|
+
d = connection.query(sql_delete, 1)
|
78
|
+
assert_equal 1, d
|
79
|
+
|
80
|
+
q = connection.query(sql_select)
|
81
|
+
assert_instance_of Array, q
|
82
|
+
assert_equal 0, q.size
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_insert_blobs_text
|
87
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20), MEMO BLOB SUB_TYPE TEXT)"
|
88
|
+
sql_insert = "INSERT INTO TEST (ID, NAME, MEMO) VALUES (?, ?, ?)"
|
89
|
+
sql_select = "SELECT * FROM TEST ORDER BY ID"
|
90
|
+
Database.create(@parms) do |connection|
|
91
|
+
connection.execute(sql_schema);
|
92
|
+
memo = "x" * 65535
|
93
|
+
assert memo.size > 50000
|
94
|
+
connection.transaction do
|
95
|
+
10.times do |i|
|
96
|
+
connection.execute(sql_insert, i, i.to_s, memo);
|
97
|
+
end
|
98
|
+
end
|
99
|
+
connection.execute(sql_select) do |cursor|
|
100
|
+
i = 0
|
101
|
+
cursor.each :hash do |row|
|
102
|
+
assert_equal i, row["ID"]
|
103
|
+
assert_equal i.to_s, row["NAME"]
|
104
|
+
assert_equal memo, row["MEMO"]
|
105
|
+
i += 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
connection.drop
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_insert_blobs_binary
|
113
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20), ATTACHMENT BLOB SEGMENT SIZE 1000)"
|
114
|
+
sql_insert = "INSERT INTO TEST (ID, NAME, ATTACHMENT) VALUES (?, ?, ?)"
|
115
|
+
sql_select = "SELECT * FROM TEST ORDER BY ID"
|
116
|
+
Database.create(@parms) do |connection|
|
117
|
+
connection.execute(sql_schema);
|
118
|
+
attachment = SecureRandom.random_bytes(250_000)
|
119
|
+
connection.transaction do
|
120
|
+
3.times do |i|
|
121
|
+
connection.execute(sql_insert, i, i.to_s, attachment);
|
122
|
+
end
|
123
|
+
end
|
124
|
+
connection.execute(sql_select) do |cursor|
|
125
|
+
i = 0
|
126
|
+
cursor.each :array do |row|
|
127
|
+
assert_equal i, row[0], "ID's do not match"
|
128
|
+
assert_equal i.to_s, row[1], "NAME's do not match"
|
129
|
+
assert_equal attachment.size, row[2].size, "ATTACHMENT sizes do not match"
|
130
|
+
i += 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
connection.drop
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_rows_affected
|
138
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
139
|
+
sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)"
|
140
|
+
sql_update = "UPDATE TEST SET NAME = 'no name' WHERE ID < ?"
|
141
|
+
sql_delete = "DELETE FROM TEST WHERE ID > ?"
|
142
|
+
sql_select = "SELECT * FROM TEST"
|
143
|
+
Database.create(@parms) do |connection|
|
144
|
+
connection.execute(sql_schema)
|
145
|
+
connection.transaction do
|
146
|
+
10.times do |i|
|
147
|
+
affected = connection.execute(sql_insert, i, "name");
|
148
|
+
assert_equal 1, affected
|
149
|
+
end
|
150
|
+
end
|
151
|
+
affected = connection.execute(sql_update, 5)
|
152
|
+
assert_equal 5, affected
|
153
|
+
affected = connection.execute(sql_delete, 5)
|
154
|
+
assert_equal 4, affected
|
155
|
+
rows = connection.execute(sql_select) do |cursor| cursor.fetchall end
|
156
|
+
assert_equal 6, rows.size
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_multi_insert
|
161
|
+
sql_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20))"
|
162
|
+
sql_insert = "INSERT INTO TEST (ID, NAME) VALUES (?, ?)"
|
163
|
+
sql_select = "SELECT * FROM TEST"
|
164
|
+
sql_data = [
|
165
|
+
[1, "Name 1"],
|
166
|
+
[2, "Name 2"],
|
167
|
+
[3, "Name 3"]]
|
168
|
+
sql_data1 = [4, "Name 4"]
|
169
|
+
sql_data2 = [5, "Name 5"]
|
170
|
+
sql_data3 = [6, "Name 6"]
|
171
|
+
Database.create(@parms) do |connection|
|
172
|
+
connection.execute(sql_schema)
|
173
|
+
connection.execute(sql_insert, sql_data)
|
174
|
+
rs = connection.query(sql_select)
|
175
|
+
assert_equal 3, rs.size
|
176
|
+
|
177
|
+
connection.execute(sql_insert, sql_data1, sql_data2, sql_data3)
|
178
|
+
rs = connection.query(sql_select)
|
179
|
+
assert_equal 6, rs.size
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_dialects
|
184
|
+
Database.create(@parms) do |connection|
|
185
|
+
assert_equal 3, connection.dialect
|
186
|
+
assert_equal 3, connection.db_dialect
|
187
|
+
connection.drop
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_open?
|
192
|
+
db = Database.create(@parms);
|
193
|
+
connection = db.connect
|
194
|
+
assert connection.open?
|
195
|
+
connection.close
|
196
|
+
assert !connection.open?
|
197
|
+
db.drop
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_properties_instance
|
201
|
+
db = Database.new(@parms)
|
202
|
+
db.create
|
203
|
+
db.connect do |connection|
|
204
|
+
assert_equal @parms[:database], connection.database
|
205
|
+
assert_equal @parms[:username], connection.username
|
206
|
+
assert_equal @parms[:password], connection.password
|
207
|
+
assert_equal @parms[:role], connection.role
|
208
|
+
assert_equal @parms[:charset], connection.charset
|
209
|
+
connection.drop
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_properties_singleton
|
214
|
+
Database.create(@parms) do |connection|
|
215
|
+
assert_equal @parms[:database], connection.database
|
216
|
+
assert_equal @parms[:username], connection.username
|
217
|
+
assert_equal @parms[:password], connection.password
|
218
|
+
assert_equal @parms[:role], connection.role
|
219
|
+
assert_equal @parms[:charset], connection.charset
|
220
|
+
connection.drop
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_drop_instance
|
225
|
+
db = Database.create(@parms)
|
226
|
+
assert File.exist?(@db_file)
|
227
|
+
connection = db.connect
|
228
|
+
assert connection.open?
|
229
|
+
connection.drop
|
230
|
+
assert !connection.open?
|
231
|
+
assert !File.exist?(@db_file)
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_drop_singleton
|
235
|
+
Database.create(@parms) do |connection|
|
236
|
+
assert File.exist?(@db_file)
|
237
|
+
connection.drop
|
238
|
+
assert !File.exist?(@db_file)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_to_s
|
243
|
+
db = Database.new(@parms)
|
244
|
+
db.create
|
245
|
+
connection = db.connect
|
246
|
+
begin
|
247
|
+
assert_equal "#{@parms[:database]} (OPEN)", connection.to_s
|
248
|
+
ensure
|
249
|
+
connection.close
|
250
|
+
assert_equal "#{@parms[:database]} (CLOSED)", connection.to_s
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_table_names
|
255
|
+
sql_schema = <<-END
|
256
|
+
CREATE TABLE TEST1 (ID INT);
|
257
|
+
CREATE TABLE TEST2 (ID INT);
|
258
|
+
END
|
259
|
+
Database.create(@parms) do |connection|
|
260
|
+
connection.execute_script(sql_schema)
|
261
|
+
table_names = connection.table_names
|
262
|
+
assert_equal 'TEST1', table_names[0]
|
263
|
+
assert_equal 'TEST2', table_names[1]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_table_names_downcased
|
268
|
+
sql_schema = <<-END
|
269
|
+
CREATE TABLE TEST1 (ID INT);
|
270
|
+
CREATE TABLE "Test2" (ID INT);
|
271
|
+
END
|
272
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
273
|
+
connection.execute_script(sql_schema)
|
274
|
+
table_names = connection.table_names
|
275
|
+
assert_equal 'test1', table_names[0]
|
276
|
+
assert_equal 'Test2', table_names[1]
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_generator_names
|
281
|
+
sql_schema = <<-END
|
282
|
+
CREATE GENERATOR TEST1_SEQ;
|
283
|
+
CREATE GENERATOR TEST2_SEQ;
|
284
|
+
END
|
285
|
+
Database.create(@parms) do |connection|
|
286
|
+
connection.execute_script(sql_schema)
|
287
|
+
names = connection.generator_names
|
288
|
+
assert_equal 'TEST1_SEQ', names[0]
|
289
|
+
assert_equal 'TEST2_SEQ', names[1]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_generator_names_downcased
|
294
|
+
sql_schema = <<-END
|
295
|
+
CREATE GENERATOR TEST1_SEQ;
|
296
|
+
CREATE GENERATOR "TEST2_seq";
|
297
|
+
END
|
298
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
299
|
+
connection.execute_script(sql_schema)
|
300
|
+
names = connection.generator_names
|
301
|
+
assert_equal 'test1_seq', names[0]
|
302
|
+
assert_equal 'TEST2_seq', names[1]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_view_names
|
307
|
+
sql_schema = <<-END
|
308
|
+
CREATE TABLE TEST1 (ID INT, NAME1 VARCHAR(10));
|
309
|
+
CREATE TABLE TEST2 (ID INT, NAME2 VARCHAR(10));
|
310
|
+
CREATE VIEW VIEW1 AS SELECT TEST1.ID, TEST1.NAME1, TEST2.NAME2 FROM TEST1 JOIN TEST2 ON TEST1.ID = TEST2.ID;
|
311
|
+
CREATE VIEW VIEW2 AS SELECT TEST2.ID, TEST1.NAME1, TEST2.NAME2 FROM TEST1 JOIN TEST2 ON TEST1.NAME1 = TEST2.NAME2;
|
312
|
+
END
|
313
|
+
Database.create(@parms) do |connection|
|
314
|
+
connection.execute_script(sql_schema)
|
315
|
+
names = connection.view_names
|
316
|
+
assert_equal 'VIEW1', names[0]
|
317
|
+
assert_equal 'VIEW2', names[1]
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_view_names_downcased
|
322
|
+
sql_schema = <<-END
|
323
|
+
CREATE TABLE TEST1 (ID INT, NAME1 VARCHAR(10));
|
324
|
+
CREATE TABLE TEST2 (ID INT, NAME2 VARCHAR(10));
|
325
|
+
CREATE VIEW VIEW1 AS SELECT TEST1.ID, TEST1.NAME1, TEST2.NAME2 FROM TEST1 JOIN TEST2 ON TEST1.ID = TEST2.ID;
|
326
|
+
CREATE VIEW "View2" AS SELECT TEST2.ID, TEST1.NAME1, TEST2.NAME2 FROM TEST1 JOIN TEST2 ON TEST1.NAME1 = TEST2.NAME2;
|
327
|
+
END
|
328
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
329
|
+
connection.execute_script(sql_schema)
|
330
|
+
names = connection.view_names
|
331
|
+
assert_equal 'view1', names[0]
|
332
|
+
assert_equal 'View2', names[1]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_role_names
|
337
|
+
sql_schema = <<-END
|
338
|
+
create role reader;
|
339
|
+
create role writer;
|
340
|
+
END
|
341
|
+
Database.create(@parms) do |connection|
|
342
|
+
connection.execute_script(sql_schema)
|
343
|
+
names = connection.role_names
|
344
|
+
assert_equal 'READER', names[0]
|
345
|
+
assert_equal 'WRITER', names[1]
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_role_names_downcased
|
350
|
+
sql_schema = <<-END
|
351
|
+
create role reader;
|
352
|
+
create role writer;
|
353
|
+
END
|
354
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
355
|
+
connection.execute_script(sql_schema)
|
356
|
+
names = connection.role_names
|
357
|
+
assert_equal 'reader', names[0]
|
358
|
+
assert_equal 'writer', names[1]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_procedure_names
|
363
|
+
sql_schema = <<-END_SQL
|
364
|
+
CREATE PROCEDURE PLUSONE(NUM1 INTEGER) RETURNS (NUM2 INTEGER) AS
|
365
|
+
BEGIN
|
366
|
+
NUM2 = NUM1 + 1;
|
367
|
+
SUSPEND;
|
368
|
+
END;
|
369
|
+
END_SQL
|
370
|
+
Database.create(@parms) do |connection|
|
371
|
+
connection.execute(sql_schema)
|
372
|
+
names = connection.procedure_names
|
373
|
+
assert_equal 'PLUSONE', names[0]
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_procedure_names_downcased
|
378
|
+
sql_schema = <<-END_SQL
|
379
|
+
CREATE PROCEDURE PLUSONE(NUM1 INTEGER) RETURNS (NUM2 INTEGER) AS
|
380
|
+
BEGIN
|
381
|
+
NUM2 = NUM1 + 1;
|
382
|
+
SUSPEND;
|
383
|
+
END;
|
384
|
+
END_SQL
|
385
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
386
|
+
connection.execute(sql_schema)
|
387
|
+
names = connection.procedure_names
|
388
|
+
assert_equal 'plusone', names[0]
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def test_trigger_names
|
393
|
+
table_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20)); CREATE GENERATOR TEST_SEQ;"
|
394
|
+
trigger_schema = <<-END_SQL
|
395
|
+
CREATE TRIGGER TEST_INSERT FOR TEST ACTIVE BEFORE INSERT AS
|
396
|
+
BEGIN
|
397
|
+
IF (NEW.ID IS NULL) THEN
|
398
|
+
NEW.ID = CAST(GEN_ID(TEST_SEQ, 1) AS INT);
|
399
|
+
END
|
400
|
+
END_SQL
|
401
|
+
Database.create(@parms) do |connection|
|
402
|
+
connection.execute_script(table_schema)
|
403
|
+
connection.execute(trigger_schema)
|
404
|
+
names = connection.trigger_names
|
405
|
+
assert names.include?('TEST_INSERT')
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_trigger_names_downcased
|
410
|
+
table_schema = "CREATE TABLE TEST (ID INT, NAME VARCHAR(20)); CREATE GENERATOR TEST_SEQ;"
|
411
|
+
trigger_schema = <<-END_SQL
|
412
|
+
CREATE TRIGGER TEST_INSERT FOR TEST ACTIVE BEFORE INSERT AS
|
413
|
+
BEGIN
|
414
|
+
IF (NEW.ID IS NULL) THEN
|
415
|
+
NEW.ID = CAST(GEN_ID(TEST_SEQ, 1) AS INT);
|
416
|
+
END
|
417
|
+
END_SQL
|
418
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
419
|
+
connection.execute_script(table_schema)
|
420
|
+
connection.execute(trigger_schema)
|
421
|
+
names = connection.trigger_names
|
422
|
+
assert names.include?('test_insert')
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_index_names
|
427
|
+
sql_schema = <<-END
|
428
|
+
CREATE TABLE MASTER (ID INT NOT NULL, NAME1 VARCHAR(10));
|
429
|
+
CREATE TABLE DETAIL (ID INT NOT NULL, MASTER_ID INT, NAME2 VARCHAR(10));
|
430
|
+
ALTER TABLE MASTER ADD CONSTRAINT PK_MASTER PRIMARY KEY(ID);
|
431
|
+
ALTER TABLE DETAIL ADD CONSTRAINT PK_DETAIL PRIMARY KEY(ID);
|
432
|
+
ALTER TABLE DETAIL ADD CONSTRAINT FK_DETAIL_MASTER_ID FOREIGN KEY(MASTER_ID) REFERENCES MASTER(ID);
|
433
|
+
CREATE UNIQUE ASCENDING INDEX IX_MASTER_NAME1 ON MASTER(NAME1);
|
434
|
+
CREATE DESCENDING INDEX IX_DETAIL_ID_DESC ON DETAIL(ID);
|
435
|
+
END
|
436
|
+
Database.create(@parms) do |connection|
|
437
|
+
connection.execute_script(sql_schema)
|
438
|
+
indexes = connection.indexes # Hash of Structs using index names as keys
|
439
|
+
assert_equal 5, indexes.size
|
440
|
+
assert indexes.keys.include?('PK_MASTER')
|
441
|
+
assert indexes.keys.include?('PK_DETAIL')
|
442
|
+
assert indexes.keys.include?('FK_DETAIL_MASTER_ID')
|
443
|
+
assert indexes.keys.include?('IX_MASTER_NAME1')
|
444
|
+
assert indexes.keys.include?('IX_DETAIL_ID_DESC')
|
445
|
+
|
446
|
+
assert indexes['PK_MASTER'].columns.include?('ID')
|
447
|
+
assert indexes['PK_DETAIL'].columns.include?('ID')
|
448
|
+
|
449
|
+
master_indexes = indexes.values.select {|ix| ix.table_name == 'MASTER' }
|
450
|
+
assert_equal 2, master_indexes.size
|
451
|
+
|
452
|
+
detail_indexes = indexes.values.select {|ix| ix.table_name == 'DETAIL' }
|
453
|
+
assert_equal 3, detail_indexes.size
|
454
|
+
|
455
|
+
assert_equal 'MASTER', indexes['PK_MASTER'].table_name
|
456
|
+
assert indexes['PK_MASTER'].unique
|
457
|
+
assert !indexes['PK_MASTER'].descending
|
458
|
+
|
459
|
+
assert_equal 'MASTER', indexes['IX_MASTER_NAME1'].table_name
|
460
|
+
assert indexes['IX_MASTER_NAME1'].unique
|
461
|
+
assert !indexes['IX_MASTER_NAME1'].descending
|
462
|
+
|
463
|
+
assert_equal 'DETAIL', indexes['PK_DETAIL'].table_name
|
464
|
+
assert indexes['PK_DETAIL'].unique
|
465
|
+
assert !indexes['PK_DETAIL'].descending
|
466
|
+
|
467
|
+
assert_equal 'DETAIL', indexes['FK_DETAIL_MASTER_ID'].table_name
|
468
|
+
assert !indexes['FK_DETAIL_MASTER_ID'].unique
|
469
|
+
assert !indexes['FK_DETAIL_MASTER_ID'].descending
|
470
|
+
|
471
|
+
assert_equal 'DETAIL', indexes['IX_DETAIL_ID_DESC'].table_name
|
472
|
+
assert !indexes['IX_DETAIL_ID_DESC'].unique
|
473
|
+
assert indexes['IX_DETAIL_ID_DESC'].descending
|
474
|
+
|
475
|
+
connection.drop
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_index_names_downcased
|
480
|
+
sql_schema = <<-END
|
481
|
+
CREATE TABLE MASTER (ID INT NOT NULL, NAME1 VARCHAR(10));
|
482
|
+
CREATE TABLE DETAIL (ID INT NOT NULL, MASTER_ID INT, NAME2 VARCHAR(10));
|
483
|
+
ALTER TABLE MASTER ADD CONSTRAINT PK_MASTER PRIMARY KEY(ID);
|
484
|
+
ALTER TABLE DETAIL ADD CONSTRAINT PK_DETAIL PRIMARY KEY(ID);
|
485
|
+
ALTER TABLE DETAIL ADD CONSTRAINT FK_DETAIL_MASTER_ID FOREIGN KEY(MASTER_ID) REFERENCES MASTER(ID);
|
486
|
+
CREATE UNIQUE ASCENDING INDEX IX_MASTER_NAME1 ON MASTER(NAME1);
|
487
|
+
CREATE DESCENDING INDEX "IX_DETAIL_ID_desc" ON DETAIL(ID);
|
488
|
+
END
|
489
|
+
Database.create(@parms.merge(:downcase_names => true)) do |connection|
|
490
|
+
connection.execute_script(sql_schema)
|
491
|
+
indexes = connection.indexes # Hash of Structs using index names as keys
|
492
|
+
assert_equal 5, indexes.size
|
493
|
+
assert indexes.keys.include?('pk_master')
|
494
|
+
assert indexes.keys.include?('pk_detail')
|
495
|
+
assert indexes.keys.include?('fk_detail_master_id')
|
496
|
+
assert indexes.keys.include?('ix_master_name1')
|
497
|
+
assert indexes.keys.include?('IX_DETAIL_ID_desc')
|
498
|
+
assert indexes['pk_master'].columns.include?('id'), "columns missing id"
|
499
|
+
assert indexes['pk_detail'].columns.include?('id'), "columns missing id"
|
500
|
+
connection.drop
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
def test_columns
|
505
|
+
sql_schema = <<-END
|
506
|
+
create domain STRING10 as VARCHAR(10);
|
507
|
+
create table TEST (
|
508
|
+
I INTEGER,
|
509
|
+
SI SMALLINT,
|
510
|
+
BI BIGINT,
|
511
|
+
F FLOAT,
|
512
|
+
D DOUBLE PRECISION,
|
513
|
+
C CHAR,
|
514
|
+
C10 CHAR(10),
|
515
|
+
VC VARCHAR(1),
|
516
|
+
VC10 STRING10,
|
517
|
+
VC10000 VARCHAR(10000),
|
518
|
+
DT DATE,
|
519
|
+
TM TIME,
|
520
|
+
TS TIMESTAMP,
|
521
|
+
N92 NUMERIC(9,2),
|
522
|
+
D92 DECIMAL(9,2));
|
523
|
+
END
|
524
|
+
expected = [
|
525
|
+
# name, domain, sql_type, sql_subtype, length, precision, scale, default, nullable
|
526
|
+
Struct::FbColumn.new("I", nil, "INTEGER", 0, 4, 0, 0, nil, true),
|
527
|
+
Struct::FbColumn.new("SI", nil, "SMALLINT", 0, 2, 0, 0, nil, true),
|
528
|
+
Struct::FbColumn.new("BI", nil, "BIGINT", 0, 8, 0, 0, nil, true),
|
529
|
+
Struct::FbColumn.new("F", nil, "FLOAT", 0, 4, nil, 0, nil, true),
|
530
|
+
Struct::FbColumn.new("D", nil, "DOUBLE PRECISION", 0, 8, nil, 0, nil, true),
|
531
|
+
Struct::FbColumn.new("C", nil, "CHAR", 0, 1, nil, 0, nil, true),
|
532
|
+
Struct::FbColumn.new("C10", nil, "CHAR", 0, 10, nil, 0, nil, true),
|
533
|
+
Struct::FbColumn.new("VC", nil, "VARCHAR", 0, 1, nil, 0, nil, true),
|
534
|
+
Struct::FbColumn.new("VC10", "STRING10", "VARCHAR", 0, 10, nil, 0, nil, true),
|
535
|
+
Struct::FbColumn.new("VC10000", nil, "VARCHAR", 0, 10000, nil, 0, nil, true),
|
536
|
+
Struct::FbColumn.new("DT", nil, "DATE", 0, 4, nil, 0, nil, true),
|
537
|
+
Struct::FbColumn.new("TM", nil, "TIME", 0, 4, nil, 0, nil, true),
|
538
|
+
Struct::FbColumn.new("TS", nil, "TIMESTAMP", 0, 8, nil, 0, nil, true),
|
539
|
+
Struct::FbColumn.new("N92", nil, "NUMERIC", 1, 4, 9, -2, nil, true),
|
540
|
+
Struct::FbColumn.new("D92", nil, "DECIMAL", 2, 4, 9, -2, nil, true),
|
541
|
+
]
|
542
|
+
Database.create(@parms) do |connection|
|
543
|
+
connection.execute_script(sql_schema)
|
544
|
+
columns = connection.columns('TEST')
|
545
|
+
expected.each_with_index do |column, i|
|
546
|
+
assert_equal column, columns[i]
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
end
|