sequel 4.47.0 → 4.48.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 +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
|
@@ -2,7 +2,9 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "Dataset#to_csv" do
|
|
4
4
|
before do
|
|
5
|
-
|
|
5
|
+
deprecated do
|
|
6
|
+
@ds = Sequel.mock(:fetch=>[{:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9}])[:items].columns(:a, :b, :c).extension(:sequel_3_dataset_methods)
|
|
7
|
+
end
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
it "should format a CSV representation of the records" do
|
|
@@ -15,7 +17,7 @@ describe "Dataset#to_csv" do
|
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
describe "Dataset#[]=" do
|
|
18
|
-
|
|
20
|
+
deprecated "should perform an update on the specified filter" do
|
|
19
21
|
db = Sequel.mock
|
|
20
22
|
ds = db[:items].extension(:sequel_3_dataset_methods)
|
|
21
23
|
ds[:a => 1] = {:x => 3}
|
|
@@ -26,7 +28,9 @@ end
|
|
|
26
28
|
describe "Dataset#insert_multiple" do
|
|
27
29
|
before do
|
|
28
30
|
@db = Sequel.mock(:autoid=>2)
|
|
29
|
-
|
|
31
|
+
deprecated do
|
|
32
|
+
@ds = @db[:items].extension(:sequel_3_dataset_methods)
|
|
33
|
+
end
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
it "should insert all items in the supplied array" do
|
|
@@ -92,7 +96,7 @@ unless Sequel.mock.dataset.frozen?
|
|
|
92
96
|
end
|
|
93
97
|
|
|
94
98
|
describe "Dataset#set" do
|
|
95
|
-
|
|
99
|
+
deprecated "should act as alias to #update" do
|
|
96
100
|
db = Sequel.mock
|
|
97
101
|
ds = db[:items].extension(:sequel_3_dataset_methods)
|
|
98
102
|
ds.set({:x => 3})
|
|
@@ -101,13 +105,13 @@ describe "Dataset#set" do
|
|
|
101
105
|
end
|
|
102
106
|
|
|
103
107
|
describe "Sequel::Dataset#qualify_to_first_source" do
|
|
104
|
-
|
|
108
|
+
deprecated "should qualify to the first source" do
|
|
105
109
|
Sequel.mock.dataset.extension(:sequel_3_dataset_methods).from(:t).filter{a<b}.qualify_to_first_source.sql.must_equal 'SELECT t.* FROM t WHERE (t.a < t.b)'
|
|
106
110
|
end
|
|
107
111
|
end
|
|
108
112
|
|
|
109
113
|
describe "Sequel::Dataset#qualify_to" do
|
|
110
|
-
|
|
114
|
+
deprecated "should qualify to the given table" do
|
|
111
115
|
Sequel.mock.dataset.extension(:sequel_3_dataset_methods).from(:t).filter{a<b}.qualify_to(:e).sql.must_equal 'SELECT e.* FROM t WHERE (e.a < e.b)'
|
|
112
116
|
end
|
|
113
117
|
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Dataset#and" do
|
|
4
|
+
before do
|
|
5
|
+
@dataset = Sequel.mock.dataset.from(:test).extension(:sequel_4_dataset_methods)
|
|
6
|
+
@d1 = @dataset.where(:x => 1)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should add a WHERE filter if none exists" do
|
|
10
|
+
@dataset.and(:a => 1).sql.must_equal 'SELECT * FROM test WHERE (a = 1)'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should add an expression to the where clause" do
|
|
14
|
+
@d1.and(:y => 2).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y = 2))'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should accept placeholder literal string filters" do
|
|
18
|
+
@d1.and(Sequel.lit('y > ?', 2)).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should accept expression filters" do
|
|
22
|
+
@d1.and(Sequel.expr(:yy) > 3).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should accept string filters with placeholders" do
|
|
26
|
+
@d1.extension(:auto_literal_strings).and('y > ?', 2).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should accept blocks passed to filter" do
|
|
30
|
+
@d1.and{yy > 3}.sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should correctly add parens to give predictable results" do
|
|
34
|
+
@d1.or(:y => 2).and(:z => 3).sql.must_equal 'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
|
35
|
+
@d1.and(:y => 2).or(:z => 3).sql.must_equal 'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "Dataset#exclude_where" do
|
|
40
|
+
before do
|
|
41
|
+
@dataset = Sequel.mock.dataset.from(:test).extension(:sequel_4_dataset_methods)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should correctly negate the expression and add it to the where clause" do
|
|
45
|
+
@dataset.exclude_where(:region=>'Asia').sql.must_equal "SELECT * FROM test WHERE (region != 'Asia')"
|
|
46
|
+
@dataset.exclude_where(:region=>'Asia').exclude_where(:region=>'NA').sql.must_equal "SELECT * FROM test WHERE ((region != 'Asia') AND (region != 'NA'))"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should affect the where clause even if having clause is already used" do
|
|
50
|
+
@dataset.group_and_count(:name).having{count > 2}.exclude_where(:region=>'Asia').sql.
|
|
51
|
+
must_equal "SELECT name, count(*) AS count FROM test WHERE (region != 'Asia') GROUP BY name HAVING (count > 2)"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "Dataset#interval" do
|
|
56
|
+
before do
|
|
57
|
+
@db = Sequel.mock(:fetch=>{:v => 1234}).extension(:sequel_4_dataset_methods)
|
|
58
|
+
@ds = @db[:test].freeze
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should generate the correct SQL statement" do
|
|
62
|
+
5.times do
|
|
63
|
+
@ds.interval(:stamp)
|
|
64
|
+
@db.sqls.must_equal ["SELECT (max(stamp) - min(stamp)) AS interval FROM test LIMIT 1"]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
@ds.filter(Sequel.expr(:price) > 100).interval(:stamp)
|
|
68
|
+
@db.sqls.must_equal ["SELECT (max(stamp) - min(stamp)) AS interval FROM test WHERE (price > 100) LIMIT 1"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should use a subselect for the same conditions as count" do
|
|
72
|
+
ds = @ds.order(:stamp).limit(5)
|
|
73
|
+
5.times do
|
|
74
|
+
ds.interval(:stamp).must_equal 1234
|
|
75
|
+
@db.sqls.must_equal ['SELECT (max(stamp) - min(stamp)) AS interval FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should accept virtual row blocks" do
|
|
80
|
+
5.times do
|
|
81
|
+
@ds.interval{a(b)}
|
|
82
|
+
@db.sqls.must_equal ["SELECT (max(a(b)) - min(a(b))) AS interval FROM test LIMIT 1"]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "Dataset#range" do
|
|
88
|
+
before do
|
|
89
|
+
@db = Sequel.mock(:fetch=>{:v1 => 1, :v2 => 10}).extension(:sequel_4_dataset_methods)
|
|
90
|
+
@ds = @db[:test].freeze
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should generate a correct SQL statement" do
|
|
94
|
+
5.times do
|
|
95
|
+
@ds.range(:stamp)
|
|
96
|
+
@db.sqls.must_equal ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test LIMIT 1"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@ds.filter(Sequel.expr(:price) > 100).range(:stamp)
|
|
100
|
+
@db.sqls.must_equal ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test WHERE (price > 100) LIMIT 1"]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should return a range object" do
|
|
104
|
+
5.times do
|
|
105
|
+
@ds.range(:tryme).must_equal(1..10)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "should use a subselect for the same conditions as count" do
|
|
110
|
+
@ds.order(:stamp).limit(5).range(:stamp).must_equal(1..10)
|
|
111
|
+
@db.sqls.must_equal ['SELECT min(stamp) AS v1, max(stamp) AS v2 FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should accept virtual row blocks" do
|
|
115
|
+
5.times do
|
|
116
|
+
@ds.range{a(b)}
|
|
117
|
+
@db.sqls.must_equal ["SELECT min(a(b)) AS v1, max(a(b)) AS v2 FROM test LIMIT 1"]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
@@ -90,7 +90,7 @@ describe Sequel::Model, "single table inheritance plugin" do
|
|
|
90
90
|
|
|
91
91
|
it "should fallback to the main class if the sti_key field is empty or nil without calling constantize" do
|
|
92
92
|
called = false
|
|
93
|
-
StiTest.
|
|
93
|
+
def StiTest.constantize(s)
|
|
94
94
|
called = true
|
|
95
95
|
Object
|
|
96
96
|
end
|
|
@@ -28,13 +28,19 @@ rescue LoadError
|
|
|
28
28
|
nil
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
Sequel.extension :meta_def
|
|
32
31
|
Sequel.extension :core_refinements if RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby'
|
|
33
32
|
|
|
34
33
|
def skip_warn(s)
|
|
35
34
|
warn "Skipping test of #{s}" if ENV["SKIPPED_TEST_WARN"]
|
|
36
35
|
end
|
|
37
36
|
|
|
37
|
+
class Minitest::HooksSpec
|
|
38
|
+
# SEQUEL5: Replace with define_singleton_method
|
|
39
|
+
def meta_def(obj, name, &block)
|
|
40
|
+
(class << obj; self end).send(:define_method, name, &block)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
# SEQUEL5: Remove
|
|
39
45
|
output = Sequel::Deprecation.output
|
|
40
46
|
Sequel::Deprecation.output = nil
|
|
@@ -113,35 +113,58 @@ describe "Sequel::Plugins::StaticCache" do
|
|
|
113
113
|
@c.all.must_equal [@c1, @c2]
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
-
it "should have to_hash without arguments run without a query" do
|
|
116
|
+
it "should have as_hash/to_hash without arguments run without a query" do
|
|
117
117
|
a = @c.to_hash
|
|
118
118
|
a.must_equal(1=>@c1, 2=>@c2)
|
|
119
119
|
a[1].must_equal @c1
|
|
120
120
|
a[2].must_equal @c2
|
|
121
|
+
|
|
122
|
+
a = @c.as_hash
|
|
123
|
+
a.must_equal(1=>@c1, 2=>@c2)
|
|
124
|
+
a[1].must_equal @c1
|
|
125
|
+
a[2].must_equal @c2
|
|
126
|
+
@db.sqls.must_equal []
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should have as_hash handle :hash option" do
|
|
130
|
+
h = {}
|
|
131
|
+
a = @c.as_hash(nil, nil, :hash=>h)
|
|
132
|
+
a.must_be_same_as h
|
|
133
|
+
a.must_equal(1=>@c1, 2=>@c2)
|
|
134
|
+
a[1].must_equal @c1
|
|
135
|
+
a[2].must_equal @c2
|
|
136
|
+
|
|
137
|
+
h = {}
|
|
138
|
+
a = @c.as_hash(:id, nil, :hash=>h)
|
|
139
|
+
a.must_be_same_as h
|
|
140
|
+
a.must_equal(1=>@c1, 2=>@c2)
|
|
141
|
+
a[1].must_equal @c1
|
|
142
|
+
a[2].must_equal @c2
|
|
143
|
+
|
|
121
144
|
@db.sqls.must_equal []
|
|
122
145
|
end
|
|
123
146
|
|
|
124
|
-
it "should have
|
|
125
|
-
a = @c.
|
|
147
|
+
it "should have as_hash with arguments return results without a query" do
|
|
148
|
+
a = @c.as_hash(:id)
|
|
126
149
|
a.must_equal(1=>@c1, 2=>@c2)
|
|
127
150
|
a[1].must_equal @c1
|
|
128
151
|
a[2].must_equal @c2
|
|
129
152
|
|
|
130
|
-
a = @c.
|
|
153
|
+
a = @c.as_hash([:id])
|
|
131
154
|
a.must_equal([1]=>@c1, [2]=>@c2)
|
|
132
155
|
a[[1]].must_equal @c1
|
|
133
156
|
a[[2]].must_equal @c2
|
|
134
157
|
|
|
135
|
-
@c.
|
|
136
|
-
@c.
|
|
137
|
-
@c.
|
|
138
|
-
@c.
|
|
158
|
+
@c.as_hash(:id, :id).must_equal(1=>1, 2=>2)
|
|
159
|
+
@c.as_hash([:id], :id).must_equal([1]=>1, [2]=>2)
|
|
160
|
+
@c.as_hash(:id, [:id]).must_equal(1=>[1], 2=>[2])
|
|
161
|
+
@c.as_hash([:id], [:id]).must_equal([1]=>[1], [2]=>[2])
|
|
139
162
|
|
|
140
163
|
@db.sqls.must_equal []
|
|
141
164
|
end
|
|
142
165
|
|
|
143
|
-
it "should have
|
|
144
|
-
@c.
|
|
166
|
+
it "should have as_hash not return a frozen object" do
|
|
167
|
+
@c.as_hash.frozen?.must_equal false
|
|
145
168
|
end
|
|
146
169
|
|
|
147
170
|
it "should have to_hash_groups without arguments return the cached objects without a query" do
|
|
@@ -163,10 +186,38 @@ describe "Sequel::Plugins::StaticCache" do
|
|
|
163
186
|
@db.sqls.must_equal []
|
|
164
187
|
end
|
|
165
188
|
|
|
189
|
+
it "should have to_hash_groups handle :hash option" do
|
|
190
|
+
h = {}
|
|
191
|
+
a = @c.to_hash_groups(:id, nil, :hash=>h)
|
|
192
|
+
a.must_be_same_as h
|
|
193
|
+
a.must_equal(1=>[@c1], 2=>[@c2])
|
|
194
|
+
a[1].first.must_equal @c1
|
|
195
|
+
a[2].first.must_equal @c2
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should have as_hash_groups without arguments return the cached objects without a query" do
|
|
199
|
+
a = @c.to_hash_groups(:id)
|
|
200
|
+
a.must_equal(1=>[@c1], 2=>[@c2])
|
|
201
|
+
a[1].first.must_equal @c1
|
|
202
|
+
a[2].first.must_equal @c2
|
|
203
|
+
|
|
204
|
+
a = @c.to_hash_groups([:id])
|
|
205
|
+
a.must_equal([1]=>[@c1], [2]=>[@c2])
|
|
206
|
+
a[[1]].first.must_equal @c1
|
|
207
|
+
a[[2]].first.must_equal @c2
|
|
208
|
+
|
|
209
|
+
@c.to_hash_groups(:id, :id).must_equal(1=>[1], 2=>[2])
|
|
210
|
+
@c.to_hash_groups([:id], :id).must_equal([1]=>[1], [2]=>[2])
|
|
211
|
+
@c.to_hash_groups(:id, [:id]).must_equal(1=>[[1]], 2=>[[2]])
|
|
212
|
+
@c.to_hash_groups([:id], [:id]).must_equal([1]=>[[1]], [2]=>[[2]])
|
|
213
|
+
|
|
214
|
+
@db.sqls.must_equal []
|
|
215
|
+
end
|
|
216
|
+
|
|
166
217
|
it "subclasses should work correctly" do
|
|
167
218
|
c = Class.new(@c)
|
|
168
219
|
c.all.must_equal [c.load(:id=>1), c.load(:id=>2)]
|
|
169
|
-
c.
|
|
220
|
+
c.as_hash.must_equal(1=>c.load(:id=>1), 2=>c.load(:id=>2))
|
|
170
221
|
@db.sqls.must_equal ['SELECT * FROM t']
|
|
171
222
|
end
|
|
172
223
|
|
|
@@ -174,8 +225,8 @@ describe "Sequel::Plugins::StaticCache" do
|
|
|
174
225
|
ds = @c.dataset.from(:t2).columns(:id).with_fetch(:id=>3)
|
|
175
226
|
@c.dataset = ds
|
|
176
227
|
@c.all.must_equal [@c.load(:id=>3)]
|
|
177
|
-
@c.
|
|
178
|
-
@c.
|
|
228
|
+
@c.as_hash.must_equal(3=>@c.load(:id=>3))
|
|
229
|
+
@c.as_hash[3].must_equal @c.all.first
|
|
179
230
|
@db.sqls.must_equal ['SELECT * FROM t2']
|
|
180
231
|
end
|
|
181
232
|
end
|
|
@@ -238,18 +289,18 @@ describe "Sequel::Plugins::StaticCache" do
|
|
|
238
289
|
a.last.must_be_same_as(@c2)
|
|
239
290
|
end
|
|
240
291
|
|
|
241
|
-
it "should have
|
|
242
|
-
a = @c.
|
|
292
|
+
it "should have as_hash without arguments use cached instances" do
|
|
293
|
+
a = @c.as_hash
|
|
243
294
|
a[1].must_be_same_as(@c1)
|
|
244
295
|
a[2].must_be_same_as(@c2)
|
|
245
296
|
end
|
|
246
297
|
|
|
247
|
-
it "should have
|
|
248
|
-
a = @c.
|
|
298
|
+
it "should have as_hash with arguments return cached instances" do
|
|
299
|
+
a = @c.as_hash(:id)
|
|
249
300
|
a[1].must_be_same_as(@c1)
|
|
250
301
|
a[2].must_be_same_as(@c2)
|
|
251
302
|
|
|
252
|
-
a = @c.
|
|
303
|
+
a = @c.as_hash([:id])
|
|
253
304
|
a[[1]].must_be_same_as(@c1)
|
|
254
305
|
a[[2]].must_be_same_as(@c2)
|
|
255
306
|
end
|
|
@@ -313,16 +364,16 @@ describe "Sequel::Plugins::StaticCache" do
|
|
|
313
364
|
@c.map.all?{|o| !o.frozen?}.must_equal true
|
|
314
365
|
end
|
|
315
366
|
|
|
316
|
-
it "none of values in the hash returned by
|
|
317
|
-
@c.
|
|
367
|
+
it "none of values in the hash returned by as_hash without an argument should be frozen" do
|
|
368
|
+
@c.as_hash.values.all?{|o| !o.frozen?}.must_equal true
|
|
318
369
|
end
|
|
319
370
|
|
|
320
|
-
it "none of values in the hash returned by
|
|
321
|
-
@c.
|
|
371
|
+
it "none of values in the hash returned by as_hash with a single argument should be frozen" do
|
|
372
|
+
@c.as_hash(:id).values.all?{|o| !o.frozen?}.must_equal true
|
|
322
373
|
end
|
|
323
374
|
|
|
324
|
-
it "none of values in the hash returned by
|
|
325
|
-
@c.
|
|
375
|
+
it "none of values in the hash returned by as_hash with a single array argument should be frozen" do
|
|
376
|
+
@c.as_hash([:id, :id]).values.all?{|o| !o.frozen?}.must_equal true
|
|
326
377
|
end
|
|
327
378
|
|
|
328
379
|
it "none of values in the hash returned by to_hash_groups with a single argument should be frozen" do
|
|
@@ -48,7 +48,7 @@ describe "string_agg extension" do
|
|
|
48
48
|
it "should correctly literalize on MySQL, H2, HSQLDB" do
|
|
49
49
|
[:mysql, :h2, :hsqldb].each do |type|
|
|
50
50
|
db = dbf.call(type)
|
|
51
|
-
|
|
51
|
+
meta_def(db, :database_type){type}
|
|
52
52
|
ds = db.dataset.with_quote_identifiers(false).with_extend{def input_identifier(v) v.to_s end}
|
|
53
53
|
ds.literal(@sa1).upcase.must_equal "GROUP_CONCAT(C SEPARATOR ',')"
|
|
54
54
|
ds.literal(@sa2).upcase.must_equal "GROUP_CONCAT(C SEPARATOR '-')"
|
|
@@ -67,6 +67,15 @@ describe "Touch plugin" do
|
|
|
67
67
|
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
it "should clear associations after touching them :associations option" do
|
|
71
|
+
@Artist.plugin :touch, :associations=>:albums
|
|
72
|
+
@a.associations[:albums] = [@Album.call(:id=>1)]
|
|
73
|
+
@a.touch
|
|
74
|
+
@a.associations[:albums].must_be_nil
|
|
75
|
+
DB.sqls.must_equal ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
76
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
77
|
+
end
|
|
78
|
+
|
|
70
79
|
it "should be able to give an array to the :associations option specifying multiple associations" do
|
|
71
80
|
@Album.plugin :touch, :associations=>[:artist, :followup_albums]
|
|
72
81
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
@@ -18,6 +18,12 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
|
18
18
|
@m.wont_be :valid?
|
|
19
19
|
@m.value = '1_1'
|
|
20
20
|
@m.must_be :valid?
|
|
21
|
+
o = String.new
|
|
22
|
+
class << o
|
|
23
|
+
undef_method :blank?
|
|
24
|
+
end
|
|
25
|
+
@m.value = o
|
|
26
|
+
@m.must_be :valid?
|
|
21
27
|
o = Object.new
|
|
22
28
|
@m.value = o
|
|
23
29
|
@m.wont_be :valid?
|
|
@@ -248,17 +254,17 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
|
248
254
|
@m.must_be :valid?
|
|
249
255
|
@m.value = '123'
|
|
250
256
|
@m.must_be :valid?
|
|
251
|
-
@m.
|
|
257
|
+
def @m.db_schema; {:value=>{:type=>:integer}} end
|
|
252
258
|
@m.wont_be :valid?
|
|
253
259
|
@m.errors.full_messages.must_equal ['value is not a valid integer']
|
|
254
260
|
|
|
255
261
|
@c.set_validations{validates_schema_types(:value)}
|
|
256
|
-
@m.
|
|
262
|
+
def @m.db_schema; {:value=>{:type=>:integer}} end
|
|
257
263
|
@m.wont_be :valid?
|
|
258
264
|
@m.errors.full_messages.must_equal ['value is not a valid integer']
|
|
259
265
|
|
|
260
266
|
@c.set_validations{validates_schema_types(:value, :message=>'is bad')}
|
|
261
|
-
@m.
|
|
267
|
+
def @m.db_schema; {:value=>{:type=>:integer}} end
|
|
262
268
|
@m.wont_be :valid?
|
|
263
269
|
@m.errors.full_messages.must_equal ['value is bad']
|
|
264
270
|
end
|
|
@@ -64,6 +64,19 @@ describe Sequel::Model, "#(set|update)_(all|only)" do
|
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
describe Sequel::Model, "#(set|update)_(all|only) without set_allowed_columns" do
|
|
68
|
+
before do
|
|
69
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
70
|
+
set_primary_key :id
|
|
71
|
+
columns :x, :y, :z, :id
|
|
72
|
+
end
|
|
73
|
+
@c.plugin :whitelist_security
|
|
74
|
+
@c.strict_param_setting = false
|
|
75
|
+
@o1 = @c.new
|
|
76
|
+
DB.reset
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
67
80
|
describe Sequel::Model, ".strict_param_setting" do
|
|
68
81
|
before do
|
|
69
82
|
@c = Class.new(Sequel::Model(:blahblah)) do
|
|
@@ -105,6 +118,19 @@ describe Sequel::Model, ".allowed_columns " do
|
|
|
105
118
|
@c.allowed_columns.must_equal [:x, :y]
|
|
106
119
|
end
|
|
107
120
|
|
|
121
|
+
it "should not change behavior if allowed_columns are not set" do
|
|
122
|
+
i = @c.new(:x => 1, :y => 2, :z => 3)
|
|
123
|
+
i.values.must_equal(:x => 1, :y => 2, :z => 3)
|
|
124
|
+
i.set(:x => 4, :y => 5, :z => 6)
|
|
125
|
+
i.values.must_equal(:x => 4, :y => 5, :z => 6)
|
|
126
|
+
|
|
127
|
+
@c.dataset = @c.dataset.with_fetch(:x => 7)
|
|
128
|
+
i = @c.new
|
|
129
|
+
i.update(:x => 7)
|
|
130
|
+
i.values.must_equal(:x => 7)
|
|
131
|
+
DB.sqls.must_equal ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE id = 10"]
|
|
132
|
+
end
|
|
133
|
+
|
|
108
134
|
it "should only set allowed columns by default" do
|
|
109
135
|
@c.set_allowed_columns :x, :y
|
|
110
136
|
i = @c.new(:x => 1, :y => 2, :z => 3)
|