sequel 4.3.0 → 4.4.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.
- 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
|
|