sequel 3.33.0 → 3.34.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.
- data/CHANGELOG +140 -0
- data/Rakefile +7 -0
- data/bin/sequel +22 -2
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/mass_assignment.rdoc +3 -1
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +23 -3
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/schema_modification.rdoc +18 -2
- data/doc/virtual_rows.rdoc +49 -0
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/ibmdb.rb +9 -4
- data/lib/sequel/adapters/jdbc.rb +9 -4
- data/lib/sequel/adapters/jdbc/h2.rb +8 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
- data/lib/sequel/adapters/mock.rb +24 -3
- data/lib/sequel/adapters/mysql.rb +29 -50
- data/lib/sequel/adapters/mysql2.rb +13 -28
- data/lib/sequel/adapters/oracle.rb +8 -2
- data/lib/sequel/adapters/postgres.rb +115 -20
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -3
- data/lib/sequel/adapters/shared/mysql.rb +59 -11
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +127 -30
- data/lib/sequel/adapters/shared/sqlite.rb +55 -38
- data/lib/sequel/adapters/sqlite.rb +9 -3
- data/lib/sequel/adapters/swift.rb +2 -2
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +10 -0
- data/lib/sequel/ast_transformer.rb +4 -0
- data/lib/sequel/connection_pool.rb +8 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +14 -0
- data/lib/sequel/core.rb +24 -3
- data/lib/sequel/database/connecting.rb +24 -14
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +16 -25
- data/lib/sequel/database/query.rb +20 -2
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +120 -23
- data/lib/sequel/dataset/actions.rb +91 -18
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -2
- data/lib/sequel/dataset/sql.rb +68 -51
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +227 -31
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model.rb +11 -2
- data/lib/sequel/model/associations.rb +35 -7
- data/lib/sequel/model/base.rb +159 -36
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +11 -3
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +4 -3
- data/lib/sequel/plugins/prepared_statements.rb +3 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +417 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +12 -15
- data/spec/adapters/mysql_spec.rb +81 -23
- data/spec/adapters/postgres_spec.rb +444 -77
- data/spec/adapters/spec_helper.rb +2 -0
- data/spec/adapters/sqlite_spec.rb +8 -8
- data/spec/core/connection_pool_spec.rb +85 -0
- data/spec/core/database_spec.rb +29 -5
- data/spec/core/dataset_spec.rb +171 -3
- data/spec/core/expression_filters_spec.rb +364 -0
- data/spec/core/mock_adapter_spec.rb +17 -3
- data/spec/core/schema_spec.rb +133 -0
- data/spec/extensions/association_dependencies_spec.rb +13 -13
- data/spec/extensions/caching_spec.rb +26 -3
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +5 -2
- data/spec/extensions/identity_map_spec.rb +17 -0
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +2 -2
- data/spec/extensions/list_spec.rb +4 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +6 -2
- data/spec/extensions/nested_attributes_spec.rb +20 -0
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +2 -2
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_spec.rb +4 -0
- data/spec/extensions/pretty_table_spec.rb +6 -0
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +231 -11
- data/spec/extensions/schema_spec.rb +14 -2
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/sharding_spec.rb +6 -6
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +2 -1
- data/spec/extensions/sql_expr_spec.rb +28 -19
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +9 -1
- data/spec/integration/associations_test.rb +6 -6
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +89 -26
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +85 -22
- data/spec/integration/prepared_statement_test.rb +28 -8
- data/spec/integration/schema_test.rb +78 -7
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +4 -6
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/associations_spec.rb +94 -8
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/hooks_spec.rb +2 -2
- data/spec/model/model_spec.rb +19 -7
- data/spec/model/record_spec.rb +135 -58
- data/spec/model/spec_helper.rb +1 -0
- metadata +35 -7
|
@@ -86,12 +86,24 @@ describe Sequel::Model, "drop_table" do
|
|
|
86
86
|
MODEL_DB.reset
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
it "should
|
|
89
|
+
it "should drop the related table" do
|
|
90
90
|
@model.drop_table
|
|
91
91
|
MODEL_DB.sqls.should == ['DROP TABLE items']
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
describe Sequel::Model, "drop_table?" do
|
|
96
|
+
before do
|
|
97
|
+
@model = Class.new(Sequel::Model(:items))
|
|
98
|
+
MODEL_DB.reset
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should drop the table if it exists" do
|
|
102
|
+
@model.drop_table?
|
|
103
|
+
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items']
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
95
107
|
describe Sequel::Model, "create_table!" do
|
|
96
108
|
before do
|
|
97
109
|
MODEL_DB.reset
|
|
@@ -100,7 +112,7 @@ describe Sequel::Model, "create_table!" do
|
|
|
100
112
|
|
|
101
113
|
it "should drop table if it exists and then create the table" do
|
|
102
114
|
@model.create_table!
|
|
103
|
-
MODEL_DB.sqls.should == ['DROP TABLE items', 'CREATE TABLE items ()']
|
|
115
|
+
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items', 'CREATE TABLE items ()']
|
|
104
116
|
end
|
|
105
117
|
end
|
|
106
118
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Dataset#select_remove" do
|
|
4
|
+
before do
|
|
5
|
+
@d = Sequel.mock.from(:test)
|
|
6
|
+
@d.columns :a, :b, :c
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
specify "should remove columns from the selected columns" do
|
|
10
|
+
@d.sql.should == 'SELECT * FROM test'
|
|
11
|
+
@d.select_remove(:a).sql.should == 'SELECT b, c FROM test'
|
|
12
|
+
@d.select_remove(:b).sql.should == 'SELECT a, c FROM test'
|
|
13
|
+
@d.select_remove(:c).sql.should == 'SELECT a, b FROM test'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
specify "should work correctly if there are already columns selected" do
|
|
17
|
+
d = @d.select(:a, :b, :c)
|
|
18
|
+
d.columns :a, :b, :c
|
|
19
|
+
d.select_remove(:c).sql.should == 'SELECT a, b FROM test'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
specify "should have no effect if the columns given are not currently selected" do
|
|
23
|
+
@d.select_remove(:d).sql.should == 'SELECT a, b, c FROM test'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
specify "should handle expressions where Sequel can't determine the alias by itself" do
|
|
27
|
+
d = @d.select(:a, :b.sql_function, :c.as(:b))
|
|
28
|
+
d.columns :a, :"b()", :b
|
|
29
|
+
d.select_remove(:"b()").sql.should == 'SELECT a, c AS b FROM test'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
specify "should remove expressions if given exact expressions" do
|
|
33
|
+
d = @d.select(:a, :b.sql_function, :c.as(:b))
|
|
34
|
+
d.columns :a, :"b()", :b
|
|
35
|
+
d.select_remove(:b.sql_function).sql.should == 'SELECT a, c AS b FROM test'
|
|
36
|
+
d.select_remove(:c.as(:b)).sql.should == 'SELECT a, b() FROM test'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -5,19 +5,19 @@ describe "sharding plugin" do
|
|
|
5
5
|
@db = Sequel.mock(:numrows=>1, :autoid=>proc{1}, :servers=>{:s1=>{}, :s2=>{}, :s3=>{}, :s4=>{}})
|
|
6
6
|
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
7
7
|
@Artist.class_eval do
|
|
8
|
-
dataset._fetch = {:id=>2, :name=>'YJM'}
|
|
8
|
+
instance_dataset._fetch = dataset._fetch = {:id=>2, :name=>'YJM'}
|
|
9
9
|
columns :id, :name
|
|
10
10
|
plugin :sharding
|
|
11
11
|
end
|
|
12
12
|
@Album = Class.new(Sequel::Model(@db[:albums]))
|
|
13
13
|
@Album.class_eval do
|
|
14
|
-
dataset._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
|
|
14
|
+
instance_dataset._fetch = dataset._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
|
|
15
15
|
columns :id, :artist_id, :name
|
|
16
16
|
plugin :sharding
|
|
17
17
|
end
|
|
18
18
|
@Tag = Class.new(Sequel::Model(@db[:tags]))
|
|
19
19
|
@Tag.class_eval do
|
|
20
|
-
dataset._fetch = {:id=>3, :name=>'M'}
|
|
20
|
+
instance_dataset._fetch = dataset._fetch = {:id=>3, :name=>'M'}
|
|
21
21
|
columns :id, :name
|
|
22
22
|
plugin :sharding
|
|
23
23
|
end
|
|
@@ -67,7 +67,7 @@ describe "sharding plugin" do
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
specify "should not use current dataset's shard when eager loading if eagerly loaded dataset has its own shard" do
|
|
70
|
-
@Artist.dataset.opts[:server] = :s2
|
|
70
|
+
@Artist.instance_dataset.opts[:server] = @Artist.dataset.opts[:server] = :s2
|
|
71
71
|
albums = @Album.server(:s1).eager(:artist).all
|
|
72
72
|
@db.sqls.should == ["SELECT * FROM albums -- s1", "SELECT * FROM artists WHERE (artists.id IN (2)) -- s2"]
|
|
73
73
|
albums.length.should == 1
|
|
@@ -86,7 +86,7 @@ describe "sharding plugin" do
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
specify "should not use current dataset's shard when eager graphing if eagerly graphed dataset has its own shard" do
|
|
89
|
-
@Artist.dataset.opts[:server] = :s2
|
|
89
|
+
@Artist.instance_dataset.opts[:server] = @Artist.dataset.opts[:server] = :s2
|
|
90
90
|
ds = @Album.server(:s1).eager_graph(:artist)
|
|
91
91
|
ds._fetch = {:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'}
|
|
92
92
|
albums = ds.all
|
|
@@ -97,7 +97,7 @@ describe "sharding plugin" do
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
specify "should use eagerly graphed dataset shard for eagerly graphed objects even if current dataset does not have a shard" do
|
|
100
|
-
@Artist.dataset.opts[:server] = :s2
|
|
100
|
+
@Artist.instance_dataset.opts[:server] = @Artist.dataset.opts[:server] = :s2
|
|
101
101
|
ds = @Album.eager_graph(:artist)
|
|
102
102
|
ds._fetch = {:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'}
|
|
103
103
|
albums = ds.all
|
|
@@ -5,7 +5,7 @@ describe "Sequel::Plugins::SkipCreateRefresh" do
|
|
|
5
5
|
c = Class.new(Sequel::Model(:a))
|
|
6
6
|
c.columns :id, :x
|
|
7
7
|
c.db.reset
|
|
8
|
-
c.
|
|
8
|
+
c.instance_dataset.meta_def(:insert){|*a| super(*a); 2}
|
|
9
9
|
c.create(:x=>1)
|
|
10
10
|
c.db.sqls.should == ['INSERT INTO a (x) VALUES (1)', 'SELECT * FROM a WHERE (id = 2) LIMIT 1']
|
|
11
11
|
|
|
@@ -8,7 +8,7 @@ unless Sequel.const_defined?('Model')
|
|
|
8
8
|
require 'sequel/model'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
Sequel.extension(*%w'string_date_time inflector pagination query pretty_table blank migration schema_dumper looser_typecasting sql_expr thread_local_timezones to_dot columns_introspection server_block arbitrary_servers')
|
|
11
|
+
Sequel.extension(*%w'string_date_time inflector pagination query pretty_table blank migration schema_dumper looser_typecasting sql_expr thread_local_timezones to_dot columns_introspection server_block arbitrary_servers pg_auto_parameterize pg_statement_cache pg_hstore pg_hstore_ops schema_caching null_dataset select_remove query_literals')
|
|
12
12
|
{:hook_class_methods=>[], :schema=>[], :validation_class_methods=>[]}.each{|p, opts| Sequel::Model.plugin(p, *opts)}
|
|
13
13
|
|
|
14
14
|
Sequel::Dataset.introspect_all_columns if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
@@ -36,6 +36,7 @@ class << Sequel::Model
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
Sequel::Model.use_transactions = false
|
|
39
|
+
Sequel::Model.cache_anonymous_models = false
|
|
39
40
|
|
|
40
41
|
db = Sequel.mock(:fetch=>{:id => 1, :x => 1}, :numrows=>1, :autoid=>proc{|sql| 10})
|
|
41
42
|
def db.schema(*) [[:id, {:primary_key=>true}]] end
|
|
@@ -1,49 +1,58 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
3
|
describe "Sequel sql_expr extension" do
|
|
4
|
+
before do
|
|
5
|
+
@ds = Sequel.mock.dataset
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
specify "Object#sql_expr should wrap the object in a GenericComplexExpression" do
|
|
5
9
|
o = Object.new
|
|
10
|
+
def o.sql_literal(ds) 'foo' end
|
|
6
11
|
s = o.sql_expr
|
|
7
|
-
s.should ==
|
|
8
|
-
(s+1).should ==
|
|
9
|
-
(s & true).should ==
|
|
10
|
-
(s < 1).should ==
|
|
11
|
-
s.sql_subscript(1).should ==
|
|
12
|
-
s.like('a').should ==
|
|
13
|
-
s.as(:a).should ==
|
|
14
|
-
s.cast(Integer).should ==
|
|
15
|
-
s.desc.should ==
|
|
16
|
-
s.sql_string.should ==
|
|
12
|
+
@ds.literal(s).should == "foo"
|
|
13
|
+
@ds.literal(s+1).should == "(foo + 1)"
|
|
14
|
+
@ds.literal(s & true).should == "(foo AND 't')"
|
|
15
|
+
@ds.literal(s < 1).should == "(foo < 1)"
|
|
16
|
+
@ds.literal(s.sql_subscript(1)).should == "foo[1]"
|
|
17
|
+
@ds.literal(s.like('a')).should == "(foo LIKE 'a')"
|
|
18
|
+
@ds.literal(s.as(:a)).should == "foo AS a"
|
|
19
|
+
@ds.literal(s.cast(Integer)).should == "CAST(foo AS integer)"
|
|
20
|
+
@ds.literal(s.desc).should == "foo DESC"
|
|
21
|
+
@ds.literal(s.sql_string + '1').should == "(foo || '1')"
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
specify "Numeric#sql_expr should wrap the object in a NumericExpression" do
|
|
20
25
|
[1, 2.0, 2^70, BigDecimal.new('1.0')].each do |o|
|
|
21
|
-
o.sql_expr.should ==
|
|
26
|
+
@ds.literal(o.sql_expr).should == @ds.literal(o)
|
|
27
|
+
@ds.literal(o.sql_expr + 1).should == "(#{@ds.literal(o)} + 1)"
|
|
22
28
|
end
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
specify "String#sql_expr should wrap the object in a StringExpression" do
|
|
26
|
-
"".sql_expr.should ==
|
|
32
|
+
@ds.literal("".sql_expr).should == "''"
|
|
33
|
+
@ds.literal("".sql_expr + :a).should == "('' || a)"
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
specify "NilClass, TrueClass, and FalseClass#sql_expr should wrap the object in a BooleanExpression" do
|
|
30
37
|
[nil, true, false].each do |o|
|
|
31
|
-
o.sql_expr.should ==
|
|
38
|
+
@ds.literal(o.sql_expr).should == @ds.literal(o)
|
|
39
|
+
@ds.literal(o.sql_expr & :a).should == "(#{@ds.literal(o)} AND a)"
|
|
32
40
|
end
|
|
33
41
|
end
|
|
34
42
|
|
|
35
43
|
specify "Proc#sql_expr should should treat the object as a virtual row block" do
|
|
36
|
-
proc{a}.sql_expr.should ==
|
|
37
|
-
proc{a__b}.sql_expr.should ==
|
|
38
|
-
proc{a(b)}.sql_expr.should ==
|
|
44
|
+
@ds.literal(proc{a}.sql_expr).should == "a"
|
|
45
|
+
@ds.literal(proc{a__b}.sql_expr).should == "a.b"
|
|
46
|
+
@ds.literal(proc{a(b)}.sql_expr).should == "a(b)"
|
|
39
47
|
end
|
|
40
48
|
|
|
41
49
|
specify "Proc#sql_expr should should wrap the object in a GenericComplexExpression if the object is not already an expression" do
|
|
42
|
-
proc{1}.sql_expr.should ==
|
|
50
|
+
@ds.literal(proc{1}.sql_expr).should == "1"
|
|
51
|
+
@ds.literal(proc{1}.sql_expr + 2).should == "(1 + 2)"
|
|
43
52
|
end
|
|
44
53
|
|
|
45
54
|
specify "Proc#sql_expr should should convert a hash or array of two element arrays to a BooleanExpression" do
|
|
46
|
-
proc{{a=>b}}.sql_expr.should ==
|
|
47
|
-
proc{[[a,b]]}.sql_expr.should ==
|
|
55
|
+
@ds.literal(proc{{a=>b}}.sql_expr).should == "(a = b)"
|
|
56
|
+
@ds.literal(proc{[[a, b]]}.sql_expr & :a).should == "((a = b) AND a)"
|
|
48
57
|
end
|
|
49
58
|
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::StaticCache" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock
|
|
6
|
+
@db.fetch = [{:id=>1}, {:id=>2}]
|
|
7
|
+
@c = Class.new(Sequel::Model(@db[:t]))
|
|
8
|
+
@c.columns :id
|
|
9
|
+
@c.plugin :static_cache
|
|
10
|
+
@c1 = @c.cache[1]
|
|
11
|
+
@c2 = @c.cache[2]
|
|
12
|
+
@db.sqls
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should use a ruby hash as a cache of all model instances" do
|
|
16
|
+
@c.cache.should == {1=>@c.load(:id=>1), 2=>@c.load(:id=>2)}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should work correctly with composite keys" do
|
|
20
|
+
@db.fetch = [{:id=>1, :id2=>1}, {:id=>2, :id2=>1}]
|
|
21
|
+
@c = Class.new(Sequel::Model(@db[:t]))
|
|
22
|
+
@c.columns :id, :id2
|
|
23
|
+
@c.set_primary_key([:id, :id2])
|
|
24
|
+
@c.plugin :static_cache
|
|
25
|
+
@db.sqls
|
|
26
|
+
@c1 = @c.cache[[1, 2]]
|
|
27
|
+
@c2 = @c.cache[[2, 1]]
|
|
28
|
+
@c[[1, 2]].should equal(@c1)
|
|
29
|
+
@c[[2, 1]].should equal(@c2)
|
|
30
|
+
@db.sqls.should == []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should make .[] method with primary key use the cache" do
|
|
34
|
+
@c[1].should equal(@c1)
|
|
35
|
+
@c[2].should equal(@c2)
|
|
36
|
+
@c[3].should be_nil
|
|
37
|
+
@c[[1, 2]].should be_nil
|
|
38
|
+
@c[nil].should be_nil
|
|
39
|
+
@c[].should be_nil
|
|
40
|
+
@db.sqls.should == []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should have .[] with a hash not use the cache" do
|
|
44
|
+
@db.fetch = {:id=>2}
|
|
45
|
+
@c[:id=>2].should == @c2
|
|
46
|
+
@db.sqls.should == ['SELECT * FROM t WHERE (id = 2) LIMIT 1']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should support cache_get_pk" do
|
|
50
|
+
@c.cache_get_pk(1).should equal(@c1)
|
|
51
|
+
@c.cache_get_pk(2).should equal(@c2)
|
|
52
|
+
@c.cache_get_pk(3).should be_nil
|
|
53
|
+
@db.sqls.should == []
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should have each just iterate over the hash's values without sending a query" do
|
|
57
|
+
a = []
|
|
58
|
+
@c.each{|o| a << o}
|
|
59
|
+
a = a.sort_by{|o| o.id}
|
|
60
|
+
a.first.should equal(@c1)
|
|
61
|
+
a.last.should equal(@c2)
|
|
62
|
+
@db.sqls.should == []
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should have map just iterate over the hash's values without sending a query if no argument is given" do
|
|
66
|
+
@c.map{|v| v.id}.sort.should == [1, 2]
|
|
67
|
+
@db.sqls.should == []
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should have map send a query if given an argument" do
|
|
71
|
+
@c.map(:id).sort.should == [1, 2]
|
|
72
|
+
@db.sqls.should == ["SELECT * FROM t"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should have map without a block or argument not raise an exception or issue a query" do
|
|
76
|
+
@c.map
|
|
77
|
+
@db.sqls.should == []
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should have map without a block not return a frozen object" do
|
|
81
|
+
@c.map.frozen?.should be_false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should have other enumerable methods work without sending a query" do
|
|
85
|
+
a = @c.sort_by{|o| o.id}
|
|
86
|
+
a.first.should equal(@c1)
|
|
87
|
+
a.last.should equal(@c2)
|
|
88
|
+
@db.sqls.should == []
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should have all just return the hashes' values" do
|
|
92
|
+
a = @c.all.sort_by{|o| o.id}
|
|
93
|
+
a.first.should equal(@c1)
|
|
94
|
+
a.last.should equal(@c2)
|
|
95
|
+
@db.sqls.should == []
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should have all not return a frozen object" do
|
|
99
|
+
@c.all.frozen?.should be_false
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should have all return things in dataset order" do
|
|
103
|
+
@c.all.should == [@c1, @c2]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should have to_hash without arguments return the cached objects without a query" do
|
|
107
|
+
a = @c.to_hash
|
|
108
|
+
a[1].should equal(@c1)
|
|
109
|
+
a[2].should equal(@c2)
|
|
110
|
+
@db.sqls.should == []
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should have to_hash with any arguments use a query" do
|
|
114
|
+
@c.to_hash(:id).should == {1=>@c1, 2=>@c2}
|
|
115
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
116
|
+
@c.to_hash(:id, :id).should == {1=>1, 2=>2}
|
|
117
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "should have all not return a frozen object" do
|
|
121
|
+
@c.to_hash.frozen?.should be_false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "all of the static cache values (model instances) should be frozen" do
|
|
125
|
+
@c.all.all?{|o| o.frozen?}.should be_true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "subclasses should work correctly" do
|
|
129
|
+
c = Class.new(@c)
|
|
130
|
+
c.all.should == [c.load(:id=>1), c.load(:id=>2)]
|
|
131
|
+
c.to_hash.should == {1=>c.load(:id=>1), 2=>c.load(:id=>2)}
|
|
132
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "set_dataset should work correctly" do
|
|
136
|
+
ds = @c.dataset.from(:t2)
|
|
137
|
+
ds.instance_variable_set(:@columns, [:id])
|
|
138
|
+
ds._fetch = {:id=>3}
|
|
139
|
+
@c.dataset = ds
|
|
140
|
+
@c.all.should == [@c.load(:id=>3)]
|
|
141
|
+
@c.to_hash.should == {3=>@c.load(:id=>3)}
|
|
142
|
+
@c.to_hash[3].should equal(@c.all.first)
|
|
143
|
+
@db.sqls.should == ['SELECT * FROM t2']
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -105,7 +105,7 @@ describe "Touch plugin" do
|
|
|
105
105
|
@Album.touch_associations(:artist, {:followup_albums=>:modified_on})
|
|
106
106
|
@Album.load(:id=>4, :artist_id=>1).destroy
|
|
107
107
|
sqls = MODEL_DB.sqls
|
|
108
|
-
sqls.shift.should == "DELETE FROM albums WHERE
|
|
108
|
+
sqls.shift.should == "DELETE FROM albums WHERE id = 4"
|
|
109
109
|
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
110
110
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
111
111
|
end
|
|
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model, "TypecastOnLoad plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@db = Sequel.mock(:fetch=>{:id=>1, :b=>"1", :y=>"0"}, :columns=>[:id, :b, :y])
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :b=>"1", :y=>"0"}, :columns=>[:id, :b, :y], :numrows=>1)
|
|
6
6
|
def @db.schema(*args)
|
|
7
7
|
[[:id, {}], [:y, {:type=>:boolean, :db_type=>'tinyint(1)'}], [:b, {:type=>:integer, :db_type=>'integer'}]]
|
|
8
8
|
end
|
|
@@ -30,6 +30,14 @@ describe Sequel::Model, "TypecastOnLoad plugin" do
|
|
|
30
30
|
o.bset.should == true
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
specify "should call setter method with value when automatically reloading the object on creation via insert_select" do
|
|
34
|
+
@c.plugin :typecast_on_load, :b
|
|
35
|
+
@c.dataset.meta_def(:insert_select){|h| insert(h); first}
|
|
36
|
+
o = @c.new({:id=>1, :b=>"1", :y=>"0"}, true)
|
|
37
|
+
o.save.values.should == {:id=>1, :b=>1, :y=>"0"}
|
|
38
|
+
o.bset.should == true
|
|
39
|
+
end
|
|
40
|
+
|
|
33
41
|
specify "should allowing setting columns separately via add_typecast_on_load_columns" do
|
|
34
42
|
@c.plugin :typecast_on_load
|
|
35
43
|
@c.load(:id=>1, :b=>"1", :y=>"0").values.should == {:id=>1, :b=>"1", :y=>"0"}
|
|
@@ -536,7 +536,7 @@ end
|
|
|
536
536
|
describe "Sequel::Model Simple Associations" do
|
|
537
537
|
before(:all) do
|
|
538
538
|
@db = INTEGRATION_DB
|
|
539
|
-
|
|
539
|
+
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
|
540
540
|
@db.create_table(:artists) do
|
|
541
541
|
primary_key :id
|
|
542
542
|
String :name
|
|
@@ -598,7 +598,7 @@ describe "Sequel::Model Simple Associations" do
|
|
|
598
598
|
[:Tag, :Album, :Artist].each{|x| Object.send(:remove_const, x)}
|
|
599
599
|
end
|
|
600
600
|
after(:all) do
|
|
601
|
-
@db.drop_table(:albums_tags, :tags, :albums, :artists)
|
|
601
|
+
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
|
602
602
|
end
|
|
603
603
|
|
|
604
604
|
it_should_behave_like "regular and composite key associations"
|
|
@@ -733,7 +733,7 @@ end
|
|
|
733
733
|
describe "Sequel::Model Composite Key Associations" do
|
|
734
734
|
before(:all) do
|
|
735
735
|
@db = INTEGRATION_DB
|
|
736
|
-
|
|
736
|
+
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
|
737
737
|
@db.create_table(:artists) do
|
|
738
738
|
Integer :id1
|
|
739
739
|
Integer :id2
|
|
@@ -813,7 +813,7 @@ describe "Sequel::Model Composite Key Associations" do
|
|
|
813
813
|
[:Tag, :Album, :Artist].each{|x| Object.send(:remove_const, x)}
|
|
814
814
|
end
|
|
815
815
|
after(:all) do
|
|
816
|
-
@db.drop_table(:albums_tags, :tags, :albums, :artists)
|
|
816
|
+
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
|
817
817
|
end
|
|
818
818
|
|
|
819
819
|
it_should_behave_like "regular and composite key associations"
|
|
@@ -868,7 +868,7 @@ end
|
|
|
868
868
|
describe "Sequel::Model Associations with clashing column names" do
|
|
869
869
|
before(:all) do
|
|
870
870
|
@db = INTEGRATION_DB
|
|
871
|
-
|
|
871
|
+
@db.drop_table?(:bars_foos, :bars, :foos)
|
|
872
872
|
@db.create_table(:foos) do
|
|
873
873
|
primary_key :id
|
|
874
874
|
Integer :object_id
|
|
@@ -899,7 +899,7 @@ describe "Sequel::Model Associations with clashing column names" do
|
|
|
899
899
|
@Foo.db[:bars_foos].insert(2, 2)
|
|
900
900
|
end
|
|
901
901
|
after(:all) do
|
|
902
|
-
@db.drop_table(:bars_foos, :bars, :foos)
|
|
902
|
+
@db.drop_table?(:bars_foos, :bars, :foos)
|
|
903
903
|
end
|
|
904
904
|
|
|
905
905
|
it "should have working regular association methods" do
|