sequel 3.37.0 → 3.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- metadata +16 -4
@@ -51,17 +51,17 @@ describe Sequel::Dataset, " graphing" do
|
|
51
51
|
ds._fetch = {:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5}
|
52
52
|
ds.all.should == [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
|
53
53
|
|
54
|
-
ds = @ds1.select(:id
|
54
|
+
ds = @ds1.select(Sequel.identifier(:id), Sequel.qualify(:points, :x)).graph(@ds2, :x=>:id)
|
55
55
|
ds.sql.should == 'SELECT points.id, points.x, lines.id AS lines_id, lines.x AS lines_x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
56
56
|
ds._fetch = {:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5}
|
57
57
|
ds.all.should == [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
|
58
58
|
|
59
|
-
ds = @ds1.select(:id.
|
59
|
+
ds = @ds1.select(Sequel.identifier(:id).qualify(:points), Sequel.identifier(:x).as(:y)).graph(@ds2, :x=>:id)
|
60
60
|
ds.sql.should == 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
61
61
|
ds._fetch = {:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5}
|
62
62
|
ds.all.should == [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
|
63
63
|
|
64
|
-
ds = @ds1.select(:id, :x.
|
64
|
+
ds = @ds1.select(:id, Sequel.identifier(:x).qualify(Sequel.identifier(:points)).as(Sequel.identifier(:y))).graph(@ds2, :x=>:id)
|
65
65
|
ds.sql.should == 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
66
66
|
ds._fetch = {:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5}
|
67
67
|
ds.all.should == [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
|
@@ -140,7 +140,7 @@ describe Sequel::Dataset, " graphing" do
|
|
140
140
|
end
|
141
141
|
|
142
142
|
it "#graph should accept a block instead of conditions and pass it to join_table" do
|
143
|
-
ds = @ds1.graph(@ds2){|ja, lja, js| [[
|
143
|
+
ds = @ds1.graph(@ds2){|ja, lja, js| [[Sequel.qualify(ja, :x), Sequel.qualify(lja, :id)], [Sequel.qualify(ja, :y), Sequel.qualify(lja, :id)]]}
|
144
144
|
ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON ((lines.x = points.id) AND (lines.y = points.id))'
|
145
145
|
end
|
146
146
|
|
@@ -197,7 +197,7 @@ describe Sequel::Dataset, " graphing" do
|
|
197
197
|
end
|
198
198
|
|
199
199
|
it "#set_graph_aliases should allow a third entry to specify an expression to use other than the default" do
|
200
|
-
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, :random
|
200
|
+
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, Sequel.function(:random)])
|
201
201
|
['SELECT 1 AS x, random() AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
|
202
202
|
'SELECT random() AS y, 1 AS x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
203
203
|
].should(include(ds.sql))
|
@@ -280,7 +280,7 @@ describe Sequel::Dataset, " graphing" do
|
|
280
280
|
|
281
281
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a third argument for each entry" do
|
282
282
|
@db.fetch = [nil, {:x=>2,:y=>3}]
|
283
|
-
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, :random
|
283
|
+
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, Sequel.function(:random)]).all.should == [{:points=>{:z1=>2}, :lines=>{:z2=>3}}]
|
284
284
|
end
|
285
285
|
|
286
286
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a single argument for each entry" do
|
data/spec/core/schema_spec.rb
CHANGED
@@ -13,14 +13,14 @@ describe "DB#create_table" do
|
|
13
13
|
specify "should accept the table name in multiple formats" do
|
14
14
|
@db.create_table(:cats__cats) {}
|
15
15
|
@db.create_table("cats__cats1") {}
|
16
|
-
@db.create_table(:cats__cats2
|
17
|
-
@db.create_table(
|
16
|
+
@db.create_table(Sequel.identifier(:cats__cats2)) {}
|
17
|
+
@db.create_table(Sequel.qualify(:cats3, :cats)) {}
|
18
18
|
@db.sqls.should == ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
|
19
19
|
end
|
20
20
|
|
21
21
|
specify "should raise an error if the table name argument is not valid" do
|
22
22
|
proc{@db.create_table(1) {}}.should raise_error(Sequel::Error)
|
23
|
-
proc{@db.create_table(
|
23
|
+
proc{@db.create_table(Sequel.as(:cats, :c)) {}}.should raise_error(Sequel::Error)
|
24
24
|
end
|
25
25
|
|
26
26
|
specify "should remove cached schema entry" do
|
@@ -391,7 +391,7 @@ describe "DB#create_table" do
|
|
391
391
|
specify "should accept functional indexes" do
|
392
392
|
@db.create_table(:cats) do
|
393
393
|
integer :id
|
394
|
-
index
|
394
|
+
index Sequel.function(:lower, :name)
|
395
395
|
end
|
396
396
|
@db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower_name__index ON cats (lower(name))"]
|
397
397
|
end
|
@@ -399,7 +399,7 @@ describe "DB#create_table" do
|
|
399
399
|
specify "should accept indexes with identifiers" do
|
400
400
|
@db.create_table(:cats) do
|
401
401
|
integer :id
|
402
|
-
index :lower__name
|
402
|
+
index Sequel.identifier(:lower__name)
|
403
403
|
end
|
404
404
|
@db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower__name_index ON cats (lower__name)"]
|
405
405
|
end
|
@@ -431,7 +431,7 @@ describe "DB#create_table" do
|
|
431
431
|
specify "should accept unnamed constraint definitions with blocks" do
|
432
432
|
@db.create_table(:cats) do
|
433
433
|
integer :score
|
434
|
-
check
|
434
|
+
check{(x.sql_number > 0) & (y.sql_number < 1)}
|
435
435
|
end
|
436
436
|
@db.sqls.should == ["CREATE TABLE cats (score integer, CHECK ((x > 0) AND (y < 1)))"]
|
437
437
|
end
|
@@ -460,7 +460,7 @@ describe "DB#create_table" do
|
|
460
460
|
|
461
461
|
specify "should accept named constraint definitions with block" do
|
462
462
|
@db.create_table(:cats) do
|
463
|
-
constraint(:blah_blah)
|
463
|
+
constraint(:blah_blah){(x.sql_number > 0) & (y.sql_number < 1)}
|
464
464
|
end
|
465
465
|
@db.sqls.should == ["CREATE TABLE cats (CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1)))"]
|
466
466
|
end
|
@@ -787,7 +787,7 @@ describe "DB#alter_table" do
|
|
787
787
|
|
788
788
|
specify "should support add_constraint with block" do
|
789
789
|
@db.alter_table(:cats) do
|
790
|
-
add_constraint(:blah_blah)
|
790
|
+
add_constraint(:blah_blah){(x.sql_number > 0) & (y.sql_number < 1)}
|
791
791
|
end
|
792
792
|
@db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1))"]
|
793
793
|
end
|
@@ -1122,7 +1122,7 @@ describe "Database#create_view" do
|
|
1122
1122
|
specify "should construct proper SQL with raw SQL" do
|
1123
1123
|
@db.create_view :test, "SELECT * FROM xyz"
|
1124
1124
|
@db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
|
1125
|
-
@db.create_view :test
|
1125
|
+
@db.create_view Sequel.identifier(:test), "SELECT * FROM xyz"
|
1126
1126
|
@db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
|
1127
1127
|
end
|
1128
1128
|
|
@@ -1136,7 +1136,7 @@ describe "Database#create_view" do
|
|
1136
1136
|
specify "should construct proper SQL with dataset" do
|
1137
1137
|
@db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
|
1138
1138
|
@db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
1139
|
-
@db.create_or_replace_view :test
|
1139
|
+
@db.create_or_replace_view Sequel.identifier(:test), @db[:items].select(:a, :b).order(:c)
|
1140
1140
|
@db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
1141
1141
|
end
|
1142
1142
|
end
|
@@ -1148,9 +1148,9 @@ describe "Database#drop_view" do
|
|
1148
1148
|
|
1149
1149
|
specify "should construct proper SQL" do
|
1150
1150
|
@db.drop_view :test
|
1151
|
-
@db.drop_view :test
|
1151
|
+
@db.drop_view Sequel.identifier(:test)
|
1152
1152
|
@db.drop_view :sch__test
|
1153
|
-
@db.drop_view
|
1153
|
+
@db.drop_view Sequel.qualify(:sch, :test)
|
1154
1154
|
@db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
|
1155
1155
|
end
|
1156
1156
|
|
@@ -1243,11 +1243,11 @@ describe "Schema Parser" do
|
|
1243
1243
|
s1 = @db.schema(:x)
|
1244
1244
|
s1.should == [['x', {:db_type=>'x', :ruby_default=>nil}]]
|
1245
1245
|
@db.schema(:x).object_id.should == s1.object_id
|
1246
|
-
@db.schema(:x
|
1246
|
+
@db.schema(Sequel.identifier(:x)).object_id.should == s1.object_id
|
1247
1247
|
s2 = @db.schema(:x__y)
|
1248
1248
|
s2.should == [['y', {:db_type=>'y', :ruby_default=>nil}]]
|
1249
1249
|
@db.schema(:x__y).object_id.should == s2.object_id
|
1250
|
-
@db.schema(
|
1250
|
+
@db.schema(Sequel.qualify(:x, :y)).object_id.should == s2.object_id
|
1251
1251
|
end
|
1252
1252
|
|
1253
1253
|
specify "should correctly parse all supported data types" do
|
data/spec/core/spec_helper.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
-
require
|
1
|
+
require 'rubygems'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
|
4
|
+
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
5
|
+
require 'sequel/no_core_ext'
|
6
|
+
end
|
7
|
+
|
8
|
+
Sequel.quote_identifiers = false
|
9
|
+
Sequel.identifier_input_method = nil
|
10
|
+
Sequel.identifier_output_method = nil
|
11
|
+
|
12
|
+
Regexp.send(:include, Sequel::SQL::StringMethods)
|
13
|
+
String.send(:include, Sequel::SQL::StringMethods)
|
14
|
+
Sequel.extension :core_extensions
|
15
15
|
|
16
|
+
describe "Sequel core extensions" do
|
16
17
|
specify "should have Sequel.core_extensions? be true if enabled" do
|
17
18
|
Sequel.core_extensions?.should be_true
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
describe "
|
22
|
+
describe "Core extensions" do
|
22
23
|
before do
|
23
24
|
db = Sequel::Database.new
|
24
25
|
@d = db[:items]
|
@@ -30,6 +31,150 @@ describe "Array and Hash extensions" do
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
if RUBY_VERSION < '1.9.0'
|
35
|
+
it "should not allow inequality operations on true, false, or nil" do
|
36
|
+
@d.lit(:x > 1).should == "(x > 1)"
|
37
|
+
@d.lit(:x < true).should == "(x < 't')"
|
38
|
+
@d.lit(:x >= false).should == "(x >= 'f')"
|
39
|
+
@d.lit(:x <= nil).should == "(x <= NULL)"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not allow inequality operations on boolean complex expressions" do
|
43
|
+
@d.lit(:x > (:y > 5)).should == "(x > (y > 5))"
|
44
|
+
@d.lit(:x < (:y < 5)).should == "(x < (y < 5))"
|
45
|
+
@d.lit(:x >= (:y >= 5)).should == "(x >= (y >= 5))"
|
46
|
+
@d.lit(:x <= (:y <= 5)).should == "(x <= (y <= 5))"
|
47
|
+
@d.lit(:x > {:y => nil}).should == "(x > (y IS NULL))"
|
48
|
+
@d.lit(:x < ~{:y => nil}).should == "(x < (y IS NOT NULL))"
|
49
|
+
@d.lit(:x >= {:y => 5}).should == "(x >= (y = 5))"
|
50
|
+
@d.lit(:x <= ~{:y => 5}).should == "(x <= (y != 5))"
|
51
|
+
@d.lit(:x >= {:y => [1,2,3]}).should == "(x >= (y IN (1, 2, 3)))"
|
52
|
+
@d.lit(:x <= ~{:y => [1,2,3]}).should == "(x <= (y NOT IN (1, 2, 3)))"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
|
56
|
+
@d.l(:x > 100).should == '(x > 100)'
|
57
|
+
@d.l(:x < 100.01).should == '(x < 100.01)'
|
58
|
+
@d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
|
59
|
+
@d.l(:x <= 100).should == '(x <= 100)'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should support negation of >, <, >=, and <= via Symbol#~" do
|
63
|
+
@d.l(~(:x > 100)).should == '(x <= 100)'
|
64
|
+
@d.l(~(:x < 100.01)).should == '(x >= 100.01)'
|
65
|
+
@d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
|
66
|
+
@d.l(~(:x <= 100)).should == '(x > 100)'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should support double negation via ~" do
|
70
|
+
@d.l(~~(:x > 100)).should == '(x > 100)'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
it "should support NOT via Symbol#~" do
|
74
|
+
@d.l(~:x).should == 'NOT x'
|
75
|
+
@d.l(~:x__y).should == 'NOT x.y'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should support + - * / via Symbol#+,-,*,/" do
|
79
|
+
@d.l(:x + 1 > 100).should == '((x + 1) > 100)'
|
80
|
+
@d.l((:x * :y) < 100.01).should == '((x * y) < 100.01)'
|
81
|
+
@d.l((:x - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
|
82
|
+
@d.l((((:x - :y)/(:x + :y))*:z) <= 100).should == '((((x - y) / (x + y)) * z) <= 100)'
|
83
|
+
@d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should support LIKE via Symbol#like" do
|
87
|
+
@d.l(:x.like('a')).should == '(x LIKE \'a\')'
|
88
|
+
@d.l(:x.like(/a/)).should == '(x ~ \'a\')'
|
89
|
+
@d.l(:x.like('a', 'b')).should == '((x LIKE \'a\') OR (x LIKE \'b\'))'
|
90
|
+
@d.l(:x.like(/a/, /b/i)).should == '((x ~ \'a\') OR (x ~* \'b\'))'
|
91
|
+
@d.l(:x.like('a', /b/)).should == '((x LIKE \'a\') OR (x ~ \'b\'))'
|
92
|
+
|
93
|
+
@d.l('a'.like(:x)).should == "('a' LIKE x)"
|
94
|
+
@d.l('a'.like(:x, 'b')).should == "(('a' LIKE x) OR ('a' LIKE 'b'))"
|
95
|
+
@d.l('a'.like(:x, /b/)).should == "(('a' LIKE x) OR ('a' ~ 'b'))"
|
96
|
+
@d.l('a'.like(:x, /b/i)).should == "(('a' LIKE x) OR ('a' ~* 'b'))"
|
97
|
+
|
98
|
+
@d.l(/a/.like(:x)).should == "('a' ~ x)"
|
99
|
+
@d.l(/a/.like(:x, 'b')).should == "(('a' ~ x) OR ('a' ~ 'b'))"
|
100
|
+
@d.l(/a/.like(:x, /b/)).should == "(('a' ~ x) OR ('a' ~ 'b'))"
|
101
|
+
@d.l(/a/.like(:x, /b/i)).should == "(('a' ~ x) OR ('a' ~* 'b'))"
|
102
|
+
|
103
|
+
@d.l(/a/i.like(:x)).should == "('a' ~* x)"
|
104
|
+
@d.l(/a/i.like(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
105
|
+
@d.l(/a/i.like(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
106
|
+
@d.l(/a/i.like(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should support NOT LIKE via Symbol#like and Symbol#~" do
|
110
|
+
@d.l(~:x.like('a')).should == '(x NOT LIKE \'a\')'
|
111
|
+
@d.l(~:x.like(/a/)).should == '(x !~ \'a\')'
|
112
|
+
@d.l(~:x.like('a', 'b')).should == '((x NOT LIKE \'a\') AND (x NOT LIKE \'b\'))'
|
113
|
+
@d.l(~:x.like(/a/, /b/i)).should == '((x !~ \'a\') AND (x !~* \'b\'))'
|
114
|
+
@d.l(~:x.like('a', /b/)).should == '((x NOT LIKE \'a\') AND (x !~ \'b\'))'
|
115
|
+
|
116
|
+
@d.l(~'a'.like(:x)).should == "('a' NOT LIKE x)"
|
117
|
+
@d.l(~'a'.like(:x, 'b')).should == "(('a' NOT LIKE x) AND ('a' NOT LIKE 'b'))"
|
118
|
+
@d.l(~'a'.like(:x, /b/)).should == "(('a' NOT LIKE x) AND ('a' !~ 'b'))"
|
119
|
+
@d.l(~'a'.like(:x, /b/i)).should == "(('a' NOT LIKE x) AND ('a' !~* 'b'))"
|
120
|
+
|
121
|
+
@d.l(~/a/.like(:x)).should == "('a' !~ x)"
|
122
|
+
@d.l(~/a/.like(:x, 'b')).should == "(('a' !~ x) AND ('a' !~ 'b'))"
|
123
|
+
@d.l(~/a/.like(:x, /b/)).should == "(('a' !~ x) AND ('a' !~ 'b'))"
|
124
|
+
@d.l(~/a/.like(:x, /b/i)).should == "(('a' !~ x) AND ('a' !~* 'b'))"
|
125
|
+
|
126
|
+
@d.l(~/a/i.like(:x)).should == "('a' !~* x)"
|
127
|
+
@d.l(~/a/i.like(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
128
|
+
@d.l(~/a/i.like(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
129
|
+
@d.l(~/a/i.like(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should support ILIKE via Symbol#ilike" do
|
133
|
+
@d.l(:x.ilike('a')).should == '(x ILIKE \'a\')'
|
134
|
+
@d.l(:x.ilike(/a/)).should == '(x ~* \'a\')'
|
135
|
+
@d.l(:x.ilike('a', 'b')).should == '((x ILIKE \'a\') OR (x ILIKE \'b\'))'
|
136
|
+
@d.l(:x.ilike(/a/, /b/i)).should == '((x ~* \'a\') OR (x ~* \'b\'))'
|
137
|
+
@d.l(:x.ilike('a', /b/)).should == '((x ILIKE \'a\') OR (x ~* \'b\'))'
|
138
|
+
|
139
|
+
@d.l('a'.ilike(:x)).should == "('a' ILIKE x)"
|
140
|
+
@d.l('a'.ilike(:x, 'b')).should == "(('a' ILIKE x) OR ('a' ILIKE 'b'))"
|
141
|
+
@d.l('a'.ilike(:x, /b/)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
|
142
|
+
@d.l('a'.ilike(:x, /b/i)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
|
143
|
+
|
144
|
+
@d.l(/a/.ilike(:x)).should == "('a' ~* x)"
|
145
|
+
@d.l(/a/.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
146
|
+
@d.l(/a/.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
147
|
+
@d.l(/a/.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
148
|
+
|
149
|
+
@d.l(/a/i.ilike(:x)).should == "('a' ~* x)"
|
150
|
+
@d.l(/a/i.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
151
|
+
@d.l(/a/i.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
152
|
+
@d.l(/a/i.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
|
156
|
+
@d.l(~:x.ilike('a')).should == '(x NOT ILIKE \'a\')'
|
157
|
+
@d.l(~:x.ilike(/a/)).should == '(x !~* \'a\')'
|
158
|
+
@d.l(~:x.ilike('a', 'b')).should == '((x NOT ILIKE \'a\') AND (x NOT ILIKE \'b\'))'
|
159
|
+
@d.l(~:x.ilike(/a/, /b/i)).should == '((x !~* \'a\') AND (x !~* \'b\'))'
|
160
|
+
@d.l(~:x.ilike('a', /b/)).should == '((x NOT ILIKE \'a\') AND (x !~* \'b\'))'
|
161
|
+
|
162
|
+
@d.l(~'a'.ilike(:x)).should == "('a' NOT ILIKE x)"
|
163
|
+
@d.l(~'a'.ilike(:x, 'b')).should == "(('a' NOT ILIKE x) AND ('a' NOT ILIKE 'b'))"
|
164
|
+
@d.l(~'a'.ilike(:x, /b/)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
|
165
|
+
@d.l(~'a'.ilike(:x, /b/i)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
|
166
|
+
|
167
|
+
@d.l(~/a/.ilike(:x)).should == "('a' !~* x)"
|
168
|
+
@d.l(~/a/.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
169
|
+
@d.l(~/a/.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
170
|
+
@d.l(~/a/.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
171
|
+
|
172
|
+
@d.l(~/a/i.ilike(:x)).should == "('a' !~* x)"
|
173
|
+
@d.l(~/a/i.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
174
|
+
@d.l(~/a/i.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
175
|
+
@d.l(~/a/i.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
176
|
+
end
|
177
|
+
|
33
178
|
it "should support sql_expr on arrays with all two pairs" do
|
34
179
|
@d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
|
35
180
|
@d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
|
@@ -429,3 +574,52 @@ describe "Symbol" do
|
|
429
574
|
:abc.extract(:year).to_s(@ds).should == "extract(year FROM abc)"
|
430
575
|
end
|
431
576
|
end
|
577
|
+
|
578
|
+
describe "Postgres extensions integration" do
|
579
|
+
before do
|
580
|
+
@db = Sequel.mock
|
581
|
+
Sequel.extension(:pg_array, :pg_array_ops, :pg_hstore, :pg_hstore_ops, :pg_json, :pg_range, :pg_range_ops, :pg_row, :pg_row_ops)
|
582
|
+
end
|
583
|
+
|
584
|
+
it "Symbol#pg_array should return an ArrayOp" do
|
585
|
+
@db.literal(:a.pg_array.unnest).should == "unnest(a)"
|
586
|
+
end
|
587
|
+
|
588
|
+
it "Symbol#pg_row should return a PGRowOp" do
|
589
|
+
@db.literal(:a.pg_row[:a]).should == "(a).a"
|
590
|
+
end
|
591
|
+
|
592
|
+
it "Symbol#hstore should return an HStoreOp" do
|
593
|
+
@db.literal(:a.hstore['a']).should == "(a -> 'a')"
|
594
|
+
end
|
595
|
+
|
596
|
+
it "Symbol#pg_range should return a RangeOp" do
|
597
|
+
@db.literal(:a.pg_range.lower).should == "lower(a)"
|
598
|
+
end
|
599
|
+
|
600
|
+
it "Array#pg_array should return a PGArray" do
|
601
|
+
@db.literal([1].pg_array.op.unnest).should == "unnest(ARRAY[1])"
|
602
|
+
@db.literal([1].pg_array(:int4).op.unnest).should == "unnest(ARRAY[1]::int4[])"
|
603
|
+
end
|
604
|
+
|
605
|
+
it "Array#pg_json should return a JSONArray" do
|
606
|
+
@db.literal([1].pg_json).should == "'[1]'::json"
|
607
|
+
end
|
608
|
+
|
609
|
+
it "Array#pg_row should return a ArrayRow" do
|
610
|
+
@db.literal([1].pg_row).should == "ROW(1)"
|
611
|
+
end
|
612
|
+
|
613
|
+
it "Hash#hstore should return an HStore" do
|
614
|
+
@db.literal({'a'=>1}.hstore.op['a']).should == '(\'"a"=>"1"\'::hstore -> \'a\')'
|
615
|
+
end
|
616
|
+
|
617
|
+
it "Hash#pg_json should return an JSONHash" do
|
618
|
+
@db.literal({'a'=>'b'}.pg_json).should == "'{\"a\":\"b\"}'::json"
|
619
|
+
end
|
620
|
+
|
621
|
+
it "Range#pg_range should return an PGRange" do
|
622
|
+
@db.literal((1..2).pg_range).should == "'[1,2]'"
|
623
|
+
@db.literal((1..2).pg_range(:int4range)).should == "'[1,2]'::int4range"
|
624
|
+
end
|
625
|
+
end
|
@@ -58,19 +58,19 @@ describe "columns_introspection extension" do
|
|
58
58
|
end
|
59
59
|
|
60
60
|
specify "should handle SQL::Identifiers " do
|
61
|
-
@ds.select(:x
|
61
|
+
@ds.select(Sequel.identifier(:x)).columns.should == [:x]
|
62
62
|
@db.sqls.length.should == 0
|
63
63
|
end
|
64
64
|
|
65
65
|
specify "should handle SQL::QualifiedIdentifiers" do
|
66
|
-
@ds.select(
|
67
|
-
@ds.select(:x.
|
66
|
+
@ds.select(Sequel.qualify(:t, :x)).columns.should == [:x]
|
67
|
+
@ds.select(Sequel.identifier(:x).qualify(:t)).columns.should == [:x]
|
68
68
|
@db.sqls.length.should == 0
|
69
69
|
end
|
70
70
|
|
71
71
|
specify "should handle SQL::AliasedExpressions" do
|
72
|
-
@ds.select(
|
73
|
-
@ds.select(:x.
|
72
|
+
@ds.select(Sequel.as(:x, :a)).columns.should == [:a]
|
73
|
+
@ds.select(Sequel.as(:x, Sequel.identifier(:a))).columns.should == [:a]
|
74
74
|
@db.sqls.length.should == 0
|
75
75
|
end
|
76
76
|
|
@@ -1,14 +1,20 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
|
-
|
3
|
+
model_class = proc do |klass, &block|
|
4
|
+
c = Class.new(klass)
|
5
|
+
c.plugin :hook_class_methods
|
6
|
+
c.class_eval(&block) if block
|
7
|
+
c
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Sequel::Model, "hook_class_methods plugin" do
|
4
11
|
before do
|
5
12
|
MODEL_DB.reset
|
6
13
|
end
|
7
14
|
|
8
15
|
specify "should be definable using a block" do
|
9
16
|
adds = []
|
10
|
-
c =
|
11
|
-
c.class_eval do
|
17
|
+
c = model_class.call Sequel::Model do
|
12
18
|
before_save{adds << 'hi'}
|
13
19
|
end
|
14
20
|
|
@@ -18,8 +24,7 @@ describe "Model hooks" do
|
|
18
24
|
|
19
25
|
specify "should be definable using a method name" do
|
20
26
|
adds = []
|
21
|
-
c =
|
22
|
-
c.class_eval do
|
27
|
+
c = model_class.call Sequel::Model do
|
23
28
|
define_method(:bye){adds << 'bye'}
|
24
29
|
before_save :bye
|
25
30
|
end
|
@@ -30,8 +35,7 @@ describe "Model hooks" do
|
|
30
35
|
|
31
36
|
specify "should be additive" do
|
32
37
|
adds = []
|
33
|
-
c =
|
34
|
-
c.class_eval do
|
38
|
+
c = model_class.call Sequel::Model do
|
35
39
|
after_save{adds << 'hyiyie'}
|
36
40
|
after_save{adds << 'byiyie'}
|
37
41
|
end
|
@@ -42,8 +46,7 @@ describe "Model hooks" do
|
|
42
46
|
|
43
47
|
specify "before hooks should run in reverse order" do
|
44
48
|
adds = []
|
45
|
-
c =
|
46
|
-
c.class_eval do
|
49
|
+
c = model_class.call Sequel::Model do
|
47
50
|
before_save{adds << 'hyiyie'}
|
48
51
|
before_save{adds << 'byiyie'}
|
49
52
|
end
|
@@ -54,8 +57,7 @@ describe "Model hooks" do
|
|
54
57
|
|
55
58
|
specify "should not be additive if the method or tag already exists" do
|
56
59
|
adds = []
|
57
|
-
c =
|
58
|
-
c.class_eval do
|
60
|
+
c = model_class.call Sequel::Model do
|
59
61
|
define_method(:bye){adds << 'bye'}
|
60
62
|
before_save :bye
|
61
63
|
before_save :bye
|
@@ -65,8 +67,7 @@ describe "Model hooks" do
|
|
65
67
|
adds.should == ['bye']
|
66
68
|
|
67
69
|
adds = []
|
68
|
-
d =
|
69
|
-
d.class_eval do
|
70
|
+
d = model_class.call Sequel::Model do
|
70
71
|
before_save(:bye){adds << 'hyiyie'}
|
71
72
|
before_save(:bye){adds << 'byiyie'}
|
72
73
|
end
|
@@ -75,8 +76,7 @@ describe "Model hooks" do
|
|
75
76
|
adds.should == ['byiyie']
|
76
77
|
|
77
78
|
adds = []
|
78
|
-
e =
|
79
|
-
e.class_eval do
|
79
|
+
e = model_class.call Sequel::Model do
|
80
80
|
define_method(:bye){adds << 'bye'}
|
81
81
|
before_save :bye
|
82
82
|
before_save(:bye){adds << 'byiyie'}
|
@@ -86,8 +86,7 @@ describe "Model hooks" do
|
|
86
86
|
adds.should == ['byiyie']
|
87
87
|
|
88
88
|
adds = []
|
89
|
-
e =
|
90
|
-
e.class_eval do
|
89
|
+
e = model_class.call Sequel::Model do
|
91
90
|
define_method(:bye){adds << 'bye'}
|
92
91
|
before_save(:bye){adds << 'byiyie'}
|
93
92
|
before_save :bye
|
@@ -99,8 +98,7 @@ describe "Model hooks" do
|
|
99
98
|
|
100
99
|
specify "should be inheritable" do
|
101
100
|
adds = []
|
102
|
-
a =
|
103
|
-
a.class_eval do
|
101
|
+
a = model_class.call Sequel::Model do
|
104
102
|
after_save{adds << '123'}
|
105
103
|
end
|
106
104
|
|
@@ -116,8 +114,7 @@ describe "Model hooks" do
|
|
116
114
|
|
117
115
|
specify "should be overridable in descendant classes" do
|
118
116
|
adds = []
|
119
|
-
a =
|
120
|
-
a.class_eval do
|
117
|
+
a = model_class.call Sequel::Model do
|
121
118
|
before_save{adds << '123'}
|
122
119
|
end
|
123
120
|
|
@@ -137,8 +134,7 @@ describe "Model hooks" do
|
|
137
134
|
flag = true
|
138
135
|
adds = []
|
139
136
|
|
140
|
-
a =
|
141
|
-
a.class_eval do
|
137
|
+
a = model_class.call Sequel::Model do
|
142
138
|
before_save{adds << 'cruel'; flag}
|
143
139
|
before_save{adds << 'blah'; flag}
|
144
140
|
end
|
@@ -173,8 +169,7 @@ describe "Model#after_initialize" do
|
|
173
169
|
values1 = nil
|
174
170
|
reached_after_initialized = false
|
175
171
|
|
176
|
-
a =
|
177
|
-
a.class_eval do
|
172
|
+
a = model_class.call Sequel::Model do
|
178
173
|
columns :x, :y
|
179
174
|
after_initialize do
|
180
175
|
values1 = @values.clone
|
@@ -192,8 +187,7 @@ describe "Model#before_create && Model#after_create" do
|
|
192
187
|
before do
|
193
188
|
MODEL_DB.reset
|
194
189
|
|
195
|
-
@c =
|
196
|
-
@c.class_eval do
|
190
|
+
@c = model_class.call Sequel::Model(:items) do
|
197
191
|
columns :x
|
198
192
|
no_primary_key
|
199
193
|
|
@@ -226,8 +220,7 @@ describe "Model#before_update && Model#after_update" do
|
|
226
220
|
before do
|
227
221
|
MODEL_DB.reset
|
228
222
|
|
229
|
-
@c =
|
230
|
-
@c.class_eval do
|
223
|
+
@c = model_class.call(Sequel::Model(:items)) do
|
231
224
|
after_update {MODEL_DB << "BLAH after"}
|
232
225
|
end
|
233
226
|
end
|
@@ -258,8 +251,7 @@ describe "Model#before_save && Model#after_save" do
|
|
258
251
|
before do
|
259
252
|
MODEL_DB.reset
|
260
253
|
|
261
|
-
@c =
|
262
|
-
@c.class_eval do
|
254
|
+
@c = model_class.call(Sequel::Model(:items)) do
|
263
255
|
columns :x
|
264
256
|
after_save {MODEL_DB << "BLAH after"}
|
265
257
|
end
|
@@ -298,8 +290,7 @@ describe "Model#before_destroy && Model#after_destroy" do
|
|
298
290
|
before do
|
299
291
|
MODEL_DB.reset
|
300
292
|
|
301
|
-
@c =
|
302
|
-
@c.class_eval do
|
293
|
+
@c = model_class.call(Sequel::Model(:items)) do
|
303
294
|
after_destroy {MODEL_DB << "BLAH after"}
|
304
295
|
end
|
305
296
|
end
|
@@ -329,8 +320,8 @@ describe "Model#before_validation && Model#after_validation" do
|
|
329
320
|
before do
|
330
321
|
MODEL_DB.reset
|
331
322
|
|
332
|
-
@c =
|
333
|
-
|
323
|
+
@c = model_class.call(Sequel::Model(:items)) do
|
324
|
+
plugin :validation_class_methods
|
334
325
|
after_validation{MODEL_DB << "BLAH after"}
|
335
326
|
|
336
327
|
def self.validate(o)
|
@@ -382,7 +373,7 @@ end
|
|
382
373
|
|
383
374
|
describe "Model.has_hooks?" do
|
384
375
|
before do
|
385
|
-
@c =
|
376
|
+
@c = model_class.call(Sequel::Model(:items))
|
386
377
|
end
|
387
378
|
|
388
379
|
specify "should return false if no hooks are defined" do
|
@@ -403,6 +394,7 @@ end
|
|
403
394
|
describe "Model#add_hook_type" do
|
404
395
|
before do
|
405
396
|
class ::Foo < Sequel::Model(:items)
|
397
|
+
plugin :hook_class_methods
|
406
398
|
add_hook_type :before_bar, :after_bar
|
407
399
|
|
408
400
|
def bar
|