sequel 4.3.0 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +34 -0
- data/README.rdoc +7 -7
- data/Rakefile +2 -2
- data/doc/active_record.rdoc +2 -2
- data/doc/association_basics.rdoc +21 -7
- data/doc/bin_sequel.rdoc +2 -2
- data/doc/cheat_sheet.rdoc +2 -1
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/migration.rdoc +2 -2
- data/doc/object_model.rdoc +2 -2
- data/doc/opening_databases.rdoc +13 -1
- data/doc/querying.rdoc +9 -4
- data/doc/release_notes/4.4.0.txt +92 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +2 -2
- data/doc/sql.rdoc +3 -3
- data/doc/thread_safety.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/jdbc.rb +85 -19
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +34 -3
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +57 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +2 -2
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/oracle.rb +41 -4
- data/lib/sequel/adapters/shared/sqlanywhere.rb +458 -0
- data/lib/sequel/adapters/sqlanywhere.rb +177 -0
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +11 -3
- data/lib/sequel/core.rb +4 -4
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +2 -2
- data/lib/sequel/dataset.rb +1 -1
- data/lib/sequel/dataset/actions.rb +2 -0
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +37 -16
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +2 -2
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +5 -4
- data/lib/sequel/extensions/pg_array.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +2 -2
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
- data/lib/sequel/extensions/pg_json.rb +2 -2
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_range_ops.rb +2 -2
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pg_row_ops.rb +3 -3
- data/lib/sequel/model.rb +1 -1
- data/lib/sequel/model/associations.rb +106 -17
- data/lib/sequel/model/base.rb +23 -19
- data/lib/sequel/plugins/json_serializer.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +14 -6
- data/lib/sequel/plugins/pg_array_associations.rb +28 -0
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +11 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/table_select.rb +41 -0
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/oracle_spec.rb +22 -1
- data/spec/adapters/postgres_spec.rb +31 -48
- data/spec/adapters/sqlanywhere_spec.rb +170 -0
- data/spec/core/dataset_spec.rb +109 -0
- data/spec/core/object_graph_spec.rb +7 -0
- data/spec/extensions/constraint_validations_spec.rb +7 -0
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +65 -0
- data/spec/extensions/pg_array_associations_spec.rb +44 -0
- data/spec/extensions/rcte_tree_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +1 -1
- data/spec/extensions/table_select_spec.rb +71 -0
- data/spec/integration/associations_test.rb +279 -7
- data/spec/integration/dataset_test.rb +13 -4
- data/spec/integration/schema_test.rb +12 -14
- data/spec/model/associations_spec.rb +472 -3
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/model_spec.rb +10 -0
- metadata +10 -2
@@ -0,0 +1,170 @@
|
|
1
|
+
SEQUEL_ADAPTER_TEST = :sqlanywhere
|
2
|
+
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
4
|
+
|
5
|
+
if DB.table_exists?(:test)
|
6
|
+
DB.drop_table(:test)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Convert smallint to boolean" do
|
10
|
+
before do
|
11
|
+
@db = DB
|
12
|
+
end
|
13
|
+
after do
|
14
|
+
Sequel::SqlAnywhere.convert_smallint_to_bool = true
|
15
|
+
@db.convert_smallint_to_bool = true
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "Sequel::SqlAnywhere.convert_smallint_to_bool" do
|
19
|
+
before do
|
20
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
21
|
+
@ds = @db[:booltest]
|
22
|
+
end
|
23
|
+
after do
|
24
|
+
@db.drop_table(:booltest)
|
25
|
+
end
|
26
|
+
|
27
|
+
specify "should consider smallint datatypes as boolean if set, but if not, as larger smallints" do
|
28
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
29
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
|
30
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
31
|
+
|
32
|
+
Sequel::SqlAnywhere.convert_smallint_to_bool = false
|
33
|
+
@db2 = Sequel.connect(DB.url)
|
34
|
+
@db2.schema(:booltest, :reload=>true).first.last[:type].should == :integer
|
35
|
+
@db2.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
36
|
+
|
37
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
|
38
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
39
|
+
|
40
|
+
@db2.disconnect
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "datasets" do
|
44
|
+
specify "should return smallints as bools and integers as integers when set" do
|
45
|
+
@ds.delete
|
46
|
+
@ds << {:b=>true, :i=>10}
|
47
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
48
|
+
@ds.delete
|
49
|
+
@ds << {:b=>false, :i=>0}
|
50
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
51
|
+
@ds.delete
|
52
|
+
@ds << {:b=>true, :i=>1}
|
53
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
54
|
+
end
|
55
|
+
|
56
|
+
specify "should return all smallints as integers when unset" do
|
57
|
+
Sequel::SqlAnywhere.convert_smallint_to_bool = false
|
58
|
+
@db2 = Sequel.connect(DB.url)
|
59
|
+
@ds2 = @db2[:booltest]
|
60
|
+
@ds2.delete
|
61
|
+
@ds2 << {:b=>true, :i=>10}
|
62
|
+
@ds2.all.should == [{:b=>1, :i=>10}]
|
63
|
+
@ds2.delete
|
64
|
+
@ds2 << {:b=>false, :i=>0}
|
65
|
+
@ds2.all.should == [{:b=>0, :i=>0}]
|
66
|
+
|
67
|
+
@ds2.delete
|
68
|
+
@ds2 << {:b=>1, :i=>10}
|
69
|
+
@ds2.all.should == [{:b=>1, :i=>10}]
|
70
|
+
@ds2.delete
|
71
|
+
@ds2 << {:b=>0, :i=>0}
|
72
|
+
@ds2.all.should == [{:b=>0, :i=>0}]
|
73
|
+
|
74
|
+
@db2.disconnect
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "Database#convert_smallint_to_bool" do
|
80
|
+
before do
|
81
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
82
|
+
end
|
83
|
+
after do
|
84
|
+
@db.drop_table(:booltest)
|
85
|
+
end
|
86
|
+
|
87
|
+
specify "should consider smallint datatypes as boolean if set, but not larger smallints" do
|
88
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
|
89
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
90
|
+
@db.convert_smallint_to_bool = false
|
91
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :integer
|
92
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "datasets" do
|
96
|
+
specify "should return smallints as bools and integers as integers when set" do
|
97
|
+
@ds = @db[:booltest]
|
98
|
+
@ds.delete
|
99
|
+
@ds << {:b=>true, :i=>10}
|
100
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
101
|
+
@ds.delete
|
102
|
+
@ds << {:b=>false, :i=>0}
|
103
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
104
|
+
@ds.delete
|
105
|
+
@ds << {:b=>true, :i=>1}
|
106
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
107
|
+
end
|
108
|
+
|
109
|
+
specify "should return all smallints as integers when unset" do
|
110
|
+
@db2 = Sequel.connect(DB.url)
|
111
|
+
@db2.convert_smallint_to_bool = false
|
112
|
+
@ds2 = @db2[:booltest]
|
113
|
+
@ds2.delete
|
114
|
+
@ds2 << {:b=>true, :i=>10}
|
115
|
+
@ds2.all.should == [{:b=>1, :i=>10}]
|
116
|
+
@ds2.delete
|
117
|
+
@ds2 << {:b=>false, :i=>0}
|
118
|
+
@ds2.all.should == [{:b=>0, :i=>0}]
|
119
|
+
|
120
|
+
@ds2.delete
|
121
|
+
@ds2 << {:b=>1, :i=>10}
|
122
|
+
@ds2.all.should == [{:b=>1, :i=>10}]
|
123
|
+
@ds2.delete
|
124
|
+
@ds2 << {:b=>0, :i=>0}
|
125
|
+
@ds2.all.should == [{:b=>0, :i=>0}]
|
126
|
+
|
127
|
+
@db2.disconnect
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "Dataset#convert_smallint_to_bool" do
|
133
|
+
before do
|
134
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
135
|
+
@ds = @db[:booltest]
|
136
|
+
end
|
137
|
+
after do
|
138
|
+
@db.drop_table(:booltest)
|
139
|
+
end
|
140
|
+
|
141
|
+
specify "should return smallints as bools and integers as integers when set" do
|
142
|
+
@ds.delete
|
143
|
+
@ds << {:b=>true, :i=>10}
|
144
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
145
|
+
@ds.delete
|
146
|
+
@ds << {:b=>false, :i=>0}
|
147
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
148
|
+
@ds.delete
|
149
|
+
@ds << {:b=>true, :i=>1}
|
150
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
151
|
+
end
|
152
|
+
|
153
|
+
specify "should return all smallints as integers when unset" do
|
154
|
+
@ds.convert_smallint_to_bool = false
|
155
|
+
@ds.delete
|
156
|
+
@ds << {:b=>true, :i=>10}
|
157
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
158
|
+
@ds.delete
|
159
|
+
@ds << {:b=>false, :i=>0}
|
160
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
161
|
+
|
162
|
+
@ds.delete
|
163
|
+
@ds << {:b=>1, :i=>10}
|
164
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
165
|
+
@ds.delete
|
166
|
+
@ds << {:b=>0, :i=>0}
|
167
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -1625,6 +1625,49 @@ describe "Dataset#limit" do
|
|
1625
1625
|
end
|
1626
1626
|
end
|
1627
1627
|
|
1628
|
+
describe "Dataset#offset" do
|
1629
|
+
before do
|
1630
|
+
@dataset = Sequel.mock.dataset.from(:test)
|
1631
|
+
end
|
1632
|
+
|
1633
|
+
specify "should include an OFFSET clause in the select statement" do
|
1634
|
+
@dataset.offset(10).sql.should == 'SELECT * FROM test OFFSET 10'
|
1635
|
+
end
|
1636
|
+
|
1637
|
+
specify "should convert regular strings to integers" do
|
1638
|
+
@dataset.offset('a() - 1').sql.should == 'SELECT * FROM test OFFSET 0'
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
specify "should raise an error if a negative offset is used" do
|
1642
|
+
proc{@dataset.offset(-1)}.should raise_error(Sequel::Error)
|
1643
|
+
end
|
1644
|
+
|
1645
|
+
specify "should be able to reset offset with nil values" do
|
1646
|
+
@dataset.offset(6).offset(nil).sql.should == 'SELECT * FROM test'
|
1647
|
+
end
|
1648
|
+
|
1649
|
+
specify "should not convert literal strings to integers" do
|
1650
|
+
@dataset.offset(Sequel.lit('a() - 1')).sql.should == 'SELECT * FROM test OFFSET a() - 1'
|
1651
|
+
end
|
1652
|
+
|
1653
|
+
specify "should not convert other objects" do
|
1654
|
+
@dataset.offset(Sequel.function(:a) - 1).sql.should == 'SELECT * FROM test OFFSET (a() - 1)'
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
specify "should override offset given to limit" do
|
1658
|
+
@dataset.limit(nil, 5).offset(6).sql.should == 'SELECT * FROM test OFFSET 6'
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
specify "should not be overridable by limit if limit is not given an offset" do
|
1662
|
+
@dataset.offset(6).limit(nil).sql.should == 'SELECT * FROM test OFFSET 6'
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
specify "should be overridable by limit if limit is given an offset" do
|
1666
|
+
@dataset.offset(6).limit(nil, nil).sql.should == 'SELECT * FROM test'
|
1667
|
+
@dataset.offset(6).limit(nil, 5).sql.should == 'SELECT * FROM test OFFSET 5'
|
1668
|
+
end
|
1669
|
+
end
|
1670
|
+
|
1628
1671
|
describe "Dataset#naked" do
|
1629
1672
|
specify "should returned clone dataset without row_proc" do
|
1630
1673
|
d = Sequel.mock.dataset
|
@@ -4584,3 +4627,69 @@ describe "Frozen Datasets" do
|
|
4584
4627
|
@ds.select(:a).sql.should == 'SELECT a FROM test'
|
4585
4628
|
end
|
4586
4629
|
end
|
4630
|
+
|
4631
|
+
describe "Dataset mutation methods" do
|
4632
|
+
def m(&block)
|
4633
|
+
ds = Sequel.mock[:t]
|
4634
|
+
ds.instance_exec(&block)
|
4635
|
+
ds.sql
|
4636
|
+
end
|
4637
|
+
|
4638
|
+
it "should modify the dataset in place" do
|
4639
|
+
dsc = Sequel.mock[:u]
|
4640
|
+
dsc.instance_variable_set(:@columns, [:v])
|
4641
|
+
|
4642
|
+
m{and!(:a=>1).or!(:b=>2)}.should == "SELECT * FROM t WHERE ((a = 1) OR (b = 2))"
|
4643
|
+
m{select!(:f).graph!(dsc, :b=>:c).set_graph_aliases!(:e=>[:m, :n]).add_graph_aliases!(:d=>[:g, :c])}.should == "SELECT m.n AS e, g.c AS d FROM t LEFT OUTER JOIN u ON (u.b = t.c)"
|
4644
|
+
m{cross_join!(:a)}.should == "SELECT * FROM t CROSS JOIN a"
|
4645
|
+
m{distinct!}.should == "SELECT DISTINCT * FROM t"
|
4646
|
+
m{except!(dsc)}.should == "SELECT * FROM (SELECT * FROM t EXCEPT SELECT * FROM u) AS t1"
|
4647
|
+
m{exclude!(:a=>1)}.should == "SELECT * FROM t WHERE (a != 1)"
|
4648
|
+
m{exclude_having!(:a=>1)}.should == "SELECT * FROM t HAVING (a != 1)"
|
4649
|
+
m{exclude_where!(:a=>1)}.should == "SELECT * FROM t WHERE (a != 1)"
|
4650
|
+
m{filter!(:a=>1)}.should == "SELECT * FROM t WHERE (a = 1)"
|
4651
|
+
m{for_update!}.should == "SELECT * FROM t FOR UPDATE"
|
4652
|
+
m{from!(:p)}.should == "SELECT * FROM p"
|
4653
|
+
m{full_join!(:a, [:b])}.should == "SELECT * FROM t FULL JOIN a USING (b)"
|
4654
|
+
m{full_outer_join!(:a, [:b])}.should == "SELECT * FROM t FULL OUTER JOIN a USING (b)"
|
4655
|
+
m{grep!(:a, 'b')}.should == "SELECT * FROM t WHERE ((a LIKE 'b' ESCAPE '\\'))"
|
4656
|
+
m{group!(:a)}.should == "SELECT * FROM t GROUP BY a"
|
4657
|
+
m{group_and_count!(:a)}.should == "SELECT a, count(*) AS count FROM t GROUP BY a"
|
4658
|
+
m{group_by!(:a)}.should == "SELECT * FROM t GROUP BY a"
|
4659
|
+
m{having!(:a)}.should == "SELECT * FROM t HAVING a"
|
4660
|
+
m{inner_join!(:a, [:b])}.should == "SELECT * FROM t INNER JOIN a USING (b)"
|
4661
|
+
m{intersect!(dsc)}.should == "SELECT * FROM (SELECT * FROM t INTERSECT SELECT * FROM u) AS t1"
|
4662
|
+
m{where!(:a).invert!}.should == "SELECT * FROM t WHERE NOT a"
|
4663
|
+
m{join!(:a, [:b])}.should == "SELECT * FROM t INNER JOIN a USING (b)"
|
4664
|
+
m{join_table!(:inner, :a, [:b])}.should == "SELECT * FROM t INNER JOIN a USING (b)"
|
4665
|
+
m{left_join!(:a, [:b])}.should == "SELECT * FROM t LEFT JOIN a USING (b)"
|
4666
|
+
m{left_outer_join!(:a, [:b])}.should == "SELECT * FROM t LEFT OUTER JOIN a USING (b)"
|
4667
|
+
m{limit!(1)}.should == "SELECT * FROM t LIMIT 1"
|
4668
|
+
m{lock_style!(:update)}.should == "SELECT * FROM t FOR UPDATE"
|
4669
|
+
m{natural_full_join!(:a)}.should == "SELECT * FROM t NATURAL FULL JOIN a"
|
4670
|
+
m{natural_join!(:a)}.should == "SELECT * FROM t NATURAL JOIN a"
|
4671
|
+
m{natural_left_join!(:a)}.should == "SELECT * FROM t NATURAL LEFT JOIN a"
|
4672
|
+
m{natural_right_join!(:a)}.should == "SELECT * FROM t NATURAL RIGHT JOIN a"
|
4673
|
+
m{offset!(1)}.should == "SELECT * FROM t OFFSET 1"
|
4674
|
+
m{order!(:a).reverse_order!}.should == "SELECT * FROM t ORDER BY a DESC"
|
4675
|
+
m{order_by!(:a).order_more!(:b).order_append!(:c).order_prepend!(:d).reverse!}.should == "SELECT * FROM t ORDER BY d DESC, a DESC, b DESC, c DESC"
|
4676
|
+
m{qualify!}.should == "SELECT t.* FROM t"
|
4677
|
+
m{right_join!(:a, [:b])}.should == "SELECT * FROM t RIGHT JOIN a USING (b)"
|
4678
|
+
m{right_outer_join!(:a, [:b])}.should == "SELECT * FROM t RIGHT OUTER JOIN a USING (b)"
|
4679
|
+
m{select!(:a)}.should == "SELECT a FROM t"
|
4680
|
+
m{select_all!(:t).select_more!(:b).select_append!(:c)}.should == "SELECT t.*, b, c FROM t"
|
4681
|
+
m{select_group!(:a)}.should == "SELECT a FROM t GROUP BY a"
|
4682
|
+
m{where!(:a).unfiltered!}.should == "SELECT * FROM t"
|
4683
|
+
m{group!(:a).ungrouped!}.should == "SELECT * FROM t"
|
4684
|
+
m{limit!(1).unlimited!}.should == "SELECT * FROM t"
|
4685
|
+
m{order!(:a).unordered!}.should == "SELECT * FROM t"
|
4686
|
+
m{union!(dsc)}.should == "SELECT * FROM (SELECT * FROM t UNION SELECT * FROM u) AS t1"
|
4687
|
+
m{with!(:a, dsc)}.should == "WITH a AS (SELECT * FROM u) SELECT * FROM t"
|
4688
|
+
m{with_recursive!(:a, dsc, dsc)}.should == "WITH a AS (SELECT * FROM u UNION ALL SELECT * FROM u) SELECT * FROM t"
|
4689
|
+
m{with_sql!('SELECT foo')}.should == "SELECT foo"
|
4690
|
+
|
4691
|
+
dsc.server!(:a)
|
4692
|
+
dsc.opts[:server].should == :a
|
4693
|
+
dsc.graph!(dsc, {:b=>:c}, :table_alias=>:foo).ungraphed!.opts[:graph].should be_nil
|
4694
|
+
end
|
4695
|
+
end
|
@@ -61,9 +61,16 @@ describe Sequel::Dataset, " graphing" do
|
|
61
61
|
proc{@ds1.select(1).graph(@ds2, :x=>:id)}.should raise_error(Sequel::Error)
|
62
62
|
end
|
63
63
|
|
64
|
+
it "#graph should accept a complex dataset and pass it directly to join" do
|
65
|
+
ds = @ds1.graph(@ds2.select_all(:lines), {:x=>:id})
|
66
|
+
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)'
|
67
|
+
end
|
68
|
+
|
64
69
|
it "#graph should accept a complex dataset and pass it directly to join" do
|
65
70
|
ds = @ds1.graph(@ds2.filter(:x=>1), {:x=>:id})
|
66
71
|
ds.sql.should == 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT * FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
|
72
|
+
ds = @ds1.graph(@ds2.select_all(:lines).filter(:x=>1), {:x=>:id})
|
73
|
+
ds.sql.should == 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT lines.* FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
|
67
74
|
end
|
68
75
|
|
69
76
|
it "#graph should work on from_self datasets" do
|
@@ -276,6 +276,13 @@ describe "constraint_validations extension" do
|
|
276
276
|
@db.sqls.should == ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "ALTER TABLE foo DROP CONSTRAINT bar"]
|
277
277
|
end
|
278
278
|
|
279
|
+
it "should drop constraints and validations before adding new ones" do
|
280
|
+
@db.alter_table(:foo){String :name; validate{unique :name; drop :bar}}
|
281
|
+
sqls = @db.sqls
|
282
|
+
parse_insert(sqls.slice!(2)).should == {:validation_type=>"unique", :column=>"name", :table=>"foo"}
|
283
|
+
sqls.should == ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)", "ALTER TABLE foo DROP CONSTRAINT bar"]
|
284
|
+
end
|
285
|
+
|
279
286
|
it "should raise an error if attempting to validate inclusion with a range of non-integers" do
|
280
287
|
proc{@db.create_table(:foo){String :name; validate{includes 'a'..'z', :name}}}.should raise_error(Sequel::Error)
|
281
288
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
|
-
if RUBY_VERSION >= '2.0.0'
|
3
|
+
if RUBY_VERSION >= '2.0.0' && respond_to?(:using)
|
4
4
|
Sequel.extension :core_refinements, :pg_array, :pg_hstore, :pg_row, :pg_range, :pg_row_ops, :pg_range_ops, :pg_array_ops, :pg_hstore_ops, :pg_json, :pg_json_ops
|
5
5
|
using Sequel::CoreRefinements
|
6
6
|
|
@@ -154,6 +154,21 @@ describe Sequel::Model, "many_through_many" do
|
|
154
154
|
@c1.filter(:tags=>@c2.load(:h1=>1234, :h2=>85)).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
|
155
155
|
end
|
156
156
|
|
157
|
+
it "should allowing filtering by many_through_many associations with :conditions" do
|
158
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
159
|
+
@c1.filter(:tags=>@c2.load(:id=>1234)).sql.should == "SELECT * FROM artists WHERE ((artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL)))) AND (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id = 1234)))))"
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should allowing filtering by many_through_many associations with :conditions with a single through table" do
|
163
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id]], :conditions=>{:name=>'A'}
|
164
|
+
@c1.filter(:tags=>@c2.load(:id=>1234)).sql.should == "SELECT * FROM artists WHERE ((artists.id IN (SELECT albums_artists.artist_id FROM albums_artists WHERE ((albums_artists.album_id = 1234) AND (albums_artists.artist_id IS NOT NULL)))) AND (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_artists ON (albums_artists.album_id = tags.id) WHERE ((name = 'A') AND (tags.id = 1234)))))"
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should allowing filtering by many_through_many associations with :conditions and composite keys" do
|
168
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
169
|
+
@c1.filter(:tags=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) AND ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id = 1)))))"
|
170
|
+
end
|
171
|
+
|
157
172
|
it "should allowing excluding by many_through_many associations" do
|
158
173
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
|
159
174
|
@c1.exclude(:tags=>@c2.load(:id=>1234)).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
|
@@ -164,6 +179,16 @@ describe Sequel::Model, "many_through_many" do
|
|
164
179
|
@c1.exclude(:tags=>@c2.load(:h1=>1234, :h2=>85)).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
|
165
180
|
end
|
166
181
|
|
182
|
+
it "should allowing excluding by many_through_many associations with :conditions" do
|
183
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
184
|
+
@c1.exclude(:tags=>@c2.load(:id=>1234)).sql.should == "SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id NOT IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id = 1234)))) OR (artists.id IS NULL))"
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should allowing excluding by many_through_many associations with :conditions and composite keys" do
|
188
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
189
|
+
@c1.exclude(:tags=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR ((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id = 1)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))"
|
190
|
+
end
|
191
|
+
|
167
192
|
it "should allowing filtering by multiple many_through_many associations" do
|
168
193
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
|
169
194
|
@c1.filter(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL))))'
|
@@ -174,6 +199,16 @@ describe Sequel::Model, "many_through_many" do
|
|
174
199
|
@c1.filter(:tags=>[@c2.load(:h1=>1234, :h2=>85), @c2.load(:h1=>2345, :h2=>95)]).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
|
175
200
|
end
|
176
201
|
|
202
|
+
it "should allowing filtering by multiple many_through_many associations with :conditions" do
|
203
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
204
|
+
@c1.filter(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == "SELECT * FROM artists WHERE ((artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL)))) AND (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id IN (1234, 2345))))))"
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should allowing filtering by multiple many_through_many associations with :conditions and composite keys" do
|
208
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
209
|
+
@c1.filter(:tags=>[@c2.load(:id=>1, :h1=>1234, :h2=>85), @c2.load(:id=>2, :h1=>2345, :h2=>95)]).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) AND ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id IN (1, 2))))))"
|
210
|
+
end
|
211
|
+
|
177
212
|
it "should allowing excluding by multiple many_through_many associations" do
|
178
213
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
|
179
214
|
@c1.exclude(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
|
@@ -184,6 +219,16 @@ describe Sequel::Model, "many_through_many" do
|
|
184
219
|
@c1.exclude(:tags=>[@c2.load(:h1=>1234, :h2=>85), @c2.load(:h1=>2345, :h2=>95)]).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
|
185
220
|
end
|
186
221
|
|
222
|
+
it "should allowing excluding by multiple many_through_many associations with :conditions" do
|
223
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
224
|
+
@c1.exclude(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == "SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id NOT IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id IN (1234, 2345))))) OR (artists.id IS NULL))"
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should allowing excluding by multiple many_through_many associations with :conditions and composite keys" do
|
228
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
229
|
+
@c1.exclude(:tags=>[@c2.load(:id=>1, :h1=>1234, :h2=>85), @c2.load(:id=>2, :h1=>2345, :h2=>95)]).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR ((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id IN (1, 2))))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))"
|
230
|
+
end
|
231
|
+
|
187
232
|
it "should allowing filtering/excluding many_through_many associations with NULL values" do
|
188
233
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
|
189
234
|
@c1.filter(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'f\''
|
@@ -200,6 +245,16 @@ describe Sequel::Model, "many_through_many" do
|
|
200
245
|
@c1.filter(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
|
201
246
|
end
|
202
247
|
|
248
|
+
it "should allowing filtering by many_through_many association datasets with :conditions" do
|
249
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
250
|
+
@c1.filter(:tags=>@c2.filter(:x=>1)).sql.should == "SELECT * FROM artists WHERE ((artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_artists.artist_id IS NOT NULL)))) AND (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should allowing filtering by many_through_many association datasets with :conditions and composite keys" do
|
254
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
255
|
+
@c1.filter(:tags=>@c2.filter(:x=>1)).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) AND ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
|
256
|
+
end
|
257
|
+
|
203
258
|
it "should allowing excluding by many_through_many association datasets" do
|
204
259
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
|
205
260
|
@c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
|
@@ -210,6 +265,16 @@ describe Sequel::Model, "many_through_many" do
|
|
210
265
|
@c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
|
211
266
|
end
|
212
267
|
|
268
|
+
it "should allowing excluding by many_through_many association datasets with :conditions" do
|
269
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}
|
270
|
+
@c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == "SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id NOT IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (artists.id IS NULL))"
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should allowing excluding by many_through_many association datasets with :conditions and composite keys" do
|
274
|
+
@c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}
|
275
|
+
@c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == "SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR ((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))"
|
276
|
+
end
|
277
|
+
|
213
278
|
it "should support a :conditions option" do
|
214
279
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:a=>32}
|
215
280
|
n = @c1.load(:id => 1234)
|
@@ -7,11 +7,13 @@ describe Sequel::Model, "pg_array_associations" do
|
|
7
7
|
columns :id, :tag_ids
|
8
8
|
plugin :pg_array_associations
|
9
9
|
pg_array_to_many :tags
|
10
|
+
pg_array_to_many :a_tags, :clone=>:tags, :conditions=>{:name=>'A'}, :key=>:tag_ids
|
10
11
|
end
|
11
12
|
class ::Tag < Sequel::Model
|
12
13
|
columns :id
|
13
14
|
plugin :pg_array_associations
|
14
15
|
many_to_pg_array :artists
|
16
|
+
many_to_pg_array :a_artists, :clone=>:artists, :conditions=>{:name=>'A'}
|
15
17
|
def id3
|
16
18
|
id*3
|
17
19
|
end
|
@@ -66,21 +68,41 @@ describe Sequel::Model, "pg_array_associations" do
|
|
66
68
|
@c2.filter(:artists=>@o1).sql.should == "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))"
|
67
69
|
end
|
68
70
|
|
71
|
+
it "should allowing filtering by associations with :conditions" do
|
72
|
+
@c1.filter(:a_tags=>@o2).sql.should == "SELECT * FROM artists WHERE ((artists.tag_ids @> ARRAY[2]) AND coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), 'f'))"
|
73
|
+
@c2.filter(:a_artists=>@o1).sql.should == "SELECT * FROM tags WHERE ((tags.id IN (1, 2, 3)) AND (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1)))))"
|
74
|
+
end
|
75
|
+
|
69
76
|
it "should allowing excluding by associations" do
|
70
77
|
@c1.exclude(:tags=>@o2).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids @> ARRAY[2]) OR (artists.tag_ids IS NULL))"
|
71
78
|
@c2.exclude(:artists=>@o1).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (1, 2, 3)) OR (tags.id IS NULL))"
|
72
79
|
end
|
73
80
|
|
81
|
+
it "should allowing excluding by associations with :conditions" do
|
82
|
+
@c1.exclude(:a_tags=>@o2).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids @> ARRAY[2]) OR NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), 'f') OR (artists.tag_ids IS NULL))"
|
83
|
+
@c2.exclude(:a_artists=>@o1).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (1, 2, 3)) OR (tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1)))) OR (tags.id IS NULL))"
|
84
|
+
end
|
85
|
+
|
74
86
|
it "should allowing filtering by multiple associations" do
|
75
87
|
@c1.filter(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2])"
|
76
88
|
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE (tags.id IN (3, 4, 5))"
|
77
89
|
end
|
78
90
|
|
91
|
+
it "should allowing filtering by multiple associations with :conditions" do
|
92
|
+
@c1.filter(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE ((artists.tag_ids && ARRAY[1,2]) AND coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), 'f'))"
|
93
|
+
@c2.filter(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE ((tags.id IN (3, 4, 5)) AND (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8))))))"
|
94
|
+
end
|
95
|
+
|
79
96
|
it "should allowing excluding by multiple associations" do
|
80
97
|
@c1.exclude(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids && ARRAY[1,2]) OR (artists.tag_ids IS NULL))"
|
81
98
|
@c2.exclude(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (3, 4, 5)) OR (tags.id IS NULL))"
|
82
99
|
end
|
83
100
|
|
101
|
+
it "should allowing excluding by multiple associations with :conditions" do
|
102
|
+
@c1.exclude(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids && ARRAY[1,2]) OR NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), 'f') OR (artists.tag_ids IS NULL))"
|
103
|
+
@c2.exclude(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (3, 4, 5)) OR (tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8))))) OR (tags.id IS NULL))"
|
104
|
+
end
|
105
|
+
|
84
106
|
it "should allowing filtering/excluding associations with NULL or empty values" do
|
85
107
|
@c1.filter(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'f\''
|
86
108
|
@c1.exclude(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'t\''
|
@@ -99,11 +121,21 @@ describe Sequel::Model, "pg_array_associations" do
|
|
99
121
|
@c2.filter(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1)))"
|
100
122
|
end
|
101
123
|
|
124
|
+
it "should allowing filtering by association datasets with :conditions" do
|
125
|
+
@c1.filter(:a_tags=>@c2.where(:id=>1)).sql.should == "SELECT * FROM artists WHERE (coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f') AND coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), 'f'))"
|
126
|
+
@c2.filter(:a_artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1))) AND (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1)))))))"
|
127
|
+
end
|
128
|
+
|
102
129
|
it "should allowing excluding by association datasets" do
|
103
130
|
@c1.exclude(:tags=>@c2.where(:id=>1)).sql.should == "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f') OR (artists.tag_ids IS NULL))"
|
104
131
|
@c2.exclude(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1))) OR (tags.id IS NULL))"
|
105
132
|
end
|
106
133
|
|
134
|
+
it "should allowing excluding by association datasets with :conditions" do
|
135
|
+
@c1.exclude(:a_tags=>@c2.where(:id=>1)).sql.should == "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f') OR NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), 'f') OR (artists.tag_ids IS NULL))"
|
136
|
+
@c2.exclude(:a_artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1))) OR (tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1)))))) OR (tags.id IS NULL))"
|
137
|
+
end
|
138
|
+
|
107
139
|
it "filter by associations should respect key options" do
|
108
140
|
@c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
|
109
141
|
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
@@ -513,6 +545,18 @@ describe Sequel::Model, "pg_array_associations" do
|
|
513
545
|
DB.sqls.should == ["UPDATE artists SET tag_ids = array_remove(tag_ids, 2) WHERE (tag_ids @> ARRAY[2])"]
|
514
546
|
end
|
515
547
|
|
548
|
+
it "should allow calling add_ and remove_ methods on new objects for pg_array_to_many associations" do
|
549
|
+
a = Artist.new
|
550
|
+
a.add_tag(@c2.load(:id=>4))
|
551
|
+
a.tag_ids.should == [4]
|
552
|
+
a.remove_tag(@c2.load(:id=>4))
|
553
|
+
a.tag_ids.should == []
|
554
|
+
a.add_tag(@c2.load(:id=>4))
|
555
|
+
a.tag_ids.should == [4]
|
556
|
+
a.remove_all_tags
|
557
|
+
a.tag_ids.should == []
|
558
|
+
end
|
559
|
+
|
516
560
|
it "should have pg_array_to_many association modification methods save if :save_after_modify option is used" do
|
517
561
|
@c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
|
518
562
|
|