sequel 3.21.0 → 3.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1061 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +103 -63
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +67 -51
- data/doc/advanced_associations.rdoc +189 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +547 -0
- data/doc/opening_databases.rdoc +114 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +56 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +279 -97
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +125 -222
- data/lib/sequel/adapters/mysql2.rb +65 -56
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +368 -138
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +343 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +401 -116
- data/lib/sequel/adapters/shared/mysql.rb +424 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +257 -45
- data/lib/sequel/adapters/shared/postgres.rb +675 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +285 -96
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +28 -19
- data/lib/sequel/adapters/tinytds.rb +174 -22
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +43 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +190 -46
- data/lib/sequel/database/query.rb +272 -110
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +300 -67
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +305 -54
- data/lib/sequel/dataset/sql.rb +720 -292
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +537 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +313 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +208 -0
- data/lib/sequel/extensions/pg_range.rb +512 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +55 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +649 -122
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +194 -66
- data/spec/adapters/mysql_spec.rb +475 -306
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +1982 -325
- data/spec/adapters/spec_helper.rb +9 -6
- data/spec/adapters/sqlite_spec.rb +203 -75
- data/spec/core/connection_pool_spec.rb +218 -93
- data/spec/core/database_spec.rb +956 -522
- data/spec/core/dataset_spec.rb +1631 -1242
- data/spec/core/expression_filters_spec.rb +690 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +320 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +194 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +58 -67
- data/spec/extensions/validation_helpers_spec.rb +31 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +11 -5
- data/spec/integration/dataset_test.rb +717 -129
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +604 -147
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +367 -57
- data/spec/integration/spec_helper.rb +42 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +31 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +209 -80
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -13,6 +13,18 @@ module Sequel
|
|
|
13
13
|
# ORA-03114: not connected to ORACLE
|
|
14
14
|
CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114 ]
|
|
15
15
|
|
|
16
|
+
ORACLE_TYPES = {:blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)}}
|
|
17
|
+
|
|
18
|
+
# Hash of conversion procs for this database.
|
|
19
|
+
attr_reader :conversion_procs
|
|
20
|
+
|
|
21
|
+
def initialize(opts={})
|
|
22
|
+
super
|
|
23
|
+
@autosequence = opts[:autosequence]
|
|
24
|
+
@primary_key_sequences = {}
|
|
25
|
+
@conversion_procs = ORACLE_TYPES.dup
|
|
26
|
+
end
|
|
27
|
+
|
|
16
28
|
def connect(server)
|
|
17
29
|
opts = server_opts(server)
|
|
18
30
|
if opts[:database]
|
|
@@ -22,61 +34,150 @@ module Sequel
|
|
|
22
34
|
dbname = opts[:host]
|
|
23
35
|
end
|
|
24
36
|
conn = OCI8.new(opts[:user], opts[:password], dbname, opts[:privilege])
|
|
37
|
+
conn.prefetch_rows = typecast_value_integer(opts[:prefetch_rows]) if opts[:prefetch_rows]
|
|
25
38
|
conn.autocommit = true
|
|
26
39
|
conn.non_blocking = true
|
|
40
|
+
|
|
41
|
+
# The ruby-oci8 gem which retrieves oracle columns with a type of
|
|
42
|
+
# DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE is complex based on the
|
|
43
|
+
# ruby version (1.9.2 or later) and Oracle version (9 or later)
|
|
44
|
+
# In the now standard case of 1.9.2 and Oracle 9 or later, the timezone
|
|
45
|
+
# is determined by the Oracle session timezone. Thus if the user
|
|
46
|
+
# requests Sequel provide UTC timezone to the application,
|
|
47
|
+
# we need to alter the session timezone to be UTC
|
|
48
|
+
if Sequel.application_timezone == :utc
|
|
49
|
+
conn.exec("ALTER SESSION SET TIME_ZONE='-00:00'")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class << conn
|
|
53
|
+
attr_reader :prepared_statements
|
|
54
|
+
end
|
|
55
|
+
conn.instance_variable_set(:@prepared_statements, {})
|
|
56
|
+
|
|
27
57
|
conn
|
|
28
58
|
end
|
|
29
|
-
|
|
30
|
-
def
|
|
31
|
-
|
|
59
|
+
|
|
60
|
+
def execute(sql, opts={}, &block)
|
|
61
|
+
_execute(nil, sql, opts, &block)
|
|
32
62
|
end
|
|
63
|
+
alias do execute
|
|
33
64
|
|
|
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
|
|
65
|
+
def execute_insert(sql, opts={})
|
|
66
|
+
_execute(:insert, sql, opts)
|
|
60
67
|
end
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def _execute(type, sql, opts={}, &block)
|
|
63
72
|
synchronize(opts[:server]) do |conn|
|
|
64
73
|
begin
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
|
|
75
|
+
if args = opts[:arguments]
|
|
76
|
+
r = conn.parse(sql)
|
|
77
|
+
args = cursor_bind_params(conn, r, args)
|
|
78
|
+
nr = log_yield(sql, args){r.exec}
|
|
79
|
+
r = nr unless block_given?
|
|
80
|
+
else
|
|
81
|
+
r = log_yield(sql){conn.exec(sql)}
|
|
82
|
+
end
|
|
83
|
+
if block_given?
|
|
84
|
+
begin
|
|
85
|
+
yield(r)
|
|
86
|
+
ensure
|
|
87
|
+
r.close
|
|
88
|
+
end
|
|
89
|
+
elsif type == :insert
|
|
90
|
+
last_insert_id(conn, opts)
|
|
91
|
+
else
|
|
92
|
+
r
|
|
93
|
+
end
|
|
94
|
+
rescue OCIException, RuntimeError => e
|
|
95
|
+
# ruby-oci8 is naughty and raises strings in some places
|
|
96
|
+
raise_error(e)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
PS_TYPES = {'string'.freeze=>String, 'integer'.freeze=>Integer, 'float'.freeze=>Float,
|
|
102
|
+
'decimal'.freeze=>Float, 'date'.freeze=>Time, 'datetime'.freeze=>Time,
|
|
103
|
+
'time'.freeze=>Time, 'boolean'.freeze=>String, 'blob'.freeze=>OCI8::BLOB}
|
|
104
|
+
def cursor_bind_params(conn, cursor, args)
|
|
105
|
+
cursor
|
|
106
|
+
i = 0
|
|
107
|
+
args.map do |arg, type|
|
|
108
|
+
i += 1
|
|
109
|
+
case arg
|
|
110
|
+
when true
|
|
111
|
+
arg = 'Y'
|
|
112
|
+
when false
|
|
113
|
+
arg = 'N'
|
|
114
|
+
when BigDecimal
|
|
115
|
+
arg = arg.to_f
|
|
116
|
+
when ::Sequel::SQL::Blob
|
|
117
|
+
raise Error, "Sequel's oracle adapter does not currently support using a blob in a bound variable"
|
|
118
|
+
end
|
|
119
|
+
if t = PS_TYPES[type]
|
|
120
|
+
cursor.bind_param(i, arg, t)
|
|
121
|
+
else
|
|
122
|
+
cursor.bind_param(i, arg, arg.class)
|
|
123
|
+
end
|
|
124
|
+
arg
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def execute_prepared_statement(conn, type, name, opts)
|
|
129
|
+
ps = prepared_statement(name)
|
|
130
|
+
sql = ps.prepared_sql
|
|
131
|
+
if cursora = conn.prepared_statements[name]
|
|
132
|
+
cursor, cursor_sql = cursora
|
|
133
|
+
if cursor_sql != sql
|
|
134
|
+
cursor.close
|
|
135
|
+
cursor = nil
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
unless cursor
|
|
139
|
+
cursor = log_yield("PREPARE #{name}: #{sql}"){conn.parse(sql)}
|
|
140
|
+
conn.prepared_statements[name] = [cursor, sql]
|
|
141
|
+
end
|
|
142
|
+
args = cursor_bind_params(conn, cursor, opts[:arguments])
|
|
143
|
+
log_sql = "EXECUTE #{name}"
|
|
144
|
+
if ps.log_sql
|
|
145
|
+
log_sql << " ("
|
|
146
|
+
log_sql << sql
|
|
147
|
+
log_sql << ")"
|
|
148
|
+
end
|
|
149
|
+
r = log_yield(log_sql, args){cursor.exec}
|
|
150
|
+
if block_given?
|
|
151
|
+
yield(cursor)
|
|
152
|
+
elsif type == :insert
|
|
153
|
+
last_insert_id(conn, opts)
|
|
154
|
+
else
|
|
155
|
+
r
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def last_insert_id(conn, opts)
|
|
160
|
+
unless sequence = opts[:sequence]
|
|
161
|
+
if t = opts[:table]
|
|
162
|
+
sequence = sequence_for_table(t)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
if sequence
|
|
166
|
+
sql = "SELECT #{literal(sequence)}.currval FROM dual"
|
|
167
|
+
begin
|
|
168
|
+
cursor = log_yield(sql){conn.exec(sql)}
|
|
169
|
+
row = cursor.fetch
|
|
170
|
+
row.each{|v| return (v.to_i if v)}
|
|
171
|
+
rescue OCIError
|
|
172
|
+
nil
|
|
173
|
+
ensure
|
|
174
|
+
cursor.close if cursor
|
|
70
175
|
end
|
|
71
176
|
end
|
|
72
177
|
end
|
|
73
|
-
alias_method :do, :execute
|
|
74
178
|
|
|
75
|
-
private
|
|
76
|
-
|
|
77
179
|
def begin_transaction(conn, opts={})
|
|
78
180
|
log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
|
|
79
|
-
conn
|
|
80
181
|
end
|
|
81
182
|
|
|
82
183
|
def commit_transaction(conn, opts={})
|
|
@@ -88,49 +189,244 @@ module Sequel
|
|
|
88
189
|
rescue OCIInvalidHandle
|
|
89
190
|
nil
|
|
90
191
|
end
|
|
192
|
+
|
|
193
|
+
def disconnect_error?(e, opts)
|
|
194
|
+
super || (e.is_a?(::OCIError) && CONNECTION_ERROR_CODES.include?(e.code))
|
|
195
|
+
end
|
|
91
196
|
|
|
92
|
-
def
|
|
93
|
-
|
|
197
|
+
def oracle_column_type(h)
|
|
198
|
+
case h[:oci8_type]
|
|
199
|
+
when :number
|
|
200
|
+
case h[:scale]
|
|
201
|
+
when 0
|
|
202
|
+
:integer
|
|
203
|
+
when -127
|
|
204
|
+
:float
|
|
205
|
+
else
|
|
206
|
+
:decimal
|
|
207
|
+
end
|
|
208
|
+
when :date
|
|
209
|
+
:datetime
|
|
210
|
+
else
|
|
211
|
+
schema_column_type(h[:db_type])
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def remove_transaction(conn, committed)
|
|
216
|
+
conn.autocommit = true
|
|
217
|
+
ensure
|
|
94
218
|
super
|
|
95
219
|
end
|
|
96
220
|
|
|
97
221
|
def rollback_transaction(conn, opts={})
|
|
98
222
|
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
99
223
|
end
|
|
224
|
+
|
|
225
|
+
def schema_parse_table(table, opts={})
|
|
226
|
+
schema, table = schema_and_table(table)
|
|
227
|
+
schema ||= opts[:schema]
|
|
228
|
+
schema_and_table = if ds = opts[:dataset]
|
|
229
|
+
ds.literal(schema ? SQL::QualifiedIdentifier.new(schema, table) : SQL::Identifier.new(table))
|
|
230
|
+
else
|
|
231
|
+
"#{"#{quote_identifier(schema)}." if schema}#{quote_identifier(table)}"
|
|
232
|
+
end
|
|
233
|
+
table_schema = []
|
|
234
|
+
m = output_identifier_meth(ds)
|
|
235
|
+
im = input_identifier_meth(ds)
|
|
236
|
+
|
|
237
|
+
# Primary Keys
|
|
238
|
+
ds = metadata_dataset.from(:all_constraints___cons, :all_cons_columns___cols).
|
|
239
|
+
where(:cols__table_name=>im.call(table), :cons__constraint_type=>'P',
|
|
240
|
+
:cons__constraint_name=>:cols__constraint_name, :cons__owner=>:cols__owner)
|
|
241
|
+
ds = ds.where(:cons__owner=>im.call(schema)) if schema
|
|
242
|
+
pks = ds.select_map(:cols__column_name)
|
|
243
|
+
|
|
244
|
+
# Default values
|
|
245
|
+
defaults = begin
|
|
246
|
+
metadata_dataset.from(:user_tab_cols).
|
|
247
|
+
where(:table_name=>im.call(table)).
|
|
248
|
+
to_hash(:column_name, :data_default)
|
|
249
|
+
rescue DatabaseError
|
|
250
|
+
{}
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
metadata = synchronize(opts[:server]) do |conn|
|
|
254
|
+
begin
|
|
255
|
+
log_yield("Connection.describe_table"){conn.describe_table(schema_and_table)}
|
|
256
|
+
rescue OCIError => e
|
|
257
|
+
raise_error(e)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
metadata.columns.each do |column|
|
|
261
|
+
h = {
|
|
262
|
+
:primary_key => pks.include?(column.name),
|
|
263
|
+
:default => defaults[column.name],
|
|
264
|
+
:oci8_type => column.data_type,
|
|
265
|
+
:db_type => column.type_string.split(' ')[0],
|
|
266
|
+
:type_string => column.type_string,
|
|
267
|
+
:charset_form => column.charset_form,
|
|
268
|
+
:char_used => column.char_used?,
|
|
269
|
+
:char_size => column.char_size,
|
|
270
|
+
:data_size => column.data_size,
|
|
271
|
+
:precision => column.precision,
|
|
272
|
+
:scale => column.scale,
|
|
273
|
+
:fsprecision => column.fsprecision,
|
|
274
|
+
:lfprecision => column.lfprecision,
|
|
275
|
+
:allow_null => column.nullable?
|
|
276
|
+
}
|
|
277
|
+
h[:type] = oracle_column_type(h)
|
|
278
|
+
table_schema << [m.call(column.name), h]
|
|
279
|
+
end
|
|
280
|
+
table_schema
|
|
281
|
+
end
|
|
100
282
|
end
|
|
101
283
|
|
|
102
284
|
class Dataset < Sequel::Dataset
|
|
103
285
|
include DatasetMethods
|
|
104
286
|
|
|
287
|
+
Database::DatasetClass = self
|
|
288
|
+
|
|
289
|
+
PREPARED_ARG_PLACEHOLDER = ':'.freeze
|
|
290
|
+
|
|
291
|
+
# Oracle already supports named bind arguments, so use directly.
|
|
292
|
+
module ArgumentMapper
|
|
293
|
+
include Sequel::Dataset::ArgumentMapper
|
|
294
|
+
|
|
295
|
+
protected
|
|
296
|
+
|
|
297
|
+
# Return a hash with the same values as the given hash,
|
|
298
|
+
# but with the keys converted to strings.
|
|
299
|
+
def map_to_prepared_args(bind_vars)
|
|
300
|
+
prepared_args.map{|v, t| [bind_vars[v], t]}
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
private
|
|
304
|
+
|
|
305
|
+
# Oracle uses a : before the name of the argument for named
|
|
306
|
+
# arguments.
|
|
307
|
+
def prepared_arg(k)
|
|
308
|
+
y, type = k.to_s.split("__", 2)
|
|
309
|
+
prepared_args << [y.to_sym, type]
|
|
310
|
+
i = prepared_args.length
|
|
311
|
+
LiteralString.new(":#{i}")
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Always assume a prepared argument.
|
|
315
|
+
def prepared_arg?(k)
|
|
316
|
+
true
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Oracle prepared statement uses a new prepared statement each time
|
|
321
|
+
# it is called, but it does use the bind arguments.
|
|
322
|
+
module BindArgumentMethods
|
|
323
|
+
include ArgumentMapper
|
|
324
|
+
|
|
325
|
+
private
|
|
326
|
+
|
|
327
|
+
# Run execute_select on the database with the given SQL and the stored
|
|
328
|
+
# bind arguments.
|
|
329
|
+
def execute(sql, opts={}, &block)
|
|
330
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
334
|
+
def execute_dui(sql, opts={}, &block)
|
|
335
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
339
|
+
def execute_insert(sql, opts={}, &block)
|
|
340
|
+
super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
module PreparedStatementMethods
|
|
345
|
+
include BindArgumentMethods
|
|
346
|
+
|
|
347
|
+
private
|
|
348
|
+
|
|
349
|
+
# Execute the stored prepared statement name and the stored bind
|
|
350
|
+
# arguments instead of the SQL given.
|
|
351
|
+
def execute(sql, opts={}, &block)
|
|
352
|
+
super(prepared_statement_name, opts, &block)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
356
|
+
def execute_dui(sql, opts={}, &block)
|
|
357
|
+
super(prepared_statement_name, opts, &block)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Same as execute, explicit due to intricacies of alias and super.
|
|
361
|
+
def execute_insert(sql, opts={}, &block)
|
|
362
|
+
super(prepared_statement_name, opts, &block)
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Execute the given type of statement with the hash of values.
|
|
367
|
+
def call(type, bind_vars={}, *values, &block)
|
|
368
|
+
ps = to_prepared_statement(type, values)
|
|
369
|
+
ps.extend(BindArgumentMethods)
|
|
370
|
+
ps.call(bind_vars, &block)
|
|
371
|
+
end
|
|
372
|
+
|
|
105
373
|
def fetch_rows(sql)
|
|
106
374
|
execute(sql) do |cursor|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
375
|
+
offset = @opts[:offset]
|
|
376
|
+
rn = row_number_column
|
|
377
|
+
cps = db.conversion_procs
|
|
378
|
+
cols = columns = cursor.get_col_names.map{|c| output_identifier(c)}
|
|
379
|
+
metadata = cursor.column_metadata
|
|
380
|
+
cm = cols.zip(metadata).map{|c, m| [c, cps[m.data_type]]}
|
|
381
|
+
columns = cols.reject{|x| x == rn} if offset
|
|
382
|
+
@columns = columns
|
|
383
|
+
while r = cursor.fetch
|
|
384
|
+
row = {}
|
|
385
|
+
r.zip(cm).each{|v, (c, cp)| row[c] = ((v && cp) ? cp.call(v) : v)}
|
|
386
|
+
row.delete(rn) if offset
|
|
387
|
+
yield row
|
|
116
388
|
end
|
|
117
389
|
end
|
|
118
390
|
self
|
|
119
391
|
end
|
|
120
392
|
|
|
393
|
+
# Prepare the given type of query with the given name and store
|
|
394
|
+
# it in the database. Note that a new native prepared statement is
|
|
395
|
+
# created on each call to this prepared statement.
|
|
396
|
+
def prepare(type, name=nil, *values)
|
|
397
|
+
ps = to_prepared_statement(type, values)
|
|
398
|
+
ps.extend(PreparedStatementMethods)
|
|
399
|
+
if name
|
|
400
|
+
ps.prepared_statement_name = name
|
|
401
|
+
db.set_prepared_statement(name, ps)
|
|
402
|
+
end
|
|
403
|
+
ps
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Oracle requires type specifiers for placeholders, at least
|
|
407
|
+
# if you ever want to use a nil/NULL value as the value for
|
|
408
|
+
# the placeholder.
|
|
409
|
+
def requires_placeholder_type_specifiers?
|
|
410
|
+
true
|
|
411
|
+
end
|
|
412
|
+
|
|
121
413
|
private
|
|
122
414
|
|
|
123
|
-
def
|
|
415
|
+
def literal_other_append(sql, v)
|
|
124
416
|
case v
|
|
125
417
|
when OraDate
|
|
126
|
-
|
|
418
|
+
literal_append(sql, db.to_application_timestamp(v))
|
|
127
419
|
when OCI8::CLOB
|
|
128
420
|
v.rewind
|
|
129
|
-
|
|
421
|
+
literal_append(sql, v.read)
|
|
130
422
|
else
|
|
131
423
|
super
|
|
132
424
|
end
|
|
133
425
|
end
|
|
426
|
+
|
|
427
|
+
def prepared_arg_placeholder
|
|
428
|
+
PREPARED_ARG_PLACEHOLDER
|
|
429
|
+
end
|
|
134
430
|
end
|
|
135
431
|
end
|
|
136
432
|
end
|