firebird 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Fb
2
+ VERSION = "0.10.0"
3
+ end
@@ -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