viking-sequel 3.10.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 +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "optimistic_locking plugin" do
|
4
|
+
before do
|
5
|
+
@c = Class.new(Sequel::Model(:people)) do
|
6
|
+
end
|
7
|
+
h = {1=>{:id=>1, :name=>'John', :lock_version=>2}}
|
8
|
+
lv = @lv = "lock_version"
|
9
|
+
@c.dataset.quote_identifiers = false
|
10
|
+
@c.dataset.meta_def(:h){h}
|
11
|
+
@c.dataset.meta_def(:lv){lv}
|
12
|
+
@c.dataset.meta_def(:update) do |opts|
|
13
|
+
case update_sql(opts)
|
14
|
+
when /UPDATE people SET (name|#{lv}) = ('Jim'|'Bob'|\d+), (?:name|#{lv}) = ('Jim'|'Bob'|\d+) WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
|
15
|
+
name, nlv = $1 == 'name' ? [$2, $3] : [$3, $2]
|
16
|
+
m = h[$4.to_i]
|
17
|
+
if m && m[:lock_version] == $5.to_i
|
18
|
+
m.merge!(:name=>name.gsub("'", ''), :lock_version=>nlv.to_i)
|
19
|
+
1
|
20
|
+
else
|
21
|
+
0
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts update_sql(opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@c.dataset.instance_eval do
|
28
|
+
def fetch_rows(sql)
|
29
|
+
m = h[1].dup
|
30
|
+
v = m.delete(:lock_version)
|
31
|
+
m[lv.to_sym] = v
|
32
|
+
yield(m)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@c.dataset.meta_def(:delete) do
|
36
|
+
case delete_sql
|
37
|
+
when /DELETE FROM people WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
|
38
|
+
m = h[$1.to_i]
|
39
|
+
if m && m[lv.to_sym] == $2.to_i
|
40
|
+
h.delete[$1.to_i]
|
41
|
+
1
|
42
|
+
else
|
43
|
+
0
|
44
|
+
end
|
45
|
+
else
|
46
|
+
puts delete_sql
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@c.columns :id, :name, :lock_version
|
50
|
+
@c.plugin :optimistic_locking
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "should raise an error when updating a stale record" do
|
54
|
+
p1 = @c[1]
|
55
|
+
p2 = @c[1]
|
56
|
+
p1.update(:name=>'Jim')
|
57
|
+
proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should raise an error when destroying a stale record" do
|
61
|
+
p1 = @c[1]
|
62
|
+
p2 = @c[1]
|
63
|
+
p1.update(:name=>'Jim')
|
64
|
+
proc{p2.destroy}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
65
|
+
end
|
66
|
+
|
67
|
+
specify "should not raise an error when updating the same record twice" do
|
68
|
+
p1 = @c[1]
|
69
|
+
p1.update(:name=>'Jim')
|
70
|
+
proc{p1.update(:name=>'Bob')}.should_not raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
specify "should allow changing the lock column via model.lock_column=" do
|
74
|
+
@lv.replace('lv')
|
75
|
+
@c.columns :id, :name, :lv
|
76
|
+
@c.lock_column = :lv
|
77
|
+
p1 = @c[1]
|
78
|
+
p2 = @c[1]
|
79
|
+
p1.update(:name=>'Jim')
|
80
|
+
proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
81
|
+
end
|
82
|
+
|
83
|
+
specify "should allow changing the lock column via plugin option" do
|
84
|
+
@lv.replace('lv')
|
85
|
+
@c.columns :id, :name, :lv
|
86
|
+
@c.plugin :optimistic_locking, :lock_column=>:lv
|
87
|
+
p1 = @c[1]
|
88
|
+
p2 = @c[1]
|
89
|
+
p1.update(:name=>'Jim')
|
90
|
+
proc{p2.destroy}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
91
|
+
end
|
92
|
+
|
93
|
+
specify "should work when subclassing" do
|
94
|
+
c = Class.new(@c)
|
95
|
+
p1 = c[1]
|
96
|
+
p2 = c[1]
|
97
|
+
p1.update(:name=>'Jim')
|
98
|
+
proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
context "A paginated dataset" do
|
4
|
+
before do
|
5
|
+
@d = Sequel::Dataset.new(nil)
|
6
|
+
@d.meta_def(:count) {153}
|
7
|
+
|
8
|
+
@paginated = @d.paginate(1, 20)
|
9
|
+
end
|
10
|
+
|
11
|
+
specify "should raise an error if the dataset already has a limit" do
|
12
|
+
proc{@d.limit(10).paginate(1,10)}.should raise_error(Sequel::Error)
|
13
|
+
proc{@paginated.paginate(2,20)}.should raise_error(Sequel::Error)
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "should set the limit and offset options correctly" do
|
17
|
+
@paginated.opts[:limit].should == 20
|
18
|
+
@paginated.opts[:offset].should == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
specify "should set the page count correctly" do
|
22
|
+
@paginated.page_count.should == 8
|
23
|
+
@d.paginate(1, 50).page_count.should == 4
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "should set the current page number correctly" do
|
27
|
+
@paginated.current_page.should == 1
|
28
|
+
@d.paginate(3, 50).current_page.should == 3
|
29
|
+
end
|
30
|
+
|
31
|
+
specify "should return the next page number or nil if we're on the last" do
|
32
|
+
@paginated.next_page.should == 2
|
33
|
+
@d.paginate(4, 50).next_page.should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "should return the previous page number or nil if we're on the last" do
|
37
|
+
@paginated.prev_page.should be_nil
|
38
|
+
@d.paginate(4, 50).prev_page.should == 3
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "should return the page range" do
|
42
|
+
@paginated.page_range.should == (1..8)
|
43
|
+
@d.paginate(4, 50).page_range.should == (1..4)
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "should return the record range for the current page" do
|
47
|
+
@paginated.current_page_record_range.should == (1..20)
|
48
|
+
@d.paginate(4, 50).current_page_record_range.should == (151..153)
|
49
|
+
@d.paginate(5, 50).current_page_record_range.should == (0..0)
|
50
|
+
end
|
51
|
+
|
52
|
+
specify "should return the record count for the current page" do
|
53
|
+
@paginated.current_page_record_count.should == 20
|
54
|
+
@d.paginate(3, 50).current_page_record_count.should == 50
|
55
|
+
@d.paginate(4, 50).current_page_record_count.should == 3
|
56
|
+
@d.paginate(5, 50).current_page_record_count.should == 0
|
57
|
+
end
|
58
|
+
|
59
|
+
specify "should know if current page is last page" do
|
60
|
+
@paginated.last_page?.should be_false
|
61
|
+
@d.paginate(2, 20).last_page?.should be_false
|
62
|
+
@d.paginate(5, 30).last_page?.should be_false
|
63
|
+
@d.paginate(6, 30).last_page?.should be_true
|
64
|
+
end
|
65
|
+
|
66
|
+
specify "should know if current page is first page" do
|
67
|
+
@paginated.first_page?.should be_true
|
68
|
+
@d.paginate(1, 20).first_page?.should be_true
|
69
|
+
@d.paginate(2, 20).first_page?.should be_false
|
70
|
+
end
|
71
|
+
|
72
|
+
specify "should work with fixed sql" do
|
73
|
+
ds = @d.clone(:sql => 'select * from blah')
|
74
|
+
ds.meta_def(:count) {150}
|
75
|
+
ds.paginate(2, 50).sql.should == 'SELECT * FROM (select * from blah) AS t1 LIMIT 50 OFFSET 50'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "Dataset#each_page" do
|
80
|
+
before do
|
81
|
+
@d = Sequel::Dataset.new(nil).from(:items)
|
82
|
+
@d.meta_def(:count) {153}
|
83
|
+
end
|
84
|
+
|
85
|
+
specify "should raise an error if the dataset already has a limit" do
|
86
|
+
proc{@d.limit(10).each_page(10){}}.should raise_error(Sequel::Error)
|
87
|
+
end
|
88
|
+
|
89
|
+
specify "should iterate over each page in the resultset as a paginated dataset" do
|
90
|
+
a = []
|
91
|
+
@d.each_page(50) {|p| a << p}
|
92
|
+
a.map {|p| p.sql}.should == [
|
93
|
+
'SELECT * FROM items LIMIT 50 OFFSET 0',
|
94
|
+
'SELECT * FROM items LIMIT 50 OFFSET 50',
|
95
|
+
'SELECT * FROM items LIMIT 50 OFFSET 100',
|
96
|
+
'SELECT * FROM items LIMIT 50 OFFSET 150',
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
context "Dataset#print" do
|
6
|
+
before do
|
7
|
+
@output = StringIO.new
|
8
|
+
@orig_stdout = $stdout
|
9
|
+
$stdout = @output
|
10
|
+
@dataset = Sequel::Dataset.new(nil).from(:items)
|
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
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
$stdout = @orig_stdout
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "should print out a table with the values" do
|
23
|
+
@dataset.print(:a, :b)
|
24
|
+
@output.rewind
|
25
|
+
@output.read.should == \
|
26
|
+
"+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "should default to the dataset's columns" do
|
30
|
+
@dataset.meta_def(:columns) {[:a, :b]}
|
31
|
+
@dataset.print
|
32
|
+
@output.rewind
|
33
|
+
@output.read.should == \
|
34
|
+
"+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "PrettyTable" do
|
39
|
+
before do
|
40
|
+
@data1 = [
|
41
|
+
{:x => 3, :y => 4}
|
42
|
+
]
|
43
|
+
|
44
|
+
@data2 = [
|
45
|
+
{:a => 23, :b => 45},
|
46
|
+
{:a => 45, :b => 2377}
|
47
|
+
]
|
48
|
+
|
49
|
+
@data3 = [
|
50
|
+
{:aaa => 1},
|
51
|
+
{:bb => 2},
|
52
|
+
{:c => 3}
|
53
|
+
]
|
54
|
+
|
55
|
+
@output = StringIO.new
|
56
|
+
@orig_stdout = $stdout
|
57
|
+
$stdout = @output
|
58
|
+
end
|
59
|
+
|
60
|
+
after do
|
61
|
+
$stdout = @orig_stdout
|
62
|
+
end
|
63
|
+
|
64
|
+
specify "should infer the columns if not given" do
|
65
|
+
Sequel::PrettyTable.print(@data1)
|
66
|
+
@output.rewind
|
67
|
+
@output.read.should =~ \
|
68
|
+
/\n(\|x\|y\|)|(\|y\|x\|)\n/
|
69
|
+
end
|
70
|
+
|
71
|
+
specify "should calculate the maximum width of each column correctly" do
|
72
|
+
Sequel::PrettyTable.print(@data2, [:a, :b])
|
73
|
+
@output.rewind
|
74
|
+
@output.read.should == \
|
75
|
+
"+--+----+\n|a |b |\n+--+----+\n|23| 45|\n|45|2377|\n+--+----+\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
specify "should also take header width into account" do
|
79
|
+
Sequel::PrettyTable.print(@data3, [:aaa, :bb, :c])
|
80
|
+
@output.rewind
|
81
|
+
@output.read.should == \
|
82
|
+
"+---+--+-+\n|aaa|bb|c|\n+---+--+-+\n| 1| | |\n| | 2| |\n| | |3|\n+---+--+-+\n"
|
83
|
+
end
|
84
|
+
|
85
|
+
specify "should print only the specified columns" do
|
86
|
+
Sequel::PrettyTable.print(@data2, [:a])
|
87
|
+
@output.rewind
|
88
|
+
@output.read.should == \
|
89
|
+
"+--+\n|a |\n+--+\n|23|\n|45|\n+--+\n"
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
context "Database#dataset" do
|
4
|
+
before do
|
5
|
+
@db = Sequel::Database.new
|
6
|
+
end
|
7
|
+
|
8
|
+
specify "should delegate to Dataset#query if block is provided" do
|
9
|
+
@d = @db.query {select :x; from :y}
|
10
|
+
@d.should be_a_kind_of(Sequel::Dataset)
|
11
|
+
@d.sql.should == "SELECT x FROM y"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "Dataset#query" do
|
16
|
+
before do
|
17
|
+
@d = Sequel::Dataset.new(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "should support #from" do
|
21
|
+
q = @d.query {from :xxx}
|
22
|
+
q.class.should == @d.class
|
23
|
+
q.sql.should == "SELECT * FROM xxx"
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "should support #select" do
|
27
|
+
q = @d.query do
|
28
|
+
select :a, :b___mongo
|
29
|
+
from :yyy
|
30
|
+
end
|
31
|
+
q.class.should == @d.class
|
32
|
+
q.sql.should == "SELECT a, b AS mongo FROM yyy"
|
33
|
+
end
|
34
|
+
|
35
|
+
specify "should support #where" do
|
36
|
+
q = @d.query do
|
37
|
+
from :zzz
|
38
|
+
where(:x + 2 > :y + 3)
|
39
|
+
end
|
40
|
+
q.class.should == @d.class
|
41
|
+
q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
|
42
|
+
|
43
|
+
q = @d.from(:zzz).query do
|
44
|
+
where((:x.sql_number > 1) & (:y.sql_number > 2))
|
45
|
+
end
|
46
|
+
q.class.should == @d.class
|
47
|
+
q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
|
48
|
+
|
49
|
+
q = @d.from(:zzz).query do
|
50
|
+
where :x => 33
|
51
|
+
end
|
52
|
+
q.class.should == @d.class
|
53
|
+
q.sql.should == "SELECT * FROM zzz WHERE (x = 33)"
|
54
|
+
end
|
55
|
+
|
56
|
+
specify "should support #group_by and #having" do
|
57
|
+
q = @d.query do
|
58
|
+
from :abc
|
59
|
+
group_by :id
|
60
|
+
having(:x.sql_number >= 2)
|
61
|
+
end
|
62
|
+
q.class.should == @d.class
|
63
|
+
q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
|
64
|
+
end
|
65
|
+
|
66
|
+
specify "should support #order, #order_by" do
|
67
|
+
q = @d.query do
|
68
|
+
from :xyz
|
69
|
+
order_by :stamp
|
70
|
+
end
|
71
|
+
q.class.should == @d.class
|
72
|
+
q.sql.should == "SELECT * FROM xyz ORDER BY stamp"
|
73
|
+
end
|
74
|
+
|
75
|
+
specify "should raise on non-chainable method calls" do
|
76
|
+
proc {@d.query {first_source}}.should raise_error(Sequel::Error)
|
77
|
+
end
|
78
|
+
|
79
|
+
specify "should raise on each, insert, update, delete" do
|
80
|
+
proc {@d.query {each}}.should raise_error(Sequel::Error)
|
81
|
+
proc {@d.query {insert(:x => 1)}}.should raise_error(Sequel::Error)
|
82
|
+
proc {@d.query {update(:x => 1)}}.should raise_error(Sequel::Error)
|
83
|
+
proc {@d.query {delete}}.should raise_error(Sequel::Error)
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model, "rcte_tree" do
|
4
|
+
before do
|
5
|
+
@c = Class.new(Sequel::Model(MODEL_DB[:nodes]))
|
6
|
+
@c.class_eval do
|
7
|
+
def self.name; 'Node'; end
|
8
|
+
columns :id, :name, :parent_id, :i, :pi
|
9
|
+
end
|
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
|
+
@o = @c.load(:id=>2, :parent_id=>1, :name=>'AA', :i=>3, :pi=>4)
|
19
|
+
MODEL_DB.reset
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should define the correct associations" do
|
23
|
+
@c.plugin :rcte_tree
|
24
|
+
@c.associations.sort_by{|x| x.to_s}.should == [:ancestors, :children, :descendants, :parent]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should define the correct associations when giving options" do
|
28
|
+
@c.plugin :rcte_tree, :ancestors=>{:name=>:as}, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}, :parent=>{:name=>:p}
|
29
|
+
@c.associations.sort_by{|x| x.to_s}.should == [:as, :cs, :ds, :p]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should use the correct SQL for lazy associations" do
|
33
|
+
@c.plugin :rcte_tree
|
34
|
+
@o.parent_dataset.sql.should == 'SELECT * FROM nodes WHERE (nodes.id = 1) LIMIT 1'
|
35
|
+
@o.children_dataset.sql.should == 'SELECT * FROM nodes WHERE (nodes.parent_id = 2)'
|
36
|
+
@o.ancestors_dataset.sql.should == 'WITH t AS (SELECT * FROM nodes WHERE (id = 1) UNION ALL SELECT nodes.* FROM nodes INNER JOIN t ON (t.parent_id = nodes.id)) SELECT * FROM t'
|
37
|
+
@o.descendants_dataset.sql.should == 'WITH t AS (SELECT * FROM nodes WHERE (parent_id = 2) UNION ALL SELECT nodes.* FROM nodes INNER JOIN t ON (t.id = nodes.parent_id)) SELECT * FROM t'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use the correct SQL for lazy associations when giving options" do
|
41
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :cte_name=>:cte, :order=>:name, :ancestors=>{:name=>:as}, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}, :parent=>{:name=>:p}
|
42
|
+
@o.p_dataset.sql.should == 'SELECT * FROM nodes WHERE (nodes.i = 4) ORDER BY name LIMIT 1'
|
43
|
+
@o.cs_dataset.sql.should == 'SELECT * FROM nodes WHERE (nodes.pi = 3) ORDER BY name'
|
44
|
+
@o.as_dataset.sql.should == 'WITH cte AS (SELECT * FROM nodes WHERE (i = 4) UNION ALL SELECT nodes.* FROM nodes INNER JOIN cte ON (cte.pi = nodes.i)) SELECT * FROM cte ORDER BY name'
|
45
|
+
@o.ds_dataset.sql.should == 'WITH cte AS (SELECT * FROM nodes WHERE (pi = 3) UNION ALL SELECT nodes.* FROM nodes INNER JOIN cte ON (cte.i = nodes.pi)) SELECT * FROM cte ORDER BY name'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should add all parent associations when lazily loading ancestors" do
|
49
|
+
@c.plugin :rcte_tree
|
50
|
+
@ds.row_sets = [[{:id=>1, :name=>'A', :parent_id=>3}, {:id=>4, :name=>'B', :parent_id=>nil}, {:id=>3, :name=>'?', :parent_id=>4}]]
|
51
|
+
@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)]
|
52
|
+
@o.associations[:parent].should == @c.load(:id=>1, :name=>'A', :parent_id=>3)
|
53
|
+
@o.associations[:parent].associations[:parent].should == @c.load(:id=>3, :name=>'?', :parent_id=>4)
|
54
|
+
@o.associations[:parent].associations[:parent].associations[:parent].should == @c.load(:id=>4, :name=>'B', :parent_id=>nil)
|
55
|
+
@o.associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).should == nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should add all parent associations when lazily loading ancestors and giving options" do
|
59
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
60
|
+
@ds.row_sets = [[{:i=>4, :name=>'A', :pi=>5}, {:i=>6, :name=>'B', :pi=>nil}, {:i=>5, :name=>'?', :pi=>6}]]
|
61
|
+
@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)]
|
62
|
+
@o.associations[:p].should == @c.load(:i=>4, :name=>'A', :pi=>5)
|
63
|
+
@o.associations[:p].associations[:p].should == @c.load(:i=>5, :name=>'?', :pi=>6)
|
64
|
+
@o.associations[:p].associations[:p].associations[:p].should == @c.load(:i=>6, :name=>'B', :pi=>nil)
|
65
|
+
@o.associations[:p].associations[:p].associations[:p].associations.fetch(:p, 1).should == nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should add all children associations when lazily loading descendants" do
|
69
|
+
@c.plugin :rcte_tree
|
70
|
+
@ds.row_sets = [[{: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}]]
|
71
|
+
@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)]
|
72
|
+
@o.associations[:children].should == [@c.load(:id=>1, :name=>'A', :parent_id=>2), @c.load(:id=>4, :name=>'B', :parent_id=>2)]
|
73
|
+
@o.associations[:children].map{|c1| c1.associations[:children]}.should == [[@c.load(:id=>3, :name=>'??', :parent_id=>1)], []]
|
74
|
+
@o.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.should == [[[@c.load(:id=>5, :name=>'?', :parent_id=>3)]], []]
|
75
|
+
@o.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children]}}}.should == [[[[]]], []]
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should add all children associations when lazily loading descendants and giving options" do
|
79
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
80
|
+
@ds.row_sets = [[{:i=>7, :name=>'??', :pi=>5}, {:i=>5, :name=>'A', :pi=>3}, {:i=>6, :name=>'B', :pi=>3}, {:i=>8, :name=>'?', :pi=>7}]]
|
81
|
+
@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)]
|
82
|
+
@o.associations[:cs].should == [@c.load(:i=>5, :name=>'A', :pi=>3), @c.load(:i=>6, :name=>'B', :pi=>3)]
|
83
|
+
@o.associations[:cs].map{|c1| c1.associations[:cs]}.should == [[@c.load(:i=>7, :name=>'??', :pi=>5)], []]
|
84
|
+
@o.associations[:cs].map{|c1| c1.associations[:cs].map{|c2| c2.associations[:cs]}}.should == [[[@c.load(:i=>8, :name=>'?', :pi=>7)]], []]
|
85
|
+
@o.associations[:cs].map{|c1| c1.associations[:cs].map{|c2| c2.associations[:cs].map{|c3| c3.associations[:cs]}}}.should == [[[[]]], []]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should eagerly load ancestors" do
|
89
|
+
@c.plugin :rcte_tree
|
90
|
+
@ds.row_sets = [[{: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'}],
|
91
|
+
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
92
|
+
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
93
|
+
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
94
|
+
os = @ds.eager(:ancestors).all
|
95
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
96
|
+
MODEL_DB.new_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/
|
97
|
+
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')]
|
98
|
+
os.map{|o| o.ancestors}.should == [[@c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
99
|
+
[@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)],
|
100
|
+
[@c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
101
|
+
[]]
|
102
|
+
os.map{|o| o.parent}.should == [@c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>2, :name=>'AA', :parent_id=>1), @c.load(:id=>1, :name=>'00', :parent_id=>8), nil]
|
103
|
+
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]
|
104
|
+
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]
|
105
|
+
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]
|
106
|
+
MODEL_DB.new_sqls.should == []
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should eagerly load ancestors when giving options" do
|
110
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
111
|
+
@ds.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}, {:i=>9, :pi=>nil, :name=>'E'}],
|
112
|
+
[{:i=>2, :name=>'AA', :pi=>1, :kal=>2},
|
113
|
+
{:i=>1, :name=>'00', :pi=>8, :kal=>1}, {:i=>1, :name=>'00', :pi=>8, :kal=>2},
|
114
|
+
{:i=>8, :name=>'?', :pi=>nil, :kal=>2}, {:i=>8, :name=>'?', :pi=>nil, :kal=>1}]]
|
115
|
+
os = @ds.eager(:as).all
|
116
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
117
|
+
MODEL_DB.new_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/
|
118
|
+
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')]
|
119
|
+
os.map{|o| o.as}.should == [[@c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
120
|
+
[@c.load(:i=>2, :name=>'AA', :pi=>1), @c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
121
|
+
[@c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
122
|
+
[]]
|
123
|
+
os.map{|o| o.p}.should == [@c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>2, :name=>'AA', :pi=>1), @c.load(:i=>1, :name=>'00', :pi=>8), nil]
|
124
|
+
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]
|
125
|
+
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]
|
126
|
+
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]
|
127
|
+
MODEL_DB.new_sqls.should == []
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should eagerly load descendants" do
|
131
|
+
@c.plugin :rcte_tree
|
132
|
+
@ds.row_sets = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
133
|
+
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
134
|
+
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
135
|
+
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
136
|
+
os = @ds.eager(:descendants).all
|
137
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
138
|
+
MODEL_DB.new_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/
|
139
|
+
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')]
|
140
|
+
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)],
|
141
|
+
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
142
|
+
[@c.load(:id=>4, :name=>'?', :parent_id=>7), @c.load(:id=>5, :name=>'?', :parent_id=>4)]]
|
143
|
+
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)]]
|
144
|
+
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)]]]
|
145
|
+
os.map{|o1| o1.children.map{|o2| o2.children.map{|o3| o3.children}}}.should == [[[[]], []], [[]], [[[]]]]
|
146
|
+
MODEL_DB.new_sqls.should == []
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should eagerly load descendants when giving options" do
|
150
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
151
|
+
@ds.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
152
|
+
[{:i=>6, :pi=>2, :name=>'C', :kal=>2}, {:i=>9, :pi=>2, :name=>'E', :kal=>2},
|
153
|
+
{:i=>3, :name=>'00', :pi=>6, :kal=>6}, {:i=>3, :name=>'00', :pi=>6, :kal=>2},
|
154
|
+
{:i=>4, :name=>'?', :pi=>7, :kal=>7}, {:i=>5, :name=>'?', :pi=>4, :kal=>7}]]
|
155
|
+
os = @ds.eager(:ds).all
|
156
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
157
|
+
MODEL_DB.new_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/
|
158
|
+
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')]
|
159
|
+
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)],
|
160
|
+
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
161
|
+
[@c.load(:i=>4, :name=>'?', :pi=>7), @c.load(:i=>5, :name=>'?', :pi=>4)]]
|
162
|
+
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)]]
|
163
|
+
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)]]]
|
164
|
+
os.map{|o1| o1.cs.map{|o2| o2.cs.map{|o3| o3.cs}}}.should == [[[[]], []], [[]], [[[]]]]
|
165
|
+
MODEL_DB.new_sqls.should == []
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should eagerly load descendants to a given level" do
|
169
|
+
@c.plugin :rcte_tree
|
170
|
+
@ds.row_sets = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
171
|
+
[{: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},
|
172
|
+
{: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},
|
173
|
+
{: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}]]
|
174
|
+
os = @ds.eager(:descendants=>2).all
|
175
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
176
|
+
MODEL_DB.new_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/
|
177
|
+
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')]
|
178
|
+
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)],
|
179
|
+
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
180
|
+
[@c.load(:id=>4, :name=>'?', :parent_id=>7), @c.load(:id=>5, :name=>'?', :parent_id=>4)]]
|
181
|
+
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)]]
|
182
|
+
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)]]]
|
183
|
+
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children].map{|o3| o3.associations[:children]}}}.should == [[[[]], []], [[]], [[nil]]]
|
184
|
+
MODEL_DB.new_sqls.should == []
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should eagerly load descendants to a given level when giving options" do
|
188
|
+
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :level_alias=>:lal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
189
|
+
@ds.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
190
|
+
[{:i=>6, :pi=>2, :name=>'C', :kal=>2, :lal=>0}, {:i=>9, :pi=>2, :name=>'E', :kal=>2, :lal=>0},
|
191
|
+
{:i=>3, :name=>'00', :pi=>6, :kal=>6, :lal=>0}, {:i=>3, :name=>'00', :pi=>6, :kal=>2, :lal=>1},
|
192
|
+
{:i=>4, :name=>'?', :pi=>7, :kal=>7, :lal=>0}, {:i=>5, :name=>'?', :pi=>4, :kal=>7, :lal=>1}]]
|
193
|
+
os = @ds.eager(:ds=>2).all
|
194
|
+
MODEL_DB.sqls.first.should == "SELECT * FROM nodes"
|
195
|
+
MODEL_DB.new_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/
|
196
|
+
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')]
|
197
|
+
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)],
|
198
|
+
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
199
|
+
[@c.load(:i=>4, :name=>'?', :pi=>7), @c.load(:i=>5, :name=>'?', :pi=>4)]]
|
200
|
+
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)]]
|
201
|
+
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)]]]
|
202
|
+
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs].map{|o3| o3.associations[:cs]}}}.should == [[[[]], []], [[]], [[nil]]]
|
203
|
+
MODEL_DB.new_sqls.should == []
|
204
|
+
end
|
205
|
+
end
|