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
|
@@ -13,6 +13,21 @@ module Sequel
|
|
|
13
13
|
# ORA-03114: not connected to ORACLE
|
|
14
14
|
CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114 ]
|
|
15
15
|
|
|
16
|
+
ORACLE_TYPES = {
|
|
17
|
+
:blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)},
|
|
18
|
+
:clob=>lambda{|b| b.read}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Hash of conversion procs for this database.
|
|
22
|
+
attr_reader :conversion_procs
|
|
23
|
+
|
|
24
|
+
def initialize(opts={})
|
|
25
|
+
super
|
|
26
|
+
@autosequence = opts[:autosequence]
|
|
27
|
+
@primary_key_sequences = {}
|
|
28
|
+
@conversion_procs = ORACLE_TYPES.dup
|
|
29
|
+
end
|
|
30
|
+
|
|
16
31
|
def connect(server)
|
|
17
32
|
opts = server_opts(server)
|
|
18
33
|
if opts[:database]
|
|
@@ -22,115 +37,407 @@ module Sequel
|
|
|
22
37
|
dbname = opts[:host]
|
|
23
38
|
end
|
|
24
39
|
conn = OCI8.new(opts[:user], opts[:password], dbname, opts[:privilege])
|
|
40
|
+
conn.prefetch_rows = typecast_value_integer(opts[:prefetch_rows]) if opts[:prefetch_rows]
|
|
25
41
|
conn.autocommit = true
|
|
26
42
|
conn.non_blocking = true
|
|
43
|
+
|
|
44
|
+
# The ruby-oci8 gem which retrieves oracle columns with a type of
|
|
45
|
+
# DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE is complex based on the
|
|
46
|
+
# ruby version (1.9.2 or later) and Oracle version (9 or later)
|
|
47
|
+
# In the now standard case of 1.9.2 and Oracle 9 or later, the timezone
|
|
48
|
+
# is determined by the Oracle session timezone. Thus if the user
|
|
49
|
+
# requests Sequel provide UTC timezone to the application,
|
|
50
|
+
# we need to alter the session timezone to be UTC
|
|
51
|
+
if Sequel.application_timezone == :utc
|
|
52
|
+
conn.exec("ALTER SESSION SET TIME_ZONE='-00:00'")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class << conn
|
|
56
|
+
attr_reader :prepared_statements
|
|
57
|
+
end
|
|
58
|
+
conn.instance_variable_set(:@prepared_statements, {})
|
|
59
|
+
|
|
27
60
|
conn
|
|
28
61
|
end
|
|
29
|
-
|
|
30
|
-
def
|
|
31
|
-
|
|
62
|
+
|
|
63
|
+
def disconnect_connection(c)
|
|
64
|
+
c.logoff
|
|
65
|
+
rescue OCIInvalidHandle
|
|
66
|
+
nil
|
|
32
67
|
end
|
|
33
68
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
ds.identifier_output_method = :downcase
|
|
37
|
-
schema_and_table = "#{"#{quote_identifier(opts[:schema])}." if opts[:schema]}#{quote_identifier(table)}"
|
|
38
|
-
table_schema = []
|
|
39
|
-
metadata = transaction(opts){|conn| conn.describe_table(schema_and_table)}
|
|
40
|
-
metadata.columns.each do |column|
|
|
41
|
-
table_schema << [
|
|
42
|
-
column.name.downcase.to_sym,
|
|
43
|
-
{
|
|
44
|
-
:type => column.data_type,
|
|
45
|
-
:db_type => column.type_string.split(' ')[0],
|
|
46
|
-
:type_string => column.type_string,
|
|
47
|
-
:charset_form => column.charset_form,
|
|
48
|
-
:char_used => column.char_used?,
|
|
49
|
-
:char_size => column.char_size,
|
|
50
|
-
:data_size => column.data_size,
|
|
51
|
-
:precision => column.precision,
|
|
52
|
-
:scale => column.scale,
|
|
53
|
-
:fsprecision => column.fsprecision,
|
|
54
|
-
:lfprecision => column.lfprecision,
|
|
55
|
-
:allow_null => column.nullable?
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
end
|
|
59
|
-
table_schema
|
|
69
|
+
def execute(sql, opts={}, &block)
|
|
70
|
+
_execute(nil, sql, opts, &block)
|
|
60
71
|
end
|
|
72
|
+
alias do execute
|
|
73
|
+
|
|
74
|
+
def execute_insert(sql, opts={})
|
|
75
|
+
_execute(:insert, sql, opts)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
61
79
|
|
|
62
|
-
def
|
|
80
|
+
def _execute(type, sql, opts={}, &block)
|
|
63
81
|
synchronize(opts[:server]) do |conn|
|
|
64
82
|
begin
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
83
|
+
return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
|
|
84
|
+
if args = opts[:arguments]
|
|
85
|
+
r = conn.parse(sql)
|
|
86
|
+
args = cursor_bind_params(conn, r, args)
|
|
87
|
+
nr = log_yield(sql, args){r.exec}
|
|
88
|
+
r = nr unless block_given?
|
|
89
|
+
else
|
|
90
|
+
r = log_yield(sql){conn.exec(sql)}
|
|
91
|
+
end
|
|
92
|
+
if block_given?
|
|
93
|
+
begin
|
|
94
|
+
yield(r)
|
|
95
|
+
ensure
|
|
96
|
+
r.close
|
|
97
|
+
end
|
|
98
|
+
elsif type == :insert
|
|
99
|
+
last_insert_id(conn, opts)
|
|
100
|
+
else
|
|
101
|
+
r
|
|
102
|
+
end
|
|
103
|
+
rescue OCIException, RuntimeError => e
|
|
104
|
+
# ruby-oci8 is naughty and raises strings in some places
|
|
105
|
+
raise_error(e)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
PS_TYPES = {'string'.freeze=>String, 'integer'.freeze=>Integer, 'float'.freeze=>Float,
|
|
111
|
+
'decimal'.freeze=>Float, 'date'.freeze=>Time, 'datetime'.freeze=>Time,
|
|
112
|
+
'time'.freeze=>Time, 'boolean'.freeze=>String, 'blob'.freeze=>OCI8::BLOB}
|
|
113
|
+
def cursor_bind_params(conn, cursor, args)
|
|
114
|
+
cursor
|
|
115
|
+
i = 0
|
|
116
|
+
args.map do |arg, type|
|
|
117
|
+
i += 1
|
|
118
|
+
case arg
|
|
119
|
+
when true
|
|
120
|
+
arg = 'Y'
|
|
121
|
+
when false
|
|
122
|
+
arg = 'N'
|
|
123
|
+
when BigDecimal
|
|
124
|
+
arg = arg.to_f
|
|
125
|
+
when ::Sequel::SQL::Blob
|
|
126
|
+
raise Error, "Sequel's oracle adapter does not currently support using a blob in a bound variable"
|
|
127
|
+
end
|
|
128
|
+
if t = PS_TYPES[type]
|
|
129
|
+
cursor.bind_param(i, arg, t)
|
|
130
|
+
else
|
|
131
|
+
cursor.bind_param(i, arg, arg.class)
|
|
132
|
+
end
|
|
133
|
+
arg
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def connection_execute_method
|
|
138
|
+
:exec
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def database_error_classes
|
|
142
|
+
[OCIException, RuntimeError]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def execute_prepared_statement(conn, type, name, opts)
|
|
146
|
+
ps = prepared_statement(name)
|
|
147
|
+
sql = ps.prepared_sql
|
|
148
|
+
if cursora = conn.prepared_statements[name]
|
|
149
|
+
cursor, cursor_sql = cursora
|
|
150
|
+
if cursor_sql != sql
|
|
151
|
+
cursor.close
|
|
152
|
+
cursor = nil
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
unless cursor
|
|
156
|
+
cursor = log_yield("PREPARE #{name}: #{sql}"){conn.parse(sql)}
|
|
157
|
+
conn.prepared_statements[name] = [cursor, sql]
|
|
158
|
+
end
|
|
159
|
+
args = cursor_bind_params(conn, cursor, opts[:arguments])
|
|
160
|
+
log_sql = "EXECUTE #{name}"
|
|
161
|
+
if ps.log_sql
|
|
162
|
+
log_sql << " ("
|
|
163
|
+
log_sql << sql
|
|
164
|
+
log_sql << ")"
|
|
165
|
+
end
|
|
166
|
+
r = log_yield(log_sql, args){cursor.exec}
|
|
167
|
+
if block_given?
|
|
168
|
+
yield(cursor)
|
|
169
|
+
elsif type == :insert
|
|
170
|
+
last_insert_id(conn, opts)
|
|
171
|
+
else
|
|
172
|
+
r
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def last_insert_id(conn, opts)
|
|
177
|
+
unless sequence = opts[:sequence]
|
|
178
|
+
if t = opts[:table]
|
|
179
|
+
sequence = sequence_for_table(t)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
if sequence
|
|
183
|
+
sql = "SELECT #{literal(sequence)}.currval FROM dual"
|
|
184
|
+
begin
|
|
185
|
+
cursor = log_yield(sql){conn.exec(sql)}
|
|
186
|
+
row = cursor.fetch
|
|
187
|
+
row.each{|v| return (v.to_i if v)}
|
|
188
|
+
rescue OCIError
|
|
189
|
+
nil
|
|
190
|
+
ensure
|
|
191
|
+
cursor.close if cursor
|
|
70
192
|
end
|
|
71
193
|
end
|
|
72
194
|
end
|
|
73
|
-
alias_method :do, :execute
|
|
74
195
|
|
|
75
|
-
private
|
|
76
|
-
|
|
77
196
|
def begin_transaction(conn, opts={})
|
|
78
197
|
log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
|
|
79
|
-
conn
|
|
80
198
|
end
|
|
81
199
|
|
|
82
200
|
def commit_transaction(conn, opts={})
|
|
83
201
|
log_yield(TRANSACTION_COMMIT){conn.commit}
|
|
84
202
|
end
|
|
85
203
|
|
|
86
|
-
def
|
|
87
|
-
|
|
88
|
-
rescue OCIInvalidHandle
|
|
89
|
-
nil
|
|
204
|
+
def disconnect_error?(e, opts)
|
|
205
|
+
super || (e.is_a?(::OCIError) && CONNECTION_ERROR_CODES.include?(e.code))
|
|
90
206
|
end
|
|
91
207
|
|
|
92
|
-
def
|
|
93
|
-
|
|
208
|
+
def oracle_column_type(h)
|
|
209
|
+
case h[:oci8_type]
|
|
210
|
+
when :number
|
|
211
|
+
case h[:scale]
|
|
212
|
+
when 0
|
|
213
|
+
:integer
|
|
214
|
+
when -127
|
|
215
|
+
:float
|
|
216
|
+
else
|
|
217
|
+
:decimal
|
|
218
|
+
end
|
|
219
|
+
when :date
|
|
220
|
+
:datetime
|
|
221
|
+
else
|
|
222
|
+
schema_column_type(h[:db_type])
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def remove_transaction(conn, committed)
|
|
227
|
+
conn.autocommit = true
|
|
228
|
+
ensure
|
|
94
229
|
super
|
|
95
230
|
end
|
|
96
231
|
|
|
97
232
|
def rollback_transaction(conn, opts={})
|
|
98
233
|
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
99
234
|
end
|
|
235
|
+
|
|
236
|
+
def schema_parse_table(table, opts={})
|
|
237
|
+
schema, table = schema_and_table(table)
|
|
238
|
+
schema ||= opts[:schema]
|
|
239
|
+
schema_and_table = if ds = opts[:dataset]
|
|
240
|
+
ds.literal(schema ? SQL::QualifiedIdentifier.new(schema, table) : SQL::Identifier.new(table))
|
|
241
|
+
else
|
|
242
|
+
"#{"#{quote_identifier(schema)}." if schema}#{quote_identifier(table)}"
|
|
243
|
+
end
|
|
244
|
+
table_schema = []
|
|
245
|
+
m = output_identifier_meth(ds)
|
|
246
|
+
im = input_identifier_meth(ds)
|
|
247
|
+
|
|
248
|
+
# Primary Keys
|
|
249
|
+
ds = metadata_dataset.from(:all_constraints___cons, :all_cons_columns___cols).
|
|
250
|
+
where(:cols__table_name=>im.call(table), :cons__constraint_type=>'P',
|
|
251
|
+
:cons__constraint_name=>:cols__constraint_name, :cons__owner=>:cols__owner)
|
|
252
|
+
ds = ds.where(:cons__owner=>im.call(schema)) if schema
|
|
253
|
+
pks = ds.select_map(:cols__column_name)
|
|
254
|
+
|
|
255
|
+
# Default values
|
|
256
|
+
defaults = begin
|
|
257
|
+
metadata_dataset.from(:user_tab_cols).
|
|
258
|
+
where(:table_name=>im.call(table)).
|
|
259
|
+
to_hash(:column_name, :data_default)
|
|
260
|
+
rescue DatabaseError
|
|
261
|
+
{}
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
metadata = synchronize(opts[:server]) do |conn|
|
|
265
|
+
begin
|
|
266
|
+
log_yield("Connection.describe_table"){conn.describe_table(schema_and_table)}
|
|
267
|
+
rescue OCIError => e
|
|
268
|
+
raise_error(e)
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
metadata.columns.each do |column|
|
|
272
|
+
h = {
|
|
273
|
+
:primary_key => pks.include?(column.name),
|
|
274
|
+
:default => defaults[column.name],
|
|
275
|
+
:oci8_type => column.data_type,
|
|
276
|
+
:db_type => column.type_string.split(' ')[0],
|
|
277
|
+
:type_string => column.type_string,
|
|
278
|
+
:charset_form => column.charset_form,
|
|
279
|
+
:char_used => column.char_used?,
|
|
280
|
+
:char_size => column.char_size,
|
|
281
|
+
:data_size => column.data_size,
|
|
282
|
+
:precision => column.precision,
|
|
283
|
+
:scale => column.scale,
|
|
284
|
+
:fsprecision => column.fsprecision,
|
|
285
|
+
:lfprecision => column.lfprecision,
|
|
286
|
+
:allow_null => column.nullable?
|
|
287
|
+
}
|
|
288
|
+
h[:type] = oracle_column_type(h)
|
|
289
|
+
table_schema << [m.call(column.name), h]
|
|
290
|
+
end
|
|
291
|
+
table_schema
|
|
292
|
+
end
|
|
100
293
|
end
|
|
101
294
|
|
|
102
295
|
class Dataset < Sequel::Dataset
|
|
103
296
|
include DatasetMethods
|
|
104
297
|
|
|
298
|
+
Database::DatasetClass = self
|
|
299
|
+
|
|
300
|
+
PREPARED_ARG_PLACEHOLDER = ':'.freeze
|
|
301
|
+
|
|
302
|
+
# Oracle already supports named bind arguments, so use directly.
|
|
303
|
+
module ArgumentMapper
|
|
304
|
+
include Sequel::Dataset::ArgumentMapper
|
|
305
|
+
|
|
306
|
+
protected
|
|
307
|
+
|
|
308
|
+
# Return a hash with the same values as the given hash,
|
|
309
|
+
# but with the keys converted to strings.
|
|
310
|
+
def map_to_prepared_args(bind_vars)
|
|
311
|
+
prepared_args.map{|v, t| [bind_vars[v], t]}
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
private
|
|
315
|
+
|
|
316
|
+
# Oracle uses a : before the name of the argument for named
|
|
317
|
+
# arguments.
|
|
318
|
+
def prepared_arg(k)
|
|
319
|
+
y, type = k.to_s.split("__", 2)
|
|
320
|
+
prepared_args << [y.to_sym, type]
|
|
321
|
+
i = prepared_args.length
|
|
322
|
+
LiteralString.new(":#{i}")
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Always assume a prepared argument.
|
|
326
|
+
def prepared_arg?(k)
|
|
327
|
+
true
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Oracle prepared statement uses a new prepared statement each time
|
|
332
|
+
# it is called, but it does use the bind arguments.
|
|
333
|
+
module BindArgumentMethods
|
|
334
|
+
include ArgumentMapper
|
|
335
|
+
|
|
336
|
+
private
|
|
337
|
+
|
|
338
|
+
# Run execute_select on the database with the given SQL and the stored
|
|
339
|
+
# bind arguments.
|
|
340
|
+
def execute(sql, opts={}, &block)
|
|
341
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
345
|
+
def execute_dui(sql, opts={}, &block)
|
|
346
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
350
|
+
def execute_insert(sql, opts={}, &block)
|
|
351
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
module PreparedStatementMethods
|
|
356
|
+
include BindArgumentMethods
|
|
357
|
+
|
|
358
|
+
private
|
|
359
|
+
|
|
360
|
+
# Execute the stored prepared statement name and the stored bind
|
|
361
|
+
# arguments instead of the SQL given.
|
|
362
|
+
def execute(sql, opts={}, &block)
|
|
363
|
+
super(prepared_statement_name, opts, &block)
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
367
|
+
def execute_dui(sql, opts={}, &block)
|
|
368
|
+
super(prepared_statement_name, opts, &block)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
372
|
+
def execute_insert(sql, opts={}, &block)
|
|
373
|
+
super(prepared_statement_name, opts, &block)
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Execute the given type of statement with the hash of values.
|
|
378
|
+
def call(type, bind_vars={}, *values, &block)
|
|
379
|
+
ps = to_prepared_statement(type, values)
|
|
380
|
+
ps.extend(BindArgumentMethods)
|
|
381
|
+
ps.call(bind_vars, &block)
|
|
382
|
+
end
|
|
383
|
+
|
|
105
384
|
def fetch_rows(sql)
|
|
106
385
|
execute(sql) do |cursor|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
386
|
+
offset = @opts[:offset]
|
|
387
|
+
rn = row_number_column
|
|
388
|
+
cps = db.conversion_procs
|
|
389
|
+
cols = columns = cursor.get_col_names.map{|c| output_identifier(c)}
|
|
390
|
+
metadata = cursor.column_metadata
|
|
391
|
+
cm = cols.zip(metadata).map{|c, m| [c, cps[m.data_type]]}
|
|
392
|
+
columns = cols.reject{|x| x == rn} if offset
|
|
393
|
+
@columns = columns
|
|
394
|
+
while r = cursor.fetch
|
|
395
|
+
row = {}
|
|
396
|
+
r.zip(cm).each{|v, (c, cp)| row[c] = ((v && cp) ? cp.call(v) : v)}
|
|
397
|
+
row.delete(rn) if offset
|
|
398
|
+
yield row
|
|
116
399
|
end
|
|
117
400
|
end
|
|
118
401
|
self
|
|
119
402
|
end
|
|
120
403
|
|
|
404
|
+
# Prepare the given type of query with the given name and store
|
|
405
|
+
# it in the database. Note that a new native prepared statement is
|
|
406
|
+
# created on each call to this prepared statement.
|
|
407
|
+
def prepare(type, name=nil, *values)
|
|
408
|
+
ps = to_prepared_statement(type, values)
|
|
409
|
+
ps.extend(PreparedStatementMethods)
|
|
410
|
+
if name
|
|
411
|
+
ps.prepared_statement_name = name
|
|
412
|
+
db.set_prepared_statement(name, ps)
|
|
413
|
+
end
|
|
414
|
+
ps
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# Oracle requires type specifiers for placeholders, at least
|
|
418
|
+
# if you ever want to use a nil/NULL value as the value for
|
|
419
|
+
# the placeholder.
|
|
420
|
+
def requires_placeholder_type_specifiers?
|
|
421
|
+
true
|
|
422
|
+
end
|
|
423
|
+
|
|
121
424
|
private
|
|
122
425
|
|
|
123
|
-
def
|
|
426
|
+
def literal_other_append(sql, v)
|
|
124
427
|
case v
|
|
125
428
|
when OraDate
|
|
126
|
-
|
|
429
|
+
literal_append(sql, db.to_application_timestamp(v))
|
|
127
430
|
when OCI8::CLOB
|
|
128
431
|
v.rewind
|
|
129
|
-
|
|
432
|
+
literal_append(sql, v.read)
|
|
130
433
|
else
|
|
131
434
|
super
|
|
132
435
|
end
|
|
133
436
|
end
|
|
437
|
+
|
|
438
|
+
def prepared_arg_placeholder
|
|
439
|
+
PREPARED_ARG_PLACEHOLDER
|
|
440
|
+
end
|
|
134
441
|
end
|
|
135
442
|
end
|
|
136
443
|
end
|