sequel 3.10.0 → 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +68 -0
- data/COPYING +1 -1
- data/README.rdoc +87 -27
- data/bin/sequel +2 -4
- data/doc/association_basics.rdoc +1383 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/opening_databases.rdoc +45 -16
- data/doc/querying.rdoc +210 -0
- data/doc/release_notes/3.11.0.txt +254 -0
- data/doc/virtual_rows.rdoc +217 -31
- data/lib/sequel/adapters/ado.rb +28 -12
- data/lib/sequel/adapters/ado/mssql.rb +33 -1
- data/lib/sequel/adapters/amalgalite.rb +13 -8
- data/lib/sequel/adapters/db2.rb +1 -2
- data/lib/sequel/adapters/dbi.rb +7 -4
- data/lib/sequel/adapters/do.rb +14 -15
- data/lib/sequel/adapters/do/postgres.rb +4 -5
- data/lib/sequel/adapters/do/sqlite.rb +9 -0
- data/lib/sequel/adapters/firebird.rb +5 -10
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +111 -49
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +8 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +12 -0
- data/lib/sequel/adapters/mysql.rb +14 -5
- data/lib/sequel/adapters/odbc.rb +2 -4
- data/lib/sequel/adapters/odbc/mssql.rb +2 -4
- data/lib/sequel/adapters/openbase.rb +1 -2
- data/lib/sequel/adapters/oracle.rb +4 -8
- data/lib/sequel/adapters/postgres.rb +4 -11
- data/lib/sequel/adapters/shared/mssql.rb +22 -9
- data/lib/sequel/adapters/shared/mysql.rb +33 -30
- data/lib/sequel/adapters/shared/oracle.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +13 -11
- data/lib/sequel/adapters/shared/sqlite.rb +56 -10
- data/lib/sequel/adapters/sqlite.rb +16 -9
- data/lib/sequel/connection_pool.rb +6 -1
- data/lib/sequel/connection_pool/single.rb +1 -0
- data/lib/sequel/core.rb +6 -1
- data/lib/sequel/database.rb +52 -23
- data/lib/sequel/database/schema_generator.rb +6 -0
- data/lib/sequel/database/schema_methods.rb +5 -5
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +4 -190
- data/lib/sequel/dataset/actions.rb +323 -1
- data/lib/sequel/dataset/features.rb +18 -2
- data/lib/sequel/dataset/graph.rb +7 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +272 -6
- data/lib/sequel/dataset/sql.rb +186 -394
- data/lib/sequel/model.rb +4 -2
- data/lib/sequel/model/associations.rb +31 -14
- data/lib/sequel/model/base.rb +32 -13
- data/lib/sequel/model/exceptions.rb +8 -4
- data/lib/sequel/model/plugins.rb +3 -13
- data/lib/sequel/plugins/active_model.rb +26 -7
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +25 -9
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +26 -0
- data/spec/adapters/mysql_spec.rb +33 -4
- data/spec/adapters/postgres_spec.rb +24 -1
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +28 -0
- data/spec/core/connection_pool_spec.rb +17 -5
- data/spec/core/database_spec.rb +101 -1
- data/spec/core/dataset_spec.rb +42 -4
- data/spec/core/schema_spec.rb +13 -0
- data/spec/extensions/active_model_spec.rb +34 -11
- data/spec/extensions/caching_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/spec_helper.rb +2 -0
- data/spec/integration/dataset_test.rb +12 -1
- data/spec/integration/model_test.rb +12 -0
- data/spec/integration/plugin_test.rb +61 -1
- data/spec/integration/schema_test.rb +14 -3
- data/spec/model/base_spec.rb +27 -0
- data/spec/model/plugins_spec.rb +0 -22
- data/spec/model/record_spec.rb +32 -1
- data/spec/model/spec_helper.rb +2 -0
- metadata +14 -3
- data/lib/sequel/dataset/convenience.rb +0 -326
data/lib/sequel/adapters/dbi.rb
CHANGED
@@ -26,6 +26,11 @@ module Sequel
|
|
26
26
|
when 'mssql'
|
27
27
|
Sequel.ts_require 'adapters/shared/mssql'
|
28
28
|
extend Sequel::MSSQL::DatabaseMethods
|
29
|
+
def self.dataset(*args)
|
30
|
+
ds = super
|
31
|
+
ds.extend Sequel::MSSQL::DatasetMethods
|
32
|
+
ds
|
33
|
+
end
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
@@ -63,17 +68,15 @@ module Sequel
|
|
63
68
|
end
|
64
69
|
|
65
70
|
def execute(sql, opts={})
|
66
|
-
log_info(sql)
|
67
71
|
synchronize(opts[:server]) do |conn|
|
68
|
-
r = conn.execute(sql)
|
72
|
+
r = log_yield(sql){conn.execute(sql)}
|
69
73
|
yield(r) if block_given?
|
70
74
|
r
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
74
78
|
def do(sql, opts={})
|
75
|
-
|
76
|
-
synchronize(opts[:server]){|conn| conn.do(sql)}
|
79
|
+
synchronize(opts[:server]){|conn| log_yield(sql){conn.do(sql)}}
|
77
80
|
end
|
78
81
|
alias_method :execute_dui, :do
|
79
82
|
|
data/lib/sequel/adapters/do.rb
CHANGED
@@ -66,11 +66,10 @@ module Sequel
|
|
66
66
|
# Otherwise, the return value is the insert id if opts[:type] is :insert,
|
67
67
|
# or the number of affected rows, otherwise.
|
68
68
|
def execute(sql, opts={})
|
69
|
-
log_info(sql)
|
70
69
|
synchronize(opts[:server]) do |conn|
|
71
70
|
begin
|
72
71
|
command = conn.create_command(sql)
|
73
|
-
res = block_given? ? command.execute_reader : command.execute_non_query
|
72
|
+
res = log_yield(sql){block_given? ? command.execute_reader : command.execute_non_query}
|
74
73
|
rescue ::DataObjects::Error => e
|
75
74
|
raise_error(e)
|
76
75
|
end
|
@@ -121,21 +120,23 @@ module Sequel
|
|
121
120
|
# substitute our own.
|
122
121
|
def begin_transaction(conn)
|
123
122
|
return super if supports_savepoints?
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
123
|
+
log_yield(TRANSACTION_BEGIN) do
|
124
|
+
t = ::DataObjects::Transaction.create_for_uri(uri)
|
125
|
+
t.instance_variable_get(:@connection).close
|
126
|
+
t.instance_variable_set(:@connection, conn)
|
127
|
+
t.begin
|
128
|
+
t
|
129
|
+
end
|
130
130
|
end
|
131
131
|
|
132
132
|
# DataObjects requires transactions be prepared before being
|
133
133
|
# committed, so we do that.
|
134
134
|
def commit_transaction(t)
|
135
135
|
return super if supports_savepoints?
|
136
|
-
|
137
|
-
|
138
|
-
|
136
|
+
log_yield(TRANSACTION_ROLLBACK) do
|
137
|
+
t.prepare
|
138
|
+
t.commit
|
139
|
+
end
|
139
140
|
end
|
140
141
|
|
141
142
|
# Method to call on a statement object to execute SQL that does
|
@@ -151,15 +152,13 @@ module Sequel
|
|
151
152
|
|
152
153
|
# Execute SQL on the connection by creating a command first
|
153
154
|
def log_connection_execute(conn, sql)
|
154
|
-
|
155
|
-
conn.create_command(sql).execute_non_query
|
155
|
+
log_yield(sql){conn.create_command(sql).execute_non_query}
|
156
156
|
end
|
157
157
|
|
158
158
|
# We use the transactions rollback method to rollback.
|
159
159
|
def rollback_transaction(t)
|
160
160
|
return super if supports_savepoints?
|
161
|
-
|
162
|
-
t.rollback
|
161
|
+
log_yield(TRANSACTION_COMMIT){t.rollback}
|
163
162
|
end
|
164
163
|
|
165
164
|
# Allow extending the given connection when it is first created.
|
@@ -19,13 +19,12 @@ module Sequel
|
|
19
19
|
begin
|
20
20
|
if block_given?
|
21
21
|
begin
|
22
|
-
reader = command.execute_reader
|
23
|
-
yield(reader)
|
22
|
+
yield(reader = @db.log_yield(sql){command.execute_reader})
|
24
23
|
ensure
|
25
24
|
reader.close if reader
|
26
25
|
end
|
27
26
|
else
|
28
|
-
command.execute_non_query
|
27
|
+
@db.log_yield(sql){command.execute_non_query}
|
29
28
|
end
|
30
29
|
rescue ::DataObjects::Error => e
|
31
30
|
raise_error(e)
|
@@ -64,9 +63,9 @@ module Sequel
|
|
64
63
|
# Run the INSERT sql on the database and return the primary key
|
65
64
|
# for the record.
|
66
65
|
def execute_insert(sql, opts={})
|
67
|
-
log_info(sql)
|
68
66
|
synchronize(opts[:server]) do |conn|
|
69
|
-
conn.create_command(sql)
|
67
|
+
com = conn.create_command(sql)
|
68
|
+
log_yield(sql){com.execute_non_query}
|
70
69
|
insert_result(conn, opts[:table], opts[:values])
|
71
70
|
end
|
72
71
|
end
|
@@ -20,6 +20,15 @@ module Sequel
|
|
20
20
|
o = super
|
21
21
|
uri == 'sqlite3::memory:' ? o.merge(:max_connections=>1) : o
|
22
22
|
end
|
23
|
+
|
24
|
+
# Execute the connection pragmas on the connection
|
25
|
+
def setup_connection(conn)
|
26
|
+
connection_pragmas.each do |s|
|
27
|
+
com = conn.create_command(s)
|
28
|
+
log_yield(s){com.execute_non_query}
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
# Dataset class for SQLite datasets accessed via DataObjects.
|
@@ -43,15 +43,13 @@ module Sequel
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def execute(sql, opts={})
|
46
|
-
log_info(sql)
|
47
46
|
begin
|
48
47
|
synchronize(opts[:server]) do |conn|
|
49
|
-
r = conn.execute(sql)
|
48
|
+
r = log_yield(sql){conn.execute(sql)}
|
50
49
|
yield(r) if block_given?
|
51
50
|
r
|
52
51
|
end
|
53
52
|
rescue => e
|
54
|
-
log_info(e.message)
|
55
53
|
raise_error(e, :classes=>[Fb::Error])
|
56
54
|
end
|
57
55
|
end
|
@@ -105,14 +103,12 @@ module Sequel
|
|
105
103
|
end
|
106
104
|
|
107
105
|
def begin_transaction(conn)
|
108
|
-
|
109
|
-
conn.transaction
|
106
|
+
log_yield(TRANSACTION_BEGIN){conn.transaction}
|
110
107
|
conn
|
111
108
|
end
|
112
109
|
|
113
110
|
def commit_transaction(conn)
|
114
|
-
|
115
|
-
conn.commit
|
111
|
+
log_yield(TRANSACTION_COMMIT){conn.commit}
|
116
112
|
end
|
117
113
|
|
118
114
|
def create_sequence_sql(name, opts={})
|
@@ -160,7 +156,7 @@ module Sequel
|
|
160
156
|
events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
|
161
157
|
whence = opts[:after] ? 'AFTER' : 'BEFORE'
|
162
158
|
inactive = opts[:inactive] ? 'INACTIVE' : 'ACTIVE'
|
163
|
-
position = opts
|
159
|
+
position = opts.fetch(:position, 0)
|
164
160
|
sql = <<-end_sql
|
165
161
|
CREATE TRIGGER #{quote_identifier(name)} for #{quote_identifier(table)}
|
166
162
|
#{inactive} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} position #{position}
|
@@ -187,8 +183,7 @@ module Sequel
|
|
187
183
|
end
|
188
184
|
|
189
185
|
def rollback_transaction(conn)
|
190
|
-
|
191
|
-
conn.rollback
|
186
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
192
187
|
end
|
193
188
|
|
194
189
|
def type_literal_generic_string(column)
|
@@ -18,14 +18,12 @@ module Sequel
|
|
18
18
|
|
19
19
|
# Returns number of rows affected
|
20
20
|
def execute_dui(sql, opts={})
|
21
|
-
|
22
|
-
synchronize(opts[:server]){|c| c.immediate(sql)}
|
21
|
+
synchronize(opts[:server]){|c| log_yield(sql){c.immediate(sql)}}
|
23
22
|
end
|
24
23
|
alias_method :do, :execute_dui
|
25
24
|
|
26
25
|
def execute(sql, opts={})
|
27
|
-
|
28
|
-
synchronize(opts[:server]){|c| yield c.cursor(sql)}
|
26
|
+
synchronize(opts[:server]){|c| yield log_yield(sql){c.cursor(sql)}}
|
29
27
|
end
|
30
28
|
alias_method :query, :execute
|
31
29
|
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -3,24 +3,6 @@ Sequel.require 'adapters/utils/stored_procedures'
|
|
3
3
|
|
4
4
|
module Sequel
|
5
5
|
# Houses Sequel's JDBC support when running on JRuby.
|
6
|
-
# Support for individual database types is done using sub adapters.
|
7
|
-
# PostgreSQL, MySQL, SQLite, Oracle, and MSSQL all have relatively good support,
|
8
|
-
# close the the level supported by the native adapter.
|
9
|
-
# PostgreSQL, MySQL, SQLite can load necessary support using
|
10
|
-
# the jdbc-* gem, if it is installed, though they will work if you
|
11
|
-
# have the correct .jar in your CLASSPATH. Oracle and MSSQL should
|
12
|
-
# load the necessary support if you have the .jar in your CLASSPATH.
|
13
|
-
# For all other databases, the Java class should be loaded manually
|
14
|
-
# before calling Sequel.connect.
|
15
|
-
#
|
16
|
-
# Note that when using a JDBC adapter, the best way to use Sequel
|
17
|
-
# is via Sequel.connect, NOT Sequel.jdbc. Use the JDBC connection
|
18
|
-
# string when connecting, which will be in a different format than
|
19
|
-
# the native connection string. The connection string should start
|
20
|
-
# with 'jdbc:'. For PostgreSQL, use 'jdbc:postgresql:', and for
|
21
|
-
# SQLite you do not need 2 preceding slashes for the database name
|
22
|
-
# (use no preceding slashes for a relative path, and one preceding
|
23
|
-
# slash for an absolute path).
|
24
6
|
module JDBC
|
25
7
|
# Make it accesing the java.lang hierarchy more ruby friendly.
|
26
8
|
module JavaLang
|
@@ -31,6 +13,19 @@ module Sequel
|
|
31
13
|
module JavaSQL
|
32
14
|
include_package 'java.sql'
|
33
15
|
end
|
16
|
+
|
17
|
+
# Make it accesing the javax.naming hierarchy more ruby friendly.
|
18
|
+
module JavaxNaming
|
19
|
+
include_package 'javax.naming'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Used to identify a jndi connection and to extract the jndi
|
23
|
+
# resource name.
|
24
|
+
JNDI_URI_REGEXP = /\Ajdbc:jndi:(.+)/
|
25
|
+
|
26
|
+
# The types to check for 0 scale to transform :decimal types
|
27
|
+
# to :integer.
|
28
|
+
DECIMAL_TYPE_RE = /number|numeric|decimal/io
|
34
29
|
|
35
30
|
# Contains procs keyed on sub adapter type that extend the
|
36
31
|
# given database object so it supports the correct database type.
|
@@ -62,6 +57,12 @@ module Sequel
|
|
62
57
|
db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
|
63
58
|
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
64
59
|
end,
|
60
|
+
:jtds=>proc do |db|
|
61
|
+
Sequel.ts_require 'adapters/jdbc/mssql'
|
62
|
+
db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
|
63
|
+
JDBC.load_gem('jtds')
|
64
|
+
Java::net.sourceforge.jtds.jdbc.Driver
|
65
|
+
end,
|
65
66
|
:h2=>proc do |db|
|
66
67
|
Sequel.ts_require 'adapters/jdbc/h2'
|
67
68
|
db.extend(Sequel::JDBC::H2::DatabaseMethods)
|
@@ -93,6 +94,9 @@ module Sequel
|
|
93
94
|
# The type of database we are connecting to
|
94
95
|
attr_reader :database_type
|
95
96
|
|
97
|
+
# The Java database driver we are using
|
98
|
+
attr_reader :driver
|
99
|
+
|
96
100
|
# Whether to convert some Java types to ruby types when retrieving rows.
|
97
101
|
# True by default, can be set to false to roughly double performance when
|
98
102
|
# fetching rows.
|
@@ -104,11 +108,14 @@ module Sequel
|
|
104
108
|
# uri, since JDBC requires one.
|
105
109
|
def initialize(opts)
|
106
110
|
super
|
107
|
-
@convert_types = @opts.
|
111
|
+
@convert_types = typecast_value_boolean(@opts.fetch(:convert_types, true))
|
108
112
|
raise(Error, "No connection string specified") unless uri
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
|
114
|
+
resolved_uri = jndi? ? get_uri_from_jndi : uri
|
115
|
+
|
116
|
+
if match = /\Ajdbc:([^:]+)/.match(resolved_uri) and prok = DATABASE_SETUP[match[1].to_sym]
|
117
|
+
@driver = prok.call(self)
|
118
|
+
end
|
112
119
|
end
|
113
120
|
|
114
121
|
# Execute the given stored procedure with the give name. If a block is
|
@@ -124,14 +131,14 @@ module Sequel
|
|
124
131
|
|
125
132
|
begin
|
126
133
|
if block_given?
|
127
|
-
yield cps.executeQuery
|
134
|
+
yield log_yield(sql){cps.executeQuery}
|
128
135
|
else
|
129
136
|
case opts[:type]
|
130
137
|
when :insert
|
131
|
-
cps.executeUpdate
|
138
|
+
log_yield(sql){cps.executeUpdate}
|
132
139
|
last_insert_id(conn, opts)
|
133
140
|
else
|
134
|
-
cps.executeUpdate
|
141
|
+
log_yield(sql){cps.executeUpdate}
|
135
142
|
end
|
136
143
|
end
|
137
144
|
rescue NativeException, JavaSQL::SQLException => e
|
@@ -141,12 +148,29 @@ module Sequel
|
|
141
148
|
end
|
142
149
|
end
|
143
150
|
end
|
144
|
-
|
151
|
+
|
145
152
|
# Connect to the database using JavaSQL::DriverManager.getConnection.
|
146
153
|
def connect(server)
|
147
|
-
|
148
|
-
|
149
|
-
|
154
|
+
opts = server_opts(server)
|
155
|
+
conn = if jndi?
|
156
|
+
get_connection_from_jndi
|
157
|
+
else
|
158
|
+
args = [uri(opts)]
|
159
|
+
args.concat([opts[:user], opts[:password]]) if opts[:user] && opts[:password]
|
160
|
+
begin
|
161
|
+
JavaSQL::DriverManager.getConnection(*args)
|
162
|
+
rescue
|
163
|
+
# If the DriverManager can't get the connection - use the connect
|
164
|
+
# method of the driver. (This happens under Tomcat for instance)
|
165
|
+
props = java.util.Properties.new
|
166
|
+
if opts && opts[:user] && opts[:password]
|
167
|
+
props.setProperty("user", opts[:user])
|
168
|
+
props.setProperty("password", opts[:password])
|
169
|
+
end
|
170
|
+
driver.new.connect(args[0], props)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
setup_connection(conn)
|
150
174
|
end
|
151
175
|
|
152
176
|
# Return instances of JDBC::Dataset with the given opts.
|
@@ -159,21 +183,26 @@ module Sequel
|
|
159
183
|
def execute(sql, opts={}, &block)
|
160
184
|
return call_sproc(sql, opts, &block) if opts[:sproc]
|
161
185
|
return execute_prepared_statement(sql, opts, &block) if [Symbol, Dataset].any?{|c| sql.is_a?(c)}
|
162
|
-
log_info(sql)
|
163
186
|
synchronize(opts[:server]) do |conn|
|
164
187
|
stmt = conn.createStatement
|
165
188
|
begin
|
166
189
|
if block_given?
|
167
|
-
yield stmt.executeQuery(sql)
|
190
|
+
yield log_yield(sql){stmt.executeQuery(sql)}
|
168
191
|
else
|
169
192
|
case opts[:type]
|
170
193
|
when :ddl
|
171
|
-
stmt.execute(sql)
|
194
|
+
log_yield(sql){stmt.execute(sql)}
|
172
195
|
when :insert
|
173
|
-
|
196
|
+
log_yield(sql) do
|
197
|
+
if requires_return_generated_keys?
|
198
|
+
stmt.executeUpdate(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS)
|
199
|
+
else
|
200
|
+
stmt.executeUpdate(sql)
|
201
|
+
end
|
202
|
+
end
|
174
203
|
last_insert_id(conn, opts.merge(:stmt=>stmt))
|
175
204
|
else
|
176
|
-
stmt.executeUpdate(sql)
|
205
|
+
log_yield(sql){stmt.executeUpdate(sql)}
|
177
206
|
end
|
178
207
|
end
|
179
208
|
rescue NativeException, JavaSQL::SQLException => e
|
@@ -235,9 +264,14 @@ module Sequel
|
|
235
264
|
ur = opts[:uri] || opts[:url] || opts[:database]
|
236
265
|
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
237
266
|
end
|
267
|
+
|
268
|
+
# Whether or not JNDI is being used for this connection.
|
269
|
+
def jndi?
|
270
|
+
!!(uri =~ JNDI_URI_REGEXP)
|
271
|
+
end
|
238
272
|
|
239
273
|
private
|
240
|
-
|
274
|
+
|
241
275
|
# JDBC uses a statement object to execute SQL on the database
|
242
276
|
def begin_transaction(conn)
|
243
277
|
conn = conn.createStatement unless supports_savepoints?
|
@@ -269,29 +303,25 @@ module Sequel
|
|
269
303
|
if name and cps = conn.prepared_statements[name] and cps[0] == sql
|
270
304
|
cps = cps[1]
|
271
305
|
else
|
272
|
-
if cps
|
273
|
-
|
274
|
-
cps[1].close
|
275
|
-
end
|
276
|
-
log_info("Preparing#{" #{name}:" if name} #{sql}")
|
277
|
-
cps = conn.prepareStatement(sql)
|
306
|
+
log_yield("Closing #{name}"){cps[1].close} if cps
|
307
|
+
cps = log_yield("Preparing#{" #{name}:" if name} #{sql}"){conn.prepareStatement(sql)}
|
278
308
|
conn.prepared_statements[name] = [sql, cps] if name
|
279
309
|
end
|
280
310
|
i = 0
|
281
311
|
args.each{|arg| set_ps_arg(cps, arg, i+=1)}
|
282
|
-
|
312
|
+
msg = "Executing#{" #{name}" if name}"
|
283
313
|
begin
|
284
314
|
if block_given?
|
285
|
-
yield cps.executeQuery
|
315
|
+
yield log_yield(msg, args){cps.executeQuery}
|
286
316
|
else
|
287
317
|
case opts[:type]
|
288
318
|
when :ddl
|
289
|
-
cps.execute
|
319
|
+
log_yield(msg, args){cps.execute}
|
290
320
|
when :insert
|
291
|
-
cps.executeUpdate
|
321
|
+
log_yield(msg, args){cps.executeUpdate}
|
292
322
|
last_insert_id(conn, opts.merge(:prepared=>true))
|
293
323
|
else
|
294
|
-
cps.executeUpdate
|
324
|
+
log_yield(msg, args){cps.executeUpdate}
|
295
325
|
end
|
296
326
|
end
|
297
327
|
rescue NativeException, JavaSQL::SQLException => e
|
@@ -301,7 +331,21 @@ module Sequel
|
|
301
331
|
end
|
302
332
|
end
|
303
333
|
end
|
334
|
+
|
335
|
+
# Gets the JDBC connection uri from the JNDI resource.
|
336
|
+
def get_uri_from_jndi
|
337
|
+
conn = get_connection_from_jndi
|
338
|
+
conn.meta_data.url
|
339
|
+
ensure
|
340
|
+
conn.close if conn
|
341
|
+
end
|
304
342
|
|
343
|
+
# Gets the connection from JNDI.
|
344
|
+
def get_connection_from_jndi
|
345
|
+
jndi_name = JNDI_URI_REGEXP.match(uri)[1]
|
346
|
+
JavaxNaming::InitialContext.new.lookup(jndi_name).connection
|
347
|
+
end
|
348
|
+
|
305
349
|
# Support fractional seconds for Time objects used in bound variables
|
306
350
|
def java_sql_timestamp(time)
|
307
351
|
millis = time.to_i * 1000
|
@@ -319,7 +363,14 @@ module Sequel
|
|
319
363
|
|
320
364
|
# Yield the metadata for this database
|
321
365
|
def metadata(*args, &block)
|
322
|
-
synchronize
|
366
|
+
synchronize do |c|
|
367
|
+
result = c.getMetaData.send(*args)
|
368
|
+
begin
|
369
|
+
metadata_dataset.send(:process_result_set, result, &block)
|
370
|
+
ensure
|
371
|
+
result.close
|
372
|
+
end
|
373
|
+
end
|
323
374
|
end
|
324
375
|
|
325
376
|
# Treat SQLExceptions with a "Connection Error" SQLState as disconnects
|
@@ -388,7 +439,11 @@ module Sequel
|
|
388
439
|
pks << h[:column_name]
|
389
440
|
end
|
390
441
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
391
|
-
|
442
|
+
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]}
|
443
|
+
if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
|
444
|
+
s[:type] = :integer
|
445
|
+
end
|
446
|
+
ts << [m.call(h[:column_name]), s]
|
392
447
|
end
|
393
448
|
ts
|
394
449
|
end
|
@@ -397,6 +452,13 @@ module Sequel
|
|
397
452
|
def transaction_statement_object(conn)
|
398
453
|
conn.createStatement
|
399
454
|
end
|
455
|
+
|
456
|
+
# This method determines whether or not to add
|
457
|
+
# Statement.RETURN_GENERATED_KEYS as an argument when inserting rows.
|
458
|
+
# Sub-adapters that require this should override this method.
|
459
|
+
def requires_return_generated_keys?
|
460
|
+
false
|
461
|
+
end
|
400
462
|
end
|
401
463
|
|
402
464
|
class Dataset < Sequel::Dataset
|
@@ -498,7 +560,7 @@ module Sequel
|
|
498
560
|
when Java::byte[]
|
499
561
|
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
500
562
|
when Java::JavaSQL::Blob
|
501
|
-
convert_type(v.getBytes(
|
563
|
+
convert_type(v.getBytes(1, v.length))
|
502
564
|
else
|
503
565
|
v
|
504
566
|
end
|