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
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -14,10 +14,6 @@ INTEGRATION_DB = MYSQL_DB unless defined?(INTEGRATION_DB)
|
|
|
14
14
|
|
|
15
15
|
MYSQL_URI = URI.parse(MYSQL_DB.uri)
|
|
16
16
|
|
|
17
|
-
MYSQL_DB.create_table! :test2 do
|
|
18
|
-
text :name
|
|
19
|
-
integer :value
|
|
20
|
-
end
|
|
21
17
|
def MYSQL_DB.sqls
|
|
22
18
|
(@sqls ||= [])
|
|
23
19
|
end
|
|
@@ -26,9 +22,7 @@ def logger.method_missing(m, msg)
|
|
|
26
22
|
MYSQL_DB.sqls << msg
|
|
27
23
|
end
|
|
28
24
|
MYSQL_DB.loggers = [logger]
|
|
29
|
-
MYSQL_DB.drop_table(:items
|
|
30
|
-
MYSQL_DB.drop_table(:dolls) rescue nil
|
|
31
|
-
MYSQL_DB.drop_table(:booltest) rescue nil
|
|
25
|
+
MYSQL_DB.drop_table?(:items, :dolls, :booltest)
|
|
32
26
|
|
|
33
27
|
SQL_BEGIN = 'BEGIN'
|
|
34
28
|
SQL_ROLLBACK = 'ROLLBACK'
|
|
@@ -40,29 +34,37 @@ describe "MySQL", '#create_table' do
|
|
|
40
34
|
MYSQL_DB.sqls.clear
|
|
41
35
|
end
|
|
42
36
|
after do
|
|
43
|
-
@db.drop_table(:dolls)
|
|
37
|
+
@db.drop_table?(:dolls)
|
|
44
38
|
end
|
|
45
|
-
|
|
39
|
+
|
|
46
40
|
specify "should allow to specify options for MySQL" do
|
|
47
41
|
@db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
|
48
|
-
|
|
42
|
+
check_sqls do
|
|
43
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
44
|
+
end
|
|
49
45
|
end
|
|
50
|
-
|
|
46
|
+
|
|
51
47
|
specify "should create a temporary table" do
|
|
52
48
|
@db.create_table(:tmp_dolls, :temp => true, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
|
53
|
-
|
|
49
|
+
check_sqls do
|
|
50
|
+
@db.sqls.should == ["CREATE TEMPORARY TABLE `tmp_dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
51
|
+
end
|
|
54
52
|
end
|
|
55
|
-
|
|
53
|
+
|
|
56
54
|
specify "should not use a default for a String :text=>true type" do
|
|
57
55
|
@db.create_table(:dolls){String :name, :text=>true, :default=>'blah'}
|
|
58
|
-
|
|
56
|
+
check_sqls do
|
|
57
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` text)"]
|
|
58
|
+
end
|
|
59
59
|
end
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
specify "should not use a default for a File type" do
|
|
62
62
|
@db.create_table(:dolls){File :name, :default=>'blah'}
|
|
63
|
-
|
|
63
|
+
check_sqls do
|
|
64
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` blob)"]
|
|
65
|
+
end
|
|
64
66
|
end
|
|
65
|
-
|
|
67
|
+
|
|
66
68
|
specify "should respect the size option for File type" do
|
|
67
69
|
@db.create_table(:dolls) do
|
|
68
70
|
File :n1
|
|
@@ -82,42 +84,41 @@ describe "MySQL", '#create_table' do
|
|
|
82
84
|
end
|
|
83
85
|
@db.schema(:dolls).map{|k, v| v[:auto_increment]}.should == [nil, nil, true]
|
|
84
86
|
end
|
|
85
|
-
end
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
specify "should support collate with various other column options" do
|
|
89
|
+
@db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
|
|
90
|
+
@db[:dolls].insert
|
|
91
|
+
@db[:dolls].select_map(:name).should == ["foo"]
|
|
90
92
|
end
|
|
91
|
-
|
|
92
|
-
specify "should
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
MYSQL_DB.transaction{MYSQL_DB[:test2].for_share.all.should == []}
|
|
93
|
+
|
|
94
|
+
specify "should be able to parse the default value for set and enum types" do
|
|
95
|
+
@db.create_table!(:dolls){column :t, "set('a', 'b', 'c', 'd')", :default=>'a,b'}
|
|
96
|
+
@db.schema(:dolls).first.last[:ruby_default].should == 'a,b'
|
|
97
|
+
@db.create_table!(:dolls){column :t, "enum('a', 'b', 'c', 'd')", :default=>'b'}
|
|
98
|
+
@db.schema(:dolls).first.last[:ruby_default].should == 'b'
|
|
98
99
|
end
|
|
99
100
|
end
|
|
100
101
|
|
|
101
|
-
if MYSQL_DB.adapter_scheme
|
|
102
|
-
describe "Sequel::MySQL
|
|
102
|
+
if [:mysql, :mysql2].include?(MYSQL_DB.adapter_scheme)
|
|
103
|
+
describe "Sequel::MySQL::Database#convert_tinyint_to_bool" do
|
|
103
104
|
before do
|
|
104
105
|
@db = MYSQL_DB
|
|
105
106
|
@db.create_table(:booltest){column :b, 'tinyint(1)'; column :i, 'tinyint(4)'}
|
|
106
107
|
@ds = @db[:booltest]
|
|
107
108
|
end
|
|
108
109
|
after do
|
|
109
|
-
|
|
110
|
-
@db.drop_table(:booltest)
|
|
110
|
+
@db.convert_tinyint_to_bool = true
|
|
111
|
+
@db.drop_table?(:booltest)
|
|
111
112
|
end
|
|
112
|
-
|
|
113
|
+
|
|
113
114
|
specify "should consider tinyint(1) datatypes as boolean if set, but not larger tinyints" do
|
|
114
115
|
@db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:boolean, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
|
|
115
|
-
|
|
116
|
+
@db.convert_tinyint_to_bool = false
|
|
116
117
|
@db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
|
|
117
118
|
end
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
specify "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
|
|
120
|
-
|
|
121
|
+
@db.convert_tinyint_to_bool = true
|
|
121
122
|
@ds.delete
|
|
122
123
|
@ds << {:b=>true, :i=>10}
|
|
123
124
|
@ds.all.should == [{:b=>true, :i=>10}]
|
|
@@ -130,14 +131,14 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
130
131
|
end
|
|
131
132
|
|
|
132
133
|
specify "should return all tinyints as integers when unset" do
|
|
133
|
-
|
|
134
|
+
@db.convert_tinyint_to_bool = false
|
|
134
135
|
@ds.delete
|
|
135
136
|
@ds << {:b=>true, :i=>10}
|
|
136
137
|
@ds.all.should == [{:b=>1, :i=>10}]
|
|
137
138
|
@ds.delete
|
|
138
139
|
@ds << {:b=>false, :i=>0}
|
|
139
140
|
@ds.all.should == [{:b=>0, :i=>0}]
|
|
140
|
-
|
|
141
|
+
|
|
141
142
|
@ds.delete
|
|
142
143
|
@ds << {:b=>1, :i=>10}
|
|
143
144
|
@ds.all.should == [{:b=>1, :i=>10}]
|
|
@@ -145,6 +146,17 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
145
146
|
@ds << {:b=>0, :i=>0}
|
|
146
147
|
@ds.all.should == [{:b=>0, :i=>0}]
|
|
147
148
|
end
|
|
149
|
+
|
|
150
|
+
specify "should allow disabling the conversion on a per-dataset basis" do
|
|
151
|
+
@db.convert_tinyint_to_bool = true
|
|
152
|
+
ds = @ds.clone
|
|
153
|
+
ds.meta_def(:cast_tinyint_integer?){|f| true} # mysql
|
|
154
|
+
ds.meta_def(:convert_tinyint_to_bool?){false} # mysql2
|
|
155
|
+
ds.delete
|
|
156
|
+
ds << {:b=>true, :i=>10}
|
|
157
|
+
ds.all.should == [{:b=>1, :i=>10}]
|
|
158
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
|
159
|
+
end
|
|
148
160
|
end
|
|
149
161
|
end
|
|
150
162
|
|
|
@@ -155,106 +167,86 @@ describe "A MySQL dataset" do
|
|
|
155
167
|
MYSQL_DB.sqls.clear
|
|
156
168
|
end
|
|
157
169
|
after do
|
|
158
|
-
MYSQL_DB.drop_table(:items)
|
|
170
|
+
MYSQL_DB.drop_table?(:items)
|
|
159
171
|
end
|
|
160
|
-
|
|
172
|
+
|
|
161
173
|
specify "should quote columns and tables using back-ticks if quoting identifiers" do
|
|
162
174
|
@d.quote_identifiers = true
|
|
163
|
-
@d.select(:name).sql.should ==
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
@d.select(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
@d.select(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
@d.select(:
|
|
173
|
-
'SELECT
|
|
174
|
-
|
|
175
|
-
@d.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
@d.order(:name.desc).sql.should == \
|
|
179
|
-
'SELECT * FROM `items` ORDER BY `name` DESC'
|
|
180
|
-
|
|
181
|
-
@d.select('items.name AS item_name'.lit).sql.should == \
|
|
182
|
-
'SELECT items.name AS item_name FROM `items`'
|
|
183
|
-
|
|
184
|
-
@d.select('`name`'.lit).sql.should == \
|
|
185
|
-
'SELECT `name` FROM `items`'
|
|
186
|
-
|
|
187
|
-
@d.select('max(items.`name`) AS `max_name`'.lit).sql.should == \
|
|
188
|
-
'SELECT max(items.`name`) AS `max_name` FROM `items`'
|
|
189
|
-
|
|
190
|
-
@d.select(:test.sql_function(:abc, 'hello')).sql.should == \
|
|
191
|
-
"SELECT test(`abc`, 'hello') FROM `items`"
|
|
192
|
-
|
|
193
|
-
@d.select(:test.sql_function(:abc__def, 'hello')).sql.should == \
|
|
194
|
-
"SELECT test(`abc`.`def`, 'hello') FROM `items`"
|
|
195
|
-
|
|
196
|
-
@d.select(:test.sql_function(:abc__def, 'hello').as(:x2)).sql.should == \
|
|
197
|
-
"SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
|
|
198
|
-
|
|
199
|
-
@d.insert_sql(:value => 333).should == \
|
|
200
|
-
'INSERT INTO `items` (`value`) VALUES (333)'
|
|
201
|
-
|
|
202
|
-
@d.insert_sql(:x => :y).should == \
|
|
203
|
-
'INSERT INTO `items` (`x`) VALUES (`y`)'
|
|
175
|
+
@d.select(:name).sql.should == 'SELECT `name` FROM `items`'
|
|
176
|
+
@d.select(Sequel.lit('COUNT(*)')).sql.should == 'SELECT COUNT(*) FROM `items`'
|
|
177
|
+
@d.select(Sequel.function(:max, :value)).sql.should == 'SELECT max(`value`) FROM `items`'
|
|
178
|
+
@d.select(Sequel.function(:NOW)).sql.should == 'SELECT NOW() FROM `items`'
|
|
179
|
+
@d.select(Sequel.function(:max, :items__value)).sql.should == 'SELECT max(`items`.`value`) FROM `items`'
|
|
180
|
+
@d.order(Sequel.expr(:name).desc).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC'
|
|
181
|
+
@d.select(Sequel.lit('items.name AS item_name')).sql.should == 'SELECT items.name AS item_name FROM `items`'
|
|
182
|
+
@d.select(Sequel.lit('`name`')).sql.should == 'SELECT `name` FROM `items`'
|
|
183
|
+
@d.select(Sequel.lit('max(items.`name`) AS `max_name`')).sql.should == 'SELECT max(items.`name`) AS `max_name` FROM `items`'
|
|
184
|
+
@d.select(Sequel.function(:test, :abc, 'hello')).sql.should == "SELECT test(`abc`, 'hello') FROM `items`"
|
|
185
|
+
@d.select(Sequel.function(:test, :abc__def, 'hello')).sql.should == "SELECT test(`abc`.`def`, 'hello') FROM `items`"
|
|
186
|
+
@d.select(Sequel.function(:test, :abc__def, 'hello').as(:x2)).sql.should == "SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
|
|
187
|
+
@d.insert_sql(:value => 333).should == 'INSERT INTO `items` (`value`) VALUES (333)'
|
|
188
|
+
@d.insert_sql(:x => :y).should == 'INSERT INTO `items` (`x`) VALUES (`y`)'
|
|
204
189
|
end
|
|
205
|
-
|
|
190
|
+
|
|
206
191
|
specify "should quote fields correctly when reversing the order" do
|
|
207
192
|
@d.quote_identifiers = true
|
|
208
|
-
@d.reverse_order(:name).sql.should ==
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
@d.reverse_order(:name
|
|
212
|
-
'SELECT * FROM `items` ORDER BY `name` ASC'
|
|
213
|
-
|
|
214
|
-
@d.reverse_order(:name, :test.desc).sql.should == \
|
|
215
|
-
'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
|
216
|
-
|
|
217
|
-
@d.reverse_order(:name.desc, :test).sql.should == \
|
|
218
|
-
'SELECT * FROM `items` ORDER BY `name` ASC, `test` DESC'
|
|
193
|
+
@d.reverse_order(:name).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC'
|
|
194
|
+
@d.reverse_order(Sequel.desc(:name)).sql.should == 'SELECT * FROM `items` ORDER BY `name` ASC'
|
|
195
|
+
@d.reverse_order(:name, Sequel.desc(:test)).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
|
196
|
+
@d.reverse_order(Sequel.desc(:name), :test).sql.should == 'SELECT * FROM `items` ORDER BY `name` ASC, `test` DESC'
|
|
219
197
|
end
|
|
220
|
-
|
|
198
|
+
|
|
221
199
|
specify "should support ORDER clause in UPDATE statements" do
|
|
222
|
-
@d.order(:name).update_sql(:value => 1).should ==
|
|
223
|
-
'UPDATE items SET value = 1 ORDER BY name'
|
|
200
|
+
@d.order(:name).update_sql(:value => 1).should == 'UPDATE `items` SET `value` = 1 ORDER BY `name`'
|
|
224
201
|
end
|
|
225
|
-
|
|
202
|
+
|
|
226
203
|
specify "should support LIMIT clause in UPDATE statements" do
|
|
227
|
-
@d.limit(10).update_sql(:value => 1).should ==
|
|
228
|
-
'UPDATE items SET value = 1 LIMIT 10'
|
|
204
|
+
@d.limit(10).update_sql(:value => 1).should == 'UPDATE `items` SET `value` = 1 LIMIT 10'
|
|
229
205
|
end
|
|
230
|
-
|
|
206
|
+
|
|
231
207
|
specify "should support regexps" do
|
|
232
208
|
@d << {:name => 'abc', :value => 1}
|
|
233
209
|
@d << {:name => 'bcd', :value => 2}
|
|
234
210
|
@d.filter(:name => /bc/).count.should == 2
|
|
235
211
|
@d.filter(:name => /^bc/).count.should == 1
|
|
236
212
|
end
|
|
237
|
-
|
|
213
|
+
|
|
214
|
+
specify "should have explain output" do
|
|
215
|
+
@d.explain.should be_a_kind_of(String)
|
|
216
|
+
@d.explain(:extended=>true).should be_a_kind_of(String)
|
|
217
|
+
@d.explain.should_not == @d.explain(:extended=>true)
|
|
218
|
+
end
|
|
219
|
+
|
|
238
220
|
specify "should correctly literalize strings with comment backslashes in them" do
|
|
239
221
|
@d.delete
|
|
240
222
|
proc {@d << {:name => ':\\'}}.should_not raise_error
|
|
241
|
-
|
|
223
|
+
|
|
242
224
|
@d.first[:name].should == ':\\'
|
|
243
225
|
end
|
|
226
|
+
|
|
227
|
+
specify "should handle prepared statements with on_duplicate_key_update" do
|
|
228
|
+
@d.db.add_index :items, :value, :unique=>true
|
|
229
|
+
ds = @d.on_duplicate_key_update
|
|
230
|
+
ps = ds.prepare(:insert, :insert_user_id_feature_name, :value => :$v, :name => :$n)
|
|
231
|
+
ps.call(:v => 1, :n => 'a')
|
|
232
|
+
ds.all.should == [{:value=>1, :name=>'a'}]
|
|
233
|
+
ps.call(:v => 1, :n => 'b')
|
|
234
|
+
ds.all.should == [{:value=>1, :name=>'b'}]
|
|
235
|
+
end
|
|
244
236
|
end
|
|
245
237
|
|
|
246
238
|
describe "MySQL datasets" do
|
|
247
239
|
before do
|
|
248
240
|
@d = MYSQL_DB[:orders]
|
|
249
241
|
end
|
|
250
|
-
|
|
242
|
+
|
|
251
243
|
specify "should correctly quote column references" do
|
|
252
244
|
@d.quote_identifiers = true
|
|
253
245
|
market = 'ICE'
|
|
254
246
|
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
|
255
|
-
@d.select(:market, :minute.
|
|
256
|
-
where{
|
|
257
|
-
group_by(:minute.
|
|
247
|
+
@d.select(:market, Sequel.function(:minute, Sequel.function(:from_unixtime, :ack)).as(:minute)).
|
|
248
|
+
where{(ack > ack_stamp) & {:market => market}}.
|
|
249
|
+
group_by(Sequel.function(:minute, Sequel.function(:from_unixtime, :ack))).sql.should == \
|
|
258
250
|
"SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
|
|
259
251
|
end
|
|
260
252
|
end
|
|
@@ -269,14 +261,14 @@ describe "Dataset#distinct" do
|
|
|
269
261
|
@ds = @db[:a]
|
|
270
262
|
end
|
|
271
263
|
after do
|
|
272
|
-
@db.drop_table(:a)
|
|
264
|
+
@db.drop_table?(:a)
|
|
273
265
|
end
|
|
274
|
-
|
|
266
|
+
|
|
275
267
|
it "#distinct with arguments should return results distinct on those arguments" do
|
|
276
268
|
@ds.insert(20, 10)
|
|
277
269
|
@ds.insert(30, 10)
|
|
278
270
|
@ds.order(:b, :a).distinct.map(:a).should == [20, 30]
|
|
279
|
-
@ds.order(:b, :a
|
|
271
|
+
@ds.order(:b, Sequel.desc(:a)).distinct.map(:a).should == [30, 20]
|
|
280
272
|
# MySQL doesn't respect orders when using the nonstandard GROUP BY
|
|
281
273
|
[[20], [30]].should include(@ds.order(:b, :a).distinct(:b).map(:a))
|
|
282
274
|
end
|
|
@@ -285,7 +277,6 @@ end
|
|
|
285
277
|
describe "MySQL join expressions" do
|
|
286
278
|
before do
|
|
287
279
|
@ds = MYSQL_DB[:nodes]
|
|
288
|
-
@ds.db.meta_def(:server_version) {50014}
|
|
289
280
|
end
|
|
290
281
|
|
|
291
282
|
specify "should raise error for :full_outer join requests." do
|
|
@@ -293,43 +284,43 @@ describe "MySQL join expressions" do
|
|
|
293
284
|
end
|
|
294
285
|
specify "should support natural left joins" do
|
|
295
286
|
@ds.join_table(:natural_left, :nodes).sql.should == \
|
|
296
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
|
287
|
+
'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
|
|
297
288
|
end
|
|
298
289
|
specify "should support natural right joins" do
|
|
299
290
|
@ds.join_table(:natural_right, :nodes).sql.should == \
|
|
300
|
-
'SELECT * FROM nodes NATURAL RIGHT JOIN nodes'
|
|
291
|
+
'SELECT * FROM `nodes` NATURAL RIGHT JOIN `nodes`'
|
|
301
292
|
end
|
|
302
293
|
specify "should support natural left outer joins" do
|
|
303
294
|
@ds.join_table(:natural_left_outer, :nodes).sql.should == \
|
|
304
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN nodes'
|
|
295
|
+
'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN `nodes`'
|
|
305
296
|
end
|
|
306
297
|
specify "should support natural right outer joins" do
|
|
307
298
|
@ds.join_table(:natural_right_outer, :nodes).sql.should == \
|
|
308
|
-
'SELECT * FROM nodes NATURAL RIGHT OUTER JOIN nodes'
|
|
299
|
+
'SELECT * FROM `nodes` NATURAL RIGHT OUTER JOIN `nodes`'
|
|
309
300
|
end
|
|
310
301
|
specify "should support natural inner joins" do
|
|
311
302
|
@ds.join_table(:natural_inner, :nodes).sql.should == \
|
|
312
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
|
303
|
+
'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
|
|
313
304
|
end
|
|
314
305
|
specify "should support cross joins" do
|
|
315
306
|
@ds.join_table(:cross, :nodes).sql.should == \
|
|
316
|
-
'SELECT * FROM nodes CROSS JOIN nodes'
|
|
307
|
+
'SELECT * FROM `nodes` CROSS JOIN `nodes`'
|
|
317
308
|
end
|
|
318
309
|
specify "should support cross joins as inner joins if conditions are used" do
|
|
319
310
|
@ds.join_table(:cross, :nodes, :id=>:id).sql.should == \
|
|
320
|
-
'SELECT * FROM nodes INNER JOIN nodes ON (nodes
|
|
311
|
+
'SELECT * FROM `nodes` INNER JOIN `nodes` ON (`nodes`.`id` = `nodes`.`id`)'
|
|
321
312
|
end
|
|
322
313
|
specify "should support straight joins (force left table to be read before right)" do
|
|
323
314
|
@ds.join_table(:straight, :nodes).sql.should == \
|
|
324
|
-
'SELECT * FROM nodes STRAIGHT_JOIN nodes'
|
|
315
|
+
'SELECT * FROM `nodes` STRAIGHT_JOIN `nodes`'
|
|
325
316
|
end
|
|
326
317
|
specify "should support natural joins on multiple tables." do
|
|
327
318
|
@ds.join_table(:natural_left_outer, [:nodes, :branches]).sql.should == \
|
|
328
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN (nodes
|
|
319
|
+
'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN (`nodes`, `branches`)'
|
|
329
320
|
end
|
|
330
321
|
specify "should support straight joins on multiple tables." do
|
|
331
322
|
@ds.join_table(:straight, [:nodes,:branches]).sql.should == \
|
|
332
|
-
'SELECT * FROM nodes STRAIGHT_JOIN (nodes
|
|
323
|
+
'SELECT * FROM `nodes` STRAIGHT_JOIN (`nodes`, `branches`)'
|
|
333
324
|
end
|
|
334
325
|
end
|
|
335
326
|
|
|
@@ -337,46 +328,79 @@ describe "Joined MySQL dataset" do
|
|
|
337
328
|
before do
|
|
338
329
|
@ds = MYSQL_DB[:nodes]
|
|
339
330
|
end
|
|
340
|
-
|
|
331
|
+
|
|
341
332
|
specify "should quote fields correctly" do
|
|
342
333
|
@ds.quote_identifiers = true
|
|
343
334
|
@ds.join(:attributes, :node_id => :id).sql.should == \
|
|
344
335
|
"SELECT * FROM `nodes` INNER JOIN `attributes` ON (`attributes`.`node_id` = `nodes`.`id`)"
|
|
345
336
|
end
|
|
346
|
-
|
|
337
|
+
|
|
347
338
|
specify "should allow a having clause on ungrouped datasets" do
|
|
348
339
|
proc {@ds.having('blah')}.should_not raise_error
|
|
349
340
|
|
|
350
341
|
@ds.having('blah').sql.should == \
|
|
351
|
-
"SELECT * FROM nodes HAVING (blah)"
|
|
342
|
+
"SELECT * FROM `nodes` HAVING (blah)"
|
|
352
343
|
end
|
|
353
|
-
|
|
344
|
+
|
|
354
345
|
specify "should put a having clause before an order by clause" do
|
|
355
346
|
@ds.order(:aaa).having(:bbb => :ccc).sql.should == \
|
|
356
|
-
"SELECT * FROM nodes HAVING (bbb = ccc) ORDER BY aaa"
|
|
347
|
+
"SELECT * FROM `nodes` HAVING (`bbb` = `ccc`) ORDER BY `aaa`"
|
|
357
348
|
end
|
|
358
349
|
end
|
|
359
350
|
|
|
360
351
|
describe "A MySQL database" do
|
|
361
|
-
|
|
352
|
+
after do
|
|
353
|
+
MYSQL_DB.drop_table?(:test_innodb)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
specify "should handle the creation and dropping of an InnoDB table with foreign keys" do
|
|
357
|
+
proc{MYSQL_DB.create_table!(:test_innodb, :engine=>:InnoDB){primary_key :id; foreign_key :fk, :test_innodb, :key=>:id}}.should_not raise_error
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
describe "A MySQL database" do
|
|
362
|
+
before(:all) do
|
|
362
363
|
@db = MYSQL_DB
|
|
364
|
+
@db.create_table! :test2 do
|
|
365
|
+
text :name
|
|
366
|
+
integer :value
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
after(:all) do
|
|
370
|
+
@db.drop_table?(:test2)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
specify "should provide the server version" do
|
|
374
|
+
@db.server_version.should >= 40000
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
specify "should cache the server version" do
|
|
378
|
+
# warm cache:
|
|
379
|
+
@db.server_version
|
|
380
|
+
@db.sqls.clear
|
|
381
|
+
3.times{@db.server_version}
|
|
382
|
+
@db.sqls.should be_empty
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
specify "should support for_share" do
|
|
386
|
+
@db.transaction{@db[:test2].for_share.all.should == []}
|
|
363
387
|
end
|
|
364
388
|
|
|
365
389
|
specify "should support add_column operations" do
|
|
366
390
|
@db.add_column :test2, :xyz, :text
|
|
367
|
-
|
|
391
|
+
|
|
368
392
|
@db[:test2].columns.should == [:name, :value, :xyz]
|
|
369
393
|
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => '000'}
|
|
370
394
|
@db[:test2].first[:xyz].should == '000'
|
|
371
395
|
end
|
|
372
|
-
|
|
396
|
+
|
|
373
397
|
specify "should support drop_column operations" do
|
|
374
398
|
@db[:test2].columns.should == [:name, :value, :xyz]
|
|
375
399
|
@db.drop_column :test2, :xyz
|
|
376
|
-
|
|
400
|
+
|
|
377
401
|
@db[:test2].columns.should == [:name, :value]
|
|
378
402
|
end
|
|
379
|
-
|
|
403
|
+
|
|
380
404
|
specify "should support rename_column operations" do
|
|
381
405
|
@db[:test2].delete
|
|
382
406
|
@db.add_column :test2, :xyz, :text
|
|
@@ -387,7 +411,7 @@ describe "A MySQL database" do
|
|
|
387
411
|
@db[:test2].columns.should == [:name, :value, :zyx]
|
|
388
412
|
@db[:test2].first[:zyx].should == 'qqqq'
|
|
389
413
|
end
|
|
390
|
-
|
|
414
|
+
|
|
391
415
|
specify "should support rename_column operations with types like varchar(255)" do
|
|
392
416
|
@db[:test2].delete
|
|
393
417
|
@db.add_column :test2, :tre, :text
|
|
@@ -398,26 +422,27 @@ describe "A MySQL database" do
|
|
|
398
422
|
@db[:test2].columns.should == [:name, :value, :zyx, :ert]
|
|
399
423
|
@db[:test2].first[:ert].should == 'qqqq'
|
|
400
424
|
end
|
|
401
|
-
|
|
425
|
+
|
|
402
426
|
specify "should support set_column_type operations" do
|
|
403
427
|
@db.add_column :test2, :xyz, :float
|
|
404
428
|
@db[:test2].delete
|
|
405
429
|
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => 56.78}
|
|
406
430
|
@db.set_column_type :test2, :xyz, :integer
|
|
407
|
-
|
|
431
|
+
|
|
408
432
|
@db[:test2].first[:xyz].should == 57
|
|
409
433
|
end
|
|
410
|
-
|
|
434
|
+
|
|
411
435
|
specify "should support add_index" do
|
|
412
436
|
@db.add_index :test2, :value
|
|
413
437
|
end
|
|
414
|
-
|
|
438
|
+
|
|
415
439
|
specify "should support drop_index" do
|
|
416
440
|
@db.drop_index :test2, :value
|
|
417
441
|
end
|
|
418
|
-
|
|
442
|
+
|
|
419
443
|
specify "should support add_foreign_key" do
|
|
420
444
|
@db.alter_table :test2 do
|
|
445
|
+
add_index :value, :unique=>true
|
|
421
446
|
add_foreign_key :value2, :test2, :key=>:value
|
|
422
447
|
end
|
|
423
448
|
@db[:test2].columns.should == [:name, :value, :zyx, :ert, :xyz, :value2]
|
|
@@ -427,79 +452,98 @@ end
|
|
|
427
452
|
describe "A MySQL database with table options" do
|
|
428
453
|
before do
|
|
429
454
|
@options = {:engine=>'MyISAM', :charset=>'latin1', :collate => 'latin1_swedish_ci'}
|
|
430
|
-
|
|
455
|
+
|
|
431
456
|
Sequel::MySQL.default_engine = 'InnoDB'
|
|
432
457
|
Sequel::MySQL.default_charset = 'utf8'
|
|
433
458
|
Sequel::MySQL.default_collate = 'utf8_general_ci'
|
|
434
|
-
|
|
459
|
+
|
|
435
460
|
@db = MYSQL_DB
|
|
436
|
-
@db.drop_table(:items)
|
|
437
|
-
|
|
461
|
+
@db.drop_table?(:items)
|
|
462
|
+
|
|
438
463
|
MYSQL_DB.sqls.clear
|
|
439
464
|
end
|
|
440
465
|
after do
|
|
441
|
-
@db.drop_table(:items)
|
|
466
|
+
@db.drop_table?(:items)
|
|
442
467
|
|
|
443
468
|
Sequel::MySQL.default_engine = nil
|
|
444
469
|
Sequel::MySQL.default_charset = nil
|
|
445
470
|
Sequel::MySQL.default_collate = nil
|
|
446
471
|
end
|
|
447
|
-
|
|
472
|
+
|
|
448
473
|
specify "should allow to pass custom options (engine, charset, collate) for table creation" do
|
|
449
474
|
@db.create_table(:items, @options){Integer :size; text :name}
|
|
450
|
-
|
|
475
|
+
check_sqls do
|
|
476
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
|
|
477
|
+
end
|
|
451
478
|
end
|
|
452
|
-
|
|
479
|
+
|
|
453
480
|
specify "should use default options if specified (engine, charset, collate) for table creation" do
|
|
454
481
|
@db.create_table(:items){Integer :size; text :name}
|
|
455
|
-
|
|
482
|
+
check_sqls do
|
|
483
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
|
|
484
|
+
end
|
|
456
485
|
end
|
|
457
|
-
|
|
486
|
+
|
|
458
487
|
specify "should not use default if option has a nil value" do
|
|
459
488
|
@db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
|
|
460
|
-
|
|
489
|
+
check_sqls do
|
|
490
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text)"]
|
|
491
|
+
end
|
|
461
492
|
end
|
|
462
493
|
end
|
|
463
494
|
|
|
464
495
|
describe "A MySQL database" do
|
|
465
496
|
before do
|
|
466
497
|
@db = MYSQL_DB
|
|
467
|
-
@db.drop_table(:items)
|
|
498
|
+
@db.drop_table?(:items)
|
|
468
499
|
MYSQL_DB.sqls.clear
|
|
469
500
|
end
|
|
470
501
|
after do
|
|
471
|
-
@db.drop_table(:items)
|
|
502
|
+
@db.drop_table?(:items, :users)
|
|
472
503
|
end
|
|
473
|
-
|
|
504
|
+
|
|
474
505
|
specify "should support defaults for boolean columns" do
|
|
475
506
|
@db.create_table(:items){TrueClass :active1, :default=>true; FalseClass :active2, :default => false}
|
|
476
|
-
|
|
507
|
+
check_sqls do
|
|
508
|
+
@db.sqls.should == ["CREATE TABLE `items` (`active1` tinyint(1) DEFAULT 1, `active2` tinyint(1) DEFAULT 0)"]
|
|
509
|
+
end
|
|
477
510
|
end
|
|
478
|
-
|
|
511
|
+
|
|
479
512
|
specify "should correctly format CREATE TABLE statements with foreign keys" do
|
|
480
|
-
@db.create_table(:items){
|
|
481
|
-
|
|
513
|
+
@db.create_table(:items){primary_key :id; foreign_key :p_id, :items, :key => :id, :null => false, :on_delete => :cascade}
|
|
514
|
+
check_sqls do
|
|
515
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer PRIMARY KEY AUTO_INCREMENT, `p_id` integer NOT NULL, UNIQUE (`id`), FOREIGN KEY (`p_id`) REFERENCES `items`(`id`) ON DELETE CASCADE)"]
|
|
516
|
+
end
|
|
482
517
|
end
|
|
483
|
-
|
|
518
|
+
|
|
484
519
|
specify "should correctly format ALTER TABLE statements with foreign keys" do
|
|
485
520
|
@db.create_table(:items){Integer :id}
|
|
521
|
+
@db.create_table(:users){primary_key :id}
|
|
486
522
|
@db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
|
|
487
|
-
|
|
523
|
+
check_sqls do
|
|
524
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer)",
|
|
525
|
+
"CREATE TABLE `users` (`id` integer PRIMARY KEY AUTO_INCREMENT)",
|
|
526
|
+
"ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL, ADD FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
|
|
527
|
+
end
|
|
488
528
|
end
|
|
489
|
-
|
|
529
|
+
|
|
490
530
|
specify "should have rename_column support keep existing options" do
|
|
491
531
|
@db.create_table(:items){String :id, :null=>false, :default=>'blah'}
|
|
492
532
|
@db.alter_table(:items){rename_column :id, :nid}
|
|
493
|
-
|
|
533
|
+
check_sqls do
|
|
534
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` varchar(255) NOT NULL DEFAULT 'blah')", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `nid` varchar(255) NOT NULL DEFAULT 'blah'"]
|
|
535
|
+
end
|
|
494
536
|
@db[:items].insert
|
|
495
537
|
@db[:items].all.should == [{:nid=>'blah'}]
|
|
496
538
|
proc{@db[:items].insert(:nid=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
497
539
|
end
|
|
498
|
-
|
|
540
|
+
|
|
499
541
|
specify "should have set_column_type support keep existing options" do
|
|
500
542
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
501
543
|
@db.alter_table(:items){set_column_type :id, Bignum}
|
|
502
|
-
|
|
544
|
+
check_sqls do
|
|
545
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` bigint NOT NULL DEFAULT 5"]
|
|
546
|
+
end
|
|
503
547
|
@db[:items].insert
|
|
504
548
|
@db[:items].all.should == [{:id=>5}]
|
|
505
549
|
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
@@ -511,35 +555,41 @@ describe "A MySQL database" do
|
|
|
511
555
|
specify "should have set_column_type pass through options" do
|
|
512
556
|
@db.create_table(:items){integer :id; enum :list, :elements=>%w[one]}
|
|
513
557
|
@db.alter_table(:items){set_column_type :id, :int, :unsigned=>true, :size=>8; set_column_type :list, :enum, :elements=>%w[two]}
|
|
514
|
-
|
|
558
|
+
check_sqls do
|
|
559
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer, `list` enum('one'))", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(8) UNSIGNED NULL, CHANGE COLUMN `list` `list` enum('two') NULL"]
|
|
560
|
+
end
|
|
515
561
|
end
|
|
516
|
-
|
|
562
|
+
|
|
517
563
|
specify "should have set_column_default support keep existing options" do
|
|
518
564
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
519
565
|
@db.alter_table(:items){set_column_default :id, 6}
|
|
520
|
-
|
|
566
|
+
check_sqls do
|
|
567
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NOT NULL DEFAULT 6"]
|
|
568
|
+
end
|
|
521
569
|
@db[:items].insert
|
|
522
570
|
@db[:items].all.should == [{:id=>6}]
|
|
523
571
|
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
524
572
|
end
|
|
525
|
-
|
|
573
|
+
|
|
526
574
|
specify "should have set_column_allow_null support keep existing options" do
|
|
527
575
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
528
576
|
@db.alter_table(:items){set_column_allow_null :id, true}
|
|
529
|
-
|
|
577
|
+
check_sqls do
|
|
578
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NULL DEFAULT 5"]
|
|
579
|
+
end
|
|
530
580
|
@db[:items].insert
|
|
531
581
|
@db[:items].all.should == [{:id=>5}]
|
|
532
582
|
proc{@db[:items].insert(:id=>nil)}.should_not
|
|
533
583
|
end
|
|
534
|
-
|
|
584
|
+
|
|
535
585
|
specify "should accept repeated raw sql statements using Database#<<" do
|
|
536
586
|
@db.create_table(:items){String :name; Integer :value}
|
|
537
587
|
@db << 'DELETE FROM items'
|
|
538
588
|
@db[:items].count.should == 0
|
|
539
|
-
|
|
589
|
+
|
|
540
590
|
@db << "INSERT INTO items (name, value) VALUES ('tutu', 1234)"
|
|
541
591
|
@db[:items].first.should == {:name => 'tutu', :value => 1234}
|
|
542
|
-
|
|
592
|
+
|
|
543
593
|
@db << 'DELETE FROM items'
|
|
544
594
|
@db[:items].first.should == nil
|
|
545
595
|
end
|
|
@@ -552,12 +602,12 @@ if %w'localhost 127.0.0.1 ::1'.include?(MYSQL_URI.host) and MYSQL_DB.adapter_sch
|
|
|
552
602
|
db = Sequel.mysql(MYSQL_DB.opts[:database], :host => 'localhost', :user => MYSQL_DB.opts[:user], :password => MYSQL_DB.opts[:password], :socket => MYSQL_SOCKET_FILE)
|
|
553
603
|
proc {db.test_connection}.should_not raise_error
|
|
554
604
|
end
|
|
555
|
-
|
|
605
|
+
|
|
556
606
|
specify "should accept a socket option without host option" do
|
|
557
607
|
db = Sequel.mysql(MYSQL_DB.opts[:database], :user => MYSQL_DB.opts[:user], :password => MYSQL_DB.opts[:password], :socket => MYSQL_SOCKET_FILE)
|
|
558
608
|
proc {db.test_connection}.should_not raise_error
|
|
559
609
|
end
|
|
560
|
-
|
|
610
|
+
|
|
561
611
|
specify "should fail to connect with invalid socket" do
|
|
562
612
|
db = Sequel.mysql(MYSQL_DB.opts[:database], :user => MYSQL_DB.opts[:user], :password => MYSQL_DB.opts[:password], :socket =>'blah')
|
|
563
613
|
proc {db.test_connection}.should raise_error
|
|
@@ -577,9 +627,58 @@ describe "A MySQL database" do
|
|
|
577
627
|
end
|
|
578
628
|
end
|
|
579
629
|
|
|
630
|
+
describe "MySQL foreign key support" do
|
|
631
|
+
after do
|
|
632
|
+
MYSQL_DB.drop_table?(:testfk, :testpk)
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
specify "should create table without :key" do
|
|
636
|
+
MYSQL_DB.create_table!(:testpk){primary_key :id}
|
|
637
|
+
MYSQL_DB.create_table!(:testfk){foreign_key :fk, :testpk}
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
specify "should create table with composite keys without :key" do
|
|
641
|
+
MYSQL_DB.create_table!(:testpk){Integer :id; Integer :id2; primary_key([:id, :id2])}
|
|
642
|
+
MYSQL_DB.create_table!(:testfk){Integer :fk; Integer :fk2; foreign_key([:fk, :fk2], :testpk)}
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
specify "should create table with self referential without :key" do
|
|
646
|
+
MYSQL_DB.create_table!(:testfk){primary_key :id; foreign_key :fk, :testfk}
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
specify "should create table with self referential with composite keys without :key" do
|
|
650
|
+
MYSQL_DB.create_table!(:testfk){Integer :id; Integer :id2; Integer :fk; Integer :fk2; primary_key([:id, :id2]); foreign_key([:fk, :fk2], :testfk)}
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
specify "should alter table without :key" do
|
|
654
|
+
MYSQL_DB.create_table!(:testpk){primary_key :id}
|
|
655
|
+
MYSQL_DB.create_table!(:testfk){Integer :id}
|
|
656
|
+
MYSQL_DB.alter_table(:testfk){add_foreign_key :fk, :testpk}
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
specify "should alter table with composite keys without :key" do
|
|
660
|
+
MYSQL_DB.create_table!(:testpk){Integer :id; Integer :id2; primary_key([:id, :id2])}
|
|
661
|
+
MYSQL_DB.create_table!(:testfk){Integer :fk; Integer :fk2}
|
|
662
|
+
MYSQL_DB.alter_table(:testfk){add_foreign_key([:fk, :fk2], :testpk)}
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
specify "should alter table with self referential without :key" do
|
|
666
|
+
MYSQL_DB.create_table!(:testfk){primary_key :id}
|
|
667
|
+
MYSQL_DB.alter_table(:testfk){add_foreign_key :fk, :testfk}
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
specify "should alter table with self referential with composite keys without :key" do
|
|
671
|
+
MYSQL_DB.create_table!(:testfk){Integer :id; Integer :id2; Integer :fk; Integer :fk2; primary_key([:id, :id2])}
|
|
672
|
+
MYSQL_DB.alter_table(:testfk){add_foreign_key [:fk, :fk2], :testfk}
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
|
|
580
676
|
describe "A grouped MySQL dataset" do
|
|
581
677
|
before do
|
|
582
|
-
MYSQL_DB
|
|
678
|
+
MYSQL_DB.create_table! :test2 do
|
|
679
|
+
text :name
|
|
680
|
+
integer :value
|
|
681
|
+
end
|
|
583
682
|
MYSQL_DB[:test2] << {:name => '11', :value => 10}
|
|
584
683
|
MYSQL_DB[:test2] << {:name => '11', :value => 20}
|
|
585
684
|
MYSQL_DB[:test2] << {:name => '11', :value => 30}
|
|
@@ -587,12 +686,15 @@ describe "A grouped MySQL dataset" do
|
|
|
587
686
|
MYSQL_DB[:test2] << {:name => '12', :value => 20}
|
|
588
687
|
MYSQL_DB[:test2] << {:name => '13', :value => 10}
|
|
589
688
|
end
|
|
590
|
-
|
|
689
|
+
after do
|
|
690
|
+
MYSQL_DB.drop_table?(:test2)
|
|
691
|
+
end
|
|
692
|
+
|
|
591
693
|
specify "should return the correct count for raw sql query" do
|
|
592
694
|
ds = MYSQL_DB["select name FROM test2 WHERE name = '11' GROUP BY name"]
|
|
593
695
|
ds.count.should == 1
|
|
594
696
|
end
|
|
595
|
-
|
|
697
|
+
|
|
596
698
|
specify "should return the correct count for a normal dataset" do
|
|
597
699
|
ds = MYSQL_DB[:test2].select(:name).where(:name => '11').group(:name)
|
|
598
700
|
ds.count.should == 1
|
|
@@ -602,21 +704,23 @@ end
|
|
|
602
704
|
describe "A MySQL database" do
|
|
603
705
|
before do
|
|
604
706
|
@db = MYSQL_DB
|
|
605
|
-
@db.drop_table(:posts)
|
|
707
|
+
@db.drop_table?(:posts)
|
|
606
708
|
@db.sqls.clear
|
|
607
709
|
end
|
|
608
710
|
after do
|
|
609
|
-
@db.drop_table(:posts)
|
|
711
|
+
@db.drop_table?(:posts)
|
|
610
712
|
end
|
|
611
|
-
|
|
713
|
+
|
|
612
714
|
specify "should support fulltext indexes and full_text_search" do
|
|
613
|
-
@db.create_table(:posts){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
715
|
+
@db.create_table(:posts, :engine=>:MyISAM){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
|
|
716
|
+
check_sqls do
|
|
717
|
+
@db.sqls.should == [
|
|
718
|
+
"CREATE TABLE `posts` (`title` text, `body` text) ENGINE=MyISAM",
|
|
719
|
+
"CREATE FULLTEXT INDEX `posts_title_index` ON `posts` (`title`)",
|
|
720
|
+
"CREATE FULLTEXT INDEX `posts_title_body_index` ON `posts` (`title`, `body`)"
|
|
721
|
+
]
|
|
722
|
+
end
|
|
723
|
+
|
|
620
724
|
@db[:posts].insert(:title=>'ruby rails', :body=>'y')
|
|
621
725
|
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
|
622
726
|
@db[:posts].insert(:title=>'ruby scooby', :body=>'x')
|
|
@@ -625,34 +729,45 @@ describe "A MySQL database" do
|
|
|
625
729
|
@db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'y'}]
|
|
626
730
|
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.should == [{:title=>'sequel', :body=>'ruby'}]
|
|
627
731
|
@db[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
732
|
+
check_sqls do
|
|
733
|
+
@db.sqls.should == [
|
|
734
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('rails'))",
|
|
735
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`, `body`) AGAINST ('sequel ruby'))",
|
|
736
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'y'}]
|
|
740
|
+
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'y'}]
|
|
632
741
|
end
|
|
633
742
|
|
|
634
743
|
specify "should support spatial indexes" do
|
|
635
|
-
@db.create_table(:posts){point :geom, :null=>false; spatial_index [:geom]}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
744
|
+
@db.create_table(:posts, :engine=>:MyISAM){point :geom, :null=>false; spatial_index [:geom]}
|
|
745
|
+
check_sqls do
|
|
746
|
+
@db.sqls.should == [
|
|
747
|
+
"CREATE TABLE `posts` (`geom` point NOT NULL) ENGINE=MyISAM",
|
|
748
|
+
"CREATE SPATIAL INDEX `posts_geom_index` ON `posts` (`geom`)"
|
|
749
|
+
]
|
|
750
|
+
end
|
|
640
751
|
end
|
|
641
752
|
|
|
642
753
|
specify "should support indexes with index type" do
|
|
643
754
|
@db.create_table(:posts){Integer :id; index :id, :type => :btree}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
755
|
+
check_sqls do
|
|
756
|
+
@db.sqls.should == [
|
|
757
|
+
"CREATE TABLE `posts` (`id` integer)",
|
|
758
|
+
"CREATE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
|
|
759
|
+
]
|
|
760
|
+
end
|
|
648
761
|
end
|
|
649
762
|
|
|
650
763
|
specify "should support unique indexes with index type" do
|
|
651
764
|
@db.create_table(:posts){Integer :id; index :id, :type => :btree, :unique => true}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
765
|
+
check_sqls do
|
|
766
|
+
@db.sqls.should == [
|
|
767
|
+
"CREATE TABLE `posts` (`id` integer)",
|
|
768
|
+
"CREATE UNIQUE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
|
|
769
|
+
]
|
|
770
|
+
end
|
|
656
771
|
end
|
|
657
772
|
|
|
658
773
|
specify "should not dump partial indexes" do
|
|
@@ -675,43 +790,31 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
675
790
|
MYSQL_DB.sqls.clear
|
|
676
791
|
end
|
|
677
792
|
after do
|
|
678
|
-
MYSQL_DB.drop_table(:items)
|
|
793
|
+
MYSQL_DB.drop_table?(:items)
|
|
679
794
|
end
|
|
680
795
|
|
|
681
796
|
specify "#insert should insert record with default values when no arguments given" do
|
|
682
797
|
@d.insert
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
]
|
|
687
|
-
|
|
688
|
-
@d.all.should == [
|
|
689
|
-
{:name => nil, :value => nil}
|
|
690
|
-
]
|
|
798
|
+
check_sqls do
|
|
799
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
800
|
+
end
|
|
801
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
691
802
|
end
|
|
692
803
|
|
|
693
804
|
specify "#insert should insert record with default values when empty hash given" do
|
|
694
805
|
@d.insert({})
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
]
|
|
699
|
-
|
|
700
|
-
@d.all.should == [
|
|
701
|
-
{:name => nil, :value => nil}
|
|
702
|
-
]
|
|
806
|
+
check_sqls do
|
|
807
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
808
|
+
end
|
|
809
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
703
810
|
end
|
|
704
811
|
|
|
705
812
|
specify "#insert should insert record with default values when empty array given" do
|
|
706
813
|
@d.insert []
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
]
|
|
711
|
-
|
|
712
|
-
@d.all.should == [
|
|
713
|
-
{:name => nil, :value => nil}
|
|
714
|
-
]
|
|
814
|
+
check_sqls do
|
|
815
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
816
|
+
end
|
|
817
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
715
818
|
end
|
|
716
819
|
|
|
717
820
|
specify "#on_duplicate_key_update should work with regular inserts" do
|
|
@@ -721,22 +824,88 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
721
824
|
@d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'abc', :value => 1)
|
|
722
825
|
@d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'def', :value => 2)
|
|
723
826
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
827
|
+
check_sqls do
|
|
828
|
+
MYSQL_DB.sqls.length.should == 3
|
|
829
|
+
MYSQL_DB.sqls[0].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\)\z/
|
|
830
|
+
MYSQL_DB.sqls[1].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
|
|
831
|
+
MYSQL_DB.sqls[2].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('def'|2), (2|'def')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
|
|
832
|
+
end
|
|
728
833
|
|
|
729
834
|
@d.all.should == [{:name => 'abc', :value => 6}, {:name => 'def', :value => 2}]
|
|
730
835
|
end
|
|
731
836
|
|
|
837
|
+
specify "#multi_replace should insert multiple records in a single statement" do
|
|
838
|
+
@d.multi_replace([{:name => 'abc'}, {:name => 'def'}])
|
|
839
|
+
|
|
840
|
+
check_sqls do
|
|
841
|
+
MYSQL_DB.sqls.should == [
|
|
842
|
+
SQL_BEGIN,
|
|
843
|
+
"REPLACE INTO `items` (`name`) VALUES ('abc'), ('def')",
|
|
844
|
+
SQL_COMMIT
|
|
845
|
+
]
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
@d.all.should == [
|
|
849
|
+
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
|
850
|
+
]
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
specify "#multi_replace should split the list of records into batches if :commit_every option is given" do
|
|
854
|
+
@d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
|
855
|
+
:commit_every => 2)
|
|
856
|
+
|
|
857
|
+
check_sqls do
|
|
858
|
+
MYSQL_DB.sqls.should == [
|
|
859
|
+
SQL_BEGIN,
|
|
860
|
+
"REPLACE INTO `items` (`value`) VALUES (1), (2)",
|
|
861
|
+
SQL_COMMIT,
|
|
862
|
+
SQL_BEGIN,
|
|
863
|
+
"REPLACE INTO `items` (`value`) VALUES (3), (4)",
|
|
864
|
+
SQL_COMMIT
|
|
865
|
+
]
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
@d.all.should == [
|
|
869
|
+
{:name => nil, :value => 1},
|
|
870
|
+
{:name => nil, :value => 2},
|
|
871
|
+
{:name => nil, :value => 3},
|
|
872
|
+
{:name => nil, :value => 4}
|
|
873
|
+
]
|
|
874
|
+
end
|
|
875
|
+
|
|
876
|
+
specify "#multi_replace should split the list of records into batches if :slice option is given" do
|
|
877
|
+
@d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
|
878
|
+
:slice => 2)
|
|
879
|
+
|
|
880
|
+
check_sqls do
|
|
881
|
+
MYSQL_DB.sqls.should == [
|
|
882
|
+
SQL_BEGIN,
|
|
883
|
+
"REPLACE INTO `items` (`value`) VALUES (1), (2)",
|
|
884
|
+
SQL_COMMIT,
|
|
885
|
+
SQL_BEGIN,
|
|
886
|
+
"REPLACE INTO `items` (`value`) VALUES (3), (4)",
|
|
887
|
+
SQL_COMMIT
|
|
888
|
+
]
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
@d.all.should == [
|
|
892
|
+
{:name => nil, :value => 1},
|
|
893
|
+
{:name => nil, :value => 2},
|
|
894
|
+
{:name => nil, :value => 3},
|
|
895
|
+
{:name => nil, :value => 4}
|
|
896
|
+
]
|
|
897
|
+
end
|
|
898
|
+
|
|
732
899
|
specify "#multi_insert should insert multiple records in a single statement" do
|
|
733
900
|
@d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
901
|
+
|
|
902
|
+
check_sqls do
|
|
903
|
+
MYSQL_DB.sqls.should == [
|
|
904
|
+
SQL_BEGIN,
|
|
905
|
+
"INSERT INTO `items` (`name`) VALUES ('abc'), ('def')",
|
|
906
|
+
SQL_COMMIT
|
|
907
|
+
]
|
|
908
|
+
end
|
|
740
909
|
|
|
741
910
|
@d.all.should == [
|
|
742
911
|
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
|
@@ -747,15 +916,17 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
747
916
|
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
|
748
917
|
:commit_every => 2)
|
|
749
918
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
919
|
+
check_sqls do
|
|
920
|
+
MYSQL_DB.sqls.should == [
|
|
921
|
+
SQL_BEGIN,
|
|
922
|
+
"INSERT INTO `items` (`value`) VALUES (1), (2)",
|
|
923
|
+
SQL_COMMIT,
|
|
924
|
+
SQL_BEGIN,
|
|
925
|
+
"INSERT INTO `items` (`value`) VALUES (3), (4)",
|
|
926
|
+
SQL_COMMIT
|
|
927
|
+
]
|
|
928
|
+
end
|
|
929
|
+
|
|
759
930
|
@d.all.should == [
|
|
760
931
|
{:name => nil, :value => 1},
|
|
761
932
|
{:name => nil, :value => 2},
|
|
@@ -768,15 +939,17 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
768
939
|
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
|
769
940
|
:slice => 2)
|
|
770
941
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
942
|
+
check_sqls do
|
|
943
|
+
MYSQL_DB.sqls.should == [
|
|
944
|
+
SQL_BEGIN,
|
|
945
|
+
"INSERT INTO `items` (`value`) VALUES (1), (2)",
|
|
946
|
+
SQL_COMMIT,
|
|
947
|
+
SQL_BEGIN,
|
|
948
|
+
"INSERT INTO `items` (`value`) VALUES (3), (4)",
|
|
949
|
+
SQL_COMMIT
|
|
950
|
+
]
|
|
951
|
+
end
|
|
952
|
+
|
|
780
953
|
@d.all.should == [
|
|
781
954
|
{:name => nil, :value => 1},
|
|
782
955
|
{:name => nil, :value => 2},
|
|
@@ -784,73 +957,105 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
784
957
|
{:name => nil, :value => 4}
|
|
785
958
|
]
|
|
786
959
|
end
|
|
787
|
-
|
|
960
|
+
|
|
788
961
|
specify "#import should support inserting using columns and values arrays" do
|
|
789
962
|
@d.import([:name, :value], [['abc', 1], ['def', 2]])
|
|
790
963
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
964
|
+
check_sqls do
|
|
965
|
+
MYSQL_DB.sqls.should == [
|
|
966
|
+
SQL_BEGIN,
|
|
967
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2)",
|
|
968
|
+
SQL_COMMIT
|
|
969
|
+
]
|
|
970
|
+
end
|
|
971
|
+
|
|
797
972
|
@d.all.should == [
|
|
798
973
|
{:name => 'abc', :value => 1},
|
|
799
974
|
{:name => 'def', :value => 2}
|
|
800
975
|
]
|
|
801
976
|
end
|
|
802
|
-
|
|
977
|
+
|
|
803
978
|
specify "#insert_ignore should add the IGNORE keyword when inserting" do
|
|
804
979
|
@d.insert_ignore.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
980
|
+
|
|
981
|
+
check_sqls do
|
|
982
|
+
MYSQL_DB.sqls.should == [
|
|
983
|
+
SQL_BEGIN,
|
|
984
|
+
"INSERT IGNORE INTO `items` (`name`) VALUES ('abc'), ('def')",
|
|
985
|
+
SQL_COMMIT
|
|
986
|
+
]
|
|
987
|
+
end
|
|
811
988
|
|
|
812
989
|
@d.all.should == [
|
|
813
990
|
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
|
814
991
|
]
|
|
815
992
|
end
|
|
816
|
-
|
|
993
|
+
|
|
817
994
|
specify "#insert_ignore should add the IGNORE keyword for single inserts" do
|
|
818
995
|
@d.insert_ignore.insert(:name => 'ghi')
|
|
819
|
-
|
|
996
|
+
check_sqls do
|
|
997
|
+
MYSQL_DB.sqls.should == ["INSERT IGNORE INTO `items` (`name`) VALUES ('ghi')"]
|
|
998
|
+
end
|
|
820
999
|
@d.all.should == [{:name => 'ghi', :value => nil}]
|
|
821
1000
|
end
|
|
822
|
-
|
|
1001
|
+
|
|
823
1002
|
specify "#on_duplicate_key_update should add the ON DUPLICATE KEY UPDATE and ALL columns when no args given" do
|
|
824
1003
|
@d.on_duplicate_key_update.import([:name,:value], [['abc', 1], ['def',2]])
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
1004
|
+
|
|
1005
|
+
check_sqls do
|
|
1006
|
+
MYSQL_DB.sqls.should == [
|
|
1007
|
+
"SELECT * FROM `items` LIMIT 1",
|
|
1008
|
+
SQL_BEGIN,
|
|
1009
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`), `value`=VALUES(`value`)",
|
|
1010
|
+
SQL_COMMIT
|
|
1011
|
+
]
|
|
1012
|
+
end
|
|
832
1013
|
|
|
833
1014
|
@d.all.should == [
|
|
834
1015
|
{:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
|
|
835
1016
|
]
|
|
836
1017
|
end
|
|
837
|
-
|
|
1018
|
+
|
|
838
1019
|
specify "#on_duplicate_key_update should add the ON DUPLICATE KEY UPDATE and columns specified when args are given" do
|
|
839
1020
|
@d.on_duplicate_key_update(:value).import([:name,:value],
|
|
840
1021
|
[['abc', 1], ['def',2]]
|
|
841
1022
|
)
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
1023
|
+
|
|
1024
|
+
check_sqls do
|
|
1025
|
+
MYSQL_DB.sqls.should == [
|
|
1026
|
+
SQL_BEGIN,
|
|
1027
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)",
|
|
1028
|
+
SQL_COMMIT
|
|
1029
|
+
]
|
|
1030
|
+
end
|
|
848
1031
|
|
|
849
1032
|
@d.all.should == [
|
|
850
1033
|
{:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
|
|
851
1034
|
]
|
|
852
1035
|
end
|
|
853
|
-
|
|
1036
|
+
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
describe "MySQL::Dataset#update and related methods" do
|
|
1040
|
+
before do
|
|
1041
|
+
MYSQL_DB.create_table(:items){String :name; Integer :value; index :name, :unique=>true}
|
|
1042
|
+
@d = MYSQL_DB[:items]
|
|
1043
|
+
end
|
|
1044
|
+
after do
|
|
1045
|
+
MYSQL_DB.drop_table?(:items)
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
specify "#update_ignore should not raise error where normal update would fail" do
|
|
1049
|
+
@d.insert(:name => 'cow', :value => 0)
|
|
1050
|
+
@d.insert(:name => 'cat', :value => 1)
|
|
1051
|
+
proc{@d.where(:value => 1).update(:name => 'cow')}.should raise_error(Sequel::DatabaseError)
|
|
1052
|
+
MYSQL_DB.sqls.clear
|
|
1053
|
+
@d.update_ignore.where(:value => 1).update(:name => 'cow')
|
|
1054
|
+
check_sqls do
|
|
1055
|
+
MYSQL_DB.sqls.should == ["UPDATE IGNORE `items` SET `name` = 'cow' WHERE (`value` = 1)"]
|
|
1056
|
+
end
|
|
1057
|
+
@d.order(:name).all.should == [{:name => 'cat', :value => 1}, {:name => 'cow', :value => 0}]
|
|
1058
|
+
end
|
|
854
1059
|
end
|
|
855
1060
|
|
|
856
1061
|
describe "MySQL::Dataset#replace" do
|
|
@@ -860,9 +1065,9 @@ describe "MySQL::Dataset#replace" do
|
|
|
860
1065
|
MYSQL_DB.sqls.clear
|
|
861
1066
|
end
|
|
862
1067
|
after do
|
|
863
|
-
MYSQL_DB.drop_table(:items)
|
|
1068
|
+
MYSQL_DB.drop_table?(:items)
|
|
864
1069
|
end
|
|
865
|
-
|
|
1070
|
+
|
|
866
1071
|
specify "should use default values if they exist" do
|
|
867
1072
|
MYSQL_DB.alter_table(:items){set_column_default :id, 1; set_column_default :value, 2}
|
|
868
1073
|
@d.replace
|
|
@@ -872,7 +1077,7 @@ describe "MySQL::Dataset#replace" do
|
|
|
872
1077
|
@d.replace({})
|
|
873
1078
|
@d.all.should == [{:id=>1, :value=>2}]
|
|
874
1079
|
end
|
|
875
|
-
|
|
1080
|
+
|
|
876
1081
|
specify "should use support arrays, datasets, and multiple values" do
|
|
877
1082
|
@d.replace([1, 2])
|
|
878
1083
|
@d.all.should == [{:id=>1, :value=>2}]
|
|
@@ -881,12 +1086,12 @@ describe "MySQL::Dataset#replace" do
|
|
|
881
1086
|
@d.replace(@d)
|
|
882
1087
|
@d.all.should == [{:id=>1, :value=>2}]
|
|
883
1088
|
end
|
|
884
|
-
|
|
1089
|
+
|
|
885
1090
|
specify "should create a record if the condition is not met" do
|
|
886
1091
|
@d.replace(:id => 111, :value => 333)
|
|
887
1092
|
@d.all.should == [{:id => 111, :value => 333}]
|
|
888
1093
|
end
|
|
889
|
-
|
|
1094
|
+
|
|
890
1095
|
specify "should update a record if the condition is met" do
|
|
891
1096
|
@d << {:id => 111}
|
|
892
1097
|
@d.all.should == [{:id => 111, :value => nil}]
|
|
@@ -901,25 +1106,25 @@ describe "MySQL::Dataset#complex_expression_sql" do
|
|
|
901
1106
|
end
|
|
902
1107
|
|
|
903
1108
|
specify "should handle pattern matches correctly" do
|
|
904
|
-
@d.literal(:x.like('a')).should == "(x LIKE BINARY 'a')"
|
|
905
|
-
@d.literal(
|
|
906
|
-
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
|
907
|
-
@d.literal(
|
|
908
|
-
@d.literal(:x.like(/a/)).should == "(x REGEXP BINARY 'a')"
|
|
909
|
-
@d.literal(
|
|
910
|
-
@d.literal(:x.like(/a/i)).should == "(x REGEXP 'a')"
|
|
911
|
-
@d.literal(
|
|
1109
|
+
@d.literal(Sequel.expr(:x).like('a')).should == "(`x` LIKE BINARY 'a')"
|
|
1110
|
+
@d.literal(~Sequel.expr(:x).like('a')).should == "(`x` NOT LIKE BINARY 'a')"
|
|
1111
|
+
@d.literal(Sequel.expr(:x).ilike('a')).should == "(`x` LIKE 'a')"
|
|
1112
|
+
@d.literal(~Sequel.expr(:x).ilike('a')).should == "(`x` NOT LIKE 'a')"
|
|
1113
|
+
@d.literal(Sequel.expr(:x).like(/a/)).should == "(`x` REGEXP BINARY 'a')"
|
|
1114
|
+
@d.literal(~Sequel.expr(:x).like(/a/)).should == "(`x` NOT REGEXP BINARY 'a')"
|
|
1115
|
+
@d.literal(Sequel.expr(:x).like(/a/i)).should == "(`x` REGEXP 'a')"
|
|
1116
|
+
@d.literal(~Sequel.expr(:x).like(/a/i)).should == "(`x` NOT REGEXP 'a')"
|
|
912
1117
|
end
|
|
913
1118
|
|
|
914
1119
|
specify "should handle string concatenation with CONCAT if more than one record" do
|
|
915
|
-
@d.literal([:x, :y]
|
|
916
|
-
@d.literal([:x, :y]
|
|
917
|
-
@d.literal([
|
|
1120
|
+
@d.literal(Sequel.join([:x, :y])).should == "CONCAT(`x`, `y`)"
|
|
1121
|
+
@d.literal(Sequel.join([:x, :y], ' ')).should == "CONCAT(`x`, ' ', `y`)"
|
|
1122
|
+
@d.literal(Sequel.join([Sequel.function(:x, :y), 1, Sequel.lit('z')], Sequel.subscript(:y, 1))).should == "CONCAT(x(`y`), `y`[1], '1', `y`[1], z)"
|
|
918
1123
|
end
|
|
919
1124
|
|
|
920
1125
|
specify "should handle string concatenation as simple string if just one record" do
|
|
921
|
-
@d.literal([:x]
|
|
922
|
-
@d.literal([:x]
|
|
1126
|
+
@d.literal(Sequel.join([:x])).should == "`x`"
|
|
1127
|
+
@d.literal(Sequel.join([:x], ' ')).should == "`x`"
|
|
923
1128
|
end
|
|
924
1129
|
end
|
|
925
1130
|
|
|
@@ -928,29 +1133,33 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
|
928
1133
|
MYSQL_DB.create_table!(:items){Integer :a}
|
|
929
1134
|
end
|
|
930
1135
|
after do
|
|
931
|
-
MYSQL_DB.drop_table(:items)
|
|
1136
|
+
MYSQL_DB.drop_table?(:items)
|
|
932
1137
|
end
|
|
933
1138
|
|
|
934
1139
|
specify "should add the SQL_CALC_FOUND_ROWS keyword when selecting" do
|
|
935
1140
|
MYSQL_DB[:items].select(:a).calc_found_rows.limit(1).sql.should == \
|
|
936
|
-
'SELECT SQL_CALC_FOUND_ROWS a FROM items LIMIT 1'
|
|
1141
|
+
'SELECT SQL_CALC_FOUND_ROWS `a` FROM `items` LIMIT 1'
|
|
937
1142
|
end
|
|
938
1143
|
|
|
939
1144
|
specify "should count matching rows disregarding LIMIT clause" do
|
|
940
1145
|
MYSQL_DB[:items].multi_insert([{:a => 1}, {:a => 1}, {:a => 2}])
|
|
941
1146
|
MYSQL_DB.sqls.clear
|
|
942
1147
|
|
|
943
|
-
MYSQL_DB
|
|
944
|
-
|
|
1148
|
+
MYSQL_DB.synchronize do
|
|
1149
|
+
MYSQL_DB[:items].calc_found_rows.filter(:a => 1).limit(1).all.should == [{:a => 1}]
|
|
1150
|
+
MYSQL_DB.dataset.select(Sequel.function(:FOUND_ROWS).as(:rows)).all.should == [{:rows => 2 }]
|
|
1151
|
+
end
|
|
945
1152
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1153
|
+
check_sqls do
|
|
1154
|
+
MYSQL_DB.sqls.should == [
|
|
1155
|
+
'SELECT SQL_CALC_FOUND_ROWS * FROM `items` WHERE (`a` = 1) LIMIT 1',
|
|
1156
|
+
'SELECT FOUND_ROWS() AS `rows`',
|
|
1157
|
+
]
|
|
1158
|
+
end
|
|
950
1159
|
end
|
|
951
1160
|
end
|
|
952
1161
|
|
|
953
|
-
if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
|
|
1162
|
+
if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc or MYSQL_DB.adapter_scheme == :mysql2
|
|
954
1163
|
describe "MySQL Stored Procedures" do
|
|
955
1164
|
before do
|
|
956
1165
|
MYSQL_DB.create_table(:items){Integer :id; Integer :value}
|
|
@@ -958,10 +1167,10 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
|
|
|
958
1167
|
MYSQL_DB.sqls.clear
|
|
959
1168
|
end
|
|
960
1169
|
after do
|
|
961
|
-
MYSQL_DB.drop_table(:items)
|
|
1170
|
+
MYSQL_DB.drop_table?(:items)
|
|
962
1171
|
MYSQL_DB.execute('DROP PROCEDURE test_sproc')
|
|
963
1172
|
end
|
|
964
|
-
|
|
1173
|
+
|
|
965
1174
|
specify "should be callable on the database object" do
|
|
966
1175
|
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc() BEGIN DELETE FROM items; END')
|
|
967
1176
|
MYSQL_DB[:items].delete
|
|
@@ -970,27 +1179,38 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
|
|
|
970
1179
|
MYSQL_DB.call_sproc(:test_sproc)
|
|
971
1180
|
MYSQL_DB[:items].count.should == 0
|
|
972
1181
|
end
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1182
|
+
|
|
1183
|
+
# Mysql2 doesn't support stored procedures that return result sets, probably because
|
|
1184
|
+
# CLIENT_MULTI_RESULTS is not set.
|
|
1185
|
+
unless MYSQL_DB.adapter_scheme == :mysql2
|
|
1186
|
+
specify "should be callable on the dataset object" do
|
|
1187
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
|
|
1188
|
+
MYSQL_DB[:items].delete
|
|
1189
|
+
@d = MYSQL_DB[:items]
|
|
1190
|
+
@d.call_sproc(:select, :test_sproc, 3).should == []
|
|
1191
|
+
@d.insert(:value=>1)
|
|
1192
|
+
@d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
|
|
1193
|
+
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
1194
|
+
@d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
specify "should be callable on the dataset object with multiple arguments" do
|
|
1198
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER, c INTEGER) BEGIN SELECT *, a AS b, c AS d FROM items; END')
|
|
1199
|
+
MYSQL_DB[:items].delete
|
|
1200
|
+
@d = MYSQL_DB[:items]
|
|
1201
|
+
@d.call_sproc(:select, :test_sproc, 3, 4).should == []
|
|
1202
|
+
@d.insert(:value=>1)
|
|
1203
|
+
@d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
|
|
1204
|
+
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
1205
|
+
@d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
|
|
1206
|
+
end
|
|
1207
|
+
end
|
|
1208
|
+
|
|
1209
|
+
specify "should deal with nil values" do
|
|
1210
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(i INTEGER, v INTEGER) BEGIN INSERT INTO items VALUES (i, v); END')
|
|
987
1211
|
MYSQL_DB[:items].delete
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
@d.insert(:value=>1)
|
|
991
|
-
@d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
|
|
992
|
-
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
993
|
-
@d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
|
|
1212
|
+
MYSQL_DB.call_sproc(:test_sproc, :args=>[1, nil])
|
|
1213
|
+
MYSQL_DB[:items].all.should == [{:id=>1, :value=>nil}]
|
|
994
1214
|
end
|
|
995
1215
|
end
|
|
996
1216
|
end
|
|
@@ -998,35 +1218,35 @@ end
|
|
|
998
1218
|
if MYSQL_DB.adapter_scheme == :mysql
|
|
999
1219
|
describe "MySQL bad date/time conversions" do
|
|
1000
1220
|
after do
|
|
1001
|
-
|
|
1221
|
+
MYSQL_DB.convert_invalid_date_time = false
|
|
1002
1222
|
end
|
|
1003
|
-
|
|
1223
|
+
|
|
1004
1224
|
specify "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
|
|
1005
|
-
|
|
1225
|
+
MYSQL_DB.convert_invalid_date_time = false
|
|
1006
1226
|
proc{MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1007
1227
|
proc{MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1008
1228
|
proc{MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1009
1229
|
end
|
|
1010
|
-
|
|
1230
|
+
|
|
1011
1231
|
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
|
|
1012
|
-
|
|
1232
|
+
MYSQL_DB.convert_invalid_date_time = nil
|
|
1013
1233
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
|
1014
1234
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
|
1015
1235
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
|
1016
|
-
|
|
1236
|
+
MYSQL_DB.convert_invalid_date_time = :nil
|
|
1017
1237
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
|
1018
1238
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
|
1019
1239
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
|
1020
1240
|
end
|
|
1021
|
-
|
|
1241
|
+
|
|
1022
1242
|
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
|
|
1023
|
-
|
|
1243
|
+
MYSQL_DB.convert_invalid_date_time = :string
|
|
1024
1244
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == '0000-00-00'
|
|
1025
1245
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == '0000-00-00 00:00:00'
|
|
1026
1246
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == '25:00:00'
|
|
1027
1247
|
end
|
|
1028
1248
|
end
|
|
1029
|
-
|
|
1249
|
+
|
|
1030
1250
|
describe "MySQL multiple result sets" do
|
|
1031
1251
|
before do
|
|
1032
1252
|
MYSQL_DB.create_table!(:a){Integer :a}
|
|
@@ -1038,43 +1258,68 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
1038
1258
|
MYSQL_DB[:b].insert(25)
|
|
1039
1259
|
end
|
|
1040
1260
|
after do
|
|
1041
|
-
MYSQL_DB.drop_table(:a, :b)
|
|
1261
|
+
MYSQL_DB.drop_table?(:a, :b)
|
|
1042
1262
|
end
|
|
1043
|
-
|
|
1263
|
+
|
|
1044
1264
|
specify "should combine all results by default" do
|
|
1045
1265
|
@ds.all.should == [{:a=>10}, {:a=>15}, {:b=>20}, {:b=>25}]
|
|
1046
1266
|
end
|
|
1047
|
-
|
|
1267
|
+
|
|
1048
1268
|
specify "should work with Database#run" do
|
|
1049
1269
|
proc{MYSQL_DB.run('SELECT * FROM a; SELECT * FROM b')}.should_not raise_error
|
|
1050
1270
|
proc{MYSQL_DB.run('SELECT * FROM a; SELECT * FROM b')}.should_not raise_error
|
|
1051
1271
|
end
|
|
1052
|
-
|
|
1272
|
+
|
|
1053
1273
|
specify "should work with Database#run and other statements" do
|
|
1054
1274
|
proc{MYSQL_DB.run('UPDATE a SET a = 1; SELECT * FROM a; DELETE FROM b')}.should_not raise_error
|
|
1055
1275
|
MYSQL_DB[:a].select_order_map(:a).should == [1, 1]
|
|
1056
1276
|
MYSQL_DB[:b].all.should == []
|
|
1057
1277
|
end
|
|
1058
|
-
|
|
1278
|
+
|
|
1059
1279
|
specify "should split results returned into arrays if split_multiple_result_sets is used" do
|
|
1060
1280
|
@ds.split_multiple_result_sets.all.should == [[{:a=>10}, {:a=>15}], [{:b=>20}, {:b=>25}]]
|
|
1061
1281
|
end
|
|
1062
|
-
|
|
1282
|
+
|
|
1063
1283
|
specify "should have regular row_procs work when splitting multiple result sets" do
|
|
1064
1284
|
@ds.row_proc = proc{|x| x[x.keys.first] *= 2; x}
|
|
1065
1285
|
@ds.split_multiple_result_sets.all.should == [[{:a=>20}, {:a=>30}], [{:b=>40}, {:b=>50}]]
|
|
1066
1286
|
end
|
|
1067
|
-
|
|
1287
|
+
|
|
1068
1288
|
specify "should use the columns from the first result set when splitting result sets" do
|
|
1069
1289
|
@ds.split_multiple_result_sets.columns.should == [:a]
|
|
1070
1290
|
end
|
|
1071
|
-
|
|
1291
|
+
|
|
1072
1292
|
specify "should not allow graphing a dataset that splits multiple statements" do
|
|
1073
1293
|
proc{@ds.split_multiple_result_sets.graph(:b, :b=>:a)}.should raise_error(Sequel::Error)
|
|
1074
1294
|
end
|
|
1075
|
-
|
|
1295
|
+
|
|
1076
1296
|
specify "should not allow splitting a graphed dataset" do
|
|
1077
1297
|
proc{MYSQL_DB[:a].graph(:b, :b=>:a).split_multiple_result_sets}.should raise_error(Sequel::Error)
|
|
1078
1298
|
end
|
|
1079
1299
|
end
|
|
1080
1300
|
end
|
|
1301
|
+
|
|
1302
|
+
if MYSQL_DB.adapter_scheme == :mysql2
|
|
1303
|
+
describe "Mysql2 streaming" do
|
|
1304
|
+
before(:all) do
|
|
1305
|
+
MYSQL_DB.create_table!(:a){Integer :a}
|
|
1306
|
+
MYSQL_DB.transaction do
|
|
1307
|
+
1000.times do |i|
|
|
1308
|
+
MYSQL_DB[:a].insert(i)
|
|
1309
|
+
end
|
|
1310
|
+
end
|
|
1311
|
+
@ds = MYSQL_DB[:a].stream.order(:a)
|
|
1312
|
+
end
|
|
1313
|
+
after(:all) do
|
|
1314
|
+
MYSQL_DB.drop_table?(:a)
|
|
1315
|
+
end
|
|
1316
|
+
|
|
1317
|
+
specify "should correctly stream results" do
|
|
1318
|
+
@ds.map(:a).should == (0...1000).to_a
|
|
1319
|
+
end
|
|
1320
|
+
|
|
1321
|
+
specify "should correctly handle early returning when streaming results" do
|
|
1322
|
+
3.times{@ds.each{|r| break r[:a]}.should == 0}
|
|
1323
|
+
end
|
|
1324
|
+
end if false
|
|
1325
|
+
end
|