sequel 3.21.0 → 3.41.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 +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- 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/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- 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 +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -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 +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- 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 +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- 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 +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- 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 +137 -16
- 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/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -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 +134 -15
- 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 +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -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 +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- 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 +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- 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 +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- 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 +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- 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/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- 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 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- 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 +268 -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 +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -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 +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- 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 +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- 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 +86 -48
- 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 +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -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 +8 -11
- data/spec/extensions/touch_spec.rb +53 -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 +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- 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 +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "split_array_nil extension" do
|
|
4
|
+
before do
|
|
5
|
+
@ds = Sequel.mock[:table].extension(:split_array_nil)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
specify "should split IN with nil in array into separate OR IS NULL clause" do
|
|
9
|
+
@ds.filter(:a=>[1, nil]).sql.should == "SELECT * FROM table WHERE ((a IN (1)) OR (a IS NULL))"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
specify "should split NOT IN with nil in array into separate AND IS NOT NULL clause" do
|
|
13
|
+
@ds.exclude(:a=>[1, nil]).sql.should == "SELECT * FROM table WHERE ((a NOT IN (1)) AND (a IS NOT NULL))"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
specify "should not affect other IN/NOT in clauses" do
|
|
17
|
+
@ds.filter(:a=>[1, 2]).sql.should == "SELECT * FROM table WHERE (a IN (1, 2))"
|
|
18
|
+
@ds.exclude(:a=>[1, 2]).sql.should == "SELECT * FROM table WHERE (a NOT IN (1, 2))"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
specify "should not affect other types of filters clauses" do
|
|
22
|
+
@ds.filter(:a=>1).sql.should == "SELECT * FROM table WHERE (a = 1)"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -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
|
|
@@ -49,4 +49,18 @@ describe Sequel::Model, "Subclasses plugin" do
|
|
|
49
49
|
ssc1.descendents.should == [sssc1]
|
|
50
50
|
sssc1.descendents.should == []
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
specify "plugin block should be called with each subclass created" do
|
|
54
|
+
c = Class.new(Sequel::Model)
|
|
55
|
+
a = []
|
|
56
|
+
c.plugin(:subclasses){|sc| a << sc}
|
|
57
|
+
sc1 = Class.new(c)
|
|
58
|
+
a.should == [sc1]
|
|
59
|
+
sc2 = Class.new(c)
|
|
60
|
+
a.should == [sc1, sc2]
|
|
61
|
+
sc3 = Class.new(sc1)
|
|
62
|
+
a.should == [sc1, sc2, sc3]
|
|
63
|
+
sc4 = Class.new(sc3)
|
|
64
|
+
a.should == [sc1, sc2, sc3, sc4]
|
|
65
|
+
end
|
|
52
66
|
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
|
|
@@ -103,19 +100,19 @@ END
|
|
|
103
100
|
end
|
|
104
101
|
|
|
105
102
|
it "should handle SQL::OrderedExpressions" do
|
|
106
|
-
dot(@ds.order(
|
|
103
|
+
dot(@ds.order(Sequel.desc(:a, :nulls=>:last))).should == ["1 -> 2 [label=\"order\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"OrderedExpression: DESC NULLS LAST\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];"]
|
|
107
104
|
end
|
|
108
105
|
|
|
109
106
|
it "should handle SQL::AliasedExpressions" do
|
|
110
|
-
dot(@ds.from(
|
|
107
|
+
dot(@ds.from(Sequel.as(:a, :b))).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"AliasedExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"alias\"];", "5 [label=\":b\"];"]
|
|
111
108
|
end
|
|
112
109
|
|
|
113
110
|
it "should handle SQL::CaseExpressions" do
|
|
114
|
-
dot(@ds.select({:a=>:b}
|
|
111
|
+
dot(@ds.select(Sequel.case({:a=>:b}, :c, :d))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"CaseExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":d\"];", "3 -> 5 [label=\"conditions\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\":a\"];", "6 -> 8 [label=\"1\"];", "8 [label=\":b\"];", "3 -> 9 [label=\"default\"];", "9 [label=\":c\"];"]
|
|
115
112
|
end
|
|
116
113
|
|
|
117
114
|
it "should handle SQL::Cast" do
|
|
118
|
-
dot(@ds.select(
|
|
115
|
+
dot(@ds.select(Sequel.cast(:a, Integer))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Cast\"];", "3 -> 4 [label=\"expr\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"type\"];", "5 [label=\"Integer\"];"]
|
|
119
116
|
end
|
|
120
117
|
|
|
121
118
|
it "should handle SQL::Function" do
|
|
@@ -123,7 +120,7 @@ END
|
|
|
123
120
|
end
|
|
124
121
|
|
|
125
122
|
it "should handle SQL::Subscript" do
|
|
126
|
-
dot(@ds.select(:a
|
|
123
|
+
dot(@ds.select(Sequel.subscript(:a, 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,11 +104,52 @@ 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
|
|
|
113
|
+
specify "should be able to touch many_to_one associations" do
|
|
114
|
+
@Album.plugin :touch, :associations=>:artist
|
|
115
|
+
@Album.load(:id=>3, :artist_id=>4).touch
|
|
116
|
+
MODEL_DB.sqls.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 3)",
|
|
117
|
+
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 4)"]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
specify "should be able to touch many_to_one associations" do
|
|
121
|
+
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
|
122
|
+
@Artist.plugin :touch, :associations=>:album
|
|
123
|
+
@a.touch
|
|
124
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
125
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
specify "should be able to touch many_to_many associations" do
|
|
129
|
+
@Artist.many_to_many :albums, :class=>@Album, :left_key=>:artist_id, :join_table=>:aa
|
|
130
|
+
@Artist.plugin :touch, :associations=>:albums
|
|
131
|
+
@a.touch
|
|
132
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
133
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON ((aa.album_id = albums.id) AND (aa.artist_id = 1))",
|
|
134
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
specify "should be able to touch many_through_many associations" do
|
|
138
|
+
@Artist.plugin :many_through_many
|
|
139
|
+
@Artist.many_through_many :albums, [[:aa, :artist_id, :album_id]], :class=>@Album
|
|
140
|
+
@Artist.plugin :touch, :associations=>:albums
|
|
141
|
+
@a.touch
|
|
142
|
+
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
143
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON ((aa.album_id = albums.id) AND (aa.artist_id = 1))",
|
|
144
|
+
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
specify "should handle touching many_to_one associations with no associated object" do
|
|
148
|
+
@Album.plugin :touch, :associations=>:artist
|
|
149
|
+
@Album.load(:id=>3, :artist_id=>nil).touch
|
|
150
|
+
MODEL_DB.sqls.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 3)"]
|
|
151
|
+
end
|
|
152
|
+
|
|
111
153
|
specify "should not update a column that doesn't exist" do
|
|
112
154
|
@Album.plugin :touch, :column=>:x
|
|
113
155
|
a = @Album.load(:id=>1)
|
|
@@ -133,18 +175,15 @@ describe "Touch plugin" do
|
|
|
133
175
|
c1 = Class.new(@Artist)
|
|
134
176
|
c1.load(:id=>4).touch
|
|
135
177
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"]
|
|
136
|
-
MODEL_DB.reset
|
|
137
178
|
|
|
138
179
|
c1.touch_column = :modified_on
|
|
139
180
|
c1.touch_associations :albums
|
|
140
181
|
c1.load(:id=>1).touch
|
|
141
182
|
MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
142
183
|
"UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
143
|
-
MODEL_DB.reset
|
|
144
184
|
|
|
145
185
|
@a.touch
|
|
146
186
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
|
147
|
-
MODEL_DB.reset
|
|
148
187
|
|
|
149
188
|
@Artist.plugin :touch, :column=>:modified_on, :associations=>:albums
|
|
150
189
|
c2 = Class.new(@Artist)
|