sequel 3.21.0 → 3.36.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 +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -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 +17 -11
- data/lib/sequel/adapters/do/postgres.rb +1 -57
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -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 +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -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 +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- 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 +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -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 +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- 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 +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +123 -8
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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/schema.rb +7 -2
- 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 +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -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/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- 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/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/caching_spec.rb +47 -51
- 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/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +251 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +85 -43
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +9 -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 +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -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 +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
|
@@ -1,89 +1,58 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
3
|
describe "Sequel sql_expr extension" do
|
|
4
|
+
before do
|
|
5
|
+
@ds = Sequel.mock.dataset
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
specify "Object#sql_expr should wrap the object in a GenericComplexExpression" do
|
|
5
9
|
o = Object.new
|
|
10
|
+
def o.sql_literal(ds) 'foo' end
|
|
6
11
|
s = o.sql_expr
|
|
7
|
-
s.should
|
|
8
|
-
s.
|
|
9
|
-
s.
|
|
10
|
-
(s
|
|
11
|
-
(s
|
|
12
|
-
(s
|
|
13
|
-
s.
|
|
14
|
-
s.
|
|
15
|
-
s.
|
|
16
|
-
s.
|
|
17
|
-
s.desc.should be_a_kind_of(Sequel::SQL::OrderedExpression)
|
|
18
|
-
s.sql_string.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
12
|
+
@ds.literal(s).should == "foo"
|
|
13
|
+
@ds.literal(s+1).should == "(foo + 1)"
|
|
14
|
+
@ds.literal(s & true).should == "(foo AND 't')"
|
|
15
|
+
@ds.literal(s < 1).should == "(foo < 1)"
|
|
16
|
+
@ds.literal(s.sql_subscript(1)).should == "foo[1]"
|
|
17
|
+
@ds.literal(s.like('a')).should == "(foo LIKE 'a')"
|
|
18
|
+
@ds.literal(s.as(:a)).should == "foo AS a"
|
|
19
|
+
@ds.literal(s.cast(Integer)).should == "CAST(foo AS integer)"
|
|
20
|
+
@ds.literal(s.desc).should == "foo DESC"
|
|
21
|
+
@ds.literal(s.sql_string + '1').should == "(foo || '1')"
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
specify "Numeric#sql_expr should wrap the object in a NumericExpression" do
|
|
22
|
-
[1, 2.0, 2^
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
s.op.should == :NOOP
|
|
26
|
-
s.args.should == [o]
|
|
25
|
+
[1, 2.0, 2^70, BigDecimal.new('1.0')].each do |o|
|
|
26
|
+
@ds.literal(o.sql_expr).should == @ds.literal(o)
|
|
27
|
+
@ds.literal(o.sql_expr + 1).should == "(#{@ds.literal(o)} + 1)"
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
specify "String#sql_expr should wrap the object in a StringExpression" do
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
s.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
34
|
-
s.op.should == :NOOP
|
|
35
|
-
s.args.should == [o]
|
|
32
|
+
@ds.literal("".sql_expr).should == "''"
|
|
33
|
+
@ds.literal("".sql_expr + :a).should == "('' || a)"
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
specify "NilClass, TrueClass, and FalseClass#sql_expr should wrap the object in a BooleanExpression" do
|
|
39
37
|
[nil, true, false].each do |o|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
s.op.should == :NOOP
|
|
43
|
-
s.args.should == [o]
|
|
38
|
+
@ds.literal(o.sql_expr).should == @ds.literal(o)
|
|
39
|
+
@ds.literal(o.sql_expr & :a).should == "(#{@ds.literal(o)} AND a)"
|
|
44
40
|
end
|
|
45
41
|
end
|
|
46
42
|
|
|
47
43
|
specify "Proc#sql_expr should should treat the object as a virtual row block" do
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
s = proc{a__b}.sql_expr
|
|
53
|
-
s.should be_a_kind_of(Sequel::SQL::QualifiedIdentifier)
|
|
54
|
-
s.table.should == "a"
|
|
55
|
-
s.column.should == "b"
|
|
56
|
-
|
|
57
|
-
s = proc{a(b)}.sql_expr
|
|
58
|
-
s.should be_a_kind_of(Sequel::SQL::Function)
|
|
59
|
-
s.f.should == :a
|
|
60
|
-
s.args.length.should == 1
|
|
61
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
62
|
-
s.args.first.value.should == :b
|
|
44
|
+
@ds.literal(proc{a}.sql_expr).should == "a"
|
|
45
|
+
@ds.literal(proc{a__b}.sql_expr).should == "a.b"
|
|
46
|
+
@ds.literal(proc{a(b)}.sql_expr).should == "a(b)"
|
|
63
47
|
end
|
|
64
48
|
|
|
65
49
|
specify "Proc#sql_expr should should wrap the object in a GenericComplexExpression if the object is not already an expression" do
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
s.op.should == :NOOP
|
|
69
|
-
s.args.should == [1]
|
|
50
|
+
@ds.literal(proc{1}.sql_expr).should == "1"
|
|
51
|
+
@ds.literal(proc{1}.sql_expr + 2).should == "(1 + 2)"
|
|
70
52
|
end
|
|
71
53
|
|
|
72
54
|
specify "Proc#sql_expr should should convert a hash or array of two element arrays to a BooleanExpression" do
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
s.op.should == :"="
|
|
76
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
77
|
-
s.args.first.value.should == :a
|
|
78
|
-
s.args.last.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
79
|
-
s.args.last.value.should == :b
|
|
80
|
-
|
|
81
|
-
s = proc{[[a,b]]}.sql_expr
|
|
82
|
-
s.should be_a_kind_of(Sequel::SQL::BooleanExpression)
|
|
83
|
-
s.op.should == :"="
|
|
84
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
85
|
-
s.args.first.value.should == :a
|
|
86
|
-
s.args.last.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
87
|
-
s.args.last.value.should == :b
|
|
55
|
+
@ds.literal(proc{{a=>b}}.sql_expr).should == "(a = b)"
|
|
56
|
+
@ds.literal(proc{[[a, b]]}.sql_expr & :a).should == "((a = b) AND a)"
|
|
88
57
|
end
|
|
89
58
|
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::StaticCache" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock
|
|
6
|
+
@db.fetch = [{:id=>1}, {:id=>2}]
|
|
7
|
+
@c = Class.new(Sequel::Model(@db[:t]))
|
|
8
|
+
@c.columns :id
|
|
9
|
+
@c.plugin :static_cache
|
|
10
|
+
@c1 = @c.cache[1]
|
|
11
|
+
@c2 = @c.cache[2]
|
|
12
|
+
@db.sqls
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should use a ruby hash as a cache of all model instances" do
|
|
16
|
+
@c.cache.should == {1=>@c.load(:id=>1), 2=>@c.load(:id=>2)}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should work correctly with composite keys" do
|
|
20
|
+
@db.fetch = [{:id=>1, :id2=>1}, {:id=>2, :id2=>1}]
|
|
21
|
+
@c = Class.new(Sequel::Model(@db[:t]))
|
|
22
|
+
@c.columns :id, :id2
|
|
23
|
+
@c.set_primary_key([:id, :id2])
|
|
24
|
+
@c.plugin :static_cache
|
|
25
|
+
@db.sqls
|
|
26
|
+
@c1 = @c.cache[[1, 2]]
|
|
27
|
+
@c2 = @c.cache[[2, 1]]
|
|
28
|
+
@c[[1, 2]].should equal(@c1)
|
|
29
|
+
@c[[2, 1]].should equal(@c2)
|
|
30
|
+
@db.sqls.should == []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should make .[] method with primary key use the cache" do
|
|
34
|
+
@c[1].should equal(@c1)
|
|
35
|
+
@c[2].should equal(@c2)
|
|
36
|
+
@c[3].should be_nil
|
|
37
|
+
@c[[1, 2]].should be_nil
|
|
38
|
+
@c[nil].should be_nil
|
|
39
|
+
@c[].should be_nil
|
|
40
|
+
@db.sqls.should == []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should have .[] with a hash not use the cache" do
|
|
44
|
+
@db.fetch = {:id=>2}
|
|
45
|
+
@c[:id=>2].should == @c2
|
|
46
|
+
@db.sqls.should == ['SELECT * FROM t WHERE (id = 2) LIMIT 1']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should support cache_get_pk" do
|
|
50
|
+
@c.cache_get_pk(1).should equal(@c1)
|
|
51
|
+
@c.cache_get_pk(2).should equal(@c2)
|
|
52
|
+
@c.cache_get_pk(3).should be_nil
|
|
53
|
+
@db.sqls.should == []
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should have each just iterate over the hash's values without sending a query" do
|
|
57
|
+
a = []
|
|
58
|
+
@c.each{|o| a << o}
|
|
59
|
+
a = a.sort_by{|o| o.id}
|
|
60
|
+
a.first.should equal(@c1)
|
|
61
|
+
a.last.should equal(@c2)
|
|
62
|
+
@db.sqls.should == []
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should have map just iterate over the hash's values without sending a query if no argument is given" do
|
|
66
|
+
@c.map{|v| v.id}.sort.should == [1, 2]
|
|
67
|
+
@db.sqls.should == []
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should have map send a query if given an argument" do
|
|
71
|
+
@c.map(:id).sort.should == [1, 2]
|
|
72
|
+
@db.sqls.should == ["SELECT * FROM t"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should have map without a block or argument not raise an exception or issue a query" do
|
|
76
|
+
@c.map
|
|
77
|
+
@db.sqls.should == []
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should have map without a block not return a frozen object" do
|
|
81
|
+
@c.map.frozen?.should be_false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should have other enumerable methods work without sending a query" do
|
|
85
|
+
a = @c.sort_by{|o| o.id}
|
|
86
|
+
a.first.should equal(@c1)
|
|
87
|
+
a.last.should equal(@c2)
|
|
88
|
+
@db.sqls.should == []
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should have all just return the hashes' values" do
|
|
92
|
+
a = @c.all.sort_by{|o| o.id}
|
|
93
|
+
a.first.should equal(@c1)
|
|
94
|
+
a.last.should equal(@c2)
|
|
95
|
+
@db.sqls.should == []
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should have all not return a frozen object" do
|
|
99
|
+
@c.all.frozen?.should be_false
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should have all return things in dataset order" do
|
|
103
|
+
@c.all.should == [@c1, @c2]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should have to_hash without arguments return the cached objects without a query" do
|
|
107
|
+
a = @c.to_hash
|
|
108
|
+
a[1].should equal(@c1)
|
|
109
|
+
a[2].should equal(@c2)
|
|
110
|
+
@db.sqls.should == []
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should have to_hash with any arguments use a query" do
|
|
114
|
+
@c.to_hash(:id).should == {1=>@c1, 2=>@c2}
|
|
115
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
116
|
+
@c.to_hash(:id, :id).should == {1=>1, 2=>2}
|
|
117
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "should have all not return a frozen object" do
|
|
121
|
+
@c.to_hash.frozen?.should be_false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "all of the static cache values (model instances) should be frozen" do
|
|
125
|
+
@c.all.all?{|o| o.frozen?}.should be_true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "subclasses should work correctly" do
|
|
129
|
+
c = Class.new(@c)
|
|
130
|
+
c.all.should == [c.load(:id=>1), c.load(:id=>2)]
|
|
131
|
+
c.to_hash.should == {1=>c.load(:id=>1), 2=>c.load(:id=>2)}
|
|
132
|
+
@db.sqls.should == ['SELECT * FROM t']
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "set_dataset should work correctly" do
|
|
136
|
+
ds = @c.dataset.from(:t2)
|
|
137
|
+
ds.instance_variable_set(:@columns, [:id])
|
|
138
|
+
ds._fetch = {:id=>3}
|
|
139
|
+
@c.dataset = ds
|
|
140
|
+
@c.all.should == [@c.load(:id=>3)]
|
|
141
|
+
@c.to_hash.should == {3=>@c.load(:id=>3)}
|
|
142
|
+
@c.to_hash[3].should equal(@c.all.first)
|
|
143
|
+
@db.sqls.should == ['SELECT * FROM t2']
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -7,23 +7,13 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
|
7
7
|
columns :id, :parent_id
|
|
8
8
|
many_to_one :parent, :class=>self
|
|
9
9
|
one_to_many :children, :class=>self, :key=>:parent_id
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
yield(:id=>101, :parent_id=>nil)
|
|
18
|
-
yield(:id=>102, :parent_id=>nil)
|
|
19
|
-
elsif where.args.first.column == :id
|
|
20
|
-
Array(where.args.last).each do |x|
|
|
21
|
-
yield(:id=>x, :parent_id=>nil)
|
|
22
|
-
end
|
|
23
|
-
elsif where.args.first.column == :parent_id
|
|
24
|
-
Array(where.args.last).each do |x|
|
|
25
|
-
yield(:id=>x-100, :parent_id=>x) if x > 100
|
|
26
|
-
end
|
|
10
|
+
dataset._fetch = proc do |sql|
|
|
11
|
+
if sql !~ /WHERE/
|
|
12
|
+
[{:id=>1, :parent_id=>101}, {:id=>2, :parent_id=>102}, {:id=>101, :parent_id=>nil}, {:id=>102, :parent_id=>nil}]
|
|
13
|
+
elsif sql =~ /WHERE.*\bid IN \(([\d, ]*)\)/
|
|
14
|
+
$1.split(', ').map{|x| {:id=>x.to_i, :parent_id=>nil}}
|
|
15
|
+
elsif sql =~ /WHERE.*\bparent_id IN \(([\d, ]*)\)/
|
|
16
|
+
$1.split(', ').map{|x| {:id=>x.to_i - 100, :parent_id=>x.to_i} if x.to_i > 100}.compact
|
|
27
17
|
end
|
|
28
18
|
end
|
|
29
19
|
end
|
|
@@ -49,9 +39,9 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
|
49
39
|
ts = @c.all
|
|
50
40
|
MODEL_DB.sqls.length.should == 1
|
|
51
41
|
ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
|
|
52
|
-
MODEL_DB.sqls.length.should ==
|
|
42
|
+
MODEL_DB.sqls.length.should == 1
|
|
53
43
|
ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
|
|
54
|
-
MODEL_DB.sqls.length.should ==
|
|
44
|
+
MODEL_DB.sqls.length.should == 1
|
|
55
45
|
end
|
|
56
46
|
|
|
57
47
|
it "association getter methods should not eagerly load the association if the association is cached" do
|
|
@@ -62,4 +52,12 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
|
62
52
|
@ds.should_not_receive(:eager_load)
|
|
63
53
|
ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
|
|
64
54
|
end
|
|
55
|
+
|
|
56
|
+
it "should handle case where an association is valid on an instance, but not on all instances" do
|
|
57
|
+
c = Class.new(@c)
|
|
58
|
+
c.many_to_one :parent2, :class=>@c, :key=>:parent_id
|
|
59
|
+
@c.dataset.row_proc = proc{|r| (r[:parent_id] == 101 ? c : @c).call(r)}
|
|
60
|
+
@c.all{|x| x.parent2 if x.is_a?(c)}
|
|
61
|
+
end
|
|
62
|
+
|
|
65
63
|
end
|
|
@@ -39,7 +39,27 @@ describe "Sequel thread_local_timezones extension" do
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it "should be thread safe" do
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
q, q1, q2 = Queue.new, Queue.new, Queue.new
|
|
43
|
+
tz1, tz2 = nil, nil
|
|
44
|
+
t1 = Thread.new do
|
|
45
|
+
Sequel.thread_application_timezone = :utc
|
|
46
|
+
q2.push nil
|
|
47
|
+
q.pop
|
|
48
|
+
tz1 = Sequel.application_timezone
|
|
49
|
+
end
|
|
50
|
+
t2 = Thread.new do
|
|
51
|
+
Sequel.thread_application_timezone = :local
|
|
52
|
+
q2.push nil
|
|
53
|
+
q1.pop
|
|
54
|
+
tz2 = Sequel.application_timezone
|
|
55
|
+
end
|
|
56
|
+
q2.pop
|
|
57
|
+
q2.pop
|
|
58
|
+
q.push nil
|
|
59
|
+
q1.push nil
|
|
60
|
+
t1.join
|
|
61
|
+
t2.join
|
|
62
|
+
tz1.should == :utc
|
|
63
|
+
tz2.should == :local
|
|
44
64
|
end
|
|
45
65
|
end
|
|
@@ -13,9 +13,10 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
13
13
|
@c.class_eval do
|
|
14
14
|
columns :id, :created_at, :updated_at
|
|
15
15
|
plugin :timestamps
|
|
16
|
+
def _save_refresh(*) end
|
|
16
17
|
db.reset
|
|
17
|
-
def _refresh(ds); self end
|
|
18
18
|
end
|
|
19
|
+
@c.dataset.autoid = nil
|
|
19
20
|
end
|
|
20
21
|
after do
|
|
21
22
|
Sequel.datetime_class = Time
|
|
@@ -40,8 +41,9 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
40
41
|
it "should use the same value for the creation and update timestamps when creating if the :update_on_create option is given" do
|
|
41
42
|
@c.plugin :timestamps, :update_on_create=>true
|
|
42
43
|
o = @c.create
|
|
43
|
-
@c.db.sqls
|
|
44
|
-
|
|
44
|
+
sqls = @c.db.sqls
|
|
45
|
+
sqls.shift.should =~ /INSERT INTO t \((creat|updat)ed_at, (creat|updat)ed_at\) VALUES \('2009-08-01', '2009-08-01'\)/
|
|
46
|
+
sqls.should == []
|
|
45
47
|
o.created_at.should === o.updated_at
|
|
46
48
|
end
|
|
47
49
|
|
|
@@ -50,8 +52,7 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
50
52
|
c.class_eval do
|
|
51
53
|
columns :id, :c
|
|
52
54
|
plugin :timestamps, :create=>:c
|
|
53
|
-
|
|
54
|
-
def _refresh(ds); self end
|
|
55
|
+
def _save_refresh(*) end
|
|
55
56
|
end
|
|
56
57
|
o = c.create
|
|
57
58
|
c.db.sqls.should == ["INSERT INTO t (c) VALUES ('2009-08-01')"]
|
|
@@ -64,7 +65,6 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
64
65
|
columns :id, :u
|
|
65
66
|
plugin :timestamps, :update=>:u
|
|
66
67
|
db.reset
|
|
67
|
-
def _refresh(ds); self end
|
|
68
68
|
end
|
|
69
69
|
o = c.load(:id=>1).save
|
|
70
70
|
c.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
|
|
@@ -2,9 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model, "to_dot extension" do
|
|
4
4
|
def dot(ds)
|
|
5
|
-
|
|
6
|
-
ds.send(:_to_dot, a, "", 0, ds, 0)
|
|
7
|
-
a[2..-1]
|
|
5
|
+
Sequel::ToDot.new(ds).instance_variable_get(:@dot)[4...-1]
|
|
8
6
|
end
|
|
9
7
|
|
|
10
8
|
before do
|
|
@@ -13,14 +11,13 @@ describe Sequel::Model, "to_dot extension" do
|
|
|
13
11
|
end
|
|
14
12
|
|
|
15
13
|
it "should output a string suitable for input to the graphviz dot program" do
|
|
16
|
-
@ds.to_dot.should == (<<END
|
|
14
|
+
@ds.to_dot.should == (<<END).strip
|
|
17
15
|
digraph G {
|
|
18
16
|
0 [label="self"];
|
|
19
17
|
0 -> 1 [label=""];
|
|
20
18
|
1 [label="Dataset"];
|
|
21
19
|
}
|
|
22
20
|
END
|
|
23
|
-
).strip
|
|
24
21
|
end
|
|
25
22
|
|
|
26
23
|
it "should handle an empty dataset" do
|
|
@@ -123,7 +120,7 @@ END
|
|
|
123
120
|
end
|
|
124
121
|
|
|
125
122
|
it "should handle SQL::Subscript" do
|
|
126
|
-
dot(@ds.select(:a.sql_subscript(1))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Subscript
|
|
123
|
+
dot(@ds.select(:a.sql_subscript(1))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Subscript\"];", "3 -> 4 [label=\"f\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"sub\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"1\"];"]
|
|
127
124
|
end
|
|
128
125
|
|
|
129
126
|
it "should handle SQL::WindowFunction" do
|
|
@@ -135,7 +132,7 @@ END
|
|
|
135
132
|
end
|
|
136
133
|
|
|
137
134
|
it "should handle JOIN ON" do
|
|
138
|
-
dot(@ds.from(:a).join(:d, :b=>:c)).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\":a\"];", "1 -> 4 [label=\"join\"];", "4 [label=\"Array\"];", "4 -> 5 [label=\"0\"];", "5 [label=\"INNER JOIN ON\"];", "5 -> 6 [label=\"table\"];", "6 [label=\":d\"];", "5 -> 7 [label=\"on\"];", "7 [label=\"
|
|
135
|
+
dot(@ds.from(:a).join(:d, :b=>:c)).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\":a\"];", "1 -> 4 [label=\"join\"];", "4 [label=\"Array\"];", "4 -> 5 [label=\"0\"];", "5 [label=\"INNER JOIN ON\"];", "5 -> 6 [label=\"table\"];", "6 [label=\":d\"];", "5 -> 7 [label=\"on\"];", "7 [label=\"ComplexExpression: =\"];", "7 -> 8 [label=\"0\"];", "8 [label=\"QualifiedIdentifier\"];", "8 -> 9 [label=\"table\"];", "9 [label=\"\\\"d\\\"\"];", "8 -> 10 [label=\"column\"];", "10 [label=\"\\\"b\\\"\"];", "7 -> 11 [label=\"1\"];", "11 [label=\"QualifiedIdentifier\"];", "11 -> 12 [label=\"table\"];", "12 [label=\"\\\"a\\\"\"];", "11 -> 13 [label=\"column\"];", "13 [label=\"\\\"c\\\"\"];"]
|
|
139
136
|
end
|
|
140
137
|
|
|
141
138
|
it "should handle JOIN USING" do
|
|
@@ -2,9 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "Touch plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@c = Class.new(Sequel::Model)
|
|
6
|
-
def _refresh(*); end
|
|
7
|
-
end
|
|
5
|
+
@c = Class.new(Sequel::Model)
|
|
8
6
|
p = proc{def touch_instance_value; touch_association_value; end}
|
|
9
7
|
@Artist = Class.new(@c, &p).set_dataset(:artists)
|
|
10
8
|
@Album = Class.new(@c, &p).set_dataset(:albums)
|
|
@@ -63,8 +61,9 @@ describe "Touch plugin" do
|
|
|
63
61
|
specify "should be able to give an array to the :associations option specifying multiple associations" do
|
|
64
62
|
@Album.plugin :touch, :associations=>[:artist, :followup_albums]
|
|
65
63
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
sqls = MODEL_DB.sqls
|
|
65
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
66
|
+
sqls.sort.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
68
67
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
69
68
|
end
|
|
70
69
|
|
|
@@ -85,8 +84,9 @@ describe "Touch plugin" do
|
|
|
85
84
|
specify "should allow the mixed use of symbols and hashes inside an array for the :associations option" do
|
|
86
85
|
@Album.plugin :touch, :associations=>[:artist, {:followup_albums=>:modified_on}]
|
|
87
86
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
sqls = MODEL_DB.sqls
|
|
88
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
89
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
90
90
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -94,8 +94,9 @@ describe "Touch plugin" do
|
|
|
94
94
|
@Album.plugin :touch
|
|
95
95
|
@Album.touch_associations(:artist, {:followup_albums=>:modified_on})
|
|
96
96
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
sqls = MODEL_DB.sqls
|
|
98
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
99
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
99
100
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
100
101
|
end
|
|
101
102
|
|
|
@@ -103,8 +104,9 @@ describe "Touch plugin" do
|
|
|
103
104
|
@Album.plugin :touch
|
|
104
105
|
@Album.touch_associations(:artist, {:followup_albums=>:modified_on})
|
|
105
106
|
@Album.load(:id=>4, :artist_id=>1).destroy
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
sqls = MODEL_DB.sqls
|
|
108
|
+
sqls.shift.should == "DELETE FROM albums WHERE id = 4"
|
|
109
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
108
110
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
109
111
|
end
|
|
110
112
|
|
|
@@ -133,18 +135,15 @@ describe "Touch plugin" do
|
|
|
133
135
|
c1 = Class.new(@Artist)
|
|
134
136
|
c1.load(:id=>4).touch
|
|
135
137
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"]
|
|
136
|
-
MODEL_DB.reset
|
|
137
138
|
|
|
138
139
|
c1.touch_column = :modified_on
|
|
139
140
|
c1.touch_associations :albums
|
|
140
141
|
c1.load(:id=>1).touch
|
|
141
142
|
MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
142
143
|
"UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
143
|
-
MODEL_DB.reset
|
|
144
144
|
|
|
145
145
|
@a.touch
|
|
146
146
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
|
147
|
-
MODEL_DB.reset
|
|
148
147
|
|
|
149
148
|
@Artist.plugin :touch, :column=>:modified_on, :associations=>:albums
|
|
150
149
|
c2 = Class.new(@Artist)
|
|
@@ -7,26 +7,11 @@ describe Sequel::Model, "tree plugin" do
|
|
|
7
7
|
c.class_eval do
|
|
8
8
|
def self.name; 'Node'; end
|
|
9
9
|
columns :id, :name, :parent_id, :i, :pi
|
|
10
|
+
plugin :tree, opts
|
|
10
11
|
end
|
|
11
|
-
ds = c.dataset
|
|
12
|
-
class << ds
|
|
13
|
-
attr_accessor :row_sets
|
|
14
|
-
def fetch_rows(sql)
|
|
15
|
-
@db << sql
|
|
16
|
-
if rs = row_sets.shift
|
|
17
|
-
rs.each{|row| yield row}
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
c.plugin :tree, opts
|
|
22
12
|
c
|
|
23
13
|
end
|
|
24
14
|
|
|
25
|
-
def y(c, *hs)
|
|
26
|
-
ds = c.dataset
|
|
27
|
-
ds.row_sets = hs
|
|
28
|
-
end
|
|
29
|
-
|
|
30
15
|
before do
|
|
31
16
|
@c = klass
|
|
32
17
|
@ds = @c.dataset
|
|
@@ -71,7 +56,7 @@ describe Sequel::Model, "tree plugin" do
|
|
|
71
56
|
end
|
|
72
57
|
|
|
73
58
|
it "should have roots return an array of the tree's roots" do
|
|
74
|
-
|
|
59
|
+
@ds._fetch = [{:id=>1, :parent_id=>nil, :name=>'r'}]
|
|
75
60
|
@c.roots.should == [@c.load(:id=>1, :parent_id=>nil, :name=>'r')]
|
|
76
61
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (parent_id IS NULL)"]
|
|
77
62
|
end
|
|
@@ -81,14 +66,14 @@ describe Sequel::Model, "tree plugin" do
|
|
|
81
66
|
end
|
|
82
67
|
|
|
83
68
|
it "should have ancestors return the ancestors of the current node" do
|
|
84
|
-
|
|
69
|
+
@ds._fetch = [[{:id=>1, :parent_id=>5, :name=>'r'}], [{:id=>5, :parent_id=>nil, :name=>'r2'}]]
|
|
85
70
|
@o.ancestors.should == [@c.load(:id=>1, :parent_id=>5, :name=>'r'), @c.load(:id=>5, :parent_id=>nil, :name=>'r2')]
|
|
86
71
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 1) LIMIT 1",
|
|
87
72
|
"SELECT * FROM nodes WHERE (nodes.id = 5) LIMIT 1"]
|
|
88
73
|
end
|
|
89
74
|
|
|
90
75
|
it "should have descendants return the descendants of the current node" do
|
|
91
|
-
|
|
76
|
+
@ds._fetch = [[{:id=>3, :parent_id=>2, :name=>'r'}, {:id=>4, :parent_id=>2, :name=>'r2'}], [{:id=>5, :parent_id=>4, :name=>'r3'}], []]
|
|
92
77
|
@o.descendants.should == [@c.load(:id=>3, :parent_id=>2, :name=>'r'), @c.load(:id=>4, :parent_id=>2, :name=>'r2'), @c.load(:id=>5, :parent_id=>4, :name=>'r3')]
|
|
93
78
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (nodes.parent_id = 2)",
|
|
94
79
|
"SELECT * FROM nodes WHERE (nodes.parent_id = 3)",
|
|
@@ -97,7 +82,7 @@ describe Sequel::Model, "tree plugin" do
|
|
|
97
82
|
end
|
|
98
83
|
|
|
99
84
|
it "should have root return the root of the current node" do
|
|
100
|
-
|
|
85
|
+
@ds._fetch = [[{:id=>1, :parent_id=>5, :name=>'r'}], [{:id=>5, :parent_id=>nil, :name=>'r2'}]]
|
|
101
86
|
@o.root.should == @c.load(:id=>5, :parent_id=>nil, :name=>'r2')
|
|
102
87
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 1) LIMIT 1",
|
|
103
88
|
"SELECT * FROM nodes WHERE (nodes.id = 5) LIMIT 1"]
|
|
@@ -113,14 +98,14 @@ describe Sequel::Model, "tree plugin" do
|
|
|
113
98
|
end
|
|
114
99
|
|
|
115
100
|
it "should have self_and_siblings return the children of the current node's parent" do
|
|
116
|
-
|
|
101
|
+
@ds._fetch = [[{:id=>1, :parent_id=>3, :name=>'r'}], [{:id=>7, :parent_id=>1, :name=>'r2'}, @o.values.dup]]
|
|
117
102
|
@o.self_and_siblings.should == [@c.load(:id=>7, :parent_id=>1, :name=>'r2'), @o]
|
|
118
103
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 1) LIMIT 1",
|
|
119
104
|
"SELECT * FROM nodes WHERE (nodes.parent_id = 1)"]
|
|
120
105
|
end
|
|
121
106
|
|
|
122
107
|
it "should have siblings return the children of the current node's parent, except for the current node" do
|
|
123
|
-
|
|
108
|
+
@ds._fetch = [[{:id=>1, :parent_id=>3, :name=>'r'}], [{:id=>7, :parent_id=>1, :name=>'r2'}, @o.values.dup]]
|
|
124
109
|
@o.siblings.should == [@c.load(:id=>7, :parent_id=>1, :name=>'r2')]
|
|
125
110
|
@db.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 1) LIMIT 1",
|
|
126
111
|
"SELECT * FROM nodes WHERE (nodes.parent_id = 1)"]
|
|
@@ -132,23 +117,23 @@ describe Sequel::Model, "tree plugin" do
|
|
|
132
117
|
end
|
|
133
118
|
|
|
134
119
|
it "should have root class method return the root" do
|
|
135
|
-
|
|
120
|
+
@c.dataset._fetch = [{:id=>1, :parent_id=>nil, :name=>'r'}]
|
|
136
121
|
@c.root.should == @c.load(:id=>1, :parent_id=>nil, :name=>'r')
|
|
137
122
|
end
|
|
138
123
|
|
|
139
124
|
it "prevents creating a second root" do
|
|
140
|
-
|
|
125
|
+
@c.dataset._fetch = [{:id=>1, :parent_id=>nil, :name=>'r'}]
|
|
141
126
|
lambda { @c.create }.should raise_error(Sequel::Plugins::Tree::TreeMultipleRootError)
|
|
142
127
|
end
|
|
143
128
|
|
|
144
129
|
it "errors when promoting an existing record to a second root" do
|
|
145
|
-
|
|
130
|
+
@c.dataset._fetch = [{:id=>1, :parent_id=>nil, :name=>'r'}]
|
|
146
131
|
n = @c.load(:id => 2, :parent_id => 1)
|
|
147
132
|
lambda { n.update(:parent_id => nil) }.should raise_error(Sequel::Plugins::Tree::TreeMultipleRootError)
|
|
148
133
|
end
|
|
149
134
|
|
|
150
135
|
it "allows updating existing root" do
|
|
151
|
-
|
|
136
|
+
@c.dataset._fetch = [{:id=>1, :parent_id=>nil, :name=>'r'}]
|
|
152
137
|
lambda { @c.root.update(:name => 'fdsa') }.should_not raise_error
|
|
153
138
|
end
|
|
154
139
|
end
|
|
@@ -2,22 +2,17 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model, "TypecastOnLoad plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@db = Sequel
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :b=>"1", :y=>"0"}, :columns=>[:id, :b, :y], :numrows=>1)
|
|
6
6
|
def @db.schema(*args)
|
|
7
7
|
[[:id, {}], [:y, {:type=>:boolean, :db_type=>'tinyint(1)'}], [:b, {:type=>:integer, :db_type=>'integer'}]]
|
|
8
8
|
end
|
|
9
9
|
@c = Class.new(Sequel::Model(@db[:items])) do
|
|
10
|
-
include(Module.new{def _refresh(ds); values[:b] = b.to_s; self; end})
|
|
11
10
|
attr_accessor :bset
|
|
12
11
|
def b=(x)
|
|
13
12
|
self.bset = true
|
|
14
13
|
super
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
|
-
@c.instance_eval do
|
|
18
|
-
@columns = [:id, :b, :y]
|
|
19
|
-
def columns; @columns; end
|
|
20
|
-
end
|
|
21
16
|
end
|
|
22
17
|
|
|
23
18
|
specify "should call setter method with value when loading the object, for all given columns" do
|
|
@@ -35,6 +30,14 @@ describe Sequel::Model, "TypecastOnLoad plugin" do
|
|
|
35
30
|
o.bset.should == true
|
|
36
31
|
end
|
|
37
32
|
|
|
33
|
+
specify "should call setter method with value when automatically reloading the object on creation via insert_select" do
|
|
34
|
+
@c.plugin :typecast_on_load, :b
|
|
35
|
+
@c.dataset.meta_def(:insert_select){|h| insert(h); first}
|
|
36
|
+
o = @c.new({:id=>1, :b=>"1", :y=>"0"}, true)
|
|
37
|
+
o.save.values.should == {:id=>1, :b=>1, :y=>"0"}
|
|
38
|
+
o.bset.should == true
|
|
39
|
+
end
|
|
40
|
+
|
|
38
41
|
specify "should allowing setting columns separately via add_typecast_on_load_columns" do
|
|
39
42
|
@c.plugin :typecast_on_load
|
|
40
43
|
@c.load(:id=>1, :b=>"1", :y=>"0").values.should == {:id=>1, :b=>"1", :y=>"0"}
|