sequel 3.21.0 → 3.29.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 +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
|
@@ -1,36 +1,26 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
|
-
require "timeout"
|
|
3
2
|
|
|
4
3
|
unless defined?(ORACLE_DB)
|
|
5
4
|
ORACLE_DB = Sequel.connect('oracle://hr:hr@localhost/XE')
|
|
6
5
|
end
|
|
7
6
|
INTEGRATION_DB = ORACLE_DB unless defined?(INTEGRATION_DB)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
varchar2 :name, :size => 50
|
|
14
|
-
number :value, :size => 38
|
|
15
|
-
date :date_created
|
|
8
|
+
ORACLE_DB.create_table!(:items) do
|
|
9
|
+
String :name, :size => 50
|
|
10
|
+
Integer :value
|
|
11
|
+
Date :date_created
|
|
16
12
|
index :value
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
number :id, :size => 38
|
|
24
|
-
varchar2 :title, :size => 50
|
|
25
|
-
number :category_id, :size => 38
|
|
15
|
+
ORACLE_DB.create_table!(:books) do
|
|
16
|
+
Integer :id
|
|
17
|
+
String :title, :size => 50
|
|
18
|
+
Integer :category_id
|
|
26
19
|
end
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ORACLE_DB.create_table :categories do
|
|
32
|
-
number :id, :size => 38
|
|
33
|
-
varchar2 :cat_name, :size => 50
|
|
21
|
+
ORACLE_DB.create_table!(:categories) do
|
|
22
|
+
Integer :id
|
|
23
|
+
String :cat_name, :size => 50
|
|
34
24
|
end
|
|
35
25
|
|
|
36
26
|
describe "An Oracle database" do
|
|
@@ -40,38 +30,39 @@ describe "An Oracle database" do
|
|
|
40
30
|
ORACLE_DB.disconnect
|
|
41
31
|
ORACLE_DB.pool.size.should == 0
|
|
42
32
|
end
|
|
33
|
+
|
|
34
|
+
specify "should be able to get current sequence value with SQL" do
|
|
35
|
+
begin
|
|
36
|
+
ORACLE_DB.create_table!(:foo){primary_key :id}
|
|
37
|
+
ORACLE_DB.fetch('SELECT seq_foo_id.nextval FROM DUAL').single_value.should == 1
|
|
38
|
+
ensure
|
|
39
|
+
ORACLE_DB.drop_table(:foo)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
43
42
|
|
|
44
43
|
specify "should provide schema information" do
|
|
45
|
-
books_schema = [
|
|
46
|
-
[:
|
|
47
|
-
[:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
[:
|
|
52
|
-
|
|
53
|
-
[:name, {:char_size=>50, :type=>:varchar2, :allow_null=>true, :type_string=>"VARCHAR2(50)", :data_size=>50, :precision=>0, :char_used=>false, :scale=>0, :charset_form=>:implicit, :fsprecision=>0, :lfprecision=>0, :db_type=>"VARCHAR2(50)"}],
|
|
54
|
-
[:value, {:char_size=>0, :type=>:number, :allow_null=>true, :type_string=>"NUMBER(38)", :data_size=>22, :precision=>38, :char_used=>false, :scale=>0, :charset_form=>nil, :fsprecision=>38, :lfprecision=>0, :db_type=>"NUMBER(38)"}],
|
|
55
|
-
[:date_created, {:charset_form=>nil, :type=>:date, :type_string=>"DATE", :fsprecision=>0, :data_size=>7, :lfprecision=>0, :precision=>0, :db_type=>"DATE", :char_used=>false, :char_size=>0, :scale=>0, :allow_null=>true}]]
|
|
44
|
+
books_schema = [[:id, [:integer, false, true, nil]],
|
|
45
|
+
[:title, [:string, false, true, nil]],
|
|
46
|
+
[:category_id, [:integer, false, true, nil]]]
|
|
47
|
+
categories_schema = [[:id, [:integer, false, true, nil]],
|
|
48
|
+
[:cat_name, [:string, false, true, nil]]]
|
|
49
|
+
items_schema = [[:name, [:string, false, true, nil]],
|
|
50
|
+
[:value, [:integer, false, true, nil]],
|
|
51
|
+
[:date_created, [:datetime, false, true, nil]]]
|
|
56
52
|
|
|
57
53
|
{:books => books_schema, :categories => categories_schema, :items => items_schema}.each_pair do |table, expected_schema|
|
|
58
54
|
schema = ORACLE_DB.schema(table)
|
|
59
55
|
schema.should_not be_nil
|
|
60
|
-
|
|
56
|
+
schema.map{|c, s| [c, s.values_at(:type, :primary_key, :allow_null, :ruby_default)]}.should == expected_schema
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
specify "should create a temporary table" do
|
|
65
|
-
ORACLE_DB.create_table :test_tmp, :
|
|
61
|
+
ORACLE_DB.create_table! :test_tmp, :temp => true do
|
|
62
|
+
varchar2 :name, :size => 50
|
|
66
63
|
primary_key :id, :integer, :null => false
|
|
67
|
-
column :name, :text
|
|
68
64
|
index :name, :unique => true
|
|
69
65
|
end
|
|
70
|
-
|
|
71
|
-
ORACLE_DB.sqls.should == [
|
|
72
|
-
'CREATE GLOBAL TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
|
|
73
|
-
'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
|
|
74
|
-
]
|
|
75
66
|
end
|
|
76
67
|
end
|
|
77
68
|
|
|
@@ -148,27 +139,27 @@ describe "An Oracle dataset" do
|
|
|
148
139
|
|
|
149
140
|
@d.max(:value).to_i.should == 789
|
|
150
141
|
|
|
151
|
-
@d.select(:name, :AVG.sql_function(:value)).filter(:name => 'abc').group(:name).to_a.should == [
|
|
152
|
-
{:name => 'abc', :
|
|
142
|
+
@d.select(:name, :AVG.sql_function(:value).as(:avg)).filter(:name => 'abc').group(:name).to_a.should == [
|
|
143
|
+
{:name => 'abc', :avg => (456+123)/2.0}
|
|
153
144
|
]
|
|
154
145
|
|
|
155
|
-
@d.select(:AVG.sql_function(:value)).group(:name).order(:name).limit(1).to_a.should == [
|
|
156
|
-
{:
|
|
146
|
+
@d.select(:AVG.sql_function(:value).as(:avg)).group(:name).order(:name).limit(1).to_a.should == [
|
|
147
|
+
{:avg => (456+123)/2.0}
|
|
157
148
|
]
|
|
158
149
|
|
|
159
|
-
@d.select(:name, :AVG.sql_function(:value)).group(:name).order(:name).to_a.should == [
|
|
160
|
-
{:name => 'abc', :
|
|
161
|
-
{:name => 'def', :
|
|
150
|
+
@d.select(:name, :AVG.sql_function(:value).as(:avg)).group(:name).order(:name).to_a.should == [
|
|
151
|
+
{:name => 'abc', :avg => (456+123)/2.0},
|
|
152
|
+
{:name => 'def', :avg => 789*1.0}
|
|
162
153
|
]
|
|
163
154
|
|
|
164
|
-
@d.select(:name, :AVG.sql_function(:value)).group(:name).order(:name).to_a.should == [
|
|
165
|
-
{:name => 'abc', :
|
|
166
|
-
{:name => 'def', :
|
|
155
|
+
@d.select(:name, :AVG.sql_function(:value).as(:avg)).group(:name).order(:name).to_a.should == [
|
|
156
|
+
{:name => 'abc', :avg => (456+123)/2.0},
|
|
157
|
+
{:name => 'def', :avg => 789*1.0}
|
|
167
158
|
]
|
|
168
159
|
|
|
169
|
-
@d.select(:name, :AVG.sql_function(:value)).group(:name).having(:name => ['abc', 'def']).order(:name).to_a.should == [
|
|
170
|
-
{:name => 'abc', :
|
|
171
|
-
{:name => 'def', :
|
|
160
|
+
@d.select(:name, :AVG.sql_function(:value).as(:avg)).group(:name).having(:name => ['abc', 'def']).order(:name).to_a.should == [
|
|
161
|
+
{:name => 'abc', :avg => (456+123)/2.0},
|
|
162
|
+
{:name => 'def', :avg => 789*1.0}
|
|
172
163
|
]
|
|
173
164
|
|
|
174
165
|
@d.select(:name, :value).filter(:name => 'abc').union(@d.select(:name, :value).filter(:name => 'def')).order(:value).to_a.should == [
|
|
@@ -194,7 +185,7 @@ describe "An Oracle dataset" do
|
|
|
194
185
|
specify "should translate values correctly" do
|
|
195
186
|
@d << {:name => 'abc', :value => 456}
|
|
196
187
|
@d << {:name => 'def', :value => 789}
|
|
197
|
-
@d.filter(
|
|
188
|
+
@d.filter('value > 500').update(:date_created => "to_timestamp('2009-09-09', 'YYYY-MM-DD')".lit)
|
|
198
189
|
|
|
199
190
|
@d[:name => 'def'][:date_created].should == Time.parse('2009-09-09')
|
|
200
191
|
end
|
|
@@ -289,34 +280,15 @@ end
|
|
|
289
280
|
describe "Row locks in Oracle" do
|
|
290
281
|
before do
|
|
291
282
|
@d1 = ORACLE_DB[:books]
|
|
292
|
-
@d1.delete
|
|
283
|
+
@d1.delete
|
|
293
284
|
@d1 << {:id => 1, :title => 'aaa'}
|
|
294
285
|
end
|
|
295
286
|
|
|
296
287
|
specify "#for_update should use FOR UPDATE" do
|
|
297
|
-
@d1.for_update.sql.should ==
|
|
288
|
+
@d1.for_update.sql.should == 'SELECT * FROM "BOOKS" FOR UPDATE'
|
|
298
289
|
end
|
|
299
290
|
|
|
300
291
|
specify "#lock_style should accept symbols" do
|
|
301
|
-
@d1.lock_style(:update).sql.should ==
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
specify "should not update during row lock" do
|
|
305
|
-
ORACLE_DB.transaction do
|
|
306
|
-
@d1.filter(:id => 1).for_update.to_a
|
|
307
|
-
proc do
|
|
308
|
-
t1 = Thread.start do
|
|
309
|
-
# wait for unlock
|
|
310
|
-
Timeout::timeout(0.02) do
|
|
311
|
-
ORACLE_DB[:books].filter(:id => 1).update(:title => "bbb")
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
t1.join
|
|
315
|
-
end.should raise_error
|
|
316
|
-
@d1.filter(:id => 1).first[:title].should == "aaa"
|
|
317
|
-
end
|
|
318
|
-
t2 = Thread.start { ORACLE_DB[:books].filter(:id => 1).update(:title => "bbb") }
|
|
319
|
-
t2.join
|
|
320
|
-
@d1.filter(:id => 1).first[:title].should == "bbb"
|
|
292
|
+
@d1.lock_style(:update).sql.should == 'SELECT * FROM "BOOKS" FOR UPDATE'
|
|
321
293
|
end
|
|
322
294
|
end
|
|
@@ -197,35 +197,39 @@ if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
|
|
197
197
|
|
|
198
198
|
specify "should handle FOR UPDATE" do
|
|
199
199
|
@ds.insert(:number=>20)
|
|
200
|
-
c = nil
|
|
201
|
-
|
|
200
|
+
c, t = nil, nil
|
|
201
|
+
q = Queue.new
|
|
202
202
|
POSTGRES_DB.transaction do
|
|
203
203
|
@ds.for_update.first(:id=>1)
|
|
204
204
|
t = Thread.new do
|
|
205
205
|
POSTGRES_DB.transaction do
|
|
206
|
+
q.push nil
|
|
206
207
|
@ds.filter(:id=>1).update(:name=>'Jim')
|
|
207
208
|
c = @ds.first(:id=>1)
|
|
209
|
+
q.push nil
|
|
208
210
|
end
|
|
209
211
|
end
|
|
210
|
-
|
|
212
|
+
q.pop
|
|
211
213
|
@ds.filter(:id=>1).update(:number=>30)
|
|
212
214
|
end
|
|
215
|
+
q.pop
|
|
213
216
|
t.join
|
|
214
217
|
c.should == {:id=>1, :number=>30, :name=>'Jim'}
|
|
215
218
|
end
|
|
216
219
|
|
|
217
220
|
specify "should handle FOR SHARE" do
|
|
218
221
|
@ds.insert(:number=>20)
|
|
219
|
-
c = nil
|
|
220
|
-
|
|
222
|
+
c, t = nil
|
|
223
|
+
q = Queue.new
|
|
221
224
|
POSTGRES_DB.transaction do
|
|
222
225
|
@ds.for_share.first(:id=>1)
|
|
223
226
|
t = Thread.new do
|
|
224
227
|
POSTGRES_DB.transaction do
|
|
225
228
|
c = @ds.for_share.filter(:id=>1).first
|
|
229
|
+
q.push nil
|
|
226
230
|
end
|
|
227
231
|
end
|
|
228
|
-
|
|
232
|
+
q.pop
|
|
229
233
|
@ds.filter(:id=>1).update(:name=>'Jim')
|
|
230
234
|
c.should == {:id=>1, :number=>20, :name=>nil}
|
|
231
235
|
end
|
|
@@ -351,17 +355,17 @@ describe "A PostgreSQL database" do
|
|
|
351
355
|
specify "should support opclass specification" do
|
|
352
356
|
@db.create_table(:posts){text :title; text :body; integer :user_id; index(:user_id, :opclass => :int4_ops, :type => :btree)}
|
|
353
357
|
@db.sqls.should == [
|
|
354
|
-
|
|
355
|
-
|
|
358
|
+
'CREATE TABLE "posts" ("title" text, "body" text, "user_id" integer)',
|
|
359
|
+
'CREATE INDEX "posts_user_id_index" ON "posts" USING btree ("user_id" int4_ops)'
|
|
356
360
|
]
|
|
357
361
|
end
|
|
358
362
|
|
|
359
363
|
specify "should support fulltext indexes and searching" do
|
|
360
364
|
@db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french'}
|
|
361
365
|
@db.sqls.should == [
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
%{CREATE TABLE "posts" ("title" text, "body" text)},
|
|
367
|
+
%{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple', (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
|
|
368
|
+
%{CREATE INDEX "posts_title_index" ON "posts" USING gin (to_tsvector('french', (COALESCE("title", ''))))}
|
|
365
369
|
]
|
|
366
370
|
|
|
367
371
|
@db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
|
|
@@ -373,48 +377,48 @@ describe "A PostgreSQL database" do
|
|
|
373
377
|
@db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
|
|
374
378
|
@db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
|
375
379
|
@db.sqls.should == [
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
380
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple', (COALESCE("title", ''))) @@ to_tsquery('simple', 'rails'))},
|
|
381
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple', (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple', 'yowsa | rails'))},
|
|
382
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('french', (COALESCE("title", ''))) @@ to_tsquery('french', 'scooby'))}]
|
|
379
383
|
end
|
|
380
384
|
|
|
381
385
|
specify "should support spatial indexes" do
|
|
382
386
|
@db.create_table(:posts){box :geom; spatial_index [:geom]}
|
|
383
387
|
@db.sqls.should == [
|
|
384
|
-
|
|
385
|
-
|
|
388
|
+
'CREATE TABLE "posts" ("geom" box)',
|
|
389
|
+
'CREATE INDEX "posts_geom_index" ON "posts" USING gist ("geom")'
|
|
386
390
|
]
|
|
387
391
|
end
|
|
388
392
|
|
|
389
393
|
specify "should support indexes with index type" do
|
|
390
394
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'hash'}
|
|
391
395
|
@db.sqls.should == [
|
|
392
|
-
|
|
393
|
-
|
|
396
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
397
|
+
'CREATE INDEX "posts_title_index" ON "posts" USING hash ("title")'
|
|
394
398
|
]
|
|
395
399
|
end
|
|
396
400
|
|
|
397
401
|
specify "should support unique indexes with index type" do
|
|
398
402
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'btree', :unique => true}
|
|
399
403
|
@db.sqls.should == [
|
|
400
|
-
|
|
401
|
-
|
|
404
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
405
|
+
'CREATE UNIQUE INDEX "posts_title_index" ON "posts" USING btree ("title")'
|
|
402
406
|
]
|
|
403
407
|
end
|
|
404
408
|
|
|
405
409
|
specify "should support partial indexes" do
|
|
406
410
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
|
407
411
|
@db.sqls.should == [
|
|
408
|
-
|
|
409
|
-
|
|
412
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
413
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
|
410
414
|
]
|
|
411
415
|
end
|
|
412
416
|
|
|
413
417
|
specify "should support identifiers for table names in indicies" do
|
|
414
418
|
@db.create_table(Sequel::SQL::Identifier.new(:posts)){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
|
415
419
|
@db.sqls.should == [
|
|
416
|
-
|
|
417
|
-
|
|
420
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
421
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
|
418
422
|
]
|
|
419
423
|
end
|
|
420
424
|
|
|
@@ -442,8 +446,8 @@ describe "Postgres::Dataset#import" do
|
|
|
442
446
|
|
|
443
447
|
@db.sqls.should == [
|
|
444
448
|
'BEGIN',
|
|
445
|
-
'INSERT INTO test (x, y) VALUES (1, 2)',
|
|
446
|
-
'INSERT INTO test (x, y) VALUES (3, 4)',
|
|
449
|
+
'INSERT INTO "test" ("x", "y") VALUES (1, 2)',
|
|
450
|
+
'INSERT INTO "test" ("x", "y") VALUES (3, 4)',
|
|
447
451
|
'COMMIT'
|
|
448
452
|
]
|
|
449
453
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
@@ -456,7 +460,7 @@ describe "Postgres::Dataset#import" do
|
|
|
456
460
|
|
|
457
461
|
@db.sqls.should == [
|
|
458
462
|
'BEGIN',
|
|
459
|
-
'INSERT INTO test (x, y) VALUES (1, 2), (3, 4)',
|
|
463
|
+
'INSERT INTO "test" ("x", "y") VALUES (1, 2), (3, 4)',
|
|
460
464
|
'COMMIT'
|
|
461
465
|
]
|
|
462
466
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
@@ -487,10 +491,10 @@ describe "Postgres::Dataset#insert" do
|
|
|
487
491
|
@ds.insert(:value=>13).should == 3
|
|
488
492
|
|
|
489
493
|
@db.sqls.reject{|x| x =~ /pg_class/}.should == [
|
|
490
|
-
'INSERT INTO test5 (value) VALUES (10) RETURNING xid',
|
|
491
|
-
'INSERT INTO test5 (value) VALUES (20)',
|
|
494
|
+
'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"',
|
|
495
|
+
'INSERT INTO "test5" ("value") VALUES (20)',
|
|
492
496
|
"SELECT currval('\"public\".test5_xid_seq')",
|
|
493
|
-
'INSERT INTO test5 (value) VALUES (13)',
|
|
497
|
+
'INSERT INTO "test5" ("value") VALUES (13)',
|
|
494
498
|
"SELECT currval('\"public\".test5_xid_seq')"
|
|
495
499
|
]
|
|
496
500
|
@ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}, {:xid=>3, :value=>13}]
|
|
@@ -498,25 +502,20 @@ describe "Postgres::Dataset#insert" do
|
|
|
498
502
|
|
|
499
503
|
specify "should call execute_insert if server_version < 80200" do
|
|
500
504
|
@ds.meta_def(:server_version){80100}
|
|
501
|
-
@ds.should_receive(:execute_insert).once.with('INSERT INTO test5 (value) VALUES (10)', :table=>:test5, :values=>{:value=>10})
|
|
505
|
+
@ds.should_receive(:execute_insert).once.with('INSERT INTO "test5" ("value") VALUES (10)', :table=>:test5, :values=>{:value=>10})
|
|
502
506
|
@ds.insert(:value=>10)
|
|
503
507
|
end
|
|
504
508
|
|
|
505
509
|
specify "should call execute_insert if disabling insert returning" do
|
|
506
510
|
@ds.disable_insert_returning!
|
|
507
|
-
@ds.should_receive(:execute_insert).once.with('INSERT INTO test5 (value) VALUES (10)', :table=>:test5, :values=>{:value=>10})
|
|
511
|
+
@ds.should_receive(:execute_insert).once.with('INSERT INTO "test5" ("value") VALUES (10)', :table=>:test5, :values=>{:value=>10})
|
|
508
512
|
@ds.insert(:value=>10)
|
|
509
513
|
end
|
|
510
514
|
|
|
511
515
|
specify "should use INSERT RETURNING if server_version >= 80200" do
|
|
512
516
|
@ds.meta_def(:server_version){80201}
|
|
513
517
|
@ds.insert(:value=>10)
|
|
514
|
-
@db.sqls.last.should == 'INSERT INTO test5 (value) VALUES (10) RETURNING xid'
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
specify "should have insert_returning_sql use the RETURNING keyword" do
|
|
518
|
-
@ds.insert_returning_sql(:xid, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING xid"
|
|
519
|
-
@ds.insert_returning_sql('*'.lit, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING *"
|
|
518
|
+
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"'
|
|
520
519
|
end
|
|
521
520
|
|
|
522
521
|
specify "should have insert_select return nil if server_version < 80200" do
|
|
@@ -606,12 +605,6 @@ describe "Postgres::Database schema qualified tables" do
|
|
|
606
605
|
POSTGRES_DB.drop_table(:domains)
|
|
607
606
|
end
|
|
608
607
|
|
|
609
|
-
specify "#table_exists? should not include tables from the default non-public schemas" do
|
|
610
|
-
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
611
|
-
POSTGRES_DB.table_exists?(:schema_test).should == true
|
|
612
|
-
POSTGRES_DB.table_exists?(:domain_udt_usage).should == false
|
|
613
|
-
end
|
|
614
|
-
|
|
615
608
|
specify "#table_exists? should see if the table is in a given schema" do
|
|
616
609
|
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
617
610
|
POSTGRES_DB.table_exists?(:schema_test__schema_test).should == true
|
|
@@ -909,7 +902,7 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
909
902
|
after do
|
|
910
903
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true)
|
|
911
904
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
|
|
912
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
905
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
913
906
|
@d.drop_table(:test) rescue nil
|
|
914
907
|
end
|
|
915
908
|
|
|
@@ -940,19 +933,19 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
940
933
|
|
|
941
934
|
specify "#create_language and #drop_language should create and drop languages" do
|
|
942
935
|
@d.send(:create_language_sql, :plpgsql).should == 'CREATE LANGUAGE plpgsql'
|
|
943
|
-
@d.create_language(:plpgsql, :replace=>true)
|
|
936
|
+
@d.create_language(:plpgsql, :replace=>true) if @d.server_version < 90000
|
|
944
937
|
proc{@d.create_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
|
|
945
938
|
@d.send(:drop_language_sql, :plpgsql).should == 'DROP LANGUAGE plpgsql'
|
|
946
|
-
@d.drop_language(:plpgsql)
|
|
947
|
-
proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
|
|
939
|
+
@d.drop_language(:plpgsql) if @d.server_version < 90000
|
|
940
|
+
proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError) if @d.server_version < 90000
|
|
948
941
|
@d.send(:create_language_sql, :plpgsql, :replace=>true, :trusted=>true, :handler=>:a, :validator=>:b).should == (@d.server_version >= 90000 ? 'CREATE OR REPLACE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b' : 'CREATE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b')
|
|
949
942
|
@d.send(:drop_language_sql, :plpgsql, :if_exists=>true, :cascade=>true).should == 'DROP LANGUAGE IF EXISTS plpgsql CASCADE'
|
|
950
943
|
# Make sure if exists works
|
|
951
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
944
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
952
945
|
end
|
|
953
946
|
|
|
954
947
|
specify "#create_trigger and #drop_trigger should create and drop triggers" do
|
|
955
|
-
@d.create_language(:plpgsql)
|
|
948
|
+
@d.create_language(:plpgsql) if @d.server_version < 90000
|
|
956
949
|
@d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
|
|
957
950
|
@d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON test FOR EACH ROW EXECUTE PROCEDURE tf()'
|
|
958
951
|
@d.create_table(:test){String :name; Integer :value}
|
|
@@ -973,17 +966,17 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
973
966
|
end
|
|
974
967
|
|
|
975
968
|
if POSTGRES_DB.adapter_scheme == :postgres
|
|
976
|
-
describe "Postgres::Dataset #use_cursor" do
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
969
|
+
describe "Postgres::Dataset #use_cursor" do
|
|
970
|
+
before(:all) do
|
|
971
|
+
@db = POSTGRES_DB
|
|
972
|
+
@db.create_table!(:test_cursor){Integer :x}
|
|
973
|
+
@db.sqls.clear
|
|
974
|
+
@ds = @db[:test_cursor]
|
|
975
|
+
@db.transaction{1001.times{|i| @ds.insert(i)}}
|
|
976
|
+
end
|
|
977
|
+
after(:all) do
|
|
978
|
+
@db.drop_table(:test_cursor) rescue nil
|
|
979
|
+
end
|
|
987
980
|
|
|
988
981
|
specify "should return the same results as the non-cursor use" do
|
|
989
982
|
@ds.all.should == @ds.use_cursor.all
|
|
@@ -1005,5 +998,164 @@ describe "Postgres::Dataset #use_cursor" do
|
|
|
1005
998
|
@ds.check_return
|
|
1006
999
|
@ds.all.should == @ds.use_cursor.all
|
|
1007
1000
|
end
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
describe "Postgres::PG_NAMED_TYPES" do
|
|
1004
|
+
before do
|
|
1005
|
+
@db = POSTGRES_DB
|
|
1006
|
+
Sequel::Postgres::PG_NAMED_TYPES[:interval] = lambda{|v| v.reverse}
|
|
1007
|
+
@db.instance_eval do
|
|
1008
|
+
disconnect
|
|
1009
|
+
@conversion_procs = nil
|
|
1010
|
+
end
|
|
1011
|
+
end
|
|
1012
|
+
after do
|
|
1013
|
+
Sequel::Postgres::PG_NAMED_TYPES.delete(:interval)
|
|
1014
|
+
@db.instance_eval do
|
|
1015
|
+
disconnect
|
|
1016
|
+
@conversion_procs = nil
|
|
1017
|
+
end
|
|
1018
|
+
@db.drop_table(:foo)
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
specify "should look up conversion procs by name" do
|
|
1022
|
+
@db.create_table!(:foo){interval :bar}
|
|
1023
|
+
@db[:foo].insert('21 days')
|
|
1024
|
+
@db[:foo].get(:bar).should == 'syad 12'
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1008
1027
|
end
|
|
1028
|
+
|
|
1029
|
+
if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRES_DB.server_version >= 90000
|
|
1030
|
+
describe "Postgres::Database#copy_table" do
|
|
1031
|
+
before(:all) do
|
|
1032
|
+
@db = POSTGRES_DB
|
|
1033
|
+
@db.create_table!(:test_copy){Integer :x; Integer :y}
|
|
1034
|
+
ds = @db[:test_copy]
|
|
1035
|
+
ds.insert(1, 2)
|
|
1036
|
+
ds.insert(3, 4)
|
|
1037
|
+
end
|
|
1038
|
+
after(:all) do
|
|
1039
|
+
@db.drop_table(:test_copy) rescue nil
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
specify "without a block or options should return a text version of the table as a single string" do
|
|
1043
|
+
@db.copy_table(:test_copy).should == "1\t2\n3\t4\n"
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
specify "without a block and with :format=>:csv should return a csv version of the table as a single string" do
|
|
1047
|
+
@db.copy_table(:test_copy, :format=>:csv).should == "1,2\n3,4\n"
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
specify "should treat string as SQL code" do
|
|
1051
|
+
@db.copy_table('COPY "test_copy" TO STDOUT').should == "1\t2\n3\t4\n"
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
specify "should respect given :options options" do
|
|
1055
|
+
@db.copy_table(:test_copy, :options=>"FORMAT csv, HEADER TRUE").should == "x,y\n1,2\n3,4\n"
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
specify "should respect given :options options when :format is used" do
|
|
1059
|
+
@db.copy_table(:test_copy, :format=>:csv, :options=>"QUOTE '''', FORCE_QUOTE *").should == "'1','2'\n'3','4'\n"
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
specify "should accept dataset as first argument" do
|
|
1063
|
+
@db.copy_table(@db[:test_copy].cross_join(:test_copy___tc).order(1, 2, 3, 4)).should == "1\t2\t1\t2\n1\t2\t3\t4\n3\t4\t1\t2\n3\t4\t3\t4\n"
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
specify "with a block and no options should yield each row as a string in text format" do
|
|
1067
|
+
buf = []
|
|
1068
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1069
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1072
|
+
specify "with a block and :format=>:csv should yield each row as a string in csv format" do
|
|
1073
|
+
buf = []
|
|
1074
|
+
@db.copy_table(:test_copy, :format=>:csv){|b| buf << b}
|
|
1075
|
+
buf.should == ["1,2\n", "3,4\n"]
|
|
1076
|
+
end
|
|
1077
|
+
|
|
1078
|
+
specify "should work fine when using a block that is terminated early with a following copy_table" do
|
|
1079
|
+
buf = []
|
|
1080
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1081
|
+
buf.should == ["1,2\n"]
|
|
1082
|
+
buf.clear
|
|
1083
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1084
|
+
buf.should == ["1,2\n"]
|
|
1085
|
+
buf.clear
|
|
1086
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1087
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
specify "should work fine when using a block that is terminated early with a following regular query" do
|
|
1091
|
+
buf = []
|
|
1092
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1093
|
+
buf.should == ["1,2\n"]
|
|
1094
|
+
buf.clear
|
|
1095
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1096
|
+
buf.should == ["1,2\n"]
|
|
1097
|
+
@db[:test_copy].select_order_map(:x).should == [1, 3]
|
|
1098
|
+
end
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
describe "Postgres::Database LISTEN/NOTIFY" do
|
|
1102
|
+
before(:all) do
|
|
1103
|
+
@db = POSTGRES_DB
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
specify "should support listen and notify" do
|
|
1107
|
+
notify_pid = @db.synchronize{|conn| conn.backend_pid}
|
|
1108
|
+
|
|
1109
|
+
called = false
|
|
1110
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo')}) do |ev, pid, payload|
|
|
1111
|
+
ev.should == 'foo'
|
|
1112
|
+
pid.should == notify_pid
|
|
1113
|
+
['', nil].should include(payload)
|
|
1114
|
+
called = true
|
|
1115
|
+
end.should == 'foo'
|
|
1116
|
+
called.should be_true
|
|
1117
|
+
|
|
1118
|
+
called = false
|
|
1119
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo', :payload=>'bar')}) do |ev, pid, payload|
|
|
1120
|
+
ev.should == 'foo'
|
|
1121
|
+
pid.should == notify_pid
|
|
1122
|
+
payload.should == 'bar'
|
|
1123
|
+
called = true
|
|
1124
|
+
end.should == 'foo'
|
|
1125
|
+
called.should be_true
|
|
1126
|
+
|
|
1127
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo')}).should == 'foo'
|
|
1128
|
+
|
|
1129
|
+
called = false
|
|
1130
|
+
called2 = false
|
|
1131
|
+
i = 0
|
|
1132
|
+
@db.listen(['foo', 'bar'], :after_listen=>proc{@db.notify('foo', :payload=>'bar'); @db.notify('bar', :payload=>'foo')}, :loop=>proc{i+=1}) do |ev, pid, payload|
|
|
1133
|
+
if !called
|
|
1134
|
+
ev.should == 'foo'
|
|
1135
|
+
pid.should == notify_pid
|
|
1136
|
+
payload.should == 'bar'
|
|
1137
|
+
called = true
|
|
1138
|
+
else
|
|
1139
|
+
ev.should == 'bar'
|
|
1140
|
+
pid.should == notify_pid
|
|
1141
|
+
payload.should == 'foo'
|
|
1142
|
+
called2 = true
|
|
1143
|
+
break
|
|
1144
|
+
end
|
|
1145
|
+
end.should be_nil
|
|
1146
|
+
called.should be_true
|
|
1147
|
+
called2.should be_true
|
|
1148
|
+
i.should == 1
|
|
1149
|
+
end
|
|
1150
|
+
|
|
1151
|
+
specify "should accept a :timeout option in listen" do
|
|
1152
|
+
@db.listen('foo2', :timeout=>0.001).should == nil
|
|
1153
|
+
called = false
|
|
1154
|
+
@db.listen('foo2', :timeout=>0.001){|ev, pid, payload| called = true}.should == nil
|
|
1155
|
+
called.should be_false
|
|
1156
|
+
i = 0
|
|
1157
|
+
@db.listen('foo2', :timeout=>0.001, :loop=>proc{i+=1; throw :stop if i > 3}){|ev, pid, payload| called = true}.should == nil
|
|
1158
|
+
i.should == 4
|
|
1159
|
+
end
|
|
1160
|
+
end
|
|
1009
1161
|
end
|
|
@@ -3,13 +3,17 @@ require 'logger'
|
|
|
3
3
|
unless Object.const_defined?('Sequel')
|
|
4
4
|
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
|
5
5
|
require 'sequel'
|
|
6
|
-
Sequel.quote_identifiers = false
|
|
7
6
|
end
|
|
8
7
|
begin
|
|
9
8
|
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'spec_config.rb')
|
|
10
9
|
rescue LoadError
|
|
11
10
|
end
|
|
12
11
|
|
|
12
|
+
if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
13
|
+
Sequel.extension :columns_introspection
|
|
14
|
+
Sequel::Dataset.introspect_all_columns
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
class Sequel::Database
|
|
14
18
|
def log_duration(duration, message)
|
|
15
19
|
log_info(message)
|
|
@@ -26,11 +30,8 @@ end
|
|
|
26
30
|
end
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
def self.log_specify(message, &block)
|
|
30
|
-
specify(message){log{instance_eval(&block)}}
|
|
31
|
-
end
|
|
32
|
-
|
|
33
33
|
def self.cspecify(message, *checked, &block)
|
|
34
|
+
return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
|
|
34
35
|
pending = false
|
|
35
36
|
checked.each do |c|
|
|
36
37
|
case c
|