sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +68 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::AssociationPks" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock
|
|
6
|
+
@db.extend_datasets do
|
|
7
|
+
def select_sql
|
|
8
|
+
sql = super
|
|
9
|
+
sql << ' -- prepared' if is_a?(Sequel::Dataset::PreparedStatementMethods)
|
|
10
|
+
sql
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
14
|
+
@Artist.columns :id, :id2
|
|
15
|
+
@Album= Class.new(Sequel::Model(@db[:albums]))
|
|
16
|
+
@Album.columns :id, :artist_id, :id2, :artist_id2
|
|
17
|
+
@Tag = Class.new(Sequel::Model(@db[:tags]))
|
|
18
|
+
@Tag.columns :id, :id2
|
|
19
|
+
@Artist.plugin :prepared_statements_associations
|
|
20
|
+
@Album.plugin :prepared_statements_associations
|
|
21
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
22
|
+
@Album.many_to_one :artist, :class=>@Artist
|
|
23
|
+
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
|
|
24
|
+
@Artist.plugin :many_through_many
|
|
25
|
+
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
|
26
|
+
@db.sqls
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
specify "should run correct SQL for associations" do
|
|
30
|
+
@Artist.load(:id=>1).albums
|
|
31
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1) -- prepared"]
|
|
32
|
+
|
|
33
|
+
@Album.load(:id=>1, :artist_id=>2).artist
|
|
34
|
+
@db.sqls.should == ["SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1 -- prepared"]
|
|
35
|
+
|
|
36
|
+
@Album.load(:id=>1, :artist_id=>2).tags
|
|
37
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.album_id = 1)) -- prepared"]
|
|
38
|
+
|
|
39
|
+
@Artist.load(:id=>1).tags
|
|
40
|
+
@db.sqls.should == ["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) AND (albums.artist_id = 1)) -- prepared"]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
specify "should run correct SQL for composite key associations" do
|
|
44
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
|
45
|
+
@Album.many_to_one :artist, :class=>@Artist, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
|
46
|
+
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>[:album_id, :album_id2], :right_key=>[:tag_id, :tag_id2], :right_primary_key=>[:id, :id2], :left_primary_key=>[:id, :id2]
|
|
47
|
+
@Artist.many_through_many :tags, [[:albums, [:artist_id, :artist_id2], [:id, :id2]], [:albums_tags, [:album_id, :album_id2], [:tag_id, :tag_id2]]], :class=>@Tag, :right_primary_key=>[:id, :id2], :left_primary_key=>[:id, :id2]
|
|
48
|
+
|
|
49
|
+
@Artist.load(:id=>1, :id2=>2).albums
|
|
50
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
|
51
|
+
|
|
52
|
+
@Album.load(:id=>1, :artist_id=>2, :artist_id2=>3).artist
|
|
53
|
+
@db.sqls.should == ["SELECT * FROM artists WHERE ((artists.id = 2) AND (artists.id2 = 3)) LIMIT 1 -- prepared"]
|
|
54
|
+
|
|
55
|
+
@Album.load(:id=>1, :artist_id=>2, :id2=>3).tags
|
|
56
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2) AND (albums_tags.album_id = 1) AND (albums_tags.album_id2 = 3)) -- prepared"]
|
|
57
|
+
|
|
58
|
+
@Artist.load(:id=>1, :id2=>2).tags
|
|
59
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) INNER JOIN albums ON ((albums.id = albums_tags.album_id) AND (albums.id2 = albums_tags.album_id2) AND (albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
specify "should not run query if no objects can be associated" do
|
|
63
|
+
@Artist.new.albums.should == []
|
|
64
|
+
@Album.new.artist.should == nil
|
|
65
|
+
@db.sqls.should == []
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
specify "should run a regular query if there is a callback" do
|
|
69
|
+
@Artist.load(:id=>1).albums(proc{|ds| ds})
|
|
70
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
specify "should run a regular query if :prepared_statement=>false option is used for the association" do
|
|
74
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :prepared_statement=>false
|
|
75
|
+
@Artist.load(:id=>1).albums
|
|
76
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
specify "should run a regular query if unrecognized association is used" do
|
|
80
|
+
a = @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
81
|
+
a[:type] = :foo
|
|
82
|
+
@Artist.load(:id=>1).albums
|
|
83
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
specify "should run a regular query if a block is used when defining the association" do
|
|
87
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id do |ds| ds end
|
|
88
|
+
@Artist.load(:id=>1).albums
|
|
89
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
specify "should run a regular query if :conditions option is used when defining the association" do
|
|
93
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{:a=>1}
|
|
94
|
+
@Artist.load(:id=>1).albums
|
|
95
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
specify "should run a regular query if :dataset option is used when defining the association" do
|
|
99
|
+
album = @Album
|
|
100
|
+
@Artist.one_to_many :albums, :class=>@Album, :dataset=>proc{album.filter(:artist_id=>id)}
|
|
101
|
+
@Artist.load(:id=>1).albums
|
|
102
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (artist_id = 1)"]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
specify "should run a regular query if :cloning an association that doesn't used prepared statements" do
|
|
106
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{:a=>1}
|
|
107
|
+
@Artist.one_to_many :oalbums, :clone=>:albums
|
|
108
|
+
@Artist.load(:id=>1).oalbums
|
|
109
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "prepared_statements_safe plugin" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
7
|
+
@c.columns :id, :name, :i
|
|
8
|
+
@c.instance_variable_set(:@db_schema, {:i=>{}, :name=>{}, :id=>{:primary_key=>true}})
|
|
9
|
+
@c.plugin :prepared_statements_safe
|
|
10
|
+
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
11
|
+
@db.sqls
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
specify "should load the prepared_statements plugin" do
|
|
15
|
+
@c.plugins.should include(Sequel::Plugins::PreparedStatements)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
specify "should set default values correctly" do
|
|
19
|
+
@c.prepared_statements_column_defaults.should == {:name=>nil, :i=>nil}
|
|
20
|
+
@c.instance_variable_set(:@db_schema, {:i=>{:default=>'f(x)'}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}})
|
|
21
|
+
Class.new(@c).prepared_statements_column_defaults.should == {:name=>'foo'}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
specify "should set default values when creating" do
|
|
25
|
+
@c.create
|
|
26
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \(NULL, NULL\)/
|
|
27
|
+
@c.create(:name=>'foo')
|
|
28
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((NULL|'foo'), (NULL|'foo')\)/
|
|
29
|
+
@c.create(:name=>'foo', :i=>2)
|
|
30
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
specify "should use database default values" do
|
|
34
|
+
@c.instance_variable_set(:@db_schema, {:i=>{:ruby_default=>2}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}})
|
|
35
|
+
c = Class.new(@c)
|
|
36
|
+
c.create
|
|
37
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
specify "should not set defaults for unparseable dataset default values" do
|
|
41
|
+
@c.instance_variable_set(:@db_schema, {:i=>{:default=>'f(x)'}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}})
|
|
42
|
+
c = Class.new(@c)
|
|
43
|
+
c.create
|
|
44
|
+
@db.sqls.first.should == "INSERT INTO people (name) VALUES ('foo')"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
specify "should save all fields when updating" do
|
|
48
|
+
@p.update(:i=>3)
|
|
49
|
+
@db.sqls.first.should =~ /UPDATE people SET (name = 'foo'|i = 3), (name = 'foo'|i = 3) WHERE \(id = 1\)/
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
specify "should work with abstract classes" do
|
|
53
|
+
c = Class.new(Sequel::Model)
|
|
54
|
+
c.plugin :prepared_statements_safe
|
|
55
|
+
c1 = Class.new(c)
|
|
56
|
+
c1.meta_def(:get_db_schema){@db_schema = {:i=>{:default=>'f(x)'}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}}}
|
|
57
|
+
c1.set_dataset(:people)
|
|
58
|
+
c1.prepared_statements_column_defaults.should == {:name=>'foo'}
|
|
59
|
+
Class.new(c1).prepared_statements_column_defaults.should == {:name=>'foo'}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "prepared_statements plugin" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
7
|
+
@c.columns :id, :name, :i
|
|
8
|
+
@c.plugin :prepared_statements
|
|
9
|
+
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
10
|
+
@ds = @c.dataset
|
|
11
|
+
@db.sqls
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
specify "should correctly lookup by primary key" do
|
|
15
|
+
@c[1].should == @p
|
|
16
|
+
@db.sqls.should == ["SELECT * FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
specify "should correctly delete instance" do
|
|
20
|
+
@p.destroy.should == @p
|
|
21
|
+
@db.sqls.should == ["DELETE FROM people WHERE (id = 1)"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
specify "should correctly update instance" do
|
|
25
|
+
@p.update(:name=>'bar').should == @c.load(:id=>1, :name=>'bar', :i => 2)
|
|
26
|
+
@db.sqls.should == ["UPDATE people SET name = 'bar' WHERE (id = 1)"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
specify "should correctly create instance" do
|
|
30
|
+
@c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
|
|
31
|
+
@db.sqls.should == ["INSERT INTO people (name) VALUES ('foo')", "SELECT * FROM people WHERE (id = 1) LIMIT 1"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
specify "should correctly create instance if dataset supports insert_select" do
|
|
35
|
+
def @ds.supports_insert_select?
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
def @ds.insert_select(h)
|
|
39
|
+
{:id=>1, :name=>'foo', :i => 2}
|
|
40
|
+
end
|
|
41
|
+
def @ds.insert_sql(*)
|
|
42
|
+
"#{super}#{' RETURNING *' if opts.has_key?(:returning)}"
|
|
43
|
+
end
|
|
44
|
+
@c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
|
|
45
|
+
@db.sqls.should == ["INSERT INTO people (name) VALUES ('foo') RETURNING *"]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
specify "should work correctly when subclassing" do
|
|
49
|
+
c = Class.new(@c)
|
|
50
|
+
c[1].should == c.load(:id=>1, :name=>'foo', :i=>2)
|
|
51
|
+
@db.sqls.should == ["SELECT * FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "prepared_statements_with_pk plugin" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
7
|
+
@c.columns :id, :name, :i
|
|
8
|
+
@c.plugin :prepared_statements_with_pk
|
|
9
|
+
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
10
|
+
@db.sqls
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
specify "should load the prepared_statements plugin" do
|
|
14
|
+
@c.plugins.should include(Sequel::Plugins::PreparedStatements)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
specify "should correctly lookup by primary key from dataset" do
|
|
18
|
+
@c.dataset.filter(:name=>'foo')[1].should == @p
|
|
19
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE ((name = 'foo') AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
specify "should still work correctly if there are multiple conflicting variables" do
|
|
23
|
+
@c.dataset.filter(:name=>'foo').or(:name=>'bar')[1].should == @p
|
|
24
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE (((name = 'foo') OR (name = 'bar')) AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
specify "should still work correctly if the primary key is used elsewhere in the query" do
|
|
28
|
+
@c.dataset.filter{id > 2}[1].should == @p
|
|
29
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE ((id > 2) AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -7,12 +7,7 @@ describe "Dataset#print" do
|
|
|
7
7
|
@output = StringIO.new
|
|
8
8
|
@orig_stdout = $stdout
|
|
9
9
|
$stdout = @output
|
|
10
|
-
@dataset = Sequel
|
|
11
|
-
def @dataset.fetch_rows(sql)
|
|
12
|
-
yield({:a=>1, :b=>2})
|
|
13
|
-
yield({:a=>3, :b=>4})
|
|
14
|
-
yield({:a=>5, :b=>6})
|
|
15
|
-
end
|
|
10
|
+
@dataset = Sequel.mock(:fetch=>[{:a=>1, :b=>2}, {:a=>3, :b=>4}, {:a=>5, :b=>6}])[:items]
|
|
16
11
|
end
|
|
17
12
|
|
|
18
13
|
after do
|
|
@@ -17,6 +17,12 @@ describe "Dataset#query" do
|
|
|
17
17
|
@d = Sequel::Dataset.new(nil)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
specify "should allow cloning without arguments" do
|
|
21
|
+
q = @d.query {clone}
|
|
22
|
+
q.class.should == @d.class
|
|
23
|
+
q.sql.should == "SELECT *"
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
specify "should support #from" do
|
|
21
27
|
q = @d.query {from :xxx}
|
|
22
28
|
q.class.should == @d.class
|
|
@@ -8,13 +8,6 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
8
8
|
columns :id, :name, :parent_id, :i, :pi
|
|
9
9
|
end
|
|
10
10
|
@ds = @c.dataset
|
|
11
|
-
class << @ds
|
|
12
|
-
attr_accessor :row_sets
|
|
13
|
-
def fetch_rows(sql)
|
|
14
|
-
@db << sql
|
|
15
|
-
row_sets.shift.each{|row| yield row}
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
11
|
@o = @c.load(:id=>2, :parent_id=>1, :name=>'AA', :i=>3, :pi=>4)
|
|
19
12
|
MODEL_DB.reset
|
|
20
13
|
end
|
|
@@ -55,7 +48,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
55
48
|
|
|
56
49
|
it "should add all parent associations when lazily loading ancestors" do
|
|
57
50
|
@c.plugin :rcte_tree
|
|
58
|
-
@ds.
|
|
51
|
+
@ds._fetch = [[{:id=>1, :name=>'A', :parent_id=>3}, {:id=>4, :name=>'B', :parent_id=>nil}, {:id=>3, :name=>'?', :parent_id=>4}]]
|
|
59
52
|
@o.ancestors.should == [@c.load(:id=>1, :name=>'A', :parent_id=>3), @c.load(:id=>4, :name=>'B', :parent_id=>nil), @c.load(:id=>3, :name=>'?', :parent_id=>4)]
|
|
60
53
|
@o.associations[:parent].should == @c.load(:id=>1, :name=>'A', :parent_id=>3)
|
|
61
54
|
@o.associations[:parent].associations[:parent].should == @c.load(:id=>3, :name=>'?', :parent_id=>4)
|
|
@@ -65,7 +58,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
65
58
|
|
|
66
59
|
it "should add all parent associations when lazily loading ancestors and giving options" do
|
|
67
60
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
|
68
|
-
@ds.
|
|
61
|
+
@ds._fetch = [[{:i=>4, :name=>'A', :pi=>5}, {:i=>6, :name=>'B', :pi=>nil}, {:i=>5, :name=>'?', :pi=>6}]]
|
|
69
62
|
@o.as.should == [@c.load(:i=>4, :name=>'A', :pi=>5), @c.load(:i=>6, :name=>'B', :pi=>nil), @c.load(:i=>5, :name=>'?', :pi=>6)]
|
|
70
63
|
@o.associations[:p].should == @c.load(:i=>4, :name=>'A', :pi=>5)
|
|
71
64
|
@o.associations[:p].associations[:p].should == @c.load(:i=>5, :name=>'?', :pi=>6)
|
|
@@ -75,7 +68,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
75
68
|
|
|
76
69
|
it "should add all children associations when lazily loading descendants" do
|
|
77
70
|
@c.plugin :rcte_tree
|
|
78
|
-
@ds.
|
|
71
|
+
@ds._fetch = [[{:id=>3, :name=>'??', :parent_id=>1}, {:id=>1, :name=>'A', :parent_id=>2}, {:id=>4, :name=>'B', :parent_id=>2}, {:id=>5, :name=>'?', :parent_id=>3}]]
|
|
79
72
|
@o.descendants.should == [@c.load(:id=>3, :name=>'??', :parent_id=>1), @c.load(:id=>1, :name=>'A', :parent_id=>2), @c.load(:id=>4, :name=>'B', :parent_id=>2), @c.load(:id=>5, :name=>'?', :parent_id=>3)]
|
|
80
73
|
@o.associations[:children].should == [@c.load(:id=>1, :name=>'A', :parent_id=>2), @c.load(:id=>4, :name=>'B', :parent_id=>2)]
|
|
81
74
|
@o.associations[:children].map{|c1| c1.associations[:children]}.should == [[@c.load(:id=>3, :name=>'??', :parent_id=>1)], []]
|
|
@@ -85,7 +78,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
85
78
|
|
|
86
79
|
it "should add all children associations when lazily loading descendants and giving options" do
|
|
87
80
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
88
|
-
@ds.
|
|
81
|
+
@ds._fetch = [[{:i=>7, :name=>'??', :pi=>5}, {:i=>5, :name=>'A', :pi=>3}, {:i=>6, :name=>'B', :pi=>3}, {:i=>8, :name=>'?', :pi=>7}]]
|
|
89
82
|
@o.ds.should == [@c.load(:i=>7, :name=>'??', :pi=>5), @c.load(:i=>5, :name=>'A', :pi=>3), @c.load(:i=>6, :name=>'B', :pi=>3), @c.load(:i=>8, :name=>'?', :pi=>7)]
|
|
90
83
|
@o.associations[:cs].should == [@c.load(:i=>5, :name=>'A', :pi=>3), @c.load(:i=>6, :name=>'B', :pi=>3)]
|
|
91
84
|
@o.associations[:cs].map{|c1| c1.associations[:cs]}.should == [[@c.load(:i=>7, :name=>'??', :pi=>5)], []]
|
|
@@ -95,13 +88,14 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
95
88
|
|
|
96
89
|
it "should eagerly load ancestors" do
|
|
97
90
|
@c.plugin :rcte_tree
|
|
98
|
-
@ds.
|
|
91
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}, {:id=>9, :parent_id=>nil, :name=>'E'}],
|
|
99
92
|
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
|
100
93
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
|
101
94
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
|
102
95
|
os = @ds.eager(:ancestors).all
|
|
103
|
-
MODEL_DB.sqls
|
|
104
|
-
|
|
96
|
+
sqls = MODEL_DB.sqls
|
|
97
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
98
|
+
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x, nodes\.\* FROM nodes WHERE \(id IN \([12], [12]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.parent_id = nodes\.id\)\) SELECT \* FROM t AS nodes/
|
|
105
99
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D'), @c.load(:id=>9, :parent_id=>nil, :name=>'E')]
|
|
106
100
|
os.map{|o| o.ancestors}.should == [[@c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
|
107
101
|
[@c.load(:id=>2, :name=>'AA', :parent_id=>1), @c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
|
@@ -111,18 +105,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
111
105
|
os.map{|o| o.parent.parent if o.parent}.should == [@c.load(:id=>8, :name=>'?', :parent_id=>nil), @c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil), nil]
|
|
112
106
|
os.map{|o| o.parent.parent.parent if o.parent and o.parent.parent}.should == [nil, @c.load(:id=>8, :name=>'?', :parent_id=>nil), nil, nil]
|
|
113
107
|
os.map{|o| o.parent.parent.parent.parent if o.parent and o.parent.parent and o.parent.parent.parent}.should == [nil, nil, nil, nil]
|
|
114
|
-
MODEL_DB.
|
|
108
|
+
MODEL_DB.sqls.should == []
|
|
115
109
|
end
|
|
116
110
|
|
|
117
111
|
it "should eagerly load ancestors when giving options" do
|
|
118
112
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
|
119
|
-
@ds.
|
|
113
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}, {:i=>9, :pi=>nil, :name=>'E'}],
|
|
120
114
|
[{:i=>2, :name=>'AA', :pi=>1, :kal=>2},
|
|
121
115
|
{:i=>1, :name=>'00', :pi=>8, :kal=>1}, {:i=>1, :name=>'00', :pi=>8, :kal=>2},
|
|
122
116
|
{:i=>8, :name=>'?', :pi=>nil, :kal=>2}, {:i=>8, :name=>'?', :pi=>nil, :kal=>1}]]
|
|
123
117
|
os = @ds.eager(:as).all
|
|
124
|
-
MODEL_DB.sqls
|
|
125
|
-
|
|
118
|
+
sqls = MODEL_DB.sqls
|
|
119
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
120
|
+
sqls.last.should =~ /WITH cte AS \(SELECT i AS kal, nodes\.\* FROM nodes WHERE \(i IN \([12], [12]\)\) UNION ALL SELECT cte\.kal, nodes\.\* FROM nodes INNER JOIN cte ON \(cte\.pi = nodes\.i\)\) SELECT \* FROM cte/
|
|
126
121
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D'), @c.load(:i=>9, :pi=>nil, :name=>'E')]
|
|
127
122
|
os.map{|o| o.as}.should == [[@c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
|
128
123
|
[@c.load(:i=>2, :name=>'AA', :pi=>1), @c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
|
@@ -132,30 +127,30 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
132
127
|
os.map{|o| o.p.p if o.p}.should == [@c.load(:i=>8, :name=>'?', :pi=>nil), @c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil), nil]
|
|
133
128
|
os.map{|o| o.p.p.p if o.p and o.p.p}.should == [nil, @c.load(:i=>8, :name=>'?', :pi=>nil), nil, nil]
|
|
134
129
|
os.map{|o| o.p.p.p.p if o.p and o.p.p and o.p.p.p}.should == [nil, nil, nil, nil]
|
|
135
|
-
MODEL_DB.new_sqls.should == []
|
|
136
130
|
end
|
|
137
131
|
|
|
138
132
|
it "should eagerly load ancestors respecting association option :conditions" do
|
|
139
133
|
@c.plugin :rcte_tree, :conditions => {:i => 1}
|
|
140
|
-
@ds.
|
|
134
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}, {:id=>9, :parent_id=>nil, :name=>'E'}],
|
|
141
135
|
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
|
142
136
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
|
143
137
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
|
144
138
|
os = @ds.eager(:ancestors).all
|
|
145
|
-
MODEL_DB.sqls
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
sqls = MODEL_DB.sqls
|
|
140
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
141
|
+
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(id IN \([12], [12]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.parent_id = nodes\.id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
|
148
142
|
end
|
|
149
143
|
|
|
150
144
|
it "should eagerly load descendants" do
|
|
151
145
|
@c.plugin :rcte_tree
|
|
152
|
-
@ds.
|
|
146
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
153
147
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
|
154
148
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
|
155
149
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
|
156
150
|
os = @ds.eager(:descendants).all
|
|
157
|
-
MODEL_DB.sqls
|
|
158
|
-
|
|
151
|
+
sqls = MODEL_DB.sqls
|
|
152
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
153
|
+
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\* FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\)\) SELECT \* FROM t AS nodes/
|
|
159
154
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D')]
|
|
160
155
|
os.map{|o| o.descendants}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E'), @c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
161
156
|
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
@@ -163,18 +158,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
163
158
|
os.map{|o| o.children}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E')], [@c.load(:id=>3, :name=>'00', :parent_id=>6)], [@c.load(:id=>4, :name=>'?', :parent_id=>7)]]
|
|
164
159
|
os.map{|o1| o1.children.map{|o2| o2.children}}.should == [[[@c.load(:id=>3, :name=>'00', :parent_id=>6)], []], [[]], [[@c.load(:id=>5, :name=>'?', :parent_id=>4)]]]
|
|
165
160
|
os.map{|o1| o1.children.map{|o2| o2.children.map{|o3| o3.children}}}.should == [[[[]], []], [[]], [[[]]]]
|
|
166
|
-
MODEL_DB.
|
|
161
|
+
MODEL_DB.sqls.should == []
|
|
167
162
|
end
|
|
168
163
|
|
|
169
164
|
it "should eagerly load descendants when giving options" do
|
|
170
165
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
171
|
-
@ds.
|
|
166
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
|
172
167
|
[{:i=>6, :pi=>2, :name=>'C', :kal=>2}, {:i=>9, :pi=>2, :name=>'E', :kal=>2},
|
|
173
168
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6}, {:i=>3, :name=>'00', :pi=>6, :kal=>2},
|
|
174
169
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7}, {:i=>5, :name=>'?', :pi=>4, :kal=>7}]]
|
|
175
170
|
os = @ds.eager(:ds).all
|
|
176
|
-
MODEL_DB.sqls
|
|
177
|
-
|
|
171
|
+
sqls = MODEL_DB.sqls
|
|
172
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
173
|
+
sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\* FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\* FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\)\) SELECT \* FROM cte/
|
|
178
174
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D')]
|
|
179
175
|
os.map{|o| o.ds}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E'), @c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
180
176
|
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
@@ -182,18 +178,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
182
178
|
os.map{|o| o.cs}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E')], [@c.load(:i=>3, :name=>'00', :pi=>6)], [@c.load(:i=>4, :name=>'?', :pi=>7)]]
|
|
183
179
|
os.map{|o1| o1.cs.map{|o2| o2.cs}}.should == [[[@c.load(:i=>3, :name=>'00', :pi=>6)], []], [[]], [[@c.load(:i=>5, :name=>'?', :pi=>4)]]]
|
|
184
180
|
os.map{|o1| o1.cs.map{|o2| o2.cs.map{|o3| o3.cs}}}.should == [[[[]], []], [[]], [[[]]]]
|
|
185
|
-
MODEL_DB.
|
|
181
|
+
MODEL_DB.sqls.should == []
|
|
186
182
|
end
|
|
187
183
|
|
|
188
184
|
it "should eagerly load descendants to a given level" do
|
|
189
185
|
@c.plugin :rcte_tree
|
|
190
|
-
@ds.
|
|
186
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
191
187
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2, :x_level_x=>0}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2, :x_level_x=>0},
|
|
192
188
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6, :x_level_x=>0}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2, :x_level_x=>1},
|
|
193
189
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7, :x_level_x=>0}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7, :x_level_x=>1}]]
|
|
194
190
|
os = @ds.eager(:descendants=>2).all
|
|
195
|
-
MODEL_DB.sqls
|
|
196
|
-
|
|
191
|
+
sqls = MODEL_DB.sqls
|
|
192
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
193
|
+
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\*, 0 AS x_level_x FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
|
|
197
194
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D')]
|
|
198
195
|
os.map{|o| o.descendants}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E'), @c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
199
196
|
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
@@ -201,18 +198,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
201
198
|
os.map{|o| o.associations[:children]}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E')], [@c.load(:id=>3, :name=>'00', :parent_id=>6)], [@c.load(:id=>4, :name=>'?', :parent_id=>7)]]
|
|
202
199
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children]}}.should == [[[@c.load(:id=>3, :name=>'00', :parent_id=>6)], []], [[]], [[@c.load(:id=>5, :name=>'?', :parent_id=>4)]]]
|
|
203
200
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children].map{|o3| o3.associations[:children]}}}.should == [[[[]], []], [[]], [[nil]]]
|
|
204
|
-
MODEL_DB.
|
|
201
|
+
MODEL_DB.sqls.should == []
|
|
205
202
|
end
|
|
206
203
|
|
|
207
204
|
it "should eagerly load descendants to a given level when giving options" do
|
|
208
205
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :level_alias=>:lal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
209
|
-
@ds.
|
|
206
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
|
210
207
|
[{:i=>6, :pi=>2, :name=>'C', :kal=>2, :lal=>0}, {:i=>9, :pi=>2, :name=>'E', :kal=>2, :lal=>0},
|
|
211
208
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6, :lal=>0}, {:i=>3, :name=>'00', :pi=>6, :kal=>2, :lal=>1},
|
|
212
209
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7, :lal=>0}, {:i=>5, :name=>'?', :pi=>4, :kal=>7, :lal=>1}]]
|
|
213
210
|
os = @ds.eager(:ds=>2).all
|
|
214
|
-
MODEL_DB.sqls
|
|
215
|
-
|
|
211
|
+
sqls = MODEL_DB.sqls
|
|
212
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
213
|
+
sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\*, 0 AS lal FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\*, \(cte\.lal \+ 1\) AS lal FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\) WHERE \(cte\.lal < 1\)\) SELECT \* FROM cte/
|
|
216
214
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D')]
|
|
217
215
|
os.map{|o| o.ds}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E'), @c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
218
216
|
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
@@ -220,18 +218,18 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
220
218
|
os.map{|o| o.associations[:cs]}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E')], [@c.load(:i=>3, :name=>'00', :pi=>6)], [@c.load(:i=>4, :name=>'?', :pi=>7)]]
|
|
221
219
|
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs]}}.should == [[[@c.load(:i=>3, :name=>'00', :pi=>6)], []], [[]], [[@c.load(:i=>5, :name=>'?', :pi=>4)]]]
|
|
222
220
|
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs].map{|o3| o3.associations[:cs]}}}.should == [[[[]], []], [[]], [[nil]]]
|
|
223
|
-
MODEL_DB.
|
|
221
|
+
MODEL_DB.sqls.should == []
|
|
224
222
|
end
|
|
225
223
|
|
|
226
224
|
it "should eagerly load descendants respecting association option :conditions" do
|
|
227
225
|
@c.plugin :rcte_tree, :conditions => {:i => 1}
|
|
228
|
-
@ds.
|
|
226
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
229
227
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
|
230
228
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
|
231
229
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
|
232
230
|
os = @ds.eager(:descendants).all
|
|
233
|
-
MODEL_DB.sqls
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
sqls = MODEL_DB.sqls
|
|
232
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
233
|
+
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(parent_id IN \([267], [267], [267]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
|
236
234
|
end
|
|
237
235
|
end
|
|
@@ -43,19 +43,17 @@ describe "Sequel::Schema::Generator dump methods" do
|
|
|
43
43
|
index [:b, :c], :unique=>true
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
t
|
|
46
|
+
g.dump_indexes(:add_index=>:t).should == (<<END_CODE).strip
|
|
47
47
|
add_index :t, [:a]
|
|
48
48
|
add_index :t, [:c, :e], :name=>:blah
|
|
49
49
|
add_index :t, [:b, :c], :unique=>true
|
|
50
50
|
END_CODE
|
|
51
|
-
g.dump_indexes(:add_index=>:t).should == t.strip
|
|
52
51
|
|
|
53
|
-
t
|
|
52
|
+
g.dump_indexes(:drop_index=>:t).should == (<<END_CODE).strip
|
|
54
53
|
drop_index :t, [:a]
|
|
55
54
|
drop_index :t, [:c, :e], :name=>:blah
|
|
56
55
|
drop_index :t, [:b, :c], :unique=>true
|
|
57
56
|
END_CODE
|
|
58
|
-
g.dump_indexes(:drop_index=>:t).should == t.strip
|
|
59
57
|
end
|
|
60
58
|
|
|
61
59
|
it "should raise an error if you try to dump a Generator that uses a constraint with a proc" do
|
|
@@ -263,8 +261,8 @@ END_MIG
|
|
|
263
261
|
s.each{|_, c| c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type])}
|
|
264
262
|
s
|
|
265
263
|
end
|
|
266
|
-
@d.dump_table_schema(:t4).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.parse(\"2008-10-29\")\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n Time :c9, :default=>
|
|
267
|
-
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>
|
|
264
|
+
@d.dump_table_schema(:t4).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.parse(\"2008-10-29\")\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n Time :c9, :default=>Sequel::SQLTime.parse(\"10:20:30\"), :only_time=>true\n String :c10\nend"
|
|
265
|
+
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30\")\n column :c10, \"interval\", :default=>\"'6 weeks'\".lit\nend"
|
|
268
266
|
end
|
|
269
267
|
|
|
270
268
|
it "should not use a '...'.lit as a fallback if using MySQL with the :same_db option" do
|
|
@@ -296,7 +294,7 @@ END_MIG
|
|
|
296
294
|
i = 0
|
|
297
295
|
types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
|
|
298
296
|
end
|
|
299
|
-
|
|
297
|
+
@d.dump_table_schema(:x).should == (<<END_MIG).chomp
|
|
300
298
|
create_table(:x) do
|
|
301
299
|
Integer :c1
|
|
302
300
|
Integer :c2
|
|
@@ -365,6 +363,5 @@ create_table(:x) do
|
|
|
365
363
|
Bignum :c65
|
|
366
364
|
end
|
|
367
365
|
END_MIG
|
|
368
|
-
@d.dump_table_schema(:x).should == table.chomp
|
|
369
366
|
end
|
|
370
367
|
end
|