sequel 3.28.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 +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- 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/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- 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 +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
|
@@ -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,20 +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'
|
|
518
|
+
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"'
|
|
515
519
|
end
|
|
516
520
|
|
|
517
521
|
specify "should have insert_select return nil if server_version < 80200" do
|
|
@@ -1093,4 +1097,65 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
|
1093
1097
|
@db[:test_copy].select_order_map(:x).should == [1, 3]
|
|
1094
1098
|
end
|
|
1095
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
|
|
1096
1161
|
end
|
|
@@ -3,7 +3,6 @@ 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')
|
|
@@ -31,10 +30,6 @@ end
|
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
34
|
-
def self.log_specify(message, &block)
|
|
35
|
-
specify(message){log{instance_eval(&block)}}
|
|
36
|
-
end
|
|
37
|
-
|
|
38
33
|
def self.cspecify(message, *checked, &block)
|
|
39
34
|
return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
|
|
40
35
|
pending = false
|