sequel 3.21.0 → 3.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
require 'ibm_db'
|
|
2
|
+
Sequel.require 'adapters/shared/db2'
|
|
3
|
+
|
|
4
|
+
module Sequel
|
|
5
|
+
|
|
6
|
+
module IBMDB
|
|
7
|
+
@convert_smallint_to_bool = true
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# Whether to convert smallint values to bool, true by default.
|
|
11
|
+
# Can also be overridden per dataset.
|
|
12
|
+
attr_accessor :convert_smallint_to_bool
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
tt = Class.new do
|
|
16
|
+
def boolean(s) !s.to_i.zero? end
|
|
17
|
+
def int(s) s.to_i end
|
|
18
|
+
end.new
|
|
19
|
+
|
|
20
|
+
# Hash holding type translation methods, used by Dataset#fetch_rows.
|
|
21
|
+
DB2_TYPES = {
|
|
22
|
+
:boolean => tt.method(:boolean),
|
|
23
|
+
:int => tt.method(:int),
|
|
24
|
+
:blob => ::Sequel::SQL::Blob.method(:new),
|
|
25
|
+
:time => ::Sequel.method(:string_to_time),
|
|
26
|
+
:date => ::Sequel.method(:string_to_date)
|
|
27
|
+
}
|
|
28
|
+
DB2_TYPES[:clob] = DB2_TYPES[:blob]
|
|
29
|
+
|
|
30
|
+
# Wraps an underlying connection to DB2 using IBM_DB.
|
|
31
|
+
class Connection
|
|
32
|
+
# A hash with prepared statement name symbol keys, where each value is
|
|
33
|
+
# a two element array with an sql string and cached Statement value.
|
|
34
|
+
attr_accessor :prepared_statements
|
|
35
|
+
|
|
36
|
+
# Error class for exceptions raised by the connection.
|
|
37
|
+
class Error < StandardError
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Create the underlying IBM_DB connection.
|
|
41
|
+
def initialize(connection_string)
|
|
42
|
+
@conn = IBM_DB.connect(connection_string, '', '')
|
|
43
|
+
self.autocommit = true
|
|
44
|
+
@prepared_statements = {}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Check whether the connection is in autocommit state or not.
|
|
48
|
+
def autocommit
|
|
49
|
+
IBM_DB.autocommit(@conn) == 1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Turn autocommit on or off for the connection.
|
|
53
|
+
def autocommit=(value)
|
|
54
|
+
IBM_DB.autocommit(@conn, value ? IBM_DB::SQL_AUTOCOMMIT_ON : IBM_DB::SQL_AUTOCOMMIT_OFF)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Close the connection, disconnecting from DB2.
|
|
58
|
+
def close
|
|
59
|
+
IBM_DB.close(@conn)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Commit the currently outstanding transaction on this connection.
|
|
63
|
+
def commit
|
|
64
|
+
IBM_DB.commit(@conn)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Return the related error message for the connection.
|
|
68
|
+
def error_msg
|
|
69
|
+
IBM_DB.getErrormsg(@conn, IBM_DB::DB_CONN)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Execute the given SQL on the database, and return a Statement instance
|
|
73
|
+
# holding the results.
|
|
74
|
+
def execute(sql)
|
|
75
|
+
stmt = IBM_DB.exec(@conn, sql)
|
|
76
|
+
raise Error, error_msg unless stmt
|
|
77
|
+
Statement.new(stmt)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Execute the related prepared statement on the database with the given
|
|
81
|
+
# arguments.
|
|
82
|
+
def execute_prepared(ps_name, *values)
|
|
83
|
+
stmt = @prepared_statements[ps_name].last
|
|
84
|
+
res = stmt.execute(*values)
|
|
85
|
+
unless res
|
|
86
|
+
raise Error, "Error executing statement #{ps_name}: #{error_msg}"
|
|
87
|
+
end
|
|
88
|
+
stmt
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Prepare a statement with the given +sql+ on the database, and
|
|
92
|
+
# cache the prepared statement value by name.
|
|
93
|
+
def prepare(sql, ps_name)
|
|
94
|
+
if stmt = IBM_DB.prepare(@conn, sql)
|
|
95
|
+
ps_name = ps_name.to_sym
|
|
96
|
+
stmt = Statement.new(stmt)
|
|
97
|
+
@prepared_statements[ps_name] = [sql, stmt]
|
|
98
|
+
else
|
|
99
|
+
err = error_msg
|
|
100
|
+
err = "Error preparing #{ps_name} with SQL: #{sql}" if error_msg.nil? || error_msg.empty?
|
|
101
|
+
raise Error, err
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Rollback the currently outstanding transaction on this connection.
|
|
106
|
+
def rollback
|
|
107
|
+
IBM_DB.rollback(@conn)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Wraps results returned by queries on IBM_DB.
|
|
112
|
+
class Statement
|
|
113
|
+
# Hold the given statement.
|
|
114
|
+
def initialize(stmt)
|
|
115
|
+
@stmt = stmt
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return the number of rows affected.
|
|
119
|
+
def affected
|
|
120
|
+
IBM_DB.num_rows(@stmt)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# If this statement is a prepared statement, execute it on the database
|
|
124
|
+
# with the given values.
|
|
125
|
+
def execute(*values)
|
|
126
|
+
IBM_DB.execute(@stmt, values)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Return the results of a query as an array of values.
|
|
130
|
+
def fetch_array
|
|
131
|
+
IBM_DB.fetch_array(@stmt) if @stmt
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Return the field name at the given column in the result set.
|
|
135
|
+
def field_name(ind)
|
|
136
|
+
IBM_DB.field_name(@stmt, ind)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return the field type for the given field name in the result set.
|
|
140
|
+
def field_type(key)
|
|
141
|
+
IBM_DB.field_type(@stmt, key)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Return the field precision for the given field name in the result set.
|
|
145
|
+
def field_precision(key)
|
|
146
|
+
IBM_DB.field_precision(@stmt, key)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Free the memory related to this result set.
|
|
150
|
+
def free
|
|
151
|
+
IBM_DB.free_result(@stmt)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Return the number of fields in the result set.
|
|
155
|
+
def num_fields
|
|
156
|
+
IBM_DB.num_fields(@stmt)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class Database < Sequel::Database
|
|
161
|
+
include Sequel::DB2::DatabaseMethods
|
|
162
|
+
|
|
163
|
+
set_adapter_scheme :ibmdb
|
|
164
|
+
|
|
165
|
+
# Hash of connection procs for converting
|
|
166
|
+
attr_reader :conversion_procs
|
|
167
|
+
|
|
168
|
+
def initialize(opts={})
|
|
169
|
+
super
|
|
170
|
+
@conversion_procs = DB2_TYPES.dup
|
|
171
|
+
@conversion_procs[:timestamp] = method(:to_application_timestamp)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# REORG the related table whenever it is altered. This is not always
|
|
175
|
+
# required, but it is necessary for compatibilty with other Sequel
|
|
176
|
+
# code in many cases.
|
|
177
|
+
def alter_table(name, generator=nil)
|
|
178
|
+
res = super
|
|
179
|
+
reorg(name)
|
|
180
|
+
res
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Create a new connection object for the given server.
|
|
184
|
+
def connect(server)
|
|
185
|
+
opts = server_opts(server)
|
|
186
|
+
|
|
187
|
+
# use uncataloged connection so that host and port can be supported
|
|
188
|
+
connection_string = ( \
|
|
189
|
+
'Driver={IBM DB2 ODBC DRIVER};' \
|
|
190
|
+
"Database=#{opts[:database]};" \
|
|
191
|
+
"Hostname=#{opts[:host]};" \
|
|
192
|
+
"Port=#{opts[:port] || 50000};" \
|
|
193
|
+
'Protocol=TCPIP;' \
|
|
194
|
+
"Uid=#{opts[:user]};" \
|
|
195
|
+
"Pwd=#{opts[:password]};" \
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
Connection.new(connection_string)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Execute the given SQL on the database.
|
|
202
|
+
def execute(sql, opts={}, &block)
|
|
203
|
+
if sql.is_a?(Symbol)
|
|
204
|
+
execute_prepared_statement(sql, opts, &block)
|
|
205
|
+
else
|
|
206
|
+
synchronize(opts[:server]){|c| _execute(c, sql, opts, &block)}
|
|
207
|
+
end
|
|
208
|
+
rescue Connection::Error => e
|
|
209
|
+
raise_error(e)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Execute the given SQL on the database, returning the last inserted
|
|
213
|
+
# identity value.
|
|
214
|
+
def execute_insert(sql, opts={})
|
|
215
|
+
synchronize(opts[:server]) do |c|
|
|
216
|
+
if sql.is_a?(Symbol)
|
|
217
|
+
execute_prepared_statement(sql, opts)
|
|
218
|
+
else
|
|
219
|
+
_execute(c, sql, opts)
|
|
220
|
+
end
|
|
221
|
+
_execute(c, "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1", opts){|stmt| i = stmt.fetch_array.first.to_i; stmt.free; i}
|
|
222
|
+
end
|
|
223
|
+
rescue Connection::Error => e
|
|
224
|
+
raise_error(e)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Execute a prepared statement named by name on the database.
|
|
228
|
+
def execute_prepared_statement(ps_name, opts)
|
|
229
|
+
args = opts[:arguments]
|
|
230
|
+
ps = prepared_statement(ps_name)
|
|
231
|
+
sql = ps.prepared_sql
|
|
232
|
+
synchronize(opts[:server]) do |conn|
|
|
233
|
+
unless conn.prepared_statements.fetch(ps_name, []).first == sql
|
|
234
|
+
log_yield("PREPARE #{ps_name}: #{sql}"){conn.prepare(sql, ps_name)}
|
|
235
|
+
end
|
|
236
|
+
args = args.map{|v| v.nil? ? nil : prepared_statement_arg(v)}
|
|
237
|
+
log_sql = "EXECUTE #{ps_name}"
|
|
238
|
+
if ps.log_sql
|
|
239
|
+
log_sql << " ("
|
|
240
|
+
log_sql << sql
|
|
241
|
+
log_sql << ")"
|
|
242
|
+
end
|
|
243
|
+
stmt = log_yield(log_sql, args){conn.execute_prepared(ps_name, *args)}
|
|
244
|
+
if block_given?
|
|
245
|
+
begin
|
|
246
|
+
yield(stmt)
|
|
247
|
+
ensure
|
|
248
|
+
stmt.free
|
|
249
|
+
end
|
|
250
|
+
else
|
|
251
|
+
stmt.affected
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Convert smallint type to boolean if convert_smallint_to_bool is true
|
|
257
|
+
def schema_column_type(db_type)
|
|
258
|
+
if Sequel::IBMDB.convert_smallint_to_bool && db_type =~ /smallint/i
|
|
259
|
+
:boolean
|
|
260
|
+
else
|
|
261
|
+
super
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# On DB2, a table might need to be REORGed if you are testing existence
|
|
266
|
+
# of it. This REORGs automatically if the database raises a specific
|
|
267
|
+
# error that indicates it should be REORGed.
|
|
268
|
+
def table_exists?(name)
|
|
269
|
+
v ||= false # only retry once
|
|
270
|
+
sch, table_name = schema_and_table(name)
|
|
271
|
+
name = SQL::QualifiedIdentifier.new(sch, table_name) if sch
|
|
272
|
+
from(name).first
|
|
273
|
+
true
|
|
274
|
+
rescue DatabaseError => e
|
|
275
|
+
if e.to_s =~ /Operation not allowed for reason code "7" on table/ && v == false
|
|
276
|
+
# table probably needs reorg
|
|
277
|
+
reorg(name)
|
|
278
|
+
v = true
|
|
279
|
+
retry
|
|
280
|
+
end
|
|
281
|
+
false
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
private
|
|
285
|
+
|
|
286
|
+
# Execute the given SQL on the database.
|
|
287
|
+
def _execute(conn, sql, opts)
|
|
288
|
+
stmt = log_yield(sql){conn.execute(sql)}
|
|
289
|
+
if block_given?
|
|
290
|
+
begin
|
|
291
|
+
yield(stmt)
|
|
292
|
+
ensure
|
|
293
|
+
stmt.free
|
|
294
|
+
end
|
|
295
|
+
else
|
|
296
|
+
stmt.affected
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# IBM_DB uses an autocommit setting instead of sending SQL queries.
|
|
301
|
+
# So starting a transaction just turns autocommit off.
|
|
302
|
+
def begin_transaction(conn, opts={})
|
|
303
|
+
log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# This commits transaction in progress on the
|
|
307
|
+
# connection and sets autocommit back on.
|
|
308
|
+
def commit_transaction(conn, opts={})
|
|
309
|
+
log_yield(TRANSACTION_COMMIT){conn.commit}
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def database_error_classes
|
|
313
|
+
[Connection::Error]
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Don't convert smallint to boolean for the metadata
|
|
317
|
+
# dataset, since the DB2 metadata does not use
|
|
318
|
+
# boolean columns, and some smallint columns are
|
|
319
|
+
# accidently treated as booleans.
|
|
320
|
+
def metadata_dataset
|
|
321
|
+
ds = super
|
|
322
|
+
ds.convert_smallint_to_bool = false
|
|
323
|
+
ds
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Format Numeric, Date, and Time types specially for use
|
|
327
|
+
# as IBM_DB prepared statements argument vlaues.
|
|
328
|
+
def prepared_statement_arg(v)
|
|
329
|
+
case v
|
|
330
|
+
when Numeric
|
|
331
|
+
v.to_s
|
|
332
|
+
when Date, Time
|
|
333
|
+
literal(v).gsub("'", '')
|
|
334
|
+
else
|
|
335
|
+
v
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# Set autocommit back on
|
|
340
|
+
def remove_transaction(conn, committed)
|
|
341
|
+
conn.autocommit = true
|
|
342
|
+
ensure
|
|
343
|
+
super
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# This rolls back the transaction in progress on the
|
|
347
|
+
# connection and sets autocommit back on.
|
|
348
|
+
def rollback_transaction(conn, opts={})
|
|
349
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
class Dataset < Sequel::Dataset
|
|
354
|
+
include Sequel::DB2::DatasetMethods
|
|
355
|
+
|
|
356
|
+
Database::DatasetClass = self
|
|
357
|
+
|
|
358
|
+
module CallableStatementMethods
|
|
359
|
+
# Extend given dataset with this module so subselects inside subselects in
|
|
360
|
+
# prepared statements work.
|
|
361
|
+
def subselect_sql_append(sql, ds)
|
|
362
|
+
ps = ds.to_prepared_statement(:select).clone(:append_sql=>sql)
|
|
363
|
+
ps.extend(CallableStatementMethods)
|
|
364
|
+
ps = ps.bind(@opts[:bind_vars]) if @opts[:bind_vars]
|
|
365
|
+
ps.prepared_args = prepared_args
|
|
366
|
+
ps.prepared_sql
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Methods for DB2 prepared statements using the native driver.
|
|
371
|
+
module PreparedStatementMethods
|
|
372
|
+
include Sequel::Dataset::UnnumberedArgumentMapper
|
|
373
|
+
|
|
374
|
+
private
|
|
375
|
+
# Execute the prepared statement with arguments instead of the given SQL.
|
|
376
|
+
def execute(sql, opts={}, &block)
|
|
377
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# Execute the prepared statment with arguments instead of the given SQL.
|
|
381
|
+
def execute_dui(sql, opts={}, &block)
|
|
382
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Execute the prepared statement with arguments instead of the given SQL.
|
|
386
|
+
def execute_insert(sql, opts={}, &block)
|
|
387
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Emulate support of bind arguments in called statements.
|
|
393
|
+
def call(type, bind_arguments={}, *values, &block)
|
|
394
|
+
ps = to_prepared_statement(type, values)
|
|
395
|
+
ps.extend(CallableStatementMethods)
|
|
396
|
+
ps.call(bind_arguments, &block)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Whether to convert smallint to boolean arguments for this dataset.
|
|
400
|
+
# Defaults to the IBMDB module setting.
|
|
401
|
+
def convert_smallint_to_bool
|
|
402
|
+
defined?(@convert_smallint_to_bool) ? @convert_smallint_to_bool : (@convert_smallint_to_bool = IBMDB.convert_smallint_to_bool)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# Override the default IBMDB.convert_smallint_to_bool setting for this dataset.
|
|
406
|
+
attr_writer :convert_smallint_to_bool
|
|
407
|
+
|
|
408
|
+
# Fetch the rows from the database and yield plain hashes.
|
|
409
|
+
def fetch_rows(sql)
|
|
410
|
+
execute(sql) do |stmt|
|
|
411
|
+
offset = @opts[:offset]
|
|
412
|
+
columns = []
|
|
413
|
+
convert = convert_smallint_to_bool
|
|
414
|
+
cps = db.conversion_procs
|
|
415
|
+
stmt.num_fields.times do |i|
|
|
416
|
+
k = stmt.field_name i
|
|
417
|
+
key = output_identifier(k)
|
|
418
|
+
type = stmt.field_type(k).downcase.to_sym
|
|
419
|
+
# decide if it is a smallint from precision
|
|
420
|
+
type = :boolean if type ==:int && convert && stmt.field_precision(k) < 8
|
|
421
|
+
columns << [key, cps[type]]
|
|
422
|
+
end
|
|
423
|
+
cols = columns.map{|c| c.at(0)}
|
|
424
|
+
cols.delete(row_number_column) if offset
|
|
425
|
+
@columns = cols
|
|
426
|
+
|
|
427
|
+
while res = stmt.fetch_array
|
|
428
|
+
row = {}
|
|
429
|
+
res.zip(columns).each do |v, (k, pr)|
|
|
430
|
+
row[k] = ((pr ? pr.call(v) : v) if v)
|
|
431
|
+
end
|
|
432
|
+
row.delete(row_number_column) if offset
|
|
433
|
+
yield row
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
self
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# Store the given type of prepared statement in the associated database
|
|
440
|
+
# with the given name.
|
|
441
|
+
def prepare(type, name=nil, *values)
|
|
442
|
+
ps = to_prepared_statement(type, values)
|
|
443
|
+
ps.extend(PreparedStatementMethods)
|
|
444
|
+
if name
|
|
445
|
+
ps.prepared_statement_name = name
|
|
446
|
+
db.set_prepared_statement(name, ps)
|
|
447
|
+
end
|
|
448
|
+
ps
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
end
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
require 'informix'
|
|
2
|
+
Sequel.require 'adapters/shared/informix'
|
|
2
3
|
|
|
3
4
|
module Sequel
|
|
4
5
|
module Informix
|
|
5
6
|
class Database < Sequel::Database
|
|
7
|
+
include DatabaseMethods
|
|
8
|
+
|
|
6
9
|
set_adapter_scheme :informix
|
|
7
10
|
|
|
8
|
-
TEMPORARY = 'TEMP '.freeze
|
|
9
|
-
|
|
10
11
|
def connect(server)
|
|
11
12
|
opts = server_opts(server)
|
|
12
13
|
::Informix.connect(opts[:database], opts[:user], opts[:password])
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
def dataset(opts = nil)
|
|
16
|
-
Sequel::Informix::Dataset.new(self, opts)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
16
|
# Returns number of rows affected
|
|
20
17
|
def execute_dui(sql, opts={})
|
|
21
18
|
synchronize(opts[:server]){|c| log_yield(sql){c.immediate(sql)}}
|
|
@@ -26,16 +23,12 @@ module Sequel
|
|
|
26
23
|
synchronize(opts[:server]){|c| yield log_yield(sql){c.cursor(sql)}}
|
|
27
24
|
end
|
|
28
25
|
alias_method :query, :execute
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def disconnect_connection(c)
|
|
33
|
-
c.close
|
|
34
|
-
end
|
|
35
26
|
end
|
|
36
27
|
|
|
37
28
|
class Dataset < Sequel::Dataset
|
|
38
|
-
|
|
29
|
+
include DatasetMethods
|
|
30
|
+
|
|
31
|
+
Database::DatasetClass = self
|
|
39
32
|
|
|
40
33
|
def fetch_rows(sql)
|
|
41
34
|
execute(sql) do |cursor|
|
|
@@ -56,22 +49,6 @@ module Sequel
|
|
|
56
49
|
end
|
|
57
50
|
self
|
|
58
51
|
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
# Informix does not support INTERSECT or EXCEPT
|
|
63
|
-
def supports_intersect_except?
|
|
64
|
-
false
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def select_clause_methods
|
|
68
|
-
SELECT_CLAUSE_METHODS
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def select_limit_sql(sql)
|
|
72
|
-
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
|
73
|
-
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
|
74
|
-
end
|
|
75
52
|
end
|
|
76
53
|
end
|
|
77
54
|
end
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
Sequel.require 'adapters/jdbc/transactions'
|
|
2
|
+
|
|
1
3
|
module Sequel
|
|
2
4
|
module JDBC
|
|
3
5
|
# Database and Dataset support for AS400 databases accessed via JDBC.
|
|
4
6
|
module AS400
|
|
5
7
|
# Instance methods for AS400 Database objects accessed via JDBC.
|
|
6
8
|
module DatabaseMethods
|
|
9
|
+
include Sequel::JDBC::Transactions
|
|
10
|
+
|
|
7
11
|
TRANSACTION_BEGIN = 'Transaction.begin'.freeze
|
|
8
12
|
TRANSACTION_COMMIT = 'Transaction.commit'.freeze
|
|
9
13
|
TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
|
|
@@ -13,11 +17,6 @@ module Sequel
|
|
|
13
17
|
:as400
|
|
14
18
|
end
|
|
15
19
|
|
|
16
|
-
# Return Sequel::JDBC::AS400::Dataset object with the given opts.
|
|
17
|
-
def dataset(opts=nil)
|
|
18
|
-
Sequel::JDBC::AS400::Dataset.new(self, opts)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
20
|
# TODO: Fix for AS400
|
|
22
21
|
def last_insert_id(conn, opts={})
|
|
23
22
|
nil
|
|
@@ -33,31 +32,16 @@ module Sequel
|
|
|
33
32
|
# Use JDBC connection's setAutoCommit to false to start transactions
|
|
34
33
|
def begin_transaction(conn, opts={})
|
|
35
34
|
set_transaction_isolation(conn, opts)
|
|
36
|
-
|
|
37
|
-
conn
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Use JDBC connection's commit method to commit transactions
|
|
41
|
-
def commit_transaction(conn, opts={})
|
|
42
|
-
log_yield(TRANSACTION_COMMIT){conn.commit}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Use JDBC connection's setAutoCommit to true to enable default
|
|
46
|
-
# auto-commit mode
|
|
47
|
-
def remove_transaction(conn)
|
|
48
|
-
conn.setAutoCommit(true) if conn
|
|
49
|
-
@transactions.delete(Thread.current)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Use JDBC connection's rollback method to rollback transactions
|
|
53
|
-
def rollback_transaction(conn, opts={})
|
|
54
|
-
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
35
|
+
super
|
|
55
36
|
end
|
|
56
37
|
end
|
|
57
38
|
|
|
58
39
|
# Dataset class for AS400 datasets accessed via JDBC.
|
|
59
40
|
class Dataset < JDBC::Dataset
|
|
60
41
|
WILDCARD = Sequel::LiteralString.new('*').freeze
|
|
42
|
+
FETCH_FIRST_ROW_ONLY = " FETCH FIRST ROW ONLY".freeze
|
|
43
|
+
FETCH_FIRST = " FETCH FIRST ".freeze
|
|
44
|
+
ROWS_ONLY = " ROWS ONLY".freeze
|
|
61
45
|
|
|
62
46
|
# AS400 needs to use a couple of subselects for queries with offsets.
|
|
63
47
|
def select_sql
|
|
@@ -79,22 +63,20 @@ module Sequel
|
|
|
79
63
|
|
|
80
64
|
# Modify the sql to limit the number of rows returned
|
|
81
65
|
def select_limit_sql(sql)
|
|
82
|
-
if @opts[:limit]
|
|
83
|
-
|
|
84
|
-
|
|
66
|
+
if l = @opts[:limit]
|
|
67
|
+
if l == 1
|
|
68
|
+
sql << FETCH_FIRST_ROW_ONLY
|
|
69
|
+
elsif l > 1
|
|
70
|
+
sql << FETCH_FIRST
|
|
71
|
+
literal_append(sql, l)
|
|
72
|
+
sql << ROWS_ONLY
|
|
73
|
+
end
|
|
85
74
|
end
|
|
86
75
|
end
|
|
87
76
|
|
|
88
77
|
def supports_window_functions?
|
|
89
78
|
true
|
|
90
79
|
end
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
# The alias to use for the row_number column when emulating LIMIT and OFFSET
|
|
95
|
-
def row_number_column
|
|
96
|
-
:x_sequel_row_number_x
|
|
97
|
-
end
|
|
98
80
|
end
|
|
99
81
|
end
|
|
100
82
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Sequel.require 'adapters/shared/cubrid'
|
|
2
|
+
Sequel.require 'adapters/jdbc/transactions'
|
|
3
|
+
|
|
4
|
+
module Sequel
|
|
5
|
+
module JDBC
|
|
6
|
+
module Cubrid
|
|
7
|
+
module DatabaseMethods
|
|
8
|
+
include Sequel::Cubrid::DatabaseMethods
|
|
9
|
+
include Sequel::JDBC::Transactions
|
|
10
|
+
|
|
11
|
+
def supports_savepoints?
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Get the last inserted id using LAST_INSERT_ID().
|
|
18
|
+
def last_insert_id(conn, opts={})
|
|
19
|
+
if stmt = opts[:stmt]
|
|
20
|
+
rs = stmt.getGeneratedKeys
|
|
21
|
+
begin
|
|
22
|
+
if rs.next
|
|
23
|
+
rs.getInt(1)
|
|
24
|
+
end
|
|
25
|
+
rescue NativeException
|
|
26
|
+
nil
|
|
27
|
+
ensure
|
|
28
|
+
rs.close
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Use execute instead of executeUpdate.
|
|
34
|
+
def execute_prepared_statement_insert(stmt)
|
|
35
|
+
stmt.execute
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Return generated keys for insert statements, and use
|
|
39
|
+
# execute intead of executeUpdate as CUBRID doesn't
|
|
40
|
+
# return generated keys in executeUpdate.
|
|
41
|
+
def execute_statement_insert(stmt, sql)
|
|
42
|
+
stmt.execute(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Return generated keys for insert statements.
|
|
46
|
+
def prepare_jdbc_statement(conn, sql, opts)
|
|
47
|
+
opts[:type] == :insert ? conn.prepareStatement(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS) : super
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|