sequel 4.45.0 → 4.46.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +108 -0
- data/doc/release_notes/4.46.0.txt +404 -0
- data/doc/security.rdoc +9 -0
- data/doc/sql.rdoc +2 -2
- data/doc/testing.rdoc +1 -1
- data/doc/validations.rdoc +1 -2
- data/lib/sequel/adapters/ado.rb +8 -3
- data/lib/sequel/adapters/ado/access.rb +8 -4
- data/lib/sequel/adapters/ado/mssql.rb +3 -1
- data/lib/sequel/adapters/amalgalite.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +16 -7
- data/lib/sequel/adapters/do.rb +7 -1
- data/lib/sequel/adapters/do/mysql.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +10 -5
- data/lib/sequel/adapters/jdbc.rb +8 -2
- data/lib/sequel/adapters/jdbc/as400.rb +10 -3
- data/lib/sequel/adapters/jdbc/db2.rb +27 -16
- data/lib/sequel/adapters/jdbc/derby.rb +47 -20
- data/lib/sequel/adapters/jdbc/h2.rb +13 -7
- data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +8 -1
- data/lib/sequel/adapters/mysql2.rb +6 -1
- data/lib/sequel/adapters/odbc.rb +20 -8
- data/lib/sequel/adapters/odbc/mssql.rb +6 -3
- data/lib/sequel/adapters/oracle.rb +12 -6
- data/lib/sequel/adapters/postgres.rb +20 -8
- data/lib/sequel/adapters/shared/access.rb +76 -47
- data/lib/sequel/adapters/shared/cubrid.rb +16 -11
- data/lib/sequel/adapters/shared/db2.rb +46 -19
- data/lib/sequel/adapters/shared/firebird.rb +20 -8
- data/lib/sequel/adapters/shared/informix.rb +6 -3
- data/lib/sequel/adapters/shared/mssql.rb +132 -72
- data/lib/sequel/adapters/shared/mysql.rb +112 -65
- data/lib/sequel/adapters/shared/oracle.rb +36 -21
- data/lib/sequel/adapters/shared/postgres.rb +91 -56
- data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
- data/lib/sequel/adapters/shared/sqlite.rb +67 -32
- data/lib/sequel/adapters/sqlanywhere.rb +9 -1
- data/lib/sequel/adapters/sqlite.rb +8 -1
- data/lib/sequel/adapters/swift.rb +5 -0
- data/lib/sequel/adapters/swift/mysql.rb +4 -2
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +10 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
- data/lib/sequel/adapters/utils/pg_types.rb +14 -6
- data/lib/sequel/adapters/utils/replace.rb +4 -2
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/core.rb +24 -11
- data/lib/sequel/database/connecting.rb +9 -3
- data/lib/sequel/database/dataset_defaults.rb +7 -1
- data/lib/sequel/database/logging.rb +1 -0
- data/lib/sequel/database/misc.rb +5 -2
- data/lib/sequel/database/query.rb +7 -5
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +50 -27
- data/lib/sequel/database/transactions.rb +19 -9
- data/lib/sequel/dataset/actions.rb +15 -6
- data/lib/sequel/dataset/graph.rb +15 -5
- data/lib/sequel/dataset/misc.rb +12 -4
- data/lib/sequel/dataset/mutation.rb +17 -8
- data/lib/sequel/dataset/prepared_statements.rb +3 -2
- data/lib/sequel/dataset/query.rb +84 -38
- data/lib/sequel/dataset/sql.rb +302 -191
- data/lib/sequel/deprecated.rb +26 -17
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/migration.rb +28 -4
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +4 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +11 -7
- data/lib/sequel/model/associations.rb +5 -7
- data/lib/sequel/model/base.rb +47 -45
- data/lib/sequel/model/dataset_module.rb +9 -14
- data/lib/sequel/model/plugins.rb +3 -0
- data/lib/sequel/no_core_ext.rb +1 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -1
- data/lib/sequel/plugins/boolean_subsets.rb +7 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/finder.rb +240 -0
- data/lib/sequel/plugins/inverted_subsets.rb +19 -12
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
- data/lib/sequel/plugins/subset_conditions.rb +11 -3
- data/lib/sequel/plugins/whitelist_security.rb +118 -0
- data/lib/sequel/sql.rb +80 -36
- data/lib/sequel/timezones.rb +2 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +20 -0
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +12 -8
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +36 -34
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +87 -9
- data/spec/core/dataset_spec.rb +501 -129
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +146 -60
- data/spec/core/mock_adapter_spec.rb +1 -1
- data/spec/core/object_graph_spec.rb +61 -9
- data/spec/core/placeholder_literalizer_spec.rb +20 -2
- data/spec/core/schema_generator_spec.rb +6 -6
- data/spec/core/schema_spec.rb +54 -5
- data/spec/core_extensions_spec.rb +122 -18
- data/spec/deprecation_helper.rb +27 -2
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
- data/spec/extensions/association_proxies_spec.rb +2 -2
- data/spec/extensions/auto_literal_strings_spec.rb +212 -0
- data/spec/extensions/blacklist_security_spec.rb +1 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
- data/spec/extensions/column_select_spec.rb +20 -8
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/core_refinements_spec.rb +29 -12
- data/spec/extensions/dataset_associations_spec.rb +12 -12
- data/spec/extensions/def_dataset_method_spec.rb +100 -0
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +260 -0
- data/spec/extensions/graph_each_spec.rb +2 -2
- data/spec/extensions/identifier_mangling_spec.rb +14 -8
- data/spec/extensions/inverted_subsets_spec.rb +4 -4
- data/spec/extensions/lazy_attributes_spec.rb +7 -0
- data/spec/extensions/many_through_many_spec.rb +38 -14
- data/spec/extensions/nested_attributes_spec.rb +18 -6
- data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
- data/spec/extensions/pg_enum_spec.rb +16 -1
- data/spec/extensions/pg_interval_spec.rb +11 -2
- data/spec/extensions/pg_loose_count_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +25 -0
- data/spec/extensions/prepared_statements_spec.rb +10 -1
- data/spec/extensions/query_spec.rb +2 -2
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/set_overrides_spec.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +0 -1
- data/spec/extensions/subset_conditions_spec.rb +6 -6
- data/spec/extensions/table_select_spec.rb +24 -12
- data/spec/extensions/to_dot_spec.rb +4 -4
- data/spec/extensions/whitelist_security_spec.rb +131 -0
- data/spec/integration/dataset_test.rb +9 -5
- data/spec/integration/model_test.rb +2 -0
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/model/associations_spec.rb +39 -11
- data/spec/model/base_spec.rb +44 -24
- data/spec/model/class_dataset_methods_spec.rb +18 -16
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +84 -24
- data/spec/model/model_spec.rb +97 -63
- data/spec/model/record_spec.rb +21 -13
- metadata +13 -2
@@ -38,7 +38,7 @@ describe Sequel::Dataset, " graphing" do
|
|
38
38
|
|
39
39
|
@ds1.graph(@ds2, :x=>:id).all.must_equal [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}]
|
40
40
|
@ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).all.must_equal [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}]
|
41
|
-
@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y
|
41
|
+
@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>Sequel[:points][:id]}, :table_alias=>:graph).all.must_equal [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}]
|
42
42
|
end
|
43
43
|
|
44
44
|
it "#graph_each should split the result set into component tables when using first" do
|
@@ -48,7 +48,7 @@ describe Sequel::Dataset, " graphing" do
|
|
48
48
|
|
49
49
|
@ds1.graph(@ds2, :x=>:id).first.must_equal(:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7})
|
50
50
|
@ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).first.must_equal(:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12})
|
51
|
-
@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y
|
51
|
+
@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>Sequel[:points][:id]}, :table_alias=>:graph).first.must_equal(:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11})
|
52
52
|
end
|
53
53
|
|
54
54
|
it "#graph_each should give a nil value instead of a hash when all values for a table are nil" do
|
@@ -24,7 +24,8 @@ describe "identifier_mangling extension" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should upcase on input and downcase on output by default" do
|
27
|
-
|
27
|
+
# SEQUEL5: Remove :identifier_mangling=>false
|
28
|
+
db = Sequel::Database.new(:identifier_mangling=>false).extension(:identifier_mangling)
|
28
29
|
db.send(:identifier_input_method_default).must_equal :upcase
|
29
30
|
db.send(:identifier_output_method_default).must_equal :downcase
|
30
31
|
end
|
@@ -141,9 +142,9 @@ describe "identifier_mangling extension" do
|
|
141
142
|
deprecated "should respect the quote_indentifiers_default method if Sequel.quote_identifiers = nil" do
|
142
143
|
Sequel.quote_identifiers = nil
|
143
144
|
Sequel::Database.new.extension(:identifier_mangling).quote_identifiers?.must_equal true
|
144
|
-
x = Class.new(Sequel::Database){def quote_identifiers_default; false end}
|
145
|
+
x = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def quote_identifiers_default; false end}
|
145
146
|
x.new.extension(:identifier_mangling).quote_identifiers?.must_equal false
|
146
|
-
y = Class.new(Sequel::Database){def quote_identifiers_default; true end}
|
147
|
+
y = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def quote_identifiers_default; true end}
|
147
148
|
y.new.extension(:identifier_mangling).quote_identifiers?.must_equal true
|
148
149
|
end
|
149
150
|
|
@@ -151,9 +152,9 @@ describe "identifier_mangling extension" do
|
|
151
152
|
class Sequel::Database
|
152
153
|
@identifier_input_method = nil
|
153
154
|
end
|
154
|
-
x = Class.new(Sequel::Database){def identifier_input_method_default; :downcase end}
|
155
|
+
x = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def identifier_input_method_default; :downcase end}
|
155
156
|
x.new.extension(:identifier_mangling).identifier_input_method.must_equal :downcase
|
156
|
-
y = Class.new(Sequel::Database){def identifier_input_method_default; :camelize end}
|
157
|
+
y = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def identifier_input_method_default; :camelize end}
|
157
158
|
y.new.extension(:identifier_mangling).identifier_input_method.must_equal :camelize
|
158
159
|
end
|
159
160
|
|
@@ -161,9 +162,9 @@ describe "identifier_mangling extension" do
|
|
161
162
|
class Sequel::Database
|
162
163
|
@identifier_output_method = nil
|
163
164
|
end
|
164
|
-
x = Class.new(Sequel::Database){def identifier_output_method_default; :upcase end}
|
165
|
+
x = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def identifier_output_method_default; :upcase end}
|
165
166
|
x.new.extension(:identifier_mangling).identifier_output_method.must_equal :upcase
|
166
|
-
y = Class.new(Sequel::Database){def identifier_output_method_default; :underscore end}
|
167
|
+
y = Class.new(Sequel::Database){def dataset_class_default; Sequel::Dataset end; def identifier_output_method_default; :underscore end}
|
167
168
|
y.new.extension(:identifier_mangling).identifier_output_method.must_equal :underscore
|
168
169
|
end
|
169
170
|
end
|
@@ -315,7 +316,7 @@ describe "identifier_mangling extension" do
|
|
315
316
|
Sequel.mock(:host=>'oracle')[:a].limit(1).sql.must_equal 'SELECT * FROM (SELECT * FROM "A") "T1" WHERE (ROWNUM <= 1)'
|
316
317
|
Sequel.mock(:host=>'postgres')[:a].full_text_search(:b, 'c').sql.must_equal "SELECT * FROM \"a\" WHERE (to_tsvector(CAST('simple' AS regconfig), (COALESCE(\"b\", ''))) @@ to_tsquery(CAST('simple' AS regconfig), 'c'))"
|
317
318
|
Sequel.mock(:host=>'sqlanywhere').from(:a).offset(1).sql.must_equal 'SELECT TOP 2147483647 START AT (1 + 1) * FROM "A"'
|
318
|
-
Sequel.mock(:host=>'sqlite')[:
|
319
|
+
Sequel.mock(:host=>'sqlite')[Sequel[:a].as(:b)].sql.must_equal "SELECT * FROM `a` AS 'b'"
|
319
320
|
ensure
|
320
321
|
deprecated do
|
321
322
|
Sequel.quote_identifiers = qi
|
@@ -341,7 +342,12 @@ describe Sequel::Model, ".[] optimization" do
|
|
341
342
|
@c.simple_table.must_equal '"ba"'
|
342
343
|
@c.set_primary_key :cd
|
343
344
|
@c.simple_pk.must_equal '"dc"'
|
345
|
+
@c.set_dataset ds.from(Sequel[:ef][:gh])
|
346
|
+
@c.simple_table.must_equal '"fe"."hg"'
|
347
|
+
end
|
344
348
|
|
349
|
+
with_symbol_splitting "should have simple_pk and simple_table respect dataset's identifier input methods when using splittable symbols" do
|
350
|
+
ds = @db.from(:ab).with_identifier_input_method(:reverse)
|
345
351
|
@c.set_dataset ds.from(:ef__gh)
|
346
352
|
@c.simple_table.must_equal '"fe"."hg"'
|
347
353
|
end
|
@@ -4,21 +4,21 @@ describe "Sequel::Plugins::InvertedSubsets" do
|
|
4
4
|
it "should add an inverted subset method which inverts the condition" do
|
5
5
|
c = Class.new(Sequel::Model(:a))
|
6
6
|
c.plugin :inverted_subsets
|
7
|
-
c.subset(:published, :published => true)
|
7
|
+
c.dataset_module{subset(:published, :published => true)}
|
8
8
|
c.not_published.sql.must_equal 'SELECT * FROM a WHERE (published IS NOT TRUE)'
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should support a configuration block to customise the inverted method name" do
|
12
12
|
c = Class.new(Sequel::Model(:a))
|
13
13
|
c.plugin(:inverted_subsets){|name| "exclude_#{name}"}
|
14
|
-
c.
|
14
|
+
c.dataset_module{where(:published, :published => true)}
|
15
15
|
c.exclude_published.sql.must_equal 'SELECT * FROM a WHERE (published IS NOT TRUE)'
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should chain to existing dataset" do
|
19
19
|
c = Class.new(Sequel::Model(:a))
|
20
20
|
c.plugin :inverted_subsets
|
21
|
-
c.
|
21
|
+
c.dataset_module{where(:published, :published => true)}
|
22
22
|
c.where(1=>0).not_published.sql.must_equal 'SELECT * FROM a WHERE ((1 = 0) AND (published IS NOT TRUE))'
|
23
23
|
end
|
24
24
|
|
@@ -27,7 +27,7 @@ describe "Sequel::Plugins::InvertedSubsets" do
|
|
27
27
|
c.plugin(:inverted_subsets){|name| "exclude_#{name}"}
|
28
28
|
c = Class.new(c)
|
29
29
|
c.dataset = :a
|
30
|
-
c.subset(:published, :published => true)
|
30
|
+
c.dataset_module{subset(:published, :published => true)}
|
31
31
|
c.exclude_published.sql.must_equal 'SELECT * FROM a WHERE (published IS NOT TRUE)'
|
32
32
|
end
|
33
33
|
end
|
@@ -63,6 +63,13 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should handle lazy attributes that are qualified in the selection" do
|
66
|
+
@c.set_dataset(@ds.select(Sequel[:la][:id], Sequel[:la][:blah]))
|
67
|
+
@c.dataset.sql.must_equal 'SELECT la.id, la.blah FROM la'
|
68
|
+
@c.plugin :lazy_attributes, :blah
|
69
|
+
@c.dataset.sql.must_equal 'SELECT la.id FROM la'
|
70
|
+
end
|
71
|
+
|
72
|
+
with_symbol_splitting "should handle lazy attributes that are qualified in the selection using symbol splitting" do
|
66
73
|
@c.set_dataset(@ds.select(:la__id, :la__blah))
|
67
74
|
@c.dataset.sql.must_equal 'SELECT la.id, la.blah FROM la'
|
68
75
|
@c.plugin :lazy_attributes, :blah
|
@@ -62,7 +62,7 @@ describe Sequel::Model, "many_through_many" do
|
|
62
62
|
it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup" do
|
63
63
|
@c1.dataset = @c1.dataset.with_fetch(:id=>1)
|
64
64
|
@c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
|
65
|
-
@c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>Sequel
|
65
|
+
@c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>(Sequel[:albums_artists][:artist_id] / 3)
|
66
66
|
a = @c1.eager(:tags).all
|
67
67
|
a.must_equal [@c1.load(:id => 1)]
|
68
68
|
DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, (albums_artists.artist_id / 3) AS x_foreign_key_x 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 ((albums_artists.artist_id / 3) IN (1))"]
|
@@ -70,6 +70,20 @@ describe Sequel::Model, "many_through_many" do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should handle schema qualified tables" do
|
73
|
+
@c1.many_through_many :tags, :through=>[[Sequel[:myschema][:albums_artists], :artist_id, :album_id], [Sequel[:myschema][:albums], :id, :id], [Sequel[:myschema][:albums_tags], :album_id, :tag_id]]
|
74
|
+
@c1.load(:id=>1).tags_dataset.sql.must_equal "SELECT tags.* FROM tags INNER JOIN myschema.albums_tags ON (myschema.albums_tags.tag_id = tags.id) INNER JOIN myschema.albums ON (myschema.albums.id = myschema.albums_tags.album_id) INNER JOIN myschema.albums_artists ON (myschema.albums_artists.album_id = myschema.albums.id) WHERE (myschema.albums_artists.artist_id = 1)"
|
75
|
+
|
76
|
+
@c1.dataset = @c1.dataset.with_fetch(:id=>1)
|
77
|
+
@c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
|
78
|
+
a = @c1.eager(:tags).all
|
79
|
+
a.must_equal [@c1.load(:id => 1)]
|
80
|
+
DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, myschema.albums_artists.artist_id AS x_foreign_key_x FROM tags INNER JOIN myschema.albums_tags ON (myschema.albums_tags.tag_id = tags.id) INNER JOIN myschema.albums ON (myschema.albums.id = myschema.albums_tags.album_id) INNER JOIN myschema.albums_artists ON (myschema.albums_artists.album_id = myschema.albums.id) WHERE (myschema.albums_artists.artist_id IN (1))"]
|
81
|
+
|
82
|
+
Tag.dataset.columns(:id, :h1, :h2)
|
83
|
+
@c1.eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id, tags.h1, tags.h2 FROM artists LEFT OUTER JOIN myschema.albums_artists AS albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN myschema.albums AS albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN myschema.albums_tags AS albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id)'
|
84
|
+
end
|
85
|
+
|
86
|
+
with_symbol_splitting "should handle schema qualified table symbols" do
|
73
87
|
@c1.many_through_many :tags, :through=>[[:myschema__albums_artists, :artist_id, :album_id], [:myschema__albums, :id, :id], [:myschema__albums_tags, :album_id, :tag_id]]
|
74
88
|
@c1.load(:id=>1).tags_dataset.sql.must_equal "SELECT tags.* FROM tags INNER JOIN myschema.albums_tags ON (myschema.albums_tags.tag_id = tags.id) INNER JOIN myschema.albums ON (myschema.albums.id = myschema.albums_tags.album_id) INNER JOIN myschema.albums_artists ON (myschema.albums_artists.album_id = myschema.albums.id) WHERE (myschema.albums_artists.artist_id = 1)"
|
75
89
|
|
@@ -335,7 +349,7 @@ describe Sequel::Model, "many_through_many" do
|
|
335
349
|
n.tags_dataset.sql.must_equal 'SELECT tags.* 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 ((a = 32) AND (albums_artists.artist_id = 1234))'
|
336
350
|
n.tags.must_equal [@c2.load(:id=>1)]
|
337
351
|
|
338
|
-
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>
|
352
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>Sequel.lit('a = ?', 42)
|
339
353
|
n = @c1.load(:id => 1234)
|
340
354
|
n.tags_dataset.sql.must_equal 'SELECT tags.* 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 ((a = 42) AND (albums_artists.artist_id = 1234))'
|
341
355
|
n.tags.must_equal [@c2.load(:id=>1)]
|
@@ -363,7 +377,7 @@ describe Sequel::Model, "many_through_many" do
|
|
363
377
|
end
|
364
378
|
|
365
379
|
it "should support an array for the select option" do
|
366
|
-
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>[Sequel::SQL::ColumnAll.new(:tags), :
|
380
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>[Sequel::SQL::ColumnAll.new(:tags), Sequel[:albums][:name]]
|
367
381
|
n = @c1.load(:id => 1234)
|
368
382
|
n.tags_dataset.sql.must_equal 'SELECT tags.*, albums.name 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 (albums_artists.artist_id = 1234)'
|
369
383
|
n.tags.must_equal [@c2.load(:id=>1)]
|
@@ -386,7 +400,7 @@ describe Sequel::Model, "many_through_many" do
|
|
386
400
|
end
|
387
401
|
|
388
402
|
it "should support a :dataset option that is used instead of the default" do
|
389
|
-
@c1.many_through_many :tags, [[:a, :b, :c]], :dataset=>proc{Tag.join(:albums_tags, [:tag_id]).join(:albums, [:album_id]).join(:albums_artists, [:album_id]).filter(:
|
403
|
+
@c1.many_through_many :tags, [[:a, :b, :c]], :dataset=>proc{Tag.join(:albums_tags, [:tag_id]).join(:albums, [:album_id]).join(:albums_artists, [:album_id]).filter(Sequel[:albums_artists][:artist_id]=>id)}
|
390
404
|
n = @c1.load(:id => 1234)
|
391
405
|
n.tags_dataset.sql.must_equal 'SELECT tags.* FROM tags INNER JOIN albums_tags USING (tag_id) INNER JOIN albums USING (album_id) INNER JOIN albums_artists USING (album_id) WHERE (albums_artists.artist_id = 1234)'
|
392
406
|
n.tags.must_equal [@c2.load(:id=>1)]
|
@@ -839,7 +853,7 @@ describe "many_through_many eager loading methods" do
|
|
839
853
|
end
|
840
854
|
|
841
855
|
it "should respect the association's :select option" do
|
842
|
-
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select
|
856
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>Sequel[:tags][:name]
|
843
857
|
a = @c1.eager(:tags).all
|
844
858
|
a.must_equal [@c1.load(:id=>1)]
|
845
859
|
DB.sqls.must_equal ['SELECT * FROM artists',
|
@@ -1103,17 +1117,22 @@ describe "many_through_many eager loading methods" do
|
|
1103
1117
|
|
1104
1118
|
it "should respect the association's :order" do
|
1105
1119
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[:blah1, :blah2]
|
1106
|
-
@c1.order(:
|
1120
|
+
@c1.order(Sequel[:artists][:blah2], Sequel[:artists][:blah3]).eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tags.blah1, tags.blah2'
|
1107
1121
|
end
|
1108
1122
|
|
1109
|
-
|
1123
|
+
with_symbol_splitting "should not qualify qualified symbols" do
|
1110
1124
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[Sequel.identifier(:blah__id), Sequel.identifier(:blah__id).desc, Sequel.desc(:blah__id), :blah__id, :album_id, Sequel.desc(:album_id), 1, Sequel.lit('RANDOM()'), Sequel.qualify(:b, :a)]
|
1111
1125
|
@c1.order(:artists__blah2, :artists__blah3).eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tags.blah__id, tags.blah__id DESC, blah.id DESC, blah.id, tags.album_id, tags.album_id DESC, 1, RANDOM(), b.a'
|
1112
1126
|
end
|
1113
1127
|
|
1128
|
+
it "should only qualify symbols, identifiers, or ordered versions in association's :order" do
|
1129
|
+
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[Sequel.identifier(:blah__id), Sequel.identifier(:blah__id).desc, Sequel.desc(Sequel[:blah][:id]), Sequel[:blah][:id], :album_id, Sequel.desc(:album_id), 1, Sequel.lit('RANDOM()'), Sequel.qualify(:b, :a)]
|
1130
|
+
@c1.order(Sequel[:artists][:blah2], Sequel[:artists][:blah3]).eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tags.blah__id, tags.blah__id DESC, blah.id DESC, blah.id, tags.album_id, tags.album_id DESC, 1, RANDOM(), b.a'
|
1131
|
+
end
|
1132
|
+
|
1114
1133
|
it "should not respect the association's :order if :order_eager_graph is false" do
|
1115
1134
|
@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[:blah1, :blah2], :order_eager_graph=>false
|
1116
|
-
@c1.order(:
|
1135
|
+
@c1.order(Sequel[:artists][:blah2], Sequel[:artists][:blah3]).eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3'
|
1117
1136
|
end
|
1118
1137
|
|
1119
1138
|
it "should add the associations :order for multiple associations" do
|
@@ -1215,7 +1234,7 @@ describe Sequel::Model, "one_through_many" do
|
|
1215
1234
|
it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup" do
|
1216
1235
|
@c1.dataset = @c1.dataset.with_fetch(:id=>1)
|
1217
1236
|
@c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
|
1218
|
-
@c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>Sequel
|
1237
|
+
@c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>(Sequel[:albums_artists][:artist_id] / 3)
|
1219
1238
|
a = @c1.eager(:tag).all
|
1220
1239
|
a.must_equal [@c1.load(:id => 1)]
|
1221
1240
|
DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, (albums_artists.artist_id / 3) AS x_foreign_key_x 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 ((albums_artists.artist_id / 3) IN (1))"]
|
@@ -1458,7 +1477,7 @@ describe Sequel::Model, "one_through_many" do
|
|
1458
1477
|
n.tag_dataset.sql.must_equal 'SELECT tags.* 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 ((a = 32) AND (albums_artists.artist_id = 1234)) LIMIT 1'
|
1459
1478
|
n.tag.must_equal @c2.load(:id=>1)
|
1460
1479
|
|
1461
|
-
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>
|
1480
|
+
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>Sequel.lit('a = ?', 42)
|
1462
1481
|
n = @c1.load(:id => 1234)
|
1463
1482
|
n.tag_dataset.sql.must_equal 'SELECT tags.* 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 ((a = 42) AND (albums_artists.artist_id = 1234)) LIMIT 1'
|
1464
1483
|
n.tag.must_equal @c2.load(:id=>1)
|
@@ -1486,7 +1505,7 @@ describe Sequel::Model, "one_through_many" do
|
|
1486
1505
|
end
|
1487
1506
|
|
1488
1507
|
it "should support an array for the select option" do
|
1489
|
-
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>[Sequel::SQL::ColumnAll.new(:tags), :
|
1508
|
+
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>[Sequel::SQL::ColumnAll.new(:tags), Sequel[:albums][:name]]
|
1490
1509
|
n = @c1.load(:id => 1234)
|
1491
1510
|
n.tag_dataset.sql.must_equal 'SELECT tags.*, albums.name 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 (albums_artists.artist_id = 1234) LIMIT 1'
|
1492
1511
|
n.tag.must_equal @c2.load(:id=>1)
|
@@ -1509,7 +1528,7 @@ describe Sequel::Model, "one_through_many" do
|
|
1509
1528
|
end
|
1510
1529
|
|
1511
1530
|
it "should support a :dataset option that is used instead of the default" do
|
1512
|
-
@c1.one_through_many :tag, [[:a, :b, :c]], :dataset=>proc{Tag.join(:albums_tags, [:tag_id]).join(:albums, [:album_id]).join(:albums_artists, [:album_id]).filter(:
|
1531
|
+
@c1.one_through_many :tag, [[:a, :b, :c]], :dataset=>proc{Tag.join(:albums_tags, [:tag_id]).join(:albums, [:album_id]).join(:albums_artists, [:album_id]).filter(Sequel[:albums_artists][:artist_id]=>id)}
|
1513
1532
|
n = @c1.load(:id => 1234)
|
1514
1533
|
n.tag_dataset.sql.must_equal 'SELECT tags.* FROM tags INNER JOIN albums_tags USING (tag_id) INNER JOIN albums USING (album_id) INNER JOIN albums_artists USING (album_id) WHERE (albums_artists.artist_id = 1234) LIMIT 1'
|
1515
1534
|
n.tag.must_equal @c2.load(:id=>1)
|
@@ -1856,7 +1875,7 @@ describe "one_through_many eager loading methods" do
|
|
1856
1875
|
end
|
1857
1876
|
|
1858
1877
|
it "should respect the association's :select option" do
|
1859
|
-
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select
|
1878
|
+
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>Sequel[:tags][:name]
|
1860
1879
|
a = @c1.eager(:tag).all
|
1861
1880
|
a.must_equal [@c1.load(:id=>1)]
|
1862
1881
|
DB.sqls.must_equal ['SELECT * FROM artists',
|
@@ -2107,10 +2126,15 @@ describe "one_through_many eager loading methods" do
|
|
2107
2126
|
|
2108
2127
|
it "should respect the association's :order" do
|
2109
2128
|
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[:blah1, :blah2]
|
2110
|
-
@c1.order(:
|
2129
|
+
@c1.order(Sequel[:artists][:blah2], Sequel[:artists][:blah3]).eager_graph(:tag).sql.must_equal 'SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tag.blah1, tag.blah2'
|
2111
2130
|
end
|
2112
2131
|
|
2113
2132
|
it "should only qualify unqualified symbols, identifiers, or ordered versions in association's :order" do
|
2133
|
+
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[Sequel.identifier(:blah__id), Sequel.identifier(:blah__id).desc, Sequel.desc(Sequel[:blah][:id]), Sequel[:blah][:id], :album_id, Sequel.desc(:album_id), 1, Sequel.lit('RANDOM()'), Sequel.qualify(:b, :a)]
|
2134
|
+
@c1.order(Sequel[:artists][:blah2], Sequel[:artists][:blah3]).eager_graph(:tag).sql.must_equal 'SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tag.blah__id, tag.blah__id DESC, blah.id DESC, blah.id, tag.album_id, tag.album_id DESC, 1, RANDOM(), b.a'
|
2135
|
+
end
|
2136
|
+
|
2137
|
+
with_symbol_splitting "should not qualify qualified symbols in association's :order" do
|
2114
2138
|
@c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], {:table=>:albums, :left=>:id, :right=>:id}, [:albums_tags, :album_id, :tag_id]], :order=>[Sequel.identifier(:blah__id), Sequel.identifier(:blah__id).desc, Sequel.desc(:blah__id), :blah__id, :album_id, Sequel.desc(:album_id), 1, Sequel.lit('RANDOM()'), Sequel.qualify(:b, :a)]
|
2115
2139
|
@c1.order(:artists__blah2, :artists__blah3).eager_graph(:tag).sql.must_equal 'SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) ORDER BY artists.blah2, artists.blah3, tag.blah__id, tag.blah__id DESC, blah.id DESC, blah.id, tag.album_id, tag.album_id DESC, 1, RANDOM(), b.a'
|
2116
2140
|
end
|
@@ -652,8 +652,12 @@ describe "NestedAttributes plugin" do
|
|
652
652
|
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
653
653
|
"INSERT INTO tags (name) VALUES ('T3')",
|
654
654
|
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
655
|
-
|
656
|
-
|
655
|
+
al.set(:tags_attributes=>[{:id=>30, :name=>'T3', :number=>3}])
|
656
|
+
al.tags.first.name.must_equal 'T3'
|
657
|
+
al.tags.first.number.must_equal 10
|
658
|
+
al.set(:tags_attributes=>[{:name=>'T4', :number=>3}])
|
659
|
+
al.tags.last.name.must_equal 'T4'
|
660
|
+
al.tags.last.number.must_be_nil
|
657
661
|
end
|
658
662
|
|
659
663
|
it "should accept a proc for the :fields option that accepts the associated object and returns an array of fields" do
|
@@ -670,8 +674,12 @@ describe "NestedAttributes plugin" do
|
|
670
674
|
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
671
675
|
"INSERT INTO tags (name) VALUES ('T3')",
|
672
676
|
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
673
|
-
|
674
|
-
|
677
|
+
al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
|
678
|
+
al.tags.first.name.must_equal 'T3'
|
679
|
+
al.tags.first.number.must_equal 10
|
680
|
+
al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
|
681
|
+
al.tags.last.name.must_equal 'T4'
|
682
|
+
al.tags.last.number.must_be_nil
|
675
683
|
end
|
676
684
|
|
677
685
|
it "should allow per-call options via the set_nested_attributes method" do
|
@@ -688,8 +696,12 @@ describe "NestedAttributes plugin" do
|
|
688
696
|
"UPDATE tags SET name = 'T2' WHERE (id = 30)",
|
689
697
|
"INSERT INTO tags (name) VALUES ('T3')",
|
690
698
|
["INSERT INTO at (album_id, tag_id) VALUES (10, 1)", "INSERT INTO at (tag_id, album_id) VALUES (1, 10)"])
|
691
|
-
|
692
|
-
|
699
|
+
al.set_nested_attributes(:tags, [{:id=>30, :name=>'T3', :number=>3}], :fields=>[:name])
|
700
|
+
al.tags.first.name.must_equal 'T3'
|
701
|
+
al.tags.first.number.must_equal 10
|
702
|
+
al.set_nested_attributes(:tags, [{:name=>'T4', :number=>3}], :fields=>[:name])
|
703
|
+
al.tags.last.name.must_equal 'T4'
|
704
|
+
al.tags.last.number.must_be_nil
|
693
705
|
end
|
694
706
|
|
695
707
|
it "should have set_nested_attributes method raise error if called with a bad association" do
|
@@ -38,7 +38,7 @@ describe "no_auto_literal_strings extension" do
|
|
38
38
|
"SELECT * FROM t WHERE (a) LIMIT 1"]
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
deprecated "should handle literal strings in arrays in filter methods" do
|
42
42
|
@ds.where([Sequel.lit("a")]).sql.must_equal 'SELECT * FROM t WHERE (a)'
|
43
43
|
end
|
44
44
|
|
@@ -33,6 +33,11 @@ describe "pg_enum extension" do
|
|
33
33
|
it "should support #create_enum method for adding a new enum" do
|
34
34
|
@db.create_enum(:foo, [:a, :b, :c])
|
35
35
|
@db.sqls.first.must_equal "CREATE TYPE foo AS ENUM ('a', 'b', 'c')"
|
36
|
+
@db.create_enum(Sequel[:sch][:foo], %w'a b c')
|
37
|
+
@db.sqls.first.must_equal "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
|
38
|
+
end
|
39
|
+
|
40
|
+
with_symbol_splitting "should support #create_enum method for adding a new enum with qualified symbol" do
|
36
41
|
@db.create_enum(:sch__foo, %w'a b c')
|
37
42
|
@db.sqls.first.must_equal "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
|
38
43
|
end
|
@@ -40,12 +45,17 @@ describe "pg_enum extension" do
|
|
40
45
|
it "should support #drop_enum method for dropping an enum" do
|
41
46
|
@db.drop_enum(:foo)
|
42
47
|
@db.sqls.first.must_equal "DROP TYPE foo"
|
43
|
-
@db.drop_enum(:
|
48
|
+
@db.drop_enum(Sequel[:sch][:foo], :if_exists=>true)
|
44
49
|
@db.sqls.first.must_equal "DROP TYPE IF EXISTS sch.foo"
|
45
50
|
@db.drop_enum('foo', :cascade=>true)
|
46
51
|
@db.sqls.first.must_equal "DROP TYPE foo CASCADE"
|
47
52
|
end
|
48
53
|
|
54
|
+
with_symbol_splitting "should support #drop_enum method for dropping an enum with a splittable symbol" do
|
55
|
+
@db.drop_enum(:sch__foo, :if_exists=>true)
|
56
|
+
@db.sqls.first.must_equal "DROP TYPE IF EXISTS sch.foo"
|
57
|
+
end
|
58
|
+
|
49
59
|
it "should support #add_enum_value method for adding value to an existing enum" do
|
50
60
|
@db.add_enum_value(:foo, :a)
|
51
61
|
@db.sqls.first.must_equal "ALTER TYPE foo ADD VALUE 'a'"
|
@@ -57,6 +67,11 @@ describe "pg_enum extension" do
|
|
57
67
|
end
|
58
68
|
|
59
69
|
it "should support :after option for #add_enum_value method for adding value after an existing enum value" do
|
70
|
+
@db.add_enum_value(Sequel[:sch][:foo], :a, :after=>:b)
|
71
|
+
@db.sqls.first.must_equal "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
|
72
|
+
end
|
73
|
+
|
74
|
+
with_symbol_splitting "should support :after option for #add_enum_value method for adding value after an existing enum value with splittable symbol" do
|
60
75
|
@db.add_enum_value(:sch__foo, :a, :after=>:b)
|
61
76
|
@db.sqls.first.must_equal "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
|
62
77
|
end
|
@@ -2,6 +2,10 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'active_support/duration'
|
5
|
+
begin
|
6
|
+
require 'active_support/gem_version'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
5
9
|
rescue LoadError => exc
|
6
10
|
skip_warn "pg_interval plugin: can't load active_support/duration (#{exc.class}: #{exc})"
|
7
11
|
else
|
@@ -21,8 +25,13 @@ describe "pg_interval extension" do
|
|
21
25
|
end
|
22
26
|
|
23
27
|
it "should literalize ActiveSupport::Duration instances with repeated parts correctly" do
|
24
|
-
|
25
|
-
|
28
|
+
if defined?(ActiveSupport::VERSION::STRING) && ActiveSupport::VERSION::STRING >= '5.1'
|
29
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1]])).must_equal "'1 seconds '::interval"
|
30
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1], [:days, 1], [:days, 4]])).must_equal "'4 days 1 seconds '::interval"
|
31
|
+
else
|
32
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1]])).must_equal "'3 seconds '::interval"
|
33
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1], [:days, 1], [:days, 4]])).must_equal "'5 days 3 seconds '::interval"
|
34
|
+
end
|
26
35
|
end
|
27
36
|
|
28
37
|
it "should not affect literalization of custom objects" do
|
@@ -12,6 +12,11 @@ describe "pg_loose_count extension" do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should support schema qualified tables" do
|
15
|
+
@db.loose_count(Sequel[:a][:b]).must_equal 1
|
16
|
+
@db.sqls.must_equal ["SELECT CAST(reltuples AS integer) AS v FROM pg_class WHERE (oid = CAST(CAST('a.b' AS regclass) AS oid)) LIMIT 1"]
|
17
|
+
end
|
18
|
+
|
19
|
+
with_symbol_splitting "should support schema qualified table symbols" do
|
15
20
|
@db.loose_count(:a__b).must_equal 1
|
16
21
|
@db.sqls.must_equal ["SELECT CAST(reltuples AS integer) AS v FROM pg_class WHERE (oid = CAST(CAST('a.b' AS regclass) AS oid)) LIMIT 1"]
|
17
22
|
end
|
@@ -207,6 +207,31 @@ describe "pg_row extension" do
|
|
207
207
|
end
|
208
208
|
|
209
209
|
it "should allow registering row type parsers for schema qualify types" do
|
210
|
+
@db.conversion_procs[4] = p4 = proc{|s| s.to_i}
|
211
|
+
@db.conversion_procs[5] = p5 = proc{|s| s * 2}
|
212
|
+
@db.fetch = [[{:oid=>1, :typrelid=>2, :typarray=>3}], [{:attname=>'bar', :atttypid=>4}, {:attname=>'baz', :atttypid=>5}]]
|
213
|
+
@db.register_row_type(Sequel[:foo][:bar])
|
214
|
+
@db.sqls.must_equal ["SELECT pg_type.oid, typrelid, typarray FROM pg_type INNER JOIN pg_namespace ON ((pg_namespace.oid = pg_type.typnamespace) AND (pg_namespace.nspname = 'foo')) WHERE ((typtype = 'c') AND (typname = 'bar')) LIMIT 1",
|
215
|
+
"SELECT attname, (CASE pg_type.typbasetype WHEN 0 THEN atttypid ELSE pg_type.typbasetype END) AS atttypid FROM pg_attribute INNER JOIN pg_type ON (pg_type.oid = pg_attribute.atttypid) WHERE ((attrelid = 2) AND (attnum > 0) AND NOT attisdropped) ORDER BY attnum"]
|
216
|
+
p1 = @db.conversion_procs[1]
|
217
|
+
p1.columns.must_equal [:bar, :baz]
|
218
|
+
p1.column_oids.must_equal [4, 5]
|
219
|
+
p1.column_converters.must_equal [p4, p5]
|
220
|
+
p1.oid.must_equal 1
|
221
|
+
|
222
|
+
c = p1.converter
|
223
|
+
c.superclass.must_equal @m::HashRow
|
224
|
+
c.columns.must_equal [:bar, :baz]
|
225
|
+
c.db_type.must_equal Sequel[:foo][:bar]
|
226
|
+
p1.typecaster.must_equal c
|
227
|
+
|
228
|
+
p1.call('(1,b)').must_equal(:bar=>1, :baz=>'bb')
|
229
|
+
@db.typecast_value(:pg_row_foo__bar, %w'1 b').must_equal(:bar=>'1', :baz=>'b')
|
230
|
+
@db.typecast_value(:pg_row_foo__bar, :bar=>'1', :baz=>'b').must_equal(:bar=>'1', :baz=>'b')
|
231
|
+
@db.literal(p1.call('(1,b)')).must_equal "ROW(1, 'bb')::foo.bar"
|
232
|
+
end
|
233
|
+
|
234
|
+
with_symbol_splitting "should allow registering row type parsers for schema qualify type symbols" do
|
210
235
|
@db.conversion_procs[4] = p4 = proc{|s| s.to_i}
|
211
236
|
@db.conversion_procs[5] = p5 = proc{|s| s * 2}
|
212
237
|
@db.fetch = [[{:oid=>1, :typrelid=>2, :typarray=>3}], [{:attname=>'bar', :atttypid=>4}, {:attname=>'baz', :atttypid=>5}]]
|