sequel 3.21.0 → 3.31.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 +485 -3
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +249 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- 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/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- 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 +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -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 +45 -0
- data/lib/sequel/adapters/jdbc/derby.rb +247 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +56 -29
- data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +335 -0
- data/lib/sequel/adapters/mysql.rb +82 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +351 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +321 -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 +231 -106
- data/lib/sequel/adapters/shared/mysql.rb +181 -63
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +231 -41
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +4 -7
- data/lib/sequel/adapters/shared/sqlite.rb +201 -57
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +231 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +48 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +665 -253
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1020 -337
- data/lib/sequel/model/base.rb +414 -132
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -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 +29 -15
- data/lib/sequel/plugins/serialization.rb +88 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +111 -29
- data/spec/adapters/mysql_spec.rb +135 -123
- data/spec/adapters/oracle_spec.rb +49 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +788 -512
- data/spec/core/dataset_spec.rb +1073 -1053
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- 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/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- 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 +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +72 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -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 +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +537 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +461 -65
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +212 -122
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +865 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +115 -73
data/lib/sequel/adapters/jdbc.rb
CHANGED
|
@@ -32,47 +32,89 @@ module Sequel
|
|
|
32
32
|
DATABASE_SETUP = {:postgresql=>proc do |db|
|
|
33
33
|
Sequel.ts_require 'adapters/jdbc/postgresql'
|
|
34
34
|
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
|
35
|
+
db.dataset_class = Sequel::JDBC::Postgres::Dataset
|
|
35
36
|
JDBC.load_gem('postgres')
|
|
36
37
|
org.postgresql.Driver
|
|
37
38
|
end,
|
|
38
39
|
:mysql=>proc do |db|
|
|
39
40
|
Sequel.ts_require 'adapters/jdbc/mysql'
|
|
40
41
|
db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
|
|
42
|
+
db.dataset_class = Sequel::JDBC::MySQL::Dataset
|
|
41
43
|
JDBC.load_gem('mysql')
|
|
42
44
|
com.mysql.jdbc.Driver
|
|
43
45
|
end,
|
|
44
46
|
:sqlite=>proc do |db|
|
|
45
47
|
Sequel.ts_require 'adapters/jdbc/sqlite'
|
|
46
48
|
db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
|
|
49
|
+
db.dataset_class = Sequel::JDBC::SQLite::Dataset
|
|
47
50
|
JDBC.load_gem('sqlite3')
|
|
48
51
|
org.sqlite.JDBC
|
|
49
52
|
end,
|
|
50
53
|
:oracle=>proc do |db|
|
|
51
54
|
Sequel.ts_require 'adapters/jdbc/oracle'
|
|
52
55
|
db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
|
|
56
|
+
db.dataset_class = Sequel::JDBC::Oracle::Dataset
|
|
53
57
|
Java::oracle.jdbc.driver.OracleDriver
|
|
54
58
|
end,
|
|
55
59
|
:sqlserver=>proc do |db|
|
|
56
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
57
|
-
db.extend(Sequel::JDBC::
|
|
60
|
+
Sequel.ts_require 'adapters/jdbc/sqlserver'
|
|
61
|
+
db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
|
|
62
|
+
db.dataset_class = Sequel::JDBC::SQLServer::Dataset
|
|
63
|
+
db.send(:set_mssql_unicode_strings)
|
|
58
64
|
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
|
59
65
|
end,
|
|
60
66
|
:jtds=>proc do |db|
|
|
61
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
62
|
-
db.extend(Sequel::JDBC::
|
|
67
|
+
Sequel.ts_require 'adapters/jdbc/jtds'
|
|
68
|
+
db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
|
|
69
|
+
db.dataset_class = Sequel::JDBC::JTDS::Dataset
|
|
70
|
+
db.send(:set_mssql_unicode_strings)
|
|
63
71
|
JDBC.load_gem('jtds')
|
|
64
72
|
Java::net.sourceforge.jtds.jdbc.Driver
|
|
65
73
|
end,
|
|
66
74
|
:h2=>proc do |db|
|
|
67
75
|
Sequel.ts_require 'adapters/jdbc/h2'
|
|
68
76
|
db.extend(Sequel::JDBC::H2::DatabaseMethods)
|
|
77
|
+
db.dataset_class = Sequel::JDBC::H2::Dataset
|
|
69
78
|
JDBC.load_gem('h2')
|
|
70
79
|
org.h2.Driver
|
|
71
80
|
end,
|
|
81
|
+
:hsqldb=>proc do |db|
|
|
82
|
+
Sequel.ts_require 'adapters/jdbc/hsqldb'
|
|
83
|
+
db.extend(Sequel::JDBC::HSQLDB::DatabaseMethods)
|
|
84
|
+
db.dataset_class = Sequel::JDBC::HSQLDB::Dataset
|
|
85
|
+
# Current gem is 1.8.1.3, but Sequel supports 2.2.5
|
|
86
|
+
org.hsqldb.jdbcDriver
|
|
87
|
+
end,
|
|
88
|
+
:derby=>proc do |db|
|
|
89
|
+
Sequel.ts_require 'adapters/jdbc/derby'
|
|
90
|
+
db.extend(Sequel::JDBC::Derby::DatabaseMethods)
|
|
91
|
+
db.dataset_class = Sequel::JDBC::Derby::Dataset
|
|
92
|
+
JDBC.load_gem('derby')
|
|
93
|
+
org.apache.derby.jdbc.EmbeddedDriver
|
|
94
|
+
end,
|
|
72
95
|
:as400=>proc do |db|
|
|
73
96
|
Sequel.ts_require 'adapters/jdbc/as400'
|
|
74
97
|
db.extend(Sequel::JDBC::AS400::DatabaseMethods)
|
|
98
|
+
db.dataset_class = Sequel::JDBC::AS400::Dataset
|
|
75
99
|
com.ibm.as400.access.AS400JDBCDriver
|
|
100
|
+
end,
|
|
101
|
+
:"informix-sqli"=>proc do |db|
|
|
102
|
+
Sequel.ts_require 'adapters/jdbc/informix'
|
|
103
|
+
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
|
104
|
+
db.dataset_class = Sequel::JDBC::Informix::Dataset
|
|
105
|
+
com.informix.jdbc.IfxDriver
|
|
106
|
+
end,
|
|
107
|
+
:db2=>proc do |db|
|
|
108
|
+
Sequel.ts_require 'adapters/jdbc/db2'
|
|
109
|
+
db.extend(Sequel::JDBC::DB2::DatabaseMethods)
|
|
110
|
+
db.dataset_class = Sequel::JDBC::DB2::Dataset
|
|
111
|
+
com.ibm.db2.jcc.DB2Driver
|
|
112
|
+
end,
|
|
113
|
+
:firebirdsql=>proc do |db|
|
|
114
|
+
Sequel.ts_require 'adapters/jdbc/firebird'
|
|
115
|
+
db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
|
|
116
|
+
db.dataset_class = Sequel::JDBC::Firebird::Dataset
|
|
117
|
+
org.firebirdsql.jdbc.FBDriver
|
|
76
118
|
end
|
|
77
119
|
}
|
|
78
120
|
|
|
@@ -101,7 +143,7 @@ module Sequel
|
|
|
101
143
|
# True by default, can be set to false to roughly double performance when
|
|
102
144
|
# fetching rows.
|
|
103
145
|
attr_accessor :convert_types
|
|
104
|
-
|
|
146
|
+
|
|
105
147
|
# Call the DATABASE_SETUP proc directly after initialization,
|
|
106
148
|
# so the object always uses sub adapter specific code. Also,
|
|
107
149
|
# raise an error immediately if the connection doesn't have a
|
|
@@ -158,6 +200,7 @@ module Sequel
|
|
|
158
200
|
args = [uri(opts)]
|
|
159
201
|
args.concat([opts[:user], opts[:password]]) if opts[:user] && opts[:password]
|
|
160
202
|
begin
|
|
203
|
+
JavaSQL::DriverManager.setLoginTimeout(opts[:login_timeout]) if opts[:login_timeout]
|
|
161
204
|
JavaSQL::DriverManager.getConnection(*args)
|
|
162
205
|
rescue => e
|
|
163
206
|
raise e unless driver
|
|
@@ -180,11 +223,6 @@ module Sequel
|
|
|
180
223
|
setup_connection(conn)
|
|
181
224
|
end
|
|
182
225
|
|
|
183
|
-
# Return instances of JDBC::Dataset with the given opts.
|
|
184
|
-
def dataset(opts = nil)
|
|
185
|
-
JDBC::Dataset.new(self, opts)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
226
|
# Execute the given SQL. If a block is given, if should be a SELECT
|
|
189
227
|
# statement or something else that returns rows.
|
|
190
228
|
def execute(sql, opts={}, &block)
|
|
@@ -246,12 +284,14 @@ module Sequel
|
|
|
246
284
|
indexes
|
|
247
285
|
end
|
|
248
286
|
|
|
287
|
+
# Whether or not JNDI is being used for this connection.
|
|
288
|
+
def jndi?
|
|
289
|
+
!!(uri =~ JNDI_URI_REGEXP)
|
|
290
|
+
end
|
|
291
|
+
|
|
249
292
|
# All tables in this database
|
|
250
293
|
def tables(opts={})
|
|
251
|
-
|
|
252
|
-
m = output_identifier_meth
|
|
253
|
-
metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
|
254
|
-
ts
|
|
294
|
+
get_tables('TABLE', opts)
|
|
255
295
|
end
|
|
256
296
|
|
|
257
297
|
# The uri for this connection. You can specify the uri
|
|
@@ -264,11 +304,11 @@ module Sequel
|
|
|
264
304
|
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
|
265
305
|
end
|
|
266
306
|
|
|
267
|
-
#
|
|
268
|
-
def
|
|
269
|
-
|
|
307
|
+
# All views in this database
|
|
308
|
+
def views(opts={})
|
|
309
|
+
get_tables('VIEW', opts)
|
|
270
310
|
end
|
|
271
|
-
|
|
311
|
+
|
|
272
312
|
private
|
|
273
313
|
|
|
274
314
|
# Close given adapter connections
|
|
@@ -276,6 +316,12 @@ module Sequel
|
|
|
276
316
|
c.close
|
|
277
317
|
end
|
|
278
318
|
|
|
319
|
+
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
|
320
|
+
def disconnect_error?(exception, opts)
|
|
321
|
+
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
|
322
|
+
super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
|
|
323
|
+
end
|
|
324
|
+
|
|
279
325
|
# Execute the prepared statement. If the provided name is a
|
|
280
326
|
# dataset, use that as the prepared statement, otherwise use
|
|
281
327
|
# it as a key to look it up in the prepared_statements hash.
|
|
@@ -325,6 +371,12 @@ module Sequel
|
|
|
325
371
|
end
|
|
326
372
|
end
|
|
327
373
|
|
|
374
|
+
# Gets the connection from JNDI.
|
|
375
|
+
def get_connection_from_jndi
|
|
376
|
+
jndi_name = JNDI_URI_REGEXP.match(uri)[1]
|
|
377
|
+
JavaxNaming::InitialContext.new.lookup(jndi_name).connection
|
|
378
|
+
end
|
|
379
|
+
|
|
328
380
|
# Gets the JDBC connection uri from the JNDI resource.
|
|
329
381
|
def get_uri_from_jndi
|
|
330
382
|
conn = get_connection_from_jndi
|
|
@@ -333,12 +385,14 @@ module Sequel
|
|
|
333
385
|
conn.close if conn
|
|
334
386
|
end
|
|
335
387
|
|
|
336
|
-
#
|
|
337
|
-
def
|
|
338
|
-
|
|
339
|
-
|
|
388
|
+
# Backbone of the tables and views support.
|
|
389
|
+
def get_tables(type, opts)
|
|
390
|
+
ts = []
|
|
391
|
+
m = output_identifier_meth
|
|
392
|
+
metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
|
393
|
+
ts
|
|
340
394
|
end
|
|
341
|
-
|
|
395
|
+
|
|
342
396
|
# Support Date objects used in bound variables
|
|
343
397
|
def java_sql_date(date)
|
|
344
398
|
java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
|
|
@@ -383,12 +437,6 @@ module Sequel
|
|
|
383
437
|
end
|
|
384
438
|
end
|
|
385
439
|
|
|
386
|
-
# Treat SQLExceptions with a "Connection Error" SQLState as disconnects
|
|
387
|
-
def raise_error(exception, opts={})
|
|
388
|
-
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
|
389
|
-
super(exception, {:disconnect => cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/}.merge(opts))
|
|
390
|
-
end
|
|
391
|
-
|
|
392
440
|
# Java being java, you need to specify the type of each argument
|
|
393
441
|
# for the prepared statement, and bind it individually. This
|
|
394
442
|
# guesses which JDBC method to use, and hopefully JRuby will convert
|
|
@@ -405,8 +453,8 @@ module Sequel
|
|
|
405
453
|
cps.setDouble(i, arg)
|
|
406
454
|
when TrueClass, FalseClass
|
|
407
455
|
cps.setBoolean(i, arg)
|
|
408
|
-
when
|
|
409
|
-
cps.
|
|
456
|
+
when NilClass
|
|
457
|
+
cps.setString(i, nil)
|
|
410
458
|
when DateTime
|
|
411
459
|
cps.setTimestamp(i, java_sql_datetime(arg))
|
|
412
460
|
when Date
|
|
@@ -435,8 +483,8 @@ module Sequel
|
|
|
435
483
|
|
|
436
484
|
# Parse the table schema for the given table.
|
|
437
485
|
def schema_parse_table(table, opts={})
|
|
438
|
-
m = output_identifier_meth
|
|
439
|
-
im = input_identifier_meth
|
|
486
|
+
m = output_identifier_meth(opts[:dataset])
|
|
487
|
+
im = input_identifier_meth(opts[:dataset])
|
|
440
488
|
ds = dataset
|
|
441
489
|
schema, table = schema_and_table(table)
|
|
442
490
|
schema ||= opts[:schema]
|
|
@@ -444,9 +492,11 @@ module Sequel
|
|
|
444
492
|
table = im.call(table)
|
|
445
493
|
pks, ts = [], []
|
|
446
494
|
metadata(:getPrimaryKeys, nil, schema, table) do |h|
|
|
495
|
+
next if schema_parse_table_skip?(h, schema)
|
|
447
496
|
pks << h[:column_name]
|
|
448
497
|
end
|
|
449
498
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
|
499
|
+
next if schema_parse_table_skip?(h, schema)
|
|
450
500
|
s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
|
|
451
501
|
if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
|
|
452
502
|
s[:type] = :integer
|
|
@@ -456,6 +506,12 @@ module Sequel
|
|
|
456
506
|
ts
|
|
457
507
|
end
|
|
458
508
|
|
|
509
|
+
# Whether schema_parse_table should skip the given row when
|
|
510
|
+
# parsing the schema.
|
|
511
|
+
def schema_parse_table_skip?(h, schema)
|
|
512
|
+
h[:table_schem] == 'INFORMATION_SCHEMA'
|
|
513
|
+
end
|
|
514
|
+
|
|
459
515
|
# Yield a new statement object, and ensure that it is closed before returning.
|
|
460
516
|
def statement(conn)
|
|
461
517
|
stmt = conn.createStatement
|
|
@@ -476,6 +532,8 @@ module Sequel
|
|
|
476
532
|
|
|
477
533
|
class Dataset < Sequel::Dataset
|
|
478
534
|
include StoredProcedures
|
|
535
|
+
|
|
536
|
+
Database::DatasetClass = self
|
|
479
537
|
|
|
480
538
|
# Use JDBC PreparedStatements instead of emulated ones. Statements
|
|
481
539
|
# created using #prepare are cached at the connection level to allow
|
|
@@ -489,17 +547,17 @@ module Sequel
|
|
|
489
547
|
# Execute the prepared SQL using the stored type and
|
|
490
548
|
# arguments derived from the hash passed to call.
|
|
491
549
|
def execute(sql, opts={}, &block)
|
|
492
|
-
super(self, {:arguments=>bind_arguments
|
|
550
|
+
super(self, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
493
551
|
end
|
|
494
552
|
|
|
495
553
|
# Same as execute, explicit due to intricacies of alias and super.
|
|
496
554
|
def execute_dui(sql, opts={}, &block)
|
|
497
|
-
super(self, {:arguments=>bind_arguments
|
|
555
|
+
super(self, {:arguments=>bind_arguments}.merge(opts), &block)
|
|
498
556
|
end
|
|
499
557
|
|
|
500
558
|
# Same as execute, explicit due to intricacies of alias and super.
|
|
501
559
|
def execute_insert(sql, opts={}, &block)
|
|
502
|
-
super(self, {:arguments=>bind_arguments, :type
|
|
560
|
+
super(self, {:arguments=>bind_arguments, :type=>:insert}.merge(opts), &block)
|
|
503
561
|
end
|
|
504
562
|
end
|
|
505
563
|
|
|
@@ -512,17 +570,17 @@ module Sequel
|
|
|
512
570
|
|
|
513
571
|
# Execute the database stored procedure with the stored arguments.
|
|
514
572
|
def execute(sql, opts={}, &block)
|
|
515
|
-
super(@sproc_name, {:args=>@sproc_args, :sproc=>true
|
|
573
|
+
super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
|
|
516
574
|
end
|
|
517
575
|
|
|
518
576
|
# Same as execute, explicit due to intricacies of alias and super.
|
|
519
577
|
def execute_dui(sql, opts={}, &block)
|
|
520
|
-
super(@sproc_name, {:args=>@sproc_args, :sproc=>true
|
|
578
|
+
super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
|
|
521
579
|
end
|
|
522
580
|
|
|
523
581
|
# Same as execute, explicit due to intricacies of alias and super.
|
|
524
582
|
def execute_insert(sql, opts={}, &block)
|
|
525
|
-
super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type
|
|
583
|
+
super(@sproc_name, {:args=>@sproc_args, :sproc=>true, :type=>:insert}.merge(opts), &block)
|
|
526
584
|
end
|
|
527
585
|
end
|
|
528
586
|
|
|
@@ -530,13 +588,7 @@ module Sequel
|
|
|
530
588
|
# Uses the database's setting by default, can be set to false to roughly
|
|
531
589
|
# double performance when fetching rows.
|
|
532
590
|
attr_accessor :convert_types
|
|
533
|
-
|
|
534
|
-
# Use the convert_types default setting from the database
|
|
535
|
-
def initialize(db, opts={})
|
|
536
|
-
@convert_types = db.convert_types
|
|
537
|
-
super
|
|
538
|
-
end
|
|
539
|
-
|
|
591
|
+
|
|
540
592
|
# Correctly return rows from the database and return them as hashes.
|
|
541
593
|
def fetch_rows(sql, &block)
|
|
542
594
|
execute(sql){|result| process_result_set(result, &block)}
|
|
@@ -556,26 +608,77 @@ module Sequel
|
|
|
556
608
|
end
|
|
557
609
|
|
|
558
610
|
private
|
|
559
|
-
|
|
560
|
-
#
|
|
561
|
-
|
|
611
|
+
|
|
612
|
+
# Cache Java class constants to speed up lookups
|
|
613
|
+
JAVA_SQL_TIMESTAMP = Java::JavaSQL::Timestamp
|
|
614
|
+
JAVA_SQL_TIME = Java::JavaSQL::Time
|
|
615
|
+
JAVA_SQL_DATE = Java::JavaSQL::Date
|
|
616
|
+
JAVA_SQL_BLOB = Java::JavaSQL::Blob
|
|
617
|
+
JAVA_SQL_CLOB = Java::JavaSQL::Clob
|
|
618
|
+
JAVA_BUFFERED_READER = Java::JavaIo::BufferedReader
|
|
619
|
+
JAVA_BIG_DECIMAL = Java::JavaMath::BigDecimal
|
|
620
|
+
JAVA_BYTE_ARRAY = Java::byte[]
|
|
621
|
+
|
|
622
|
+
# Handle type conversions for common Java types.
|
|
623
|
+
class TYPE_TRANSLATOR
|
|
624
|
+
LF = "\n".freeze
|
|
625
|
+
def time(v) Sequel.string_to_time(v.to_string) end
|
|
626
|
+
def date(v) Date.civil(v.getYear + 1900, v.getMonth + 1, v.getDate) end
|
|
627
|
+
def decimal(v) BigDecimal.new(v.to_string) end
|
|
628
|
+
def byte_array(v) Sequel::SQL::Blob.new(String.from_java_bytes(v)) end
|
|
629
|
+
def blob(v) Sequel::SQL::Blob.new(String.from_java_bytes(v.getBytes(1, v.length))) end
|
|
630
|
+
def clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
|
|
631
|
+
def buffered_reader(v)
|
|
632
|
+
lines = ""
|
|
633
|
+
c = false
|
|
634
|
+
while(line = v.read_line) do
|
|
635
|
+
lines << LF if c
|
|
636
|
+
lines << line
|
|
637
|
+
c ||= true
|
|
638
|
+
end
|
|
639
|
+
lines
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
TYPE_TRANSLATOR_INSTANCE = tt = TYPE_TRANSLATOR.new
|
|
643
|
+
|
|
644
|
+
# Cache type translator methods so that duplicate Method
|
|
645
|
+
# objects are not created.
|
|
646
|
+
DECIMAL_METHOD = tt.method(:decimal)
|
|
647
|
+
TIME_METHOD = tt.method(:time)
|
|
648
|
+
DATE_METHOD = tt.method(:date)
|
|
649
|
+
BUFFERED_READER_METHOD = tt.method(:buffered_reader)
|
|
650
|
+
BYTE_ARRAY_METHOD = tt.method(:byte_array)
|
|
651
|
+
BLOB_METHOD = tt.method(:blob)
|
|
652
|
+
CLOB_METHOD = tt.method(:clob)
|
|
653
|
+
|
|
654
|
+
# Convert the given Java timestamp to an instance of Sequel.datetime_class.
|
|
655
|
+
def convert_type_timestamp(v)
|
|
656
|
+
db.to_application_timestamp([v.getYear + 1900, v.getMonth + 1, v.getDate, v.getHours, v.getMinutes, v.getSeconds, v.getNanos])
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
# Return a callable object that will convert any value of <tt>v</tt>'s
|
|
660
|
+
# class to a ruby object. If no callable object can handle <tt>v</tt>'s
|
|
661
|
+
# class, return false so that the negative lookup is cached.
|
|
662
|
+
def convert_type_proc(v)
|
|
562
663
|
case v
|
|
563
|
-
when
|
|
564
|
-
|
|
565
|
-
when
|
|
566
|
-
|
|
567
|
-
when
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
when
|
|
572
|
-
|
|
573
|
-
when
|
|
574
|
-
|
|
575
|
-
when
|
|
576
|
-
|
|
664
|
+
when JAVA_BIG_DECIMAL
|
|
665
|
+
DECIMAL_METHOD
|
|
666
|
+
when JAVA_SQL_TIMESTAMP
|
|
667
|
+
method(:convert_type_timestamp)
|
|
668
|
+
when JAVA_SQL_TIME
|
|
669
|
+
TIME_METHOD
|
|
670
|
+
when JAVA_SQL_DATE
|
|
671
|
+
DATE_METHOD
|
|
672
|
+
when JAVA_BUFFERED_READER
|
|
673
|
+
BUFFERED_READER_METHOD
|
|
674
|
+
when JAVA_BYTE_ARRAY
|
|
675
|
+
BYTE_ARRAY_METHOD
|
|
676
|
+
when JAVA_SQL_BLOB
|
|
677
|
+
BLOB_METHOD
|
|
678
|
+
when JAVA_SQL_CLOB
|
|
679
|
+
CLOB_METHOD
|
|
577
680
|
else
|
|
578
|
-
|
|
681
|
+
false
|
|
579
682
|
end
|
|
580
683
|
end
|
|
581
684
|
|
|
@@ -586,32 +689,82 @@ module Sequel
|
|
|
586
689
|
|
|
587
690
|
# Split out from fetch rows to allow processing of JDBC result sets
|
|
588
691
|
# that don't come from issuing an SQL string.
|
|
589
|
-
def process_result_set(result)
|
|
692
|
+
def process_result_set(result, &block)
|
|
590
693
|
# get column names
|
|
591
694
|
meta = result.getMetaData
|
|
592
695
|
cols = []
|
|
593
696
|
i = 0
|
|
594
697
|
meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
698
|
+
columns = cols.map{|c| c.at(0)}
|
|
699
|
+
if opts[:offset] && offset_returns_row_number_column?
|
|
700
|
+
rn = row_number_column
|
|
701
|
+
columns.delete(rn)
|
|
702
|
+
end
|
|
703
|
+
@columns = columns
|
|
704
|
+
ct = @convert_types
|
|
705
|
+
if (ct.nil? ? db.convert_types : ct)
|
|
706
|
+
cols.each{|c| c << nil}
|
|
707
|
+
process_result_set_convert(cols, result, rn, &block)
|
|
708
|
+
else
|
|
709
|
+
process_result_set_no_convert(cols, result, rn, &block)
|
|
710
|
+
end
|
|
711
|
+
ensure
|
|
712
|
+
result.close
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
# Use conversion procs to convert data retrieved
|
|
716
|
+
# from the database. This has been optimized, the algorithm it uses
|
|
717
|
+
# is roughly, for each column value in each row:
|
|
718
|
+
# * check if the value is truthy (not false/nil)
|
|
719
|
+
# * if not truthy, return object
|
|
720
|
+
# * otherwise, see if a conversion method exists for
|
|
721
|
+
# the column. All columns start with a nil conversion proc,
|
|
722
|
+
# since unlike other adapters, Sequel doesn't get the type of
|
|
723
|
+
# the column when parsing the column metadata.
|
|
724
|
+
# * if a conversion proc is not false/nil, call it with the object
|
|
725
|
+
# and return the result.
|
|
726
|
+
# * if a conversion proc has already been looked up and doesn't
|
|
727
|
+
# exist (false value), return object.
|
|
728
|
+
# * if a conversion proc hasn't been looked up yet (nil value),
|
|
729
|
+
# call convert_type_proc to get the conversion method. Cache
|
|
730
|
+
# the result of as the column's conversion proc to speed up
|
|
731
|
+
# later processing. If the conversion proc exists, call it
|
|
732
|
+
# and return the result, otherwise, return the object.
|
|
733
|
+
def process_result_set_convert(cols, result, rn)
|
|
598
734
|
while result.next
|
|
599
735
|
row = {}
|
|
600
|
-
cols.each do |n, i|
|
|
601
|
-
|
|
736
|
+
cols.each do |n, i, p|
|
|
737
|
+
v = result.getObject(i)
|
|
738
|
+
row[n] = if v
|
|
739
|
+
if p
|
|
740
|
+
p.call(v)
|
|
741
|
+
elsif p.nil?
|
|
742
|
+
cols[i-1][2] = p = convert_type_proc(v)
|
|
743
|
+
if p
|
|
744
|
+
p.call(v)
|
|
745
|
+
else
|
|
746
|
+
v
|
|
747
|
+
end
|
|
748
|
+
else
|
|
749
|
+
v
|
|
750
|
+
end
|
|
751
|
+
else
|
|
752
|
+
v
|
|
753
|
+
end
|
|
602
754
|
end
|
|
755
|
+
row.delete(rn) if rn
|
|
603
756
|
yield row
|
|
604
757
|
end
|
|
605
758
|
end
|
|
606
759
|
|
|
607
|
-
#
|
|
608
|
-
#
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
760
|
+
# Yield rows without calling any conversion procs. This
|
|
761
|
+
# may yield Java values and not ruby values.
|
|
762
|
+
def process_result_set_no_convert(cols, result, rn)
|
|
763
|
+
while result.next
|
|
764
|
+
row = {}
|
|
765
|
+
cols.each{|n, i| row[n] = result.getObject(i)}
|
|
766
|
+
row.delete(rn) if rn
|
|
767
|
+
yield row
|
|
615
768
|
end
|
|
616
769
|
end
|
|
617
770
|
end
|