sequel 3.38.0 → 3.39.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.
- data/CHANGELOG +62 -0
- data/README.rdoc +2 -2
- data/bin/sequel +12 -2
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/association_basics.rdoc +13 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/schema_modification.rdoc +4 -4
- data/lib/sequel/adapters/jdbc/derby.rb +1 -0
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +8 -1
- data/lib/sequel/adapters/mysql2.rb +10 -3
- data/lib/sequel/adapters/postgres.rb +72 -8
- data/lib/sequel/adapters/shared/db2.rb +1 -0
- data/lib/sequel/adapters/shared/mssql.rb +57 -0
- data/lib/sequel/adapters/shared/mysql.rb +95 -19
- data/lib/sequel/adapters/shared/oracle.rb +14 -0
- data/lib/sequel/adapters/shared/postgres.rb +63 -24
- data/lib/sequel/adapters/shared/sqlite.rb +6 -9
- data/lib/sequel/connection_pool/sharded_threaded.rb +8 -3
- data/lib/sequel/connection_pool/threaded.rb +9 -4
- data/lib/sequel/database/query.rb +60 -48
- data/lib/sequel/database/schema_generator.rb +13 -6
- data/lib/sequel/database/schema_methods.rb +65 -12
- data/lib/sequel/dataset/actions.rb +22 -4
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/graph.rb +2 -3
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/query.rb +0 -2
- data/lib/sequel/dataset/sql.rb +33 -12
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/extensions/eval_inspect.rb +17 -2
- data/lib/sequel/extensions/pg_array_ops.rb +15 -5
- data/lib/sequel/extensions/pg_interval.rb +2 -2
- data/lib/sequel/extensions/pg_row_ops.rb +18 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -11
- data/lib/sequel/model/associations.rb +3 -2
- data/lib/sequel/model/base.rb +57 -13
- data/lib/sequel/model/exceptions.rb +20 -2
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/defaults_setter.rb +15 -1
- data/lib/sequel/plugins/dirty.rb +2 -2
- data/lib/sequel/plugins/identity_map.rb +12 -8
- data/lib/sequel/plugins/subclasses.rb +19 -1
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/validation_helpers.rb +24 -4
- data/lib/sequel/sql.rb +64 -24
- data/lib/sequel/timezones.rb +10 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +26 -25
- data/spec/adapters/mysql_spec.rb +57 -23
- data/spec/adapters/oracle_spec.rb +34 -49
- data/spec/adapters/postgres_spec.rb +226 -128
- data/spec/adapters/sqlite_spec.rb +50 -49
- data/spec/core/connection_pool_spec.rb +22 -0
- data/spec/core/database_spec.rb +53 -47
- data/spec/core/dataset_spec.rb +36 -32
- data/spec/core/expression_filters_spec.rb +14 -2
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/object_graph_spec.rb +0 -13
- data/spec/core/schema_spec.rb +64 -5
- data/spec/core_extensions_spec.rb +1 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/defaults_setter_spec.rb +24 -0
- data/spec/extensions/eval_inspect_spec.rb +9 -0
- data/spec/extensions/identity_map_spec.rb +11 -2
- data/spec/extensions/pg_array_ops_spec.rb +9 -0
- data/spec/extensions/pg_row_ops_spec.rb +11 -1
- data/spec/extensions/pg_row_plugin_spec.rb +4 -0
- data/spec/extensions/schema_dumper_spec.rb +8 -5
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/validation_helpers_spec.rb +15 -2
- data/spec/integration/dataset_test.rb +75 -1
- data/spec/integration/plugin_test.rb +146 -0
- data/spec/integration/schema_test.rb +34 -0
- data/spec/model/dataset_methods_spec.rb +38 -0
- data/spec/model/hooks_spec.rb +6 -0
- data/spec/model/validations_spec.rb +27 -2
- metadata +8 -2
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -14,10 +14,6 @@ INTEGRATION_DB = MYSQL_DB unless defined?(INTEGRATION_DB)
|
|
|
14
14
|
|
|
15
15
|
MYSQL_URI = URI.parse(MYSQL_DB.uri)
|
|
16
16
|
|
|
17
|
-
MYSQL_DB.create_table! :test2 do
|
|
18
|
-
text :name
|
|
19
|
-
integer :value
|
|
20
|
-
end
|
|
21
17
|
def MYSQL_DB.sqls
|
|
22
18
|
(@sqls ||= [])
|
|
23
19
|
end
|
|
@@ -86,24 +82,17 @@ describe "MySQL", '#create_table' do
|
|
|
86
82
|
@db[:dolls].insert
|
|
87
83
|
@db[:dolls].select_map(:name).should == ["foo"]
|
|
88
84
|
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
describe "A MySQL database" do
|
|
92
|
-
specify "should provide the server version" do
|
|
93
|
-
MYSQL_DB.server_version.should >= 40000
|
|
94
|
-
end
|
|
95
85
|
|
|
96
|
-
specify "should
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
MYSQL_DB.transaction{MYSQL_DB[:test2].for_share.all.should == []}
|
|
86
|
+
specify "should be able to parse the default value for set and enum types" do
|
|
87
|
+
@db.create_table!(:dolls){column :t, "set('a', 'b', 'c', 'd')", :default=>'a,b'}
|
|
88
|
+
@db.schema(:dolls).first.last[:ruby_default].should == 'a,b'
|
|
89
|
+
@db.create_table!(:dolls){column :t, "enum('a', 'b', 'c', 'd')", :default=>'b'}
|
|
90
|
+
@db.schema(:dolls).first.last[:ruby_default].should == 'b'
|
|
102
91
|
end
|
|
103
92
|
end
|
|
104
93
|
|
|
105
|
-
if MYSQL_DB.adapter_scheme
|
|
106
|
-
describe "Sequel::MySQL
|
|
94
|
+
if [:mysql, :mysql2].include?(MYSQL_DB.adapter_scheme)
|
|
95
|
+
describe "Sequel::MySQL::Database#convert_tinyint_to_bool" do
|
|
107
96
|
before do
|
|
108
97
|
@db = MYSQL_DB
|
|
109
98
|
@db.create_table(:booltest){column :b, 'tinyint(1)'; column :i, 'tinyint(4)'}
|
|
@@ -149,6 +138,17 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
149
138
|
@ds << {:b=>0, :i=>0}
|
|
150
139
|
@ds.all.should == [{:b=>0, :i=>0}]
|
|
151
140
|
end
|
|
141
|
+
|
|
142
|
+
specify "should allow disabling the conversion on a per-dataset basis" do
|
|
143
|
+
@db.convert_tinyint_to_bool = true
|
|
144
|
+
ds = @ds.clone
|
|
145
|
+
ds.meta_def(:cast_tinyint_integer?){|f| true} # mysql
|
|
146
|
+
ds.meta_def(:convert_tinyint_to_bool?){false} # mysql2
|
|
147
|
+
ds.delete
|
|
148
|
+
ds << {:b=>true, :i=>10}
|
|
149
|
+
ds.all.should == [{:b=>1, :i=>10}]
|
|
150
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
|
151
|
+
end
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
154
|
|
|
@@ -269,7 +269,6 @@ end
|
|
|
269
269
|
describe "MySQL join expressions" do
|
|
270
270
|
before do
|
|
271
271
|
@ds = MYSQL_DB[:nodes]
|
|
272
|
-
@ds.db.meta_def(:server_version) {50014}
|
|
273
272
|
end
|
|
274
273
|
|
|
275
274
|
specify "should raise error for :full_outer join requests." do
|
|
@@ -342,8 +341,41 @@ describe "Joined MySQL dataset" do
|
|
|
342
341
|
end
|
|
343
342
|
|
|
344
343
|
describe "A MySQL database" do
|
|
345
|
-
|
|
344
|
+
after do
|
|
345
|
+
MYSQL_DB.drop_table?(:test_innodb)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
specify "should handle the creation and dropping of an InnoDB table with foreign keys" do
|
|
349
|
+
proc{MYSQL_DB.create_table!(:test_innodb, :engine=>:InnoDB){primary_key :id; foreign_key :fk, :test_innodb, :key=>:id}}.should_not raise_error
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
describe "A MySQL database" do
|
|
354
|
+
before(:all) do
|
|
346
355
|
@db = MYSQL_DB
|
|
356
|
+
@db.create_table! :test2 do
|
|
357
|
+
text :name
|
|
358
|
+
integer :value
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
after(:all) do
|
|
362
|
+
@db.drop_table?(:test2)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
specify "should provide the server version" do
|
|
366
|
+
@db.server_version.should >= 40000
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
specify "should cache the server version" do
|
|
370
|
+
# warm cache:
|
|
371
|
+
@db.server_version
|
|
372
|
+
@db.sqls.clear
|
|
373
|
+
3.times{@db.server_version}
|
|
374
|
+
@db.sqls.should be_empty
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
specify "should support for_share" do
|
|
378
|
+
@db.transaction{@db[:test2].for_share.all.should == []}
|
|
347
379
|
end
|
|
348
380
|
|
|
349
381
|
specify "should support add_column operations" do
|
|
@@ -472,8 +504,7 @@ describe "A MySQL database" do
|
|
|
472
504
|
@db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
|
|
473
505
|
@db.sqls.should == ["CREATE TABLE `items` (`id` integer)",
|
|
474
506
|
"CREATE TABLE `users` (`id` integer PRIMARY KEY AUTO_INCREMENT)",
|
|
475
|
-
"ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL"
|
|
476
|
-
"ALTER TABLE `items` ADD FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
|
|
507
|
+
"ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL, ADD FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
|
|
477
508
|
end
|
|
478
509
|
|
|
479
510
|
specify "should have rename_column support keep existing options" do
|
|
@@ -500,7 +531,7 @@ describe "A MySQL database" do
|
|
|
500
531
|
specify "should have set_column_type pass through options" do
|
|
501
532
|
@db.create_table(:items){integer :id; enum :list, :elements=>%w[one]}
|
|
502
533
|
@db.alter_table(:items){set_column_type :id, :int, :unsigned=>true, :size=>8; set_column_type :list, :enum, :elements=>%w[two]}
|
|
503
|
-
@db.sqls.should == ["CREATE TABLE `items` (`id` integer, `list` enum('one'))", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(8) UNSIGNED NULL
|
|
534
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer, `list` enum('one'))", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(8) UNSIGNED NULL, CHANGE COLUMN `list` `list` enum('two') NULL"]
|
|
504
535
|
end
|
|
505
536
|
|
|
506
537
|
specify "should have set_column_default support keep existing options" do
|
|
@@ -625,6 +656,9 @@ describe "A grouped MySQL dataset" do
|
|
|
625
656
|
MYSQL_DB[:test2] << {:name => '12', :value => 20}
|
|
626
657
|
MYSQL_DB[:test2] << {:name => '13', :value => 10}
|
|
627
658
|
end
|
|
659
|
+
after do
|
|
660
|
+
MYSQL_DB.drop_table?(:test2)
|
|
661
|
+
end
|
|
628
662
|
|
|
629
663
|
specify "should return the correct count for raw sql query" do
|
|
630
664
|
ds = MYSQL_DB["select name FROM test2 WHERE name = '11' GROUP BY name"]
|
|
@@ -5,25 +5,34 @@ unless defined?(ORACLE_DB)
|
|
|
5
5
|
end
|
|
6
6
|
INTEGRATION_DB = ORACLE_DB unless defined?(INTEGRATION_DB)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
describe "An Oracle database" do
|
|
9
|
+
before(:all) do
|
|
10
|
+
ORACLE_DB.create_table!(:items) do
|
|
11
|
+
String :name, :size => 50
|
|
12
|
+
Integer :value
|
|
13
|
+
Date :date_created
|
|
14
|
+
index :value
|
|
15
|
+
end
|
|
14
16
|
|
|
15
|
-
ORACLE_DB.create_table!(:books) do
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
17
|
+
ORACLE_DB.create_table!(:books) do
|
|
18
|
+
Integer :id
|
|
19
|
+
String :title, :size => 50
|
|
20
|
+
Integer :category_id
|
|
21
|
+
end
|
|
20
22
|
|
|
21
|
-
ORACLE_DB.create_table!(:categories) do
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
end
|
|
23
|
+
ORACLE_DB.create_table!(:categories) do
|
|
24
|
+
Integer :id
|
|
25
|
+
String :cat_name, :size => 50
|
|
26
|
+
end
|
|
27
|
+
@d = ORACLE_DB[:items]
|
|
28
|
+
end
|
|
29
|
+
after do
|
|
30
|
+
@d.delete
|
|
31
|
+
end
|
|
32
|
+
after(:all) do
|
|
33
|
+
ORACLE_DB.drop_table?(:items, :books, :categories)
|
|
34
|
+
end
|
|
25
35
|
|
|
26
|
-
describe "An Oracle database" do
|
|
27
36
|
specify "should provide disconnect functionality" do
|
|
28
37
|
ORACLE_DB.execute("select user from dual")
|
|
29
38
|
ORACLE_DB.pool.size.should == 1
|
|
@@ -81,15 +90,9 @@ describe "An Oracle database" do
|
|
|
81
90
|
primary_key :id, :integer, :null => false
|
|
82
91
|
index :name, :unique => true
|
|
83
92
|
end
|
|
93
|
+
ORACLE_DB.drop_table?(:test_tmp)
|
|
84
94
|
end
|
|
85
|
-
end
|
|
86
95
|
|
|
87
|
-
describe "An Oracle dataset" do
|
|
88
|
-
before do
|
|
89
|
-
@d = ORACLE_DB[:items]
|
|
90
|
-
@d.delete # remove all records
|
|
91
|
-
end
|
|
92
|
-
|
|
93
96
|
specify "should return the correct record count" do
|
|
94
97
|
@d.count.should == 0
|
|
95
98
|
@d << {:name => 'abc', :value => 123}
|
|
@@ -194,8 +197,6 @@ describe "An Oracle dataset" do
|
|
|
194
197
|
@d << {:name => 'def', :value => 789}
|
|
195
198
|
@d.filter(:name => 'abc').update(:value => 530)
|
|
196
199
|
|
|
197
|
-
# the third record should stay the same
|
|
198
|
-
# floating-point precision bullshit
|
|
199
200
|
@d[:name => 'def'][:value].should == 789
|
|
200
201
|
@d.filter(:value => 530).count.should == 2
|
|
201
202
|
end
|
|
@@ -230,24 +231,20 @@ describe "An Oracle dataset" do
|
|
|
230
231
|
|
|
231
232
|
@d.count.should == 1
|
|
232
233
|
end
|
|
233
|
-
end
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
before do
|
|
235
|
+
specify "should return correct result" do
|
|
237
236
|
@d1 = ORACLE_DB[:books]
|
|
238
|
-
@d1.delete
|
|
237
|
+
@d1.delete
|
|
239
238
|
@d1 << {:id => 1, :title => 'aaa', :category_id => 100}
|
|
240
239
|
@d1 << {:id => 2, :title => 'bbb', :category_id => 100}
|
|
241
240
|
@d1 << {:id => 3, :title => 'ccc', :category_id => 101}
|
|
242
241
|
@d1 << {:id => 4, :title => 'ddd', :category_id => 102}
|
|
243
242
|
|
|
244
243
|
@d2 = ORACLE_DB[:categories]
|
|
245
|
-
@d2.delete
|
|
244
|
+
@d2.delete
|
|
246
245
|
@d2 << {:id => 100, :cat_name => 'ruby'}
|
|
247
246
|
@d2 << {:id => 101, :cat_name => 'rails'}
|
|
248
|
-
end
|
|
249
247
|
|
|
250
|
-
specify "should return correct result" do
|
|
251
248
|
@d1.join(:categories, :id => :category_id).select(:books__id, :title, :cat_name).order(:books__id).to_a.should == [
|
|
252
249
|
{:id => 1, :title => 'aaa', :cat_name => 'ruby'},
|
|
253
250
|
{:id => 2, :title => 'bbb', :cat_name => 'ruby'},
|
|
@@ -271,18 +268,14 @@ describe "Joined Oracle dataset" do
|
|
|
271
268
|
{:id => 3, :title => 'ccc', :cat_name => 'rails'}
|
|
272
269
|
]
|
|
273
270
|
end
|
|
274
|
-
end
|
|
275
271
|
|
|
276
|
-
|
|
277
|
-
before do
|
|
272
|
+
specify "should allow columns to be renamed" do
|
|
278
273
|
@d1 = ORACLE_DB[:books]
|
|
279
|
-
@d1.delete
|
|
274
|
+
@d1.delete
|
|
280
275
|
@d1 << {:id => 1, :title => 'aaa', :category_id => 100}
|
|
281
276
|
@d1 << {:id => 2, :title => 'bbb', :category_id => 100}
|
|
282
277
|
@d1 << {:id => 3, :title => 'bbb', :category_id => 100}
|
|
283
|
-
end
|
|
284
278
|
|
|
285
|
-
specify "should allow columns to be renamed" do
|
|
286
279
|
@d1.select(Sequel.as(:title, :name)).order_by(:id).to_a.should == [
|
|
287
280
|
{ :name => 'aaa' },
|
|
288
281
|
{ :name => 'bbb' },
|
|
@@ -291,22 +284,14 @@ describe "Oracle aliasing" do
|
|
|
291
284
|
end
|
|
292
285
|
|
|
293
286
|
specify "nested queries should work" do
|
|
294
|
-
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
describe "Row locks in Oracle" do
|
|
299
|
-
before do
|
|
300
|
-
@d1 = ORACLE_DB[:books]
|
|
301
|
-
@d1.delete
|
|
302
|
-
@d1 << {:id => 1, :title => 'aaa'}
|
|
287
|
+
ORACLE_DB[:books].select(:title).group_by(:title).count.should == 2
|
|
303
288
|
end
|
|
304
289
|
|
|
305
290
|
specify "#for_update should use FOR UPDATE" do
|
|
306
|
-
|
|
291
|
+
ORACLE_DB[:books].for_update.sql.should == 'SELECT * FROM "BOOKS" FOR UPDATE'
|
|
307
292
|
end
|
|
308
293
|
|
|
309
294
|
specify "#lock_style should accept symbols" do
|
|
310
|
-
|
|
295
|
+
ORACLE_DB[:books].lock_style(:update).sql.should == 'SELECT * FROM "BOOKS" FOR UPDATE'
|
|
311
296
|
end
|
|
312
297
|
end
|
|
@@ -24,26 +24,14 @@ end
|
|
|
24
24
|
POSTGRES_DB.loggers << logger
|
|
25
25
|
|
|
26
26
|
#POSTGRES_DB.instance_variable_set(:@server_version, 80200)
|
|
27
|
-
POSTGRES_DB.create_table! :test do
|
|
28
|
-
text :name
|
|
29
|
-
integer :value, :index => true
|
|
30
|
-
end
|
|
31
|
-
POSTGRES_DB.create_table! :test2 do
|
|
32
|
-
text :name
|
|
33
|
-
integer :value
|
|
34
|
-
end
|
|
35
|
-
POSTGRES_DB.create_table! :test3 do
|
|
36
|
-
integer :value
|
|
37
|
-
timestamp :time
|
|
38
|
-
end
|
|
39
|
-
POSTGRES_DB.create_table! :test4 do
|
|
40
|
-
varchar :name, :size => 20
|
|
41
|
-
bytea :value
|
|
42
|
-
end
|
|
43
27
|
|
|
44
28
|
describe "A PostgreSQL database" do
|
|
45
|
-
before do
|
|
29
|
+
before(:all) do
|
|
46
30
|
@db = POSTGRES_DB
|
|
31
|
+
@db.create_table!(:public__testfk){primary_key :id; foreign_key :i, :public__testfk}
|
|
32
|
+
end
|
|
33
|
+
after(:all) do
|
|
34
|
+
@db.drop_table?(:public__testfk)
|
|
47
35
|
end
|
|
48
36
|
|
|
49
37
|
specify "should provide the server version" do
|
|
@@ -51,23 +39,13 @@ describe "A PostgreSQL database" do
|
|
|
51
39
|
end
|
|
52
40
|
|
|
53
41
|
specify "should correctly parse the schema" do
|
|
54
|
-
@db.schema(:
|
|
55
|
-
[:
|
|
56
|
-
[:
|
|
57
|
-
]
|
|
58
|
-
@db.schema(:test4, :reload=>true).should == [
|
|
59
|
-
[:name, {:oid=>1043, :type=>:string, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"character varying(20)", :primary_key=>false}],
|
|
60
|
-
[:value, {:oid=>17, :type=>:blob, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"bytea", :primary_key=>false}]
|
|
61
|
-
]
|
|
42
|
+
@db.schema(:public__testfk, :reload=>true).should == [
|
|
43
|
+
[:id, {:type=>:integer, :ruby_default=>nil, :db_type=>"integer", :default=>"nextval('testfk_id_seq'::regclass)", :oid=>23, :primary_key=>true, :allow_null=>false}],
|
|
44
|
+
[:i, {:type=>:integer, :ruby_default=>nil, :db_type=>"integer", :default=>nil, :oid=>23, :primary_key=>false, :allow_null=>true}]]
|
|
62
45
|
end
|
|
63
46
|
|
|
64
47
|
specify "should parse foreign keys for tables in a schema" do
|
|
65
|
-
|
|
66
|
-
@db.create_table!(:public__testfk){primary_key :id; foreign_key :i, :public__testfk}
|
|
67
|
-
@db.foreign_key_list(:public__testfk).should == [{:on_delete=>:no_action, :on_update=>:no_action, :columns=>[:i], :key=>[:id], :deferrable=>false, :table=>Sequel.qualify(:public, :testfk), :name=>:testfk_i_fkey}]
|
|
68
|
-
ensure
|
|
69
|
-
@db.drop_table(:public__testfk)
|
|
70
|
-
end
|
|
48
|
+
@db.foreign_key_list(:public__testfk).should == [{:on_delete=>:no_action, :on_update=>:no_action, :columns=>[:i], :key=>[:id], :deferrable=>false, :table=>Sequel.qualify(:public, :testfk), :name=>:testfk_i_fkey}]
|
|
71
49
|
end
|
|
72
50
|
|
|
73
51
|
specify "should return uuid fields as strings" do
|
|
@@ -76,10 +54,23 @@ describe "A PostgreSQL database" do
|
|
|
76
54
|
end
|
|
77
55
|
|
|
78
56
|
describe "A PostgreSQL dataset" do
|
|
57
|
+
before(:all) do
|
|
58
|
+
@db = POSTGRES_DB
|
|
59
|
+
@d = @db[:test]
|
|
60
|
+
@db.create_table! :test do
|
|
61
|
+
text :name
|
|
62
|
+
integer :value, :index => true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
79
65
|
before do
|
|
80
|
-
@d = POSTGRES_DB[:test]
|
|
81
66
|
@d.delete
|
|
82
|
-
|
|
67
|
+
@db.sqls.clear
|
|
68
|
+
end
|
|
69
|
+
after do
|
|
70
|
+
@db.drop_table?(:atest)
|
|
71
|
+
end
|
|
72
|
+
after(:all) do
|
|
73
|
+
@db.drop_table?(:test)
|
|
83
74
|
end
|
|
84
75
|
|
|
85
76
|
specify "should quote columns and tables using double quotes if quoting identifiers" do
|
|
@@ -130,68 +121,52 @@ describe "A PostgreSQL dataset" do
|
|
|
130
121
|
end
|
|
131
122
|
|
|
132
123
|
specify "should support exclusion constraints when creating or altering tables" do
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
proc{@db[:atest].insert(2)}.should raise_error(Sequel::DatabaseError)
|
|
145
|
-
@db.alter_table(:atest){drop_constraint 'atest_ex'}
|
|
146
|
-
ensure
|
|
147
|
-
@db.drop_table?(:atest)
|
|
148
|
-
end
|
|
124
|
+
@db.create_table!(:atest){Integer :t; exclude [[Sequel.desc(:t, :nulls=>:last), '=']], :using=>:btree, :where=>proc{t > 0}}
|
|
125
|
+
@db[:atest].insert(1)
|
|
126
|
+
@db[:atest].insert(2)
|
|
127
|
+
proc{@db[:atest].insert(2)}.should raise_error(Sequel::DatabaseError)
|
|
128
|
+
|
|
129
|
+
@db.create_table!(:atest){Integer :t}
|
|
130
|
+
@db.alter_table(:atest){add_exclusion_constraint [[:t, '=']], :using=>:btree, :name=>'atest_ex'}
|
|
131
|
+
@db[:atest].insert(1)
|
|
132
|
+
@db[:atest].insert(2)
|
|
133
|
+
proc{@db[:atest].insert(2)}.should raise_error(Sequel::DatabaseError)
|
|
134
|
+
@db.alter_table(:atest){drop_constraint 'atest_ex'}
|
|
149
135
|
end if POSTGRES_DB.server_version >= 90000
|
|
150
136
|
|
|
151
137
|
specify "should support adding foreign key constarints that are not yet valid, and validating them later" do
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
@db.alter_table(:atest){validate_constraint :atest_fk}
|
|
163
|
-
proc{@db.alter_table(:atest){validate_constraint :atest_fk}}.should_not raise_error
|
|
164
|
-
ensure
|
|
165
|
-
@db.drop_table?(:atest)
|
|
166
|
-
end
|
|
138
|
+
@db.create_table!(:atest){primary_key :id; Integer :fk}
|
|
139
|
+
@db[:atest].insert(1, 5)
|
|
140
|
+
@db.alter_table(:atest){add_foreign_key [:fk], :atest, :not_valid=>true, :name=>:atest_fk}
|
|
141
|
+
@db[:atest].insert(2, 1)
|
|
142
|
+
proc{@db[:atest].insert(3, 4)}.should raise_error(Sequel::DatabaseError)
|
|
143
|
+
|
|
144
|
+
proc{@db.alter_table(:atest){validate_constraint :atest_fk}}.should raise_error(Sequel::DatabaseError)
|
|
145
|
+
@db[:atest].where(:id=>1).update(:fk=>2)
|
|
146
|
+
@db.alter_table(:atest){validate_constraint :atest_fk}
|
|
147
|
+
proc{@db.alter_table(:atest){validate_constraint :atest_fk}}.should_not raise_error
|
|
167
148
|
end if POSTGRES_DB.server_version >= 90200
|
|
168
149
|
|
|
169
150
|
specify "should support :using when altering a column's type" do
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
@db.alter_table(:atest){set_column_type :t, Time, :using=>Sequel.cast('epoch', Time) + Sequel.cast('1 second', :interval) * :t}
|
|
175
|
-
@db[:atest].get(Sequel.extract(:year, :t)).should == 2010
|
|
176
|
-
ensure
|
|
177
|
-
@db.drop_table?(:atest)
|
|
178
|
-
end
|
|
151
|
+
@db.create_table!(:atest){Integer :t}
|
|
152
|
+
@db[:atest].insert(1262304000)
|
|
153
|
+
@db.alter_table(:atest){set_column_type :t, Time, :using=>Sequel.cast('epoch', Time) + Sequel.cast('1 second', :interval) * :t}
|
|
154
|
+
@db[:atest].get(Sequel.extract(:year, :t)).should == 2010
|
|
179
155
|
end
|
|
180
156
|
|
|
181
157
|
specify "should support :using with a string when altering a column's type" do
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
158
|
+
@db.create_table!(:atest){Integer :t}
|
|
159
|
+
@db[:atest].insert(1262304000)
|
|
160
|
+
@db.alter_table(:atest){set_column_type :t, Time, :using=>"'epoch'::timestamp + '1 second'::interval * t"}
|
|
161
|
+
@db[:atest].get(Sequel.extract(:year, :t)).should == 2010
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
specify "should be able to parse the default value for an interval type" do
|
|
165
|
+
@db.create_table!(:atest){interval :t, :default=>'1 week'}
|
|
166
|
+
@db.schema(:atest).first.last[:ruby_default].should == '7 days'
|
|
191
167
|
end
|
|
192
168
|
|
|
193
169
|
specify "should have #transaction support various types of synchronous options" do
|
|
194
|
-
@db = POSTGRES_DB
|
|
195
170
|
@db.transaction(:synchronous=>:on){}
|
|
196
171
|
@db.transaction(:synchronous=>true){}
|
|
197
172
|
@db.transaction(:synchronous=>:off){}
|
|
@@ -216,7 +191,6 @@ describe "A PostgreSQL dataset" do
|
|
|
216
191
|
end
|
|
217
192
|
|
|
218
193
|
specify "should have #transaction support read only transactions" do
|
|
219
|
-
@db = POSTGRES_DB
|
|
220
194
|
@db.transaction(:read_only=>true){}
|
|
221
195
|
@db.transaction(:read_only=>false){}
|
|
222
196
|
@db.transaction(:isolation=>:serializable, :read_only=>true){}
|
|
@@ -225,7 +199,6 @@ describe "A PostgreSQL dataset" do
|
|
|
225
199
|
end
|
|
226
200
|
|
|
227
201
|
specify "should have #transaction support deferrable transactions" do
|
|
228
|
-
@db = POSTGRES_DB
|
|
229
202
|
@db.transaction(:deferrable=>true){}
|
|
230
203
|
@db.transaction(:deferrable=>false){}
|
|
231
204
|
@db.transaction(:deferrable=>true, :read_only=>true){}
|
|
@@ -236,43 +209,42 @@ describe "A PostgreSQL dataset" do
|
|
|
236
209
|
end if POSTGRES_DB.server_version >= 90100
|
|
237
210
|
|
|
238
211
|
specify "should support creating indexes concurrently" do
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
POSTGRES_DB.sqls.should == ['CREATE INDEX CONCURRENTLY "test_name_value_index" ON "test" ("name", "value")'] if check_sqls
|
|
212
|
+
@db.add_index :test, [:name, :value], :concurrently=>true
|
|
213
|
+
@db.sqls.should == ['CREATE INDEX CONCURRENTLY "test_name_value_index" ON "test" ("name", "value")'] if check_sqls
|
|
242
214
|
end
|
|
243
215
|
|
|
244
216
|
specify "should support dropping indexes only if they already exist" do
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
217
|
+
@db.add_index :test, [:name, :value], :name=>'tnv1'
|
|
218
|
+
@db.sqls.clear
|
|
219
|
+
@db.drop_index :test, [:name, :value], :if_exists=>true, :name=>'tnv1'
|
|
220
|
+
@db.sqls.should == ['DROP INDEX IF EXISTS "tnv1"']
|
|
249
221
|
end
|
|
250
222
|
|
|
251
223
|
specify "should support CASCADE when dropping indexes" do
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
224
|
+
@db.add_index :test, [:name, :value], :name=>'tnv2'
|
|
225
|
+
@db.sqls.clear
|
|
226
|
+
@db.drop_index :test, [:name, :value], :cascade=>true, :name=>'tnv2'
|
|
227
|
+
@db.sqls.should == ['DROP INDEX "tnv2" CASCADE']
|
|
256
228
|
end
|
|
257
229
|
|
|
258
230
|
specify "should support dropping indexes concurrently" do
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
231
|
+
@db.add_index :test, [:name, :value], :name=>'tnv2'
|
|
232
|
+
@db.sqls.clear
|
|
233
|
+
@db.drop_index :test, [:name, :value], :concurrently=>true, :name=>'tnv2'
|
|
234
|
+
@db.sqls.should == ['DROP INDEX CONCURRENTLY "tnv2"']
|
|
263
235
|
end if POSTGRES_DB.server_version >= 90200
|
|
264
236
|
|
|
265
237
|
specify "#lock should lock table if inside a transaction" do
|
|
266
|
-
|
|
238
|
+
@db.transaction{@d.lock('EXCLUSIVE'); @d.insert(:name=>'a')}
|
|
267
239
|
end
|
|
268
240
|
|
|
269
241
|
specify "#lock should return nil" do
|
|
270
242
|
@d.lock('EXCLUSIVE'){@d.insert(:name=>'a')}.should == nil
|
|
271
|
-
|
|
243
|
+
@db.transaction{@d.lock('EXCLUSIVE').should == nil; @d.insert(:name=>'a')}
|
|
272
244
|
end
|
|
273
245
|
|
|
274
246
|
specify "should raise an error if attempting to update a joined dataset with a single FROM table" do
|
|
275
|
-
proc{
|
|
247
|
+
proc{@db[:test].join(:test, [:name]).update(:name=>'a')}.should raise_error(Sequel::Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs')
|
|
276
248
|
end
|
|
277
249
|
|
|
278
250
|
specify "should truncate with options" do
|
|
@@ -288,9 +260,9 @@ describe "A PostgreSQL dataset" do
|
|
|
288
260
|
end
|
|
289
261
|
|
|
290
262
|
specify "should truncate multiple tables at once" do
|
|
291
|
-
tables = [:test, :
|
|
263
|
+
tables = [:test, :test]
|
|
292
264
|
tables.each{|t| @d.from(t).insert}
|
|
293
|
-
@d.from(:test, :
|
|
265
|
+
@d.from(:test, :test).truncate
|
|
294
266
|
tables.each{|t| @d.from(t).count.should == 0}
|
|
295
267
|
end
|
|
296
268
|
end
|
|
@@ -377,14 +349,23 @@ if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
|
|
377
349
|
end
|
|
378
350
|
|
|
379
351
|
describe "A PostgreSQL dataset with a timestamp field" do
|
|
380
|
-
before do
|
|
352
|
+
before(:all) do
|
|
381
353
|
@db = POSTGRES_DB
|
|
354
|
+
@db.create_table! :test3 do
|
|
355
|
+
integer :value
|
|
356
|
+
timestamp :time
|
|
357
|
+
end
|
|
382
358
|
@d = @db[:test3]
|
|
359
|
+
end
|
|
360
|
+
before do
|
|
383
361
|
@d.delete
|
|
384
362
|
end
|
|
385
363
|
after do
|
|
386
364
|
@db.convert_infinite_timestamps = false if @db.adapter_scheme == :postgres
|
|
387
365
|
end
|
|
366
|
+
after(:all) do
|
|
367
|
+
@db.drop_table?(:test3)
|
|
368
|
+
end
|
|
388
369
|
|
|
389
370
|
cspecify "should store milliseconds in time fields for Time objects", :do, :swift do
|
|
390
371
|
t = Time.now
|
|
@@ -432,19 +413,29 @@ describe "A PostgreSQL dataset with a timestamp field" do
|
|
|
432
413
|
c.new(:time=>-1.0/0.0).time.should == -1.0/0.0
|
|
433
414
|
end
|
|
434
415
|
end
|
|
435
|
-
end
|
|
436
416
|
|
|
437
|
-
|
|
438
|
-
specify "should not raise errors" do
|
|
417
|
+
specify "explain and analyze should not raise errors" do
|
|
439
418
|
@d = POSTGRES_DB[:test3]
|
|
440
419
|
proc{@d.explain}.should_not raise_error
|
|
441
420
|
proc{@d.analyze}.should_not raise_error
|
|
442
421
|
end
|
|
422
|
+
|
|
423
|
+
specify "#locks should be a dataset returning database locks " do
|
|
424
|
+
@db.locks.should be_a_kind_of(Sequel::Dataset)
|
|
425
|
+
@db.locks.all.should be_a_kind_of(Array)
|
|
426
|
+
end
|
|
443
427
|
end
|
|
444
428
|
|
|
445
429
|
describe "A PostgreSQL database" do
|
|
446
430
|
before do
|
|
447
431
|
@db = POSTGRES_DB
|
|
432
|
+
@db.create_table! :test2 do
|
|
433
|
+
text :name
|
|
434
|
+
integer :value
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
after do
|
|
438
|
+
@db.drop_table?(:test2)
|
|
448
439
|
end
|
|
449
440
|
|
|
450
441
|
specify "should support column operations" do
|
|
@@ -478,11 +469,6 @@ describe "A PostgreSQL database" do
|
|
|
478
469
|
|
|
479
470
|
@db[:test2].first[:xyz].should == 57
|
|
480
471
|
end
|
|
481
|
-
|
|
482
|
-
specify "#locks should be a dataset returning database locks " do
|
|
483
|
-
@db.locks.should be_a_kind_of(Sequel::Dataset)
|
|
484
|
-
@db.locks.all.should be_a_kind_of(Array)
|
|
485
|
-
end
|
|
486
472
|
end
|
|
487
473
|
|
|
488
474
|
describe "A PostgreSQL database" do
|
|
@@ -679,9 +665,9 @@ describe "Postgres::Dataset#insert" do
|
|
|
679
665
|
end
|
|
680
666
|
|
|
681
667
|
specify "should return nil if the table has no primary key" do
|
|
682
|
-
|
|
683
|
-
ds.delete
|
|
684
|
-
ds.insert(:name=>'a').should == nil
|
|
668
|
+
@db.create_table!(:test5){String :name; Integer :value}
|
|
669
|
+
@ds.delete
|
|
670
|
+
@ds.insert(:name=>'a').should == nil
|
|
685
671
|
end
|
|
686
672
|
end
|
|
687
673
|
|
|
@@ -763,7 +749,7 @@ describe "Postgres::Database schema qualified tables" do
|
|
|
763
749
|
|
|
764
750
|
specify "should be able to get serial sequences for tables in a given schema" do
|
|
765
751
|
POSTGRES_DB.create_table(:schema_test__schema_test){primary_key :i}
|
|
766
|
-
POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".schema_test_i_seq'
|
|
752
|
+
POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
|
|
767
753
|
end
|
|
768
754
|
|
|
769
755
|
specify "should be able to get serial sequences for tables that have spaces in the name in a given schema" do
|
|
@@ -789,7 +775,7 @@ describe "Postgres::Database schema qualified tables" do
|
|
|
789
775
|
POSTGRES_DB.table_exists?(:schema_test).should == true
|
|
790
776
|
POSTGRES_DB.tables.should == [:schema_test]
|
|
791
777
|
POSTGRES_DB.primary_key(:schema_test__schema_test).should == 'i'
|
|
792
|
-
POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".schema_test_i_seq'
|
|
778
|
+
POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
|
|
793
779
|
end
|
|
794
780
|
end
|
|
795
781
|
|
|
@@ -972,20 +958,21 @@ describe "Postgres::Database schema qualified tables and eager graphing" do
|
|
|
972
958
|
end
|
|
973
959
|
|
|
974
960
|
if POSTGRES_DB.server_version >= 80300
|
|
975
|
-
|
|
976
|
-
POSTGRES_DB.create_table! :test6 do
|
|
977
|
-
text :title
|
|
978
|
-
text :body
|
|
979
|
-
full_text_index [:title, :body]
|
|
980
|
-
end
|
|
981
|
-
|
|
982
961
|
describe "PostgreSQL tsearch2" do
|
|
983
|
-
before do
|
|
962
|
+
before(:all) do
|
|
963
|
+
POSTGRES_DB.create_table! :test6 do
|
|
964
|
+
text :title
|
|
965
|
+
text :body
|
|
966
|
+
full_text_index [:title, :body]
|
|
967
|
+
end
|
|
984
968
|
@ds = POSTGRES_DB[:test6]
|
|
985
969
|
end
|
|
986
970
|
after do
|
|
987
971
|
POSTGRES_DB[:test6].delete
|
|
988
972
|
end
|
|
973
|
+
after(:all) do
|
|
974
|
+
POSTGRES_DB.drop_table?(:test6)
|
|
975
|
+
end
|
|
989
976
|
|
|
990
977
|
specify "should search by indexed column" do
|
|
991
978
|
record = {:title => "oopsla conference", :body => "test"}
|
|
@@ -1244,6 +1231,78 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
|
1244
1231
|
end
|
|
1245
1232
|
end
|
|
1246
1233
|
|
|
1234
|
+
describe "Postgres::Database#copy_table_from" do
|
|
1235
|
+
before(:all) do
|
|
1236
|
+
@db = POSTGRES_DB
|
|
1237
|
+
@db.create_table!(:test_copy){Integer :x; Integer :y}
|
|
1238
|
+
@ds = @db[:test_copy].order(:x, :y)
|
|
1239
|
+
end
|
|
1240
|
+
before do
|
|
1241
|
+
@db[:test_copy].delete
|
|
1242
|
+
end
|
|
1243
|
+
after(:all) do
|
|
1244
|
+
@db.drop_table?(:test_copy)
|
|
1245
|
+
end
|
|
1246
|
+
|
|
1247
|
+
specify "should work with a :data option containing data in PostgreSQL text format" do
|
|
1248
|
+
@db.copy_into(:test_copy, :data=>"1\t2\n3\t4\n")
|
|
1249
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1250
|
+
end
|
|
1251
|
+
|
|
1252
|
+
specify "should work with :format=>:csv option and :data option containing data in CSV format" do
|
|
1253
|
+
@db.copy_into(:test_copy, :format=>:csv, :data=>"1,2\n3,4\n")
|
|
1254
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1255
|
+
end
|
|
1256
|
+
|
|
1257
|
+
specify "should respect given :options" do
|
|
1258
|
+
@db.copy_into(:test_copy, :options=>"FORMAT csv, HEADER TRUE", :data=>"x,y\n1,2\n3,4\n")
|
|
1259
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1260
|
+
end
|
|
1261
|
+
|
|
1262
|
+
specify "should respect given :options options when :format is used" do
|
|
1263
|
+
@db.copy_into(:test_copy, :options=>"QUOTE '''', DELIMITER '|'", :format=>:csv, :data=>"'1'|'2'\n'3'|'4'\n")
|
|
1264
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
specify "should accept :columns option to online copy the given columns" do
|
|
1268
|
+
@db.copy_into(:test_copy, :data=>"1\t2\n3\t4\n", :columns=>[:y, :x])
|
|
1269
|
+
@ds.select_map([:x, :y]).should == [[2, 1], [4, 3]]
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
specify "should accept a block and use returned values for the copy in data stream" do
|
|
1273
|
+
buf = ["1\t2\n", "3\t4\n"]
|
|
1274
|
+
@db.copy_into(:test_copy){buf.shift}
|
|
1275
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1276
|
+
end
|
|
1277
|
+
|
|
1278
|
+
specify "should work correctly with a block and :format=>:csv" do
|
|
1279
|
+
buf = ["1,2\n", "3,4\n"]
|
|
1280
|
+
@db.copy_into(:test_copy, :format=>:csv){buf.shift}
|
|
1281
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1282
|
+
end
|
|
1283
|
+
|
|
1284
|
+
specify "should accept an enumerable as the :data option" do
|
|
1285
|
+
@db.copy_into(:test_copy, :data=>["1\t2\n", "3\t4\n"])
|
|
1286
|
+
@ds.select_map([:x, :y]).should == [[1, 2], [3, 4]]
|
|
1287
|
+
end
|
|
1288
|
+
|
|
1289
|
+
specify "should have an exception should cause a rollback of copied data and still have a usable connection" do
|
|
1290
|
+
2.times do
|
|
1291
|
+
sent = false
|
|
1292
|
+
proc{@db.copy_into(:test_copy){raise ArgumentError if sent; sent = true; "1\t2\n"}}.should raise_error(ArgumentError)
|
|
1293
|
+
@ds.select_map([:x, :y]).should == []
|
|
1294
|
+
end
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1297
|
+
specify "should raise an Error if both :data and a block are provided" do
|
|
1298
|
+
proc{@db.copy_into(:test_copy, :data=>["1\t2\n", "3\t4\n"]){}}.should raise_error(Sequel::Error)
|
|
1299
|
+
end
|
|
1300
|
+
|
|
1301
|
+
specify "should raise an Error if neither :data or a block are provided" do
|
|
1302
|
+
proc{@db.copy_into(:test_copy)}.should raise_error(Sequel::Error)
|
|
1303
|
+
end
|
|
1304
|
+
end
|
|
1305
|
+
|
|
1247
1306
|
describe "Postgres::Database LISTEN/NOTIFY" do
|
|
1248
1307
|
before(:all) do
|
|
1249
1308
|
@db = POSTGRES_DB
|
|
@@ -2363,6 +2422,7 @@ end if ((require 'active_support/duration'; require 'active_support/inflector';
|
|
|
2363
2422
|
describe 'PostgreSQL row-valued/composite types' do
|
|
2364
2423
|
before(:all) do
|
|
2365
2424
|
@db = POSTGRES_DB
|
|
2425
|
+
Sequel.extension :pg_array_ops, :pg_row_ops
|
|
2366
2426
|
@db.extension :pg_array, :pg_row
|
|
2367
2427
|
@ds = @db[:person]
|
|
2368
2428
|
|
|
@@ -2450,7 +2510,6 @@ describe 'PostgreSQL row-valued/composite types' do
|
|
|
2450
2510
|
end if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG
|
|
2451
2511
|
|
|
2452
2512
|
specify 'operations/functions with pg_row_ops' do
|
|
2453
|
-
Sequel.extension :pg_row_ops, :pg_array_ops
|
|
2454
2513
|
@ds.insert(:id=>1, :address=>Sequel.pg_row(['123 Sesame St', 'Somewhere', '12345']))
|
|
2455
2514
|
@ds.get(Sequel.pg_row(:address)[:street]).should == '123 Sesame St'
|
|
2456
2515
|
@ds.get(Sequel.pg_row(:address)[:city]).should == 'Somewhere'
|
|
@@ -2470,6 +2529,45 @@ describe 'PostgreSQL row-valued/composite types' do
|
|
|
2470
2529
|
@ds.get(Sequel.pg_row(:company)[:employees][1][:address][:zip]).should == '12345'
|
|
2471
2530
|
end
|
|
2472
2531
|
|
|
2532
|
+
context "#splat and #*" do
|
|
2533
|
+
before(:all) do
|
|
2534
|
+
@db.create_table!(:a){Integer :a}
|
|
2535
|
+
@db.create_table!(:b){a :b; Integer :a}
|
|
2536
|
+
@db.register_row_type(:a)
|
|
2537
|
+
@db.register_row_type(:b)
|
|
2538
|
+
@db[:b].insert(:a=>1, :b=>@db.row_type(:a, [2]))
|
|
2539
|
+
end
|
|
2540
|
+
after(:all) do
|
|
2541
|
+
@db.drop_table?(:b, :a)
|
|
2542
|
+
end
|
|
2543
|
+
|
|
2544
|
+
specify "splat should reference the table type" do
|
|
2545
|
+
@db[:b].select(:a).first.should == {:a=>1}
|
|
2546
|
+
@db[:b].select(:b__a).first.should == {:a=>1}
|
|
2547
|
+
@db[:b].select(Sequel.pg_row(:b)[:a]).first.should == {:a=>2}
|
|
2548
|
+
@db[:b].select(Sequel.pg_row(:b).splat[:a]).first.should == {:a=>1}
|
|
2549
|
+
|
|
2550
|
+
if @native
|
|
2551
|
+
@db[:b].select(:b).first.should == {:b=>{:a=>2}}
|
|
2552
|
+
@db[:b].select(Sequel.pg_row(:b).splat).first.should == {:a=>1, :b=>{:a=>2}}
|
|
2553
|
+
@db[:b].select(Sequel.pg_row(:b).splat(:b)).first.should == {:b=>{:a=>1, :b=>{:a=>2}}}
|
|
2554
|
+
end
|
|
2555
|
+
end
|
|
2556
|
+
|
|
2557
|
+
specify "* should expand the table type into separate columns" do
|
|
2558
|
+
ds = @db[:b].select(Sequel.pg_row(:b).splat(:b)).from_self(:alias=>:t)
|
|
2559
|
+
if @native
|
|
2560
|
+
ds.first.should == {:b=>{:a=>1, :b=>{:a=>2}}}
|
|
2561
|
+
ds.select(Sequel.pg_row(:b).*).first.should == {:a=>1, :b=>{:a=>2}}
|
|
2562
|
+
ds.select(Sequel.pg_row(:b)[:b]).first.should == {:b=>{:a=>2}}
|
|
2563
|
+
ds.select(Sequel.pg_row(:t__b).*).first.should == {:a=>1, :b=>{:a=>2}}
|
|
2564
|
+
ds.select(Sequel.pg_row(:t__b)[:b]).first.should == {:b=>{:a=>2}}
|
|
2565
|
+
end
|
|
2566
|
+
ds.select(Sequel.pg_row(:b)[:a]).first.should == {:a=>1}
|
|
2567
|
+
ds.select(Sequel.pg_row(:t__b)[:a]).first.should == {:a=>1}
|
|
2568
|
+
end
|
|
2569
|
+
end
|
|
2570
|
+
|
|
2473
2571
|
context "with models" do
|
|
2474
2572
|
before(:all) do
|
|
2475
2573
|
class Address < Sequel::Model(:address)
|