sequel 3.21.0 → 3.39.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 +1061 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +103 -63
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +67 -51
- data/doc/advanced_associations.rdoc +189 -75
- data/doc/association_basics.rdoc +327 -79
- 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 +547 -0
- data/doc/opening_databases.rdoc +114 -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/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/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 +2 -61
- 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 +56 -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 +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 +40 -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 +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 +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +279 -97
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +125 -222
- data/lib/sequel/adapters/mysql2.rb +65 -56
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- 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 +368 -138
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +343 -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 +401 -116
- data/lib/sequel/adapters/shared/mysql.rb +424 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +257 -45
- data/lib/sequel/adapters/shared/postgres.rb +675 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +285 -96
- data/lib/sequel/adapters/sqlite.rb +101 -39
- 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 +28 -19
- data/lib/sequel/adapters/tinytds.rb +174 -22
- 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/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 +33 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +43 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +143 -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 +190 -46
- data/lib/sequel/database/query.rb +272 -110
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +300 -67
- 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 +305 -54
- data/lib/sequel/dataset/sql.rb +720 -292
- 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/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 +537 -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 +313 -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 +208 -0
- data/lib/sequel/extensions/pg_range.rb +512 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +572 -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 +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/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 +58 -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 +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 +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 +5 -3
- 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/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 +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +55 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +649 -122
- 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 +1 -1
- data/spec/adapters/mssql_spec.rb +194 -66
- data/spec/adapters/mysql_spec.rb +475 -306
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +1982 -325
- data/spec/adapters/spec_helper.rb +9 -6
- data/spec/adapters/sqlite_spec.rb +203 -75
- data/spec/core/connection_pool_spec.rb +218 -93
- data/spec/core/database_spec.rb +956 -522
- data/spec/core/dataset_spec.rb +1631 -1242
- data/spec/core/expression_filters_spec.rb +690 -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 +66 -32
- 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/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 +320 -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 +194 -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 +323 -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 +23 -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 +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 +58 -67
- data/spec/extensions/validation_helpers_spec.rb +31 -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 +11 -5
- data/spec/integration/dataset_test.rb +717 -129
- 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 +604 -147
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +367 -57
- data/spec/integration/spec_helper.rb +42 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +31 -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 +209 -80
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
# H2 and MSSQL don't support USING joins
|
|
4
|
-
|
|
4
|
+
# DB2 does not seem to support USING joins in every version; it seems to be
|
|
5
|
+
# valid expression in DB2 iSeries UDB though.
|
|
6
|
+
unless Sequel.guarded?(:h2, :mssql, :db2)
|
|
5
7
|
describe "Class Table Inheritance Plugin" do
|
|
6
|
-
before do
|
|
8
|
+
before(:all) do
|
|
7
9
|
@db = INTEGRATION_DB
|
|
8
10
|
@db.instance_variable_set(:@schemas, {})
|
|
9
|
-
@db.
|
|
11
|
+
@db.drop_table?(:staff, :executives, :managers, :employees)
|
|
12
|
+
@db.create_table(:employees) do
|
|
10
13
|
primary_key :id
|
|
11
14
|
String :name
|
|
12
15
|
String :kind
|
|
13
16
|
end
|
|
14
|
-
@db.create_table
|
|
17
|
+
@db.create_table(:managers) do
|
|
15
18
|
foreign_key :id, :employees, :primary_key=>true
|
|
16
19
|
Integer :num_staff
|
|
17
20
|
end
|
|
18
|
-
@db.create_table
|
|
21
|
+
@db.create_table(:executives) do
|
|
19
22
|
foreign_key :id, :managers, :primary_key=>true
|
|
20
23
|
Integer :num_managers
|
|
21
24
|
end
|
|
22
|
-
@db.create_table
|
|
25
|
+
@db.create_table(:staff) do
|
|
23
26
|
foreign_key :id, :employees, :primary_key=>true
|
|
24
27
|
foreign_key :manager_id, :managers
|
|
25
28
|
end
|
|
29
|
+
end
|
|
30
|
+
before do
|
|
31
|
+
[:staff, :executives, :managers, :employees].each{|t| @db[t].delete}
|
|
26
32
|
class ::Employee < Sequel::Model(@db)
|
|
27
33
|
plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}
|
|
28
34
|
end
|
|
@@ -32,7 +38,7 @@ describe "Class Table Inheritance Plugin" do
|
|
|
32
38
|
class ::Executive < Manager
|
|
33
39
|
end
|
|
34
40
|
class ::Staff < Employee
|
|
35
|
-
many_to_one :manager
|
|
41
|
+
many_to_one :manager, :qualify=>false
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
@i1 =@db[:employees].insert(:name=>'E', :kind=>'Employee')
|
|
@@ -43,13 +49,13 @@ describe "Class Table Inheritance Plugin" do
|
|
|
43
49
|
@db[:managers].insert(:id=>@i4, :num_staff=>5)
|
|
44
50
|
@db[:executives].insert(:id=>@i4, :num_managers=>6)
|
|
45
51
|
@db[:staff].insert(:id=>@i2, :manager_id=>@i4)
|
|
46
|
-
|
|
47
|
-
clear_sqls
|
|
48
52
|
end
|
|
49
53
|
after do
|
|
50
|
-
@db.drop_table :staff, :executives, :managers, :employees
|
|
51
54
|
[:Executive, :Manager, :Staff, :Employee].each{|s| Object.send(:remove_const, s)}
|
|
52
55
|
end
|
|
56
|
+
after(:all) do
|
|
57
|
+
@db.drop_table? :staff, :executives, :managers, :employees
|
|
58
|
+
end
|
|
53
59
|
|
|
54
60
|
specify "should return rows as subclass instances" do
|
|
55
61
|
Employee.order(:id).all.should == [
|
|
@@ -94,8 +100,7 @@ describe "Class Table Inheritance Plugin" do
|
|
|
94
100
|
Employee.filter(:id=>@i2).all.first.manager.id.should == @i4
|
|
95
101
|
end
|
|
96
102
|
|
|
97
|
-
|
|
98
|
-
cspecify "should insert rows into all tables", :sqlite do
|
|
103
|
+
cspecify "should insert rows into all tables", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
|
|
99
104
|
e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
|
|
100
105
|
i = e.id
|
|
101
106
|
@db[:employees][:id=>i].should == {:id=>i, :name=>'Ex2', :kind=>'Executive'}
|
|
@@ -110,17 +115,17 @@ describe "Class Table Inheritance Plugin" do
|
|
|
110
115
|
@db[:executives][:id=>@i4].should == {:id=>@i4, :num_managers=>8}
|
|
111
116
|
end
|
|
112
117
|
|
|
113
|
-
|
|
118
|
+
specify "should handle many_to_one relationships" do
|
|
114
119
|
m = Staff.first.manager
|
|
115
120
|
m.should == Manager[@i4]
|
|
116
121
|
m.should be_a_kind_of(Executive)
|
|
117
122
|
end
|
|
118
123
|
|
|
119
|
-
|
|
124
|
+
specify "should handle eagerly loading many_to_one relationships" do
|
|
120
125
|
Staff.limit(1).eager(:manager).all.map{|x| x.manager}.should == [Manager[@i4]]
|
|
121
126
|
end
|
|
122
127
|
|
|
123
|
-
|
|
128
|
+
specify "should handle eagerly graphing many_to_one relationships" do
|
|
124
129
|
ss = Staff.eager_graph(:manager).all
|
|
125
130
|
ss.should == [Staff[@i2]]
|
|
126
131
|
ss.map{|x| x.manager}.should == [Manager[@i4]]
|
|
@@ -134,7 +139,7 @@ describe "Class Table Inheritance Plugin" do
|
|
|
134
139
|
Executive.limit(1).eager(:staff_members).first.staff_members.should == [Staff[@i2]]
|
|
135
140
|
end
|
|
136
141
|
|
|
137
|
-
cspecify "should handle eagerly graphing one_to_many relationships", :sqlite do
|
|
142
|
+
cspecify "should handle eagerly graphing one_to_many relationships", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
|
|
138
143
|
es = Executive.limit(1).eager_graph(:staff_members).all
|
|
139
144
|
es.should == [Executive[@i4]]
|
|
140
145
|
es.map{|x| x.staff_members}.should == [[Staff[@i2]]]
|
|
@@ -143,21 +148,25 @@ end
|
|
|
143
148
|
end
|
|
144
149
|
|
|
145
150
|
describe "Many Through Many Plugin" do
|
|
146
|
-
before do
|
|
151
|
+
before(:all) do
|
|
147
152
|
@db = INTEGRATION_DB
|
|
148
153
|
@db.instance_variable_set(:@schemas, {})
|
|
149
|
-
@db.
|
|
154
|
+
@db.drop_table?(:albums_artists, :albums, :artists)
|
|
155
|
+
@db.create_table(:albums) do
|
|
150
156
|
primary_key :id
|
|
151
157
|
String :name
|
|
152
158
|
end
|
|
153
|
-
@db.create_table
|
|
159
|
+
@db.create_table(:artists) do
|
|
154
160
|
primary_key :id
|
|
155
161
|
String :name
|
|
156
162
|
end
|
|
157
|
-
@db.create_table
|
|
163
|
+
@db.create_table(:albums_artists) do
|
|
158
164
|
foreign_key :album_id, :albums
|
|
159
165
|
foreign_key :artist_id, :artists
|
|
160
166
|
end
|
|
167
|
+
end
|
|
168
|
+
before do
|
|
169
|
+
[:albums_artists, :albums, :artists].each{|t| @db[t].delete}
|
|
161
170
|
class ::Album < Sequel::Model(@db)
|
|
162
171
|
many_to_many :artists
|
|
163
172
|
end
|
|
@@ -181,21 +190,31 @@ describe "Many Through Many Plugin" do
|
|
|
181
190
|
@album4 = Album.create(:name=>'D')
|
|
182
191
|
@album4.add_artist(@artist1)
|
|
183
192
|
@album4.add_artist(@artist4)
|
|
184
|
-
|
|
185
|
-
clear_sqls
|
|
186
193
|
end
|
|
187
194
|
after do
|
|
188
|
-
@db.drop_table :albums_artists, :albums, :artists
|
|
189
195
|
[:Album, :Artist].each{|s| Object.send(:remove_const, s)}
|
|
190
196
|
end
|
|
197
|
+
after(:all) do
|
|
198
|
+
@db.drop_table? :albums_artists, :albums, :artists
|
|
199
|
+
end
|
|
191
200
|
|
|
201
|
+
def self_join(c)
|
|
202
|
+
c.join(Sequel.as(c.table_name, :b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
|
|
203
|
+
end
|
|
204
|
+
|
|
192
205
|
specify "should handle super simple case with 1 join table" do
|
|
193
206
|
Artist.many_through_many :albums, [[:albums_artists, :artist_id, :album_id]]
|
|
194
|
-
Artist[
|
|
195
|
-
Artist[
|
|
196
|
-
Artist[
|
|
197
|
-
Artist[
|
|
207
|
+
Artist[@artist1.id].albums.map{|x| x.name}.sort.should == %w'A D'
|
|
208
|
+
Artist[@artist2.id].albums.map{|x| x.name}.sort.should == %w'A C'
|
|
209
|
+
Artist[@artist3.id].albums.map{|x| x.name}.sort.should == %w'B C'
|
|
210
|
+
Artist[@artist4.id].albums.map{|x| x.name}.sort.should == %w'B D'
|
|
198
211
|
|
|
212
|
+
Artist.plugin :prepared_statements_associations
|
|
213
|
+
Artist[@artist1.id].albums.map{|x| x.name}.sort.should == %w'A D'
|
|
214
|
+
Artist[@artist2.id].albums.map{|x| x.name}.sort.should == %w'A C'
|
|
215
|
+
Artist[@artist3.id].albums.map{|x| x.name}.sort.should == %w'B C'
|
|
216
|
+
Artist[@artist4.id].albums.map{|x| x.name}.sort.should == %w'B D'
|
|
217
|
+
|
|
199
218
|
Artist.filter(:id=>1).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A D'
|
|
200
219
|
Artist.filter(:id=>2).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
|
|
201
220
|
Artist.filter(:id=>3).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
|
|
@@ -205,24 +224,102 @@ describe "Many Through Many Plugin" do
|
|
|
205
224
|
Artist.filter(:artists__id=>2).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
|
|
206
225
|
Artist.filter(:artists__id=>3).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
|
|
207
226
|
Artist.filter(:artists__id=>4).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
|
|
227
|
+
|
|
228
|
+
Artist.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
229
|
+
Artist.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
230
|
+
Artist.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
|
|
231
|
+
Artist.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
|
|
232
|
+
|
|
233
|
+
Artist.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
234
|
+
Artist.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
235
|
+
Artist.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
|
|
236
|
+
Artist.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
|
|
237
|
+
|
|
238
|
+
Artist.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
239
|
+
Artist.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
|
|
240
|
+
|
|
241
|
+
Artist.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
|
|
242
|
+
Artist.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
|
|
243
|
+
|
|
244
|
+
Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
245
|
+
Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
|
|
246
|
+
|
|
247
|
+
c = self_join(Artist)
|
|
248
|
+
c.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
249
|
+
c.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
250
|
+
c.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
|
|
251
|
+
c.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
|
|
252
|
+
|
|
253
|
+
c.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
254
|
+
c.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
255
|
+
c.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
|
|
256
|
+
c.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
|
|
257
|
+
|
|
258
|
+
c.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
259
|
+
c.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
|
|
260
|
+
|
|
261
|
+
c.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
|
|
262
|
+
c.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
|
|
263
|
+
|
|
264
|
+
c.filter(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
265
|
+
c.exclude(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
|
|
208
266
|
end
|
|
209
267
|
|
|
210
268
|
specify "should handle typical case with 3 join tables" do
|
|
211
269
|
Artist.many_through_many :related_artists, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id]], :class=>Artist, :distinct=>true
|
|
212
|
-
Artist[
|
|
213
|
-
Artist[
|
|
214
|
-
Artist[
|
|
215
|
-
Artist[
|
|
270
|
+
Artist[@artist1.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
|
|
271
|
+
Artist[@artist2.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
|
|
272
|
+
Artist[@artist3.id].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
|
|
273
|
+
Artist[@artist4.id].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
|
|
274
|
+
|
|
275
|
+
Artist.plugin :prepared_statements_associations
|
|
276
|
+
Artist[@artist1.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
|
|
277
|
+
Artist[@artist2.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
|
|
278
|
+
Artist[@artist3.id].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
|
|
279
|
+
Artist[@artist4.id].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
|
|
216
280
|
|
|
217
|
-
Artist.filter(:id
|
|
218
|
-
Artist.filter(:id
|
|
219
|
-
Artist.filter(:id
|
|
220
|
-
Artist.filter(:id
|
|
281
|
+
Artist.filter(:id=>@artist1.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
|
|
282
|
+
Artist.filter(:id=>@artist2.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
|
|
283
|
+
Artist.filter(:id=>@artist3.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
|
|
284
|
+
Artist.filter(:id=>@artist4.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
|
|
221
285
|
|
|
222
|
-
Artist.filter(:artists__id
|
|
223
|
-
Artist.filter(:artists__id
|
|
224
|
-
Artist.filter(:artists__id
|
|
225
|
-
Artist.filter(:artists__id
|
|
286
|
+
Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
|
|
287
|
+
Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
|
|
288
|
+
Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
|
|
289
|
+
Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
|
|
290
|
+
|
|
291
|
+
Artist.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
|
|
292
|
+
Artist.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
293
|
+
Artist.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
|
|
294
|
+
Artist.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
|
|
295
|
+
|
|
296
|
+
Artist.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
|
|
297
|
+
Artist.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
|
|
298
|
+
Artist.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
|
|
299
|
+
Artist.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
|
|
300
|
+
|
|
301
|
+
Artist.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
302
|
+
Artist.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
|
|
303
|
+
|
|
304
|
+
Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
|
|
305
|
+
Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
|
|
306
|
+
|
|
307
|
+
c = self_join(Artist)
|
|
308
|
+
c.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
|
|
309
|
+
c.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
310
|
+
c.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
|
|
311
|
+
c.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
|
|
312
|
+
|
|
313
|
+
c.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
|
|
314
|
+
c.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
|
|
315
|
+
c.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
|
|
316
|
+
c.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
|
|
317
|
+
|
|
318
|
+
c.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
319
|
+
c.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
|
|
320
|
+
|
|
321
|
+
c.filter(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
|
|
322
|
+
c.exclude(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
|
|
226
323
|
end
|
|
227
324
|
|
|
228
325
|
specify "should handle extreme case with 5 join tables" do
|
|
@@ -236,38 +333,84 @@ describe "Many Through Many Plugin" do
|
|
|
236
333
|
@album4.add_artist(@artist3)
|
|
237
334
|
@album4.add_artist(@artist4)
|
|
238
335
|
|
|
239
|
-
Artist[
|
|
240
|
-
Artist[
|
|
241
|
-
Artist[
|
|
242
|
-
Artist[
|
|
336
|
+
Artist[@artist1.id].related_albums.map{|x| x.name}.sort.should == %w'A B C'
|
|
337
|
+
Artist[@artist2.id].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
|
|
338
|
+
Artist[@artist3.id].related_albums.map{|x| x.name}.sort.should == %w'A B D'
|
|
339
|
+
Artist[@artist4.id].related_albums.map{|x| x.name}.sort.should == %w'B D'
|
|
243
340
|
|
|
244
|
-
Artist.
|
|
245
|
-
Artist.
|
|
246
|
-
Artist.
|
|
247
|
-
Artist.
|
|
341
|
+
Artist.plugin :prepared_statements_associations
|
|
342
|
+
Artist[@artist1.id].related_albums.map{|x| x.name}.sort.should == %w'A B C'
|
|
343
|
+
Artist[@artist2.id].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
|
|
344
|
+
Artist[@artist3.id].related_albums.map{|x| x.name}.sort.should == %w'A B D'
|
|
345
|
+
Artist[@artist4.id].related_albums.map{|x| x.name}.sort.should == %w'B D'
|
|
248
346
|
|
|
249
|
-
Artist.filter(:
|
|
250
|
-
Artist.filter(:
|
|
251
|
-
Artist.filter(:
|
|
252
|
-
Artist.filter(:
|
|
347
|
+
Artist.filter(:id=>@artist1.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
|
|
348
|
+
Artist.filter(:id=>@artist2.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
|
|
349
|
+
Artist.filter(:id=>@artist3.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
|
|
350
|
+
Artist.filter(:id=>@artist4.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
|
|
351
|
+
|
|
352
|
+
Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
|
|
353
|
+
Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
|
|
354
|
+
Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
|
|
355
|
+
Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
|
|
356
|
+
|
|
357
|
+
Artist.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
358
|
+
Artist.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
359
|
+
Artist.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
360
|
+
Artist.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
|
|
361
|
+
|
|
362
|
+
Artist.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
|
|
363
|
+
Artist.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
|
|
364
|
+
Artist.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
365
|
+
Artist.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
|
|
366
|
+
|
|
367
|
+
Artist.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
368
|
+
Artist.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
369
|
+
|
|
370
|
+
Artist.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
|
|
371
|
+
Artist.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
|
|
372
|
+
|
|
373
|
+
Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
374
|
+
Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
|
|
375
|
+
|
|
376
|
+
c = self_join(Artist)
|
|
377
|
+
c.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
378
|
+
c.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
379
|
+
c.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
|
|
380
|
+
c.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
|
|
381
|
+
|
|
382
|
+
c.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
|
|
383
|
+
c.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
|
|
384
|
+
c.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
|
|
385
|
+
c.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
|
|
386
|
+
|
|
387
|
+
c.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
388
|
+
c.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
|
|
389
|
+
|
|
390
|
+
c.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
|
|
391
|
+
c.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
|
|
392
|
+
|
|
393
|
+
c.filter(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
|
|
394
|
+
c.exclude(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
|
|
253
395
|
end
|
|
254
396
|
end
|
|
255
397
|
|
|
256
398
|
describe "Lazy Attributes plugin" do
|
|
257
|
-
before do
|
|
399
|
+
before(:all) do
|
|
258
400
|
@db = INTEGRATION_DB
|
|
259
401
|
@db.create_table!(:items) do
|
|
260
402
|
primary_key :id
|
|
261
403
|
String :name
|
|
262
404
|
Integer :num
|
|
263
405
|
end
|
|
406
|
+
@db[:items].delete
|
|
264
407
|
class ::Item < Sequel::Model(@db)
|
|
265
408
|
plugin :lazy_attributes, :num
|
|
266
409
|
end
|
|
267
410
|
Item.create(:name=>'J', :num=>1)
|
|
268
411
|
end
|
|
269
|
-
after do
|
|
270
|
-
@db.drop_table(:items)
|
|
412
|
+
after(:all) do
|
|
413
|
+
@db.drop_table?(:items)
|
|
271
414
|
Object.send(:remove_const, :Item)
|
|
272
415
|
end
|
|
273
416
|
|
|
@@ -299,7 +442,7 @@ describe "Lazy Attributes plugin" do
|
|
|
299
442
|
end
|
|
300
443
|
|
|
301
444
|
describe "Tactical Eager Loading Plugin" do
|
|
302
|
-
before do
|
|
445
|
+
before(:all) do
|
|
303
446
|
@db = INTEGRATION_DB
|
|
304
447
|
@db.instance_variable_set(:@schemas, {})
|
|
305
448
|
@db.create_table!(:artists) do
|
|
@@ -311,6 +454,10 @@ describe "Tactical Eager Loading Plugin" do
|
|
|
311
454
|
String :name
|
|
312
455
|
foreign_key :artist_id, :artists
|
|
313
456
|
end
|
|
457
|
+
end
|
|
458
|
+
before do
|
|
459
|
+
@db[:albums].delete
|
|
460
|
+
@db[:artists].delete
|
|
314
461
|
class ::Album < Sequel::Model(@db)
|
|
315
462
|
plugin :tactical_eager_loading
|
|
316
463
|
many_to_one :artist
|
|
@@ -328,13 +475,13 @@ describe "Tactical Eager Loading Plugin" do
|
|
|
328
475
|
@album2 = Album.create(:name=>'B', :artist=>@artist1)
|
|
329
476
|
@album3 = Album.create(:name=>'C', :artist=>@artist2)
|
|
330
477
|
@album4 = Album.create(:name=>'D', :artist=>@artist3)
|
|
331
|
-
|
|
332
|
-
clear_sqls
|
|
333
478
|
end
|
|
334
479
|
after do
|
|
335
|
-
@db.drop_table :albums, :artists
|
|
336
480
|
[:Album, :Artist].each{|s| Object.send(:remove_const, s)}
|
|
337
481
|
end
|
|
482
|
+
after(:all) do
|
|
483
|
+
@db.drop_table? :albums, :artists
|
|
484
|
+
end
|
|
338
485
|
|
|
339
486
|
specify "should eagerly load associations for all items when accessing any item" do
|
|
340
487
|
a = Artist.order(:name).all
|
|
@@ -363,7 +510,7 @@ describe "Identity Map plugin" do
|
|
|
363
510
|
Item.create(:name=>'J', :num=>3)
|
|
364
511
|
end
|
|
365
512
|
after do
|
|
366
|
-
@db.drop_table(:items)
|
|
513
|
+
@db.drop_table?(:items)
|
|
367
514
|
Object.send(:remove_const, :Item)
|
|
368
515
|
end
|
|
369
516
|
|
|
@@ -382,7 +529,7 @@ describe "Identity Map plugin" do
|
|
|
382
529
|
end
|
|
383
530
|
|
|
384
531
|
describe "Touch plugin" do
|
|
385
|
-
before do
|
|
532
|
+
before(:all) do
|
|
386
533
|
@db = INTEGRATION_DB
|
|
387
534
|
@db.instance_variable_set(:@schemas, {})
|
|
388
535
|
@db.create_table!(:artists) do
|
|
@@ -396,6 +543,10 @@ describe "Touch plugin" do
|
|
|
396
543
|
foreign_key :artist_id, :artists
|
|
397
544
|
DateTime :updated_at
|
|
398
545
|
end
|
|
546
|
+
end
|
|
547
|
+
before do
|
|
548
|
+
@db[:albums].delete
|
|
549
|
+
@db[:artists].delete
|
|
399
550
|
class ::Album < Sequel::Model(@db)
|
|
400
551
|
many_to_one :artist
|
|
401
552
|
plugin :touch, :associations=>:artist
|
|
@@ -407,9 +558,11 @@ describe "Touch plugin" do
|
|
|
407
558
|
@album = Album.create(:name=>'A', :artist=>@artist)
|
|
408
559
|
end
|
|
409
560
|
after do
|
|
410
|
-
@db.drop_table :albums, :artists
|
|
411
561
|
[:Album, :Artist].each{|s| Object.send(:remove_const, s)}
|
|
412
562
|
end
|
|
563
|
+
after(:all) do
|
|
564
|
+
@db.drop_table? :albums, :artists
|
|
565
|
+
end
|
|
413
566
|
|
|
414
567
|
specify "should update the timestamp column when touching the record" do
|
|
415
568
|
@album.updated_at.should == nil
|
|
@@ -417,7 +570,7 @@ describe "Touch plugin" do
|
|
|
417
570
|
@album.updated_at.to_i.should be_within(2).of(Time.now.to_i)
|
|
418
571
|
end
|
|
419
572
|
|
|
420
|
-
cspecify "should update the timestamp column for associated records when the record is updated or destroyed", [:do, :sqlite], [:jdbc, :sqlite] do
|
|
573
|
+
cspecify "should update the timestamp column for associated records when the record is updated or destroyed", [:do, :sqlite], [:jdbc, :sqlite], [:swift] do
|
|
421
574
|
@artist.updated_at.should == nil
|
|
422
575
|
@album.update(:name=>'B')
|
|
423
576
|
ua = @artist.reload.updated_at
|
|
@@ -448,7 +601,7 @@ describe "Serialization plugin" do
|
|
|
448
601
|
end
|
|
449
602
|
end
|
|
450
603
|
after do
|
|
451
|
-
@db.drop_table(:items)
|
|
604
|
+
@db.drop_table?(:items)
|
|
452
605
|
Object.send(:remove_const, :Item)
|
|
453
606
|
end
|
|
454
607
|
|
|
@@ -464,7 +617,7 @@ describe "Serialization plugin" do
|
|
|
464
617
|
end
|
|
465
618
|
|
|
466
619
|
describe "OptimisticLocking plugin" do
|
|
467
|
-
before do
|
|
620
|
+
before(:all) do
|
|
468
621
|
@db = INTEGRATION_DB
|
|
469
622
|
@db.create_table!(:people) do
|
|
470
623
|
primary_key :id
|
|
@@ -473,30 +626,33 @@ describe "OptimisticLocking plugin" do
|
|
|
473
626
|
end
|
|
474
627
|
class ::Person < Sequel::Model(@db)
|
|
475
628
|
plugin :optimistic_locking
|
|
476
|
-
create(:name=>'John')
|
|
477
629
|
end
|
|
478
630
|
end
|
|
479
|
-
|
|
480
|
-
@db
|
|
631
|
+
before do
|
|
632
|
+
@db[:people].delete
|
|
633
|
+
@p = Person.create(:name=>'John')
|
|
634
|
+
end
|
|
635
|
+
after(:all) do
|
|
636
|
+
@db.drop_table?(:people)
|
|
481
637
|
Object.send(:remove_const, :Person)
|
|
482
638
|
end
|
|
483
639
|
|
|
484
640
|
specify "should raise an error when updating a stale record" do
|
|
485
|
-
p1 = Person[
|
|
486
|
-
p2 = Person[
|
|
641
|
+
p1 = Person[@p.id]
|
|
642
|
+
p2 = Person[@p.id]
|
|
487
643
|
p1.update(:name=>'Jim')
|
|
488
644
|
proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
|
489
645
|
end
|
|
490
646
|
|
|
491
647
|
specify "should raise an error when destroying a stale record" do
|
|
492
|
-
p1 = Person[
|
|
493
|
-
p2 = Person[
|
|
648
|
+
p1 = Person[@p.id]
|
|
649
|
+
p2 = Person[@p.id]
|
|
494
650
|
p1.update(:name=>'Jim')
|
|
495
651
|
proc{p2.destroy}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
|
|
496
652
|
end
|
|
497
653
|
|
|
498
654
|
specify "should not raise an error when updating the same record twice" do
|
|
499
|
-
p1 = Person[
|
|
655
|
+
p1 = Person[@p.id]
|
|
500
656
|
p1.update(:name=>'Jim')
|
|
501
657
|
proc{p1.update(:name=>'Bob')}.should_not raise_error
|
|
502
658
|
end
|
|
@@ -525,10 +681,10 @@ describe "Composition plugin" do
|
|
|
525
681
|
composition :date, :mapping=>[:year, :month, :day]
|
|
526
682
|
end
|
|
527
683
|
@e1 = Event.create(:year=>2010, :month=>2, :day=>15)
|
|
528
|
-
@e2 = Event.create(
|
|
684
|
+
@e2 = Event.create(:year=>nil)
|
|
529
685
|
end
|
|
530
686
|
after do
|
|
531
|
-
@db.drop_table(:events)
|
|
687
|
+
@db.drop_table?(:events)
|
|
532
688
|
Object.send(:remove_const, :Event)
|
|
533
689
|
end
|
|
534
690
|
|
|
@@ -555,9 +711,10 @@ describe "Composition plugin" do
|
|
|
555
711
|
end
|
|
556
712
|
end
|
|
557
713
|
|
|
558
|
-
|
|
714
|
+
# DB2's implemention of CTE is too limited to use this plugin
|
|
715
|
+
if INTEGRATION_DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
|
|
559
716
|
describe "RcteTree Plugin" do
|
|
560
|
-
before do
|
|
717
|
+
before(:all) do
|
|
561
718
|
@db = INTEGRATION_DB
|
|
562
719
|
@db.create_table!(:nodes) do
|
|
563
720
|
primary_key :id
|
|
@@ -568,22 +725,26 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
|
568
725
|
plugin :rcte_tree, :order=>:name
|
|
569
726
|
end
|
|
570
727
|
|
|
571
|
-
@
|
|
572
|
-
@
|
|
573
|
-
@
|
|
574
|
-
@
|
|
575
|
-
@
|
|
576
|
-
@
|
|
577
|
-
@
|
|
578
|
-
@
|
|
579
|
-
@
|
|
580
|
-
@
|
|
581
|
-
@
|
|
582
|
-
@
|
|
583
|
-
@
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
728
|
+
@nodes = []
|
|
729
|
+
@nodes << @a = Node.create(:name=>'a')
|
|
730
|
+
@nodes << @b = Node.create(:name=>'b')
|
|
731
|
+
@nodes << @aa = Node.create(:name=>'aa', :parent=>@a)
|
|
732
|
+
@nodes << @ab = Node.create(:name=>'ab', :parent=>@a)
|
|
733
|
+
@nodes << @ba = Node.create(:name=>'ba', :parent=>@b)
|
|
734
|
+
@nodes << @bb = Node.create(:name=>'bb', :parent=>@b)
|
|
735
|
+
@nodes << @aaa = Node.create(:name=>'aaa', :parent=>@aa)
|
|
736
|
+
@nodes << @aab = Node.create(:name=>'aab', :parent=>@aa)
|
|
737
|
+
@nodes << @aba = Node.create(:name=>'aba', :parent=>@ab)
|
|
738
|
+
@nodes << @abb = Node.create(:name=>'abb', :parent=>@ab)
|
|
739
|
+
@nodes << @aaaa = Node.create(:name=>'aaaa', :parent=>@aaa)
|
|
740
|
+
@nodes << @aaab = Node.create(:name=>'aaab', :parent=>@aaa)
|
|
741
|
+
@nodes << @aaaaa = Node.create(:name=>'aaaaa', :parent=>@aaaa)
|
|
742
|
+
end
|
|
743
|
+
before do
|
|
744
|
+
@nodes.each{|n| n.associations.clear}
|
|
745
|
+
end
|
|
746
|
+
after(:all) do
|
|
747
|
+
@db.drop_table? :nodes
|
|
587
748
|
Object.send(:remove_const, :Node)
|
|
588
749
|
end
|
|
589
750
|
|
|
@@ -659,13 +820,15 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
|
659
820
|
end
|
|
660
821
|
|
|
661
822
|
specify "should work correctly if not all columns are selected" do
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
nodes
|
|
668
|
-
nodes
|
|
823
|
+
c = Class.new(Sequel::Model(@db[:nodes]))
|
|
824
|
+
c.plugin :rcte_tree, :order=>:name
|
|
825
|
+
c.plugin :lazy_attributes, :name
|
|
826
|
+
c[:name=>'aaaa'].descendants.should == [c.load(:parent_id=>11, :id=>13)]
|
|
827
|
+
c[:name=>'aa'].ancestors.should == [c.load(:parent_id=>nil, :id=>1)]
|
|
828
|
+
nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
|
|
829
|
+
nodes.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
|
|
830
|
+
nodes[2].descendants.should == [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
|
|
831
|
+
nodes[1].ancestors.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
|
|
669
832
|
end
|
|
670
833
|
|
|
671
834
|
specify "should eagerly load descendants to a given level" do
|
|
@@ -751,7 +914,7 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
|
751
914
|
nodes[0].associations.fetch(:parent, 1).should == nil
|
|
752
915
|
nodes[1].associations[:parent].should == @aa
|
|
753
916
|
nodes[1].associations[:parent].associations[:parent].should == @a
|
|
754
|
-
nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1) == nil
|
|
917
|
+
nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1).should == nil
|
|
755
918
|
nodes[2].associations[:parent].should == @aaaa
|
|
756
919
|
nodes[2].associations[:parent].associations[:parent].should == @aaa
|
|
757
920
|
nodes[2].associations[:parent].associations[:parent].associations[:parent].should == @aa
|
|
@@ -783,7 +946,7 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
|
783
946
|
end
|
|
784
947
|
|
|
785
948
|
describe "Instance Filters plugin" do
|
|
786
|
-
before do
|
|
949
|
+
before(:all) do
|
|
787
950
|
@db = INTEGRATION_DB
|
|
788
951
|
@db.create_table!(:items) do
|
|
789
952
|
primary_key :id
|
|
@@ -794,12 +957,15 @@ describe "Instance Filters plugin" do
|
|
|
794
957
|
class ::Item < Sequel::Model(@db)
|
|
795
958
|
plugin :instance_filters
|
|
796
959
|
end
|
|
960
|
+
end
|
|
961
|
+
before do
|
|
962
|
+
@db[:items].delete
|
|
797
963
|
@i = Item.create(:name=>'J', :number=>1, :cost=>2)
|
|
798
964
|
@i.instance_filter(:number=>1)
|
|
799
965
|
@i.set(:name=>'K')
|
|
800
966
|
end
|
|
801
|
-
after do
|
|
802
|
-
@db.drop_table(:items)
|
|
967
|
+
after(:all) do
|
|
968
|
+
@db.drop_table?(:items)
|
|
803
969
|
Object.send(:remove_const, :Item)
|
|
804
970
|
end
|
|
805
971
|
|
|
@@ -843,21 +1009,24 @@ describe "Instance Filters plugin" do
|
|
|
843
1009
|
end
|
|
844
1010
|
|
|
845
1011
|
describe "UpdatePrimaryKey plugin" do
|
|
846
|
-
before do
|
|
1012
|
+
before(:all) do
|
|
847
1013
|
@db = INTEGRATION_DB
|
|
848
1014
|
@db.create_table!(:t) do
|
|
849
1015
|
Integer :a, :primary_key=>true
|
|
850
1016
|
Integer :b
|
|
851
1017
|
end
|
|
852
1018
|
@ds = @db[:t]
|
|
853
|
-
@ds.insert(:a=>1, :b=>3)
|
|
854
1019
|
@c = Class.new(Sequel::Model(@ds))
|
|
855
1020
|
@c.set_primary_key(:a)
|
|
856
1021
|
@c.unrestrict_primary_key
|
|
857
1022
|
@c.plugin :update_primary_key
|
|
858
1023
|
end
|
|
859
|
-
|
|
860
|
-
@
|
|
1024
|
+
before do
|
|
1025
|
+
@ds.delete
|
|
1026
|
+
@ds.insert(:a=>1, :b=>3)
|
|
1027
|
+
end
|
|
1028
|
+
after(:all) do
|
|
1029
|
+
@db.drop_table?(:t)
|
|
861
1030
|
end
|
|
862
1031
|
|
|
863
1032
|
specify "should handle regular updates" do
|
|
@@ -898,22 +1067,23 @@ describe "UpdatePrimaryKey plugin" do
|
|
|
898
1067
|
end
|
|
899
1068
|
|
|
900
1069
|
describe "AssociationPks plugin" do
|
|
901
|
-
before do
|
|
1070
|
+
before(:all) do
|
|
902
1071
|
@db = INTEGRATION_DB
|
|
903
|
-
@db.
|
|
1072
|
+
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
|
1073
|
+
@db.create_table(:artists) do
|
|
904
1074
|
primary_key :id
|
|
905
1075
|
String :name
|
|
906
1076
|
end
|
|
907
|
-
@db.create_table
|
|
1077
|
+
@db.create_table(:albums) do
|
|
908
1078
|
primary_key :id
|
|
909
1079
|
String :name
|
|
910
1080
|
foreign_key :artist_id, :artists
|
|
911
1081
|
end
|
|
912
|
-
@db.create_table
|
|
1082
|
+
@db.create_table(:tags) do
|
|
913
1083
|
primary_key :id
|
|
914
1084
|
String :name
|
|
915
1085
|
end
|
|
916
|
-
@db.create_table
|
|
1086
|
+
@db.create_table(:albums_tags) do
|
|
917
1087
|
foreign_key :album_id, :albums
|
|
918
1088
|
foreign_key :tag_id, :tags
|
|
919
1089
|
end
|
|
@@ -927,7 +1097,9 @@ describe "AssociationPks plugin" do
|
|
|
927
1097
|
end
|
|
928
1098
|
class ::Tag < Sequel::Model
|
|
929
1099
|
end
|
|
930
|
-
|
|
1100
|
+
end
|
|
1101
|
+
before do
|
|
1102
|
+
[:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
|
|
931
1103
|
@ar1 =@db[:artists].insert(:name=>'YJM')
|
|
932
1104
|
@ar2 =@db[:artists].insert(:name=>'AS')
|
|
933
1105
|
@al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
|
|
@@ -940,8 +1112,8 @@ describe "AssociationPks plugin" do
|
|
|
940
1112
|
tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
|
|
941
1113
|
end
|
|
942
1114
|
end
|
|
943
|
-
after do
|
|
944
|
-
@db.drop_table :albums_tags, :tags, :albums, :artists
|
|
1115
|
+
after(:all) do
|
|
1116
|
+
@db.drop_table? :albums_tags, :tags, :albums, :artists
|
|
945
1117
|
[:Artist, :Album, :Tag].each{|s| Object.send(:remove_const, s)}
|
|
946
1118
|
end
|
|
947
1119
|
|
|
@@ -994,9 +1166,9 @@ end
|
|
|
994
1166
|
|
|
995
1167
|
|
|
996
1168
|
describe "List plugin without a scope" do
|
|
997
|
-
before do
|
|
1169
|
+
before(:all) do
|
|
998
1170
|
@db = INTEGRATION_DB
|
|
999
|
-
@db.create_table
|
|
1171
|
+
@db.create_table!(:sites) do
|
|
1000
1172
|
primary_key :id
|
|
1001
1173
|
String :name
|
|
1002
1174
|
Integer :position
|
|
@@ -1004,14 +1176,15 @@ describe "List plugin without a scope" do
|
|
|
1004
1176
|
|
|
1005
1177
|
@c = Class.new(Sequel::Model(@db[:sites]))
|
|
1006
1178
|
@c.plugin :list
|
|
1179
|
+
end
|
|
1180
|
+
before do
|
|
1007
1181
|
@c.delete
|
|
1008
|
-
@c.create :name => "
|
|
1009
|
-
@c.create :name => "def"
|
|
1010
|
-
@c.create :name => "
|
|
1182
|
+
@c.create :name => "abc"
|
|
1183
|
+
@c.create :name => "def"
|
|
1184
|
+
@c.create :name => "hig"
|
|
1011
1185
|
end
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
@db.drop_table(:sites)
|
|
1186
|
+
after(:all) do
|
|
1187
|
+
@db.drop_table?(:sites)
|
|
1015
1188
|
end
|
|
1016
1189
|
|
|
1017
1190
|
it "should return rows in order of position" do
|
|
@@ -1067,9 +1240,9 @@ describe "List plugin without a scope" do
|
|
|
1067
1240
|
end
|
|
1068
1241
|
|
|
1069
1242
|
describe "List plugin with a scope" do
|
|
1070
|
-
before do
|
|
1243
|
+
before(:all) do
|
|
1071
1244
|
@db = INTEGRATION_DB
|
|
1072
|
-
@db.create_table
|
|
1245
|
+
@db.create_table!(:pages) do
|
|
1073
1246
|
primary_key :id
|
|
1074
1247
|
String :name
|
|
1075
1248
|
Integer :pos
|
|
@@ -1078,19 +1251,21 @@ describe "List plugin with a scope" do
|
|
|
1078
1251
|
|
|
1079
1252
|
@c = Class.new(Sequel::Model(@db[:pages]))
|
|
1080
1253
|
@c.plugin :list, :field => :pos, :scope => :parent_id
|
|
1081
|
-
p1 = @c.create :name => "Hm", :pos => 1, :parent_id => 0
|
|
1082
|
-
p2 = @c.create :name => "Ps", :pos => 1, :parent_id => p1.id
|
|
1083
|
-
@c.create :name => "P1", :pos => 1, :parent_id => p2.id
|
|
1084
|
-
@c.create :name => "P2", :pos => 2, :parent_id => p2.id
|
|
1085
|
-
@c.create :name => "P3", :pos => 3, :parent_id => p2.id
|
|
1086
|
-
@c.create :name => "Au", :pos => 2, :parent_id => p1.id
|
|
1087
1254
|
end
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
@
|
|
1255
|
+
before do
|
|
1256
|
+
@c.delete
|
|
1257
|
+
p1 = @c.create :name => "Hm", :parent_id => 0
|
|
1258
|
+
p2 = @c.create :name => "Ps", :parent_id => p1.id
|
|
1259
|
+
@c.create :name => "P1", :parent_id => p2.id
|
|
1260
|
+
@c.create :name => "P2", :parent_id => p2.id
|
|
1261
|
+
@c.create :name => "P3", :parent_id => p2.id
|
|
1262
|
+
@c.create :name => "Au", :parent_id => p1.id
|
|
1263
|
+
end
|
|
1264
|
+
after(:all) do
|
|
1265
|
+
@db.drop_table?(:pages)
|
|
1091
1266
|
end
|
|
1092
1267
|
|
|
1093
|
-
|
|
1268
|
+
specify "should return rows in order of position" do
|
|
1094
1269
|
@c.map(:name).should == %w[ Hm Ps Au P1 P2 P3 ]
|
|
1095
1270
|
end
|
|
1096
1271
|
|
|
@@ -1111,7 +1286,7 @@ describe "List plugin with a scope" do
|
|
|
1111
1286
|
@c[:name => "P3"].next.should == nil
|
|
1112
1287
|
end
|
|
1113
1288
|
|
|
1114
|
-
|
|
1289
|
+
specify "should define move_to" do
|
|
1115
1290
|
@c[:name => "P2"].move_to(1)
|
|
1116
1291
|
@c.map(:name).should == %w[ Hm Ps Au P2 P1 P3 ]
|
|
1117
1292
|
|
|
@@ -1122,7 +1297,7 @@ describe "List plugin with a scope" do
|
|
|
1122
1297
|
proc { @c[:name => "P2"].move_to(10) }.should raise_error(Sequel::Error)
|
|
1123
1298
|
end
|
|
1124
1299
|
|
|
1125
|
-
|
|
1300
|
+
specify "should define move_to_top and move_to_bottom" do
|
|
1126
1301
|
@c[:name => "Au"].move_to_top
|
|
1127
1302
|
@c.map(:name).should == %w[ Hm Au Ps P1 P2 P3 ]
|
|
1128
1303
|
|
|
@@ -1130,7 +1305,7 @@ describe "List plugin with a scope" do
|
|
|
1130
1305
|
@c.map(:name).should == %w[ Hm Ps Au P1 P2 P3 ]
|
|
1131
1306
|
end
|
|
1132
1307
|
|
|
1133
|
-
|
|
1308
|
+
specify "should define move_up and move_down" do
|
|
1134
1309
|
@c[:name => "P2"].move_up
|
|
1135
1310
|
@c.map(:name).should == %w[ Hm Ps Au P2 P1 P3 ]
|
|
1136
1311
|
|
|
@@ -1143,12 +1318,12 @@ describe "List plugin with a scope" do
|
|
|
1143
1318
|
end
|
|
1144
1319
|
|
|
1145
1320
|
describe "Sequel::Plugins::Tree" do
|
|
1146
|
-
before do
|
|
1321
|
+
before(:all) do
|
|
1147
1322
|
@db = INTEGRATION_DB
|
|
1148
1323
|
end
|
|
1149
1324
|
|
|
1150
1325
|
describe "with natural database order" do
|
|
1151
|
-
before do
|
|
1326
|
+
before(:all) do
|
|
1152
1327
|
@db.create_table!(:nodes) do
|
|
1153
1328
|
Integer :id, :primary_key=>true
|
|
1154
1329
|
String :name
|
|
@@ -1174,8 +1349,8 @@ describe "Sequel::Plugins::Tree" do
|
|
|
1174
1349
|
plugin :tree
|
|
1175
1350
|
end
|
|
1176
1351
|
end
|
|
1177
|
-
after do
|
|
1178
|
-
@db.drop_table(:nodes)
|
|
1352
|
+
after(:all) do
|
|
1353
|
+
@db.drop_table?(:nodes)
|
|
1179
1354
|
Object.send(:remove_const, :Node)
|
|
1180
1355
|
end
|
|
1181
1356
|
|
|
@@ -1249,12 +1424,12 @@ describe "Sequel::Plugins::Tree" do
|
|
|
1249
1424
|
end
|
|
1250
1425
|
|
|
1251
1426
|
describe "Nodes in specified order" do
|
|
1252
|
-
before do
|
|
1427
|
+
before(:all) do
|
|
1253
1428
|
class ::OrderedNode < Sequel::Model(:nodes)
|
|
1254
1429
|
plugin :tree, :order => :position
|
|
1255
1430
|
end
|
|
1256
1431
|
end
|
|
1257
|
-
after do
|
|
1432
|
+
after(:all) do
|
|
1258
1433
|
Object.send(:remove_const, :OrderedNode)
|
|
1259
1434
|
end
|
|
1260
1435
|
|
|
@@ -1272,7 +1447,7 @@ describe "Sequel::Plugins::Tree" do
|
|
|
1272
1447
|
end
|
|
1273
1448
|
|
|
1274
1449
|
describe "Lorems in specified order" do
|
|
1275
|
-
before do
|
|
1450
|
+
before(:all) do
|
|
1276
1451
|
@db.create_table!(:lorems) do
|
|
1277
1452
|
Integer :id, :primary_key=>true
|
|
1278
1453
|
String :name
|
|
@@ -1290,8 +1465,8 @@ describe "Sequel::Plugins::Tree" do
|
|
|
1290
1465
|
plugin :tree, :key => :ipsum_id, :order => :neque
|
|
1291
1466
|
end
|
|
1292
1467
|
end
|
|
1293
|
-
after do
|
|
1294
|
-
@db.drop_table(:lorems)
|
|
1468
|
+
after(:all) do
|
|
1469
|
+
@db.drop_table?(:lorems)
|
|
1295
1470
|
Object.send(:remove_const, :Lorem)
|
|
1296
1471
|
end
|
|
1297
1472
|
|
|
@@ -1306,3 +1481,285 @@ describe "Sequel::Plugins::Tree" do
|
|
|
1306
1481
|
end
|
|
1307
1482
|
end
|
|
1308
1483
|
end
|
|
1484
|
+
|
|
1485
|
+
describe "Sequel::Plugins::PreparedStatements" do
|
|
1486
|
+
before(:all) do
|
|
1487
|
+
@db = INTEGRATION_DB
|
|
1488
|
+
@db.create_table!(:ps_test) do
|
|
1489
|
+
primary_key :id
|
|
1490
|
+
String :name
|
|
1491
|
+
Integer :i
|
|
1492
|
+
end
|
|
1493
|
+
@c = Class.new(Sequel::Model(@db[:ps_test]))
|
|
1494
|
+
@c.plugin :prepared_statements_with_pk
|
|
1495
|
+
end
|
|
1496
|
+
before do
|
|
1497
|
+
@c.delete
|
|
1498
|
+
@foo = @c.create(:name=>'foo', :i=>10)
|
|
1499
|
+
@bar = @c.create(:name=>'bar', :i=>20)
|
|
1500
|
+
end
|
|
1501
|
+
after(:all) do
|
|
1502
|
+
@db.drop_table?(:ps_test)
|
|
1503
|
+
end
|
|
1504
|
+
|
|
1505
|
+
it "should work with looking up using Model.[]" do
|
|
1506
|
+
@c[@foo.id].should == @foo
|
|
1507
|
+
@c[@bar.id].should == @bar
|
|
1508
|
+
@c[0].should == nil
|
|
1509
|
+
@c[nil].should == nil
|
|
1510
|
+
end
|
|
1511
|
+
|
|
1512
|
+
it "should work with looking up using Dataset#with_pk" do
|
|
1513
|
+
@c.dataset.with_pk(@foo.id).should == @foo
|
|
1514
|
+
@c.dataset.with_pk(@bar.id).should == @bar
|
|
1515
|
+
@c.dataset.with_pk(0).should == nil
|
|
1516
|
+
@c.dataset.with_pk(nil).should == nil
|
|
1517
|
+
|
|
1518
|
+
@c.dataset.filter(:i=>0).with_pk(@foo.id).should == nil
|
|
1519
|
+
@c.dataset.filter(:i=>10).with_pk(@foo.id).should == @foo
|
|
1520
|
+
@c.dataset.filter(:i=>20).with_pk(@bar.id).should == @bar
|
|
1521
|
+
@c.dataset.filter(:i=>10).with_pk(nil).should == nil
|
|
1522
|
+
@c.dataset.filter(:name=>'foo').with_pk(@foo.id).should == @foo
|
|
1523
|
+
@c.dataset.filter(:name=>'bar').with_pk(@bar.id).should == @bar
|
|
1524
|
+
@c.dataset.filter(:name=>'baz').with_pk(@bar.id).should == nil
|
|
1525
|
+
@c.dataset.filter(:name=>'bar').with_pk(nil).should == nil
|
|
1526
|
+
end
|
|
1527
|
+
|
|
1528
|
+
it "should work with Model#destroy" do
|
|
1529
|
+
@foo.destroy
|
|
1530
|
+
@bar.destroy
|
|
1531
|
+
@c[@foo.id].should == nil
|
|
1532
|
+
@c[@bar.id].should == nil
|
|
1533
|
+
end
|
|
1534
|
+
|
|
1535
|
+
it "should work with Model#update" do
|
|
1536
|
+
@foo.update(:name=>'foo2', :i=>30)
|
|
1537
|
+
@c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo2', :i=>30)
|
|
1538
|
+
@foo.update(:name=>'foo3')
|
|
1539
|
+
@c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>30)
|
|
1540
|
+
@foo.update(:i=>40)
|
|
1541
|
+
@c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>40)
|
|
1542
|
+
@foo.update(:i=>nil)
|
|
1543
|
+
@c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>nil)
|
|
1544
|
+
end
|
|
1545
|
+
|
|
1546
|
+
it "should work with Model#create" do
|
|
1547
|
+
o = @c.create(:name=>'foo2', :i=>30)
|
|
1548
|
+
@c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>30)
|
|
1549
|
+
o = @c.create(:name=>'foo2')
|
|
1550
|
+
@c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>nil)
|
|
1551
|
+
o = @c.create(:i=>30)
|
|
1552
|
+
@c[o.id].should == @c.load(:id=>o.id, :name=>nil, :i=>30)
|
|
1553
|
+
o = @c.create(:name=>nil, :i=>40)
|
|
1554
|
+
@c[o.id].should == @c.load(:id=>o.id, :name=>nil, :i=>40)
|
|
1555
|
+
end
|
|
1556
|
+
end
|
|
1557
|
+
|
|
1558
|
+
describe "Caching plugins" do
|
|
1559
|
+
before(:all) do
|
|
1560
|
+
@db = INTEGRATION_DB
|
|
1561
|
+
@db.drop_table?(:albums, :artists)
|
|
1562
|
+
@db.create_table(:artists) do
|
|
1563
|
+
primary_key :id
|
|
1564
|
+
end
|
|
1565
|
+
@db.create_table(:albums) do
|
|
1566
|
+
primary_key :id
|
|
1567
|
+
foreign_key :artist_id, :artists
|
|
1568
|
+
end
|
|
1569
|
+
@db[:artists].insert
|
|
1570
|
+
@db[:albums].insert(:artist_id=>1)
|
|
1571
|
+
end
|
|
1572
|
+
before do
|
|
1573
|
+
@Album = Class.new(Sequel::Model(@db[:albums]))
|
|
1574
|
+
@Album.plugin :many_to_one_pk_lookup
|
|
1575
|
+
end
|
|
1576
|
+
after(:all) do
|
|
1577
|
+
@db.drop_table?(:albums, :artists)
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
shared_examples_for "a caching plugin" do
|
|
1581
|
+
it "should work with looking up using Model.[]" do
|
|
1582
|
+
@Artist[1].should equal(@Artist[1])
|
|
1583
|
+
@Artist[:id=>1].should == @Artist[1]
|
|
1584
|
+
@Artist[0].should == nil
|
|
1585
|
+
@Artist[nil].should == nil
|
|
1586
|
+
end
|
|
1587
|
+
|
|
1588
|
+
it "should work with lookup up many_to_one associated objects" do
|
|
1589
|
+
a = @Artist[1]
|
|
1590
|
+
@Album.first.artist.should equal(a)
|
|
1591
|
+
end
|
|
1592
|
+
end
|
|
1593
|
+
|
|
1594
|
+
describe "caching plugin" do
|
|
1595
|
+
before do
|
|
1596
|
+
@cache_class = Class.new(Hash) do
|
|
1597
|
+
def set(k, v, ttl) self[k] = v end
|
|
1598
|
+
alias get []
|
|
1599
|
+
end
|
|
1600
|
+
@cache = @cache_class.new
|
|
1601
|
+
|
|
1602
|
+
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
1603
|
+
@Artist.plugin :caching, @cache
|
|
1604
|
+
@Album.many_to_one :artist, :class=>@Artist
|
|
1605
|
+
end
|
|
1606
|
+
|
|
1607
|
+
it_should_behave_like "a caching plugin"
|
|
1608
|
+
end
|
|
1609
|
+
|
|
1610
|
+
describe "static_cache plugin" do
|
|
1611
|
+
before do
|
|
1612
|
+
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
1613
|
+
@Artist.plugin :static_cache
|
|
1614
|
+
@Album.many_to_one :artist, :class=>@Artist
|
|
1615
|
+
end
|
|
1616
|
+
|
|
1617
|
+
it_should_behave_like "a caching plugin"
|
|
1618
|
+
end
|
|
1619
|
+
end
|
|
1620
|
+
|
|
1621
|
+
describe "Sequel::Plugins::ConstraintValidations" do
|
|
1622
|
+
before(:all) do
|
|
1623
|
+
@db = INTEGRATION_DB
|
|
1624
|
+
@db.extension(:constraint_validations)
|
|
1625
|
+
@db.create_constraint_validations_table
|
|
1626
|
+
@ds = @db[:cv_test]
|
|
1627
|
+
@regexp = regexp = @db.dataset.supports_regexp?
|
|
1628
|
+
@validate_block = proc do
|
|
1629
|
+
presence :pre, :name=>:p
|
|
1630
|
+
exact_length 5, :exactlen, :name=>:el
|
|
1631
|
+
min_length 5, :minlen, :name=>:minl
|
|
1632
|
+
max_length 5, :maxlen, :name=>:maxl
|
|
1633
|
+
length_range 3..5, :lenrange, :name=>:lr
|
|
1634
|
+
if regexp
|
|
1635
|
+
format /^foo\d+/, :form, :name=>:f
|
|
1636
|
+
end
|
|
1637
|
+
like 'foo%', :lik, :name=>:l
|
|
1638
|
+
ilike 'foo%', :ilik, :name=>:il
|
|
1639
|
+
includes %w'abc def', :inc, :name=>:i
|
|
1640
|
+
unique :uniq, :name=>:u
|
|
1641
|
+
max_length 6, :minlen, :name=>:maxl2
|
|
1642
|
+
end
|
|
1643
|
+
@valid_row = {:pre=>'a', :exactlen=>'12345', :minlen=>'12345', :maxlen=>'12345', :lenrange=>'1234', :lik=>'fooabc', :ilik=>'FooABC', :inc=>'abc', :uniq=>'u'}
|
|
1644
|
+
@violations = [
|
|
1645
|
+
[:pre, [nil, '', ' ']],
|
|
1646
|
+
[:exactlen, [nil, '', '1234', '123456']],
|
|
1647
|
+
[:minlen, [nil, '', '1234']],
|
|
1648
|
+
[:maxlen, [nil, '123456']],
|
|
1649
|
+
[:lenrange, [nil, '', '12', '123456']],
|
|
1650
|
+
[:lik, [nil, '', 'fo', 'fotabc', 'FOOABC']],
|
|
1651
|
+
[:ilik, [nil, '', 'fo', 'fotabc']],
|
|
1652
|
+
[:inc, [nil, '', 'ab', 'abcd']],
|
|
1653
|
+
]
|
|
1654
|
+
|
|
1655
|
+
if @regexp
|
|
1656
|
+
@valid_row[:form] = 'foo1'
|
|
1657
|
+
@violations << [:form, [nil, '', 'foo', 'fooa']]
|
|
1658
|
+
end
|
|
1659
|
+
end
|
|
1660
|
+
after(:all) do
|
|
1661
|
+
@db.drop_constraint_validations_table
|
|
1662
|
+
end
|
|
1663
|
+
|
|
1664
|
+
shared_examples_for "constraint validations" do
|
|
1665
|
+
cspecify "should set up constraints that work even outside the model", :mysql do
|
|
1666
|
+
proc{@ds.insert(@valid_row)}.should_not raise_error
|
|
1667
|
+
|
|
1668
|
+
# Test for unique constraint
|
|
1669
|
+
proc{@ds.insert(@valid_row)}.should raise_error(Sequel::DatabaseError)
|
|
1670
|
+
|
|
1671
|
+
@ds.delete
|
|
1672
|
+
@violations.each do |col, vals|
|
|
1673
|
+
try = @valid_row.dup
|
|
1674
|
+
vals += ['1234567'] if col == :minlen
|
|
1675
|
+
vals.each do |val|
|
|
1676
|
+
try[col] = val
|
|
1677
|
+
proc{@ds.insert(try)}.should raise_error(Sequel::DatabaseError)
|
|
1678
|
+
end
|
|
1679
|
+
end
|
|
1680
|
+
|
|
1681
|
+
# Test for dropping of constraint
|
|
1682
|
+
@db.alter_table(:cv_test){validate{drop :maxl2}}
|
|
1683
|
+
proc{@ds.insert(@valid_row.merge(:minlen=>'1234567'))}.should_not raise_error
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1686
|
+
it "should set up automatic validations inside the model" do
|
|
1687
|
+
c = Class.new(Sequel::Model(@ds))
|
|
1688
|
+
c.plugin :constraint_validations
|
|
1689
|
+
c.delete
|
|
1690
|
+
proc{c.create(@valid_row)}.should_not raise_error
|
|
1691
|
+
|
|
1692
|
+
# Test for unique validation
|
|
1693
|
+
c.new(@valid_row).should_not be_valid
|
|
1694
|
+
|
|
1695
|
+
c.delete
|
|
1696
|
+
@violations.each do |col, vals|
|
|
1697
|
+
try = @valid_row.dup
|
|
1698
|
+
vals.each do |val|
|
|
1699
|
+
try[col] = val
|
|
1700
|
+
c.new(try).should_not be_valid
|
|
1701
|
+
end
|
|
1702
|
+
end
|
|
1703
|
+
end
|
|
1704
|
+
end
|
|
1705
|
+
|
|
1706
|
+
describe "via create_table" do
|
|
1707
|
+
before(:all) do
|
|
1708
|
+
regexp = @regexp
|
|
1709
|
+
validate_block = @validate_block
|
|
1710
|
+
@db.create_table!(:cv_test) do
|
|
1711
|
+
primary_key :id
|
|
1712
|
+
String :pre
|
|
1713
|
+
String :exactlen
|
|
1714
|
+
String :minlen
|
|
1715
|
+
String :maxlen
|
|
1716
|
+
String :lenrange
|
|
1717
|
+
if regexp
|
|
1718
|
+
String :form
|
|
1719
|
+
end
|
|
1720
|
+
String :lik
|
|
1721
|
+
String :ilik
|
|
1722
|
+
String :inc
|
|
1723
|
+
String :uniq, :null=>false
|
|
1724
|
+
validate(&validate_block)
|
|
1725
|
+
end
|
|
1726
|
+
end
|
|
1727
|
+
after(:all) do
|
|
1728
|
+
@db.drop_table?(:cv_test)
|
|
1729
|
+
@db.drop_constraint_validations_for(:table=>:cv_test)
|
|
1730
|
+
end
|
|
1731
|
+
|
|
1732
|
+
it_should_behave_like "constraint validations"
|
|
1733
|
+
end
|
|
1734
|
+
|
|
1735
|
+
describe "via alter_table" do
|
|
1736
|
+
before(:all) do
|
|
1737
|
+
regexp = @regexp
|
|
1738
|
+
validate_block = @validate_block
|
|
1739
|
+
@db.create_table!(:cv_test) do
|
|
1740
|
+
primary_key :id
|
|
1741
|
+
String :lik
|
|
1742
|
+
String :ilik
|
|
1743
|
+
String :inc
|
|
1744
|
+
String :uniq, :null=>false
|
|
1745
|
+
end
|
|
1746
|
+
@db.alter_table(:cv_test) do
|
|
1747
|
+
add_column :pre, String
|
|
1748
|
+
add_column :exactlen, String
|
|
1749
|
+
add_column :minlen, String
|
|
1750
|
+
add_column :maxlen, String
|
|
1751
|
+
add_column :lenrange, String
|
|
1752
|
+
if regexp
|
|
1753
|
+
add_column :form, String
|
|
1754
|
+
end
|
|
1755
|
+
validate(&validate_block)
|
|
1756
|
+
end
|
|
1757
|
+
end
|
|
1758
|
+
after(:all) do
|
|
1759
|
+
@db.drop_table?(:cv_test)
|
|
1760
|
+
@db.drop_constraint_validations_for(:table=>:cv_test)
|
|
1761
|
+
end
|
|
1762
|
+
|
|
1763
|
+
it_should_behave_like "constraint validations"
|
|
1764
|
+
end
|
|
1765
|
+
end
|