sequel 3.23.0 → 3.24.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 +64 -0
- data/doc/association_basics.rdoc +43 -5
- data/doc/model_hooks.rdoc +64 -27
- data/doc/prepared_statements.rdoc +8 -4
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.23.0.txt +1 -1
- data/doc/release_notes/3.24.0.txt +420 -0
- data/lib/sequel/adapters/db2.rb +8 -1
- data/lib/sequel/adapters/firebird.rb +25 -9
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc.rb +34 -17
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/postgres.rb +30 -1
- data/lib/sequel/adapters/shared/access.rb +10 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +82 -8
- data/lib/sequel/adapters/shared/mysql.rb +25 -7
- data/lib/sequel/adapters/shared/postgres.rb +39 -6
- data/lib/sequel/adapters/shared/sqlite.rb +57 -5
- data/lib/sequel/adapters/sqlite.rb +8 -3
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/misc.rb +6 -0
- data/lib/sequel/database/query.rb +33 -3
- data/lib/sequel/database/schema_methods.rb +6 -2
- data/lib/sequel/dataset/features.rb +6 -0
- data/lib/sequel/dataset/prepared_statements.rb +17 -2
- data/lib/sequel/dataset/query.rb +17 -0
- data/lib/sequel/dataset/sql.rb +2 -53
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model.rb +5 -0
- data/lib/sequel/model/associations.rb +80 -14
- data/lib/sequel/model/base.rb +182 -55
- data/lib/sequel/model/exceptions.rb +3 -1
- data/lib/sequel/plugins/association_pks.rb +6 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/many_through_many.rb +8 -3
- data/lib/sequel/plugins/prepared_statements.rb +140 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/sql.rb +8 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +43 -18
- data/spec/core/connection_pool_spec.rb +56 -77
- data/spec/core/database_spec.rb +25 -0
- data/spec/core/dataset_spec.rb +127 -16
- data/spec/core/expression_filters_spec.rb +13 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/association_pks_spec.rb +7 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/many_through_many_spec.rb +60 -4
- data/spec/extensions/nested_attributes_spec.rb +1 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/integration/associations_test.rb +155 -1
- data/spec/integration/dataset_test.rb +8 -1
- data/spec/integration/plugin_test.rb +119 -0
- data/spec/integration/prepared_statement_test.rb +72 -1
- data/spec/integration/schema_test.rb +66 -8
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/model/associations_spec.rb +349 -8
- data/spec/model/base_spec.rb +59 -0
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/record_spec.rb +24 -0
- metadata +21 -4
data/lib/sequel/adapters/db2.rb
CHANGED
@@ -93,9 +93,16 @@ module Sequel
|
|
93
93
|
def supports_window_functions?
|
94
94
|
true
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
private
|
98
98
|
|
99
|
+
# Modify the sql to limit the number of rows returned
|
100
|
+
def select_limit_sql(sql)
|
101
|
+
if l = @opts[:limit]
|
102
|
+
sql << " FETCH FIRST #{l == 1 ? 'ROW' : "#{literal(l)} ROWS"} ONLY"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
99
106
|
def get_column_info(sth)
|
100
107
|
rc, column_count = SQLNumResultCols(sth)
|
101
108
|
@db.check_error(rc, "Could not get number of result columns")
|
@@ -198,6 +198,7 @@ module Sequel
|
|
198
198
|
NULL = LiteralString.new('NULL').freeze
|
199
199
|
COMMA_SEPARATOR = ', '.freeze
|
200
200
|
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with distinct limit columns from join where group having compounds order')
|
201
|
+
INSERT_CLAUSE_METHODS = clause_methods(:insert, %w'into columns values returning_select')
|
201
202
|
|
202
203
|
# Yield all rows returned by executing the given SQL and converting
|
203
204
|
# the types.
|
@@ -242,19 +243,13 @@ module Sequel
|
|
242
243
|
def insert_select(*values)
|
243
244
|
naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
|
244
245
|
end
|
245
|
-
|
246
|
+
|
246
247
|
def requires_sql_standard_datetimes?
|
247
248
|
true
|
248
249
|
end
|
249
250
|
|
250
|
-
|
251
|
-
|
252
|
-
SELECT_CLAUSE_METHODS
|
253
|
-
end
|
254
|
-
|
255
|
-
def select_limit_sql(sql)
|
256
|
-
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
257
|
-
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
251
|
+
def supports_insert_select?
|
252
|
+
true
|
258
253
|
end
|
259
254
|
|
260
255
|
# Firebird does not support INTERSECT or EXCEPT
|
@@ -264,6 +259,16 @@ module Sequel
|
|
264
259
|
|
265
260
|
private
|
266
261
|
|
262
|
+
def insert_clause_methods
|
263
|
+
INSERT_CLAUSE_METHODS
|
264
|
+
end
|
265
|
+
|
266
|
+
def insert_returning_select_sql(sql)
|
267
|
+
if opts.has_key?(:returning)
|
268
|
+
sql << " RETURNING #{column_list(Array(opts[:returning]))}"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
267
272
|
def hash_row(stmt, row)
|
268
273
|
@columns.inject({}) do |m, c|
|
269
274
|
m[c] = row.shift
|
@@ -278,6 +283,17 @@ module Sequel
|
|
278
283
|
def literal_true
|
279
284
|
BOOL_TRUE
|
280
285
|
end
|
286
|
+
|
287
|
+
# The order of clauses in the SELECT SQL statement
|
288
|
+
def select_clause_methods
|
289
|
+
SELECT_CLAUSE_METHODS
|
290
|
+
end
|
291
|
+
|
292
|
+
def select_limit_sql(sql)
|
293
|
+
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
294
|
+
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
295
|
+
end
|
296
|
+
|
281
297
|
end
|
282
298
|
end
|
283
299
|
end
|
@@ -1,12 +1,13 @@
|
|
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])
|
@@ -35,7 +36,7 @@ module Sequel
|
|
35
36
|
end
|
36
37
|
|
37
38
|
class Dataset < Sequel::Dataset
|
38
|
-
|
39
|
+
include DatasetMethods
|
39
40
|
|
40
41
|
def fetch_rows(sql)
|
41
42
|
execute(sql) do |cursor|
|
@@ -56,22 +57,6 @@ module Sequel
|
|
56
57
|
end
|
57
58
|
self
|
58
59
|
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
60
|
end
|
76
61
|
end
|
77
62
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -53,14 +53,14 @@ module Sequel
|
|
53
53
|
Java::oracle.jdbc.driver.OracleDriver
|
54
54
|
end,
|
55
55
|
:sqlserver=>proc do |db|
|
56
|
-
Sequel.ts_require 'adapters/jdbc/
|
57
|
-
db.extend(Sequel::JDBC::
|
56
|
+
Sequel.ts_require 'adapters/jdbc/sqlserver'
|
57
|
+
db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
|
58
58
|
db.send(:set_mssql_unicode_strings)
|
59
59
|
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
60
60
|
end,
|
61
61
|
:jtds=>proc do |db|
|
62
|
-
Sequel.ts_require 'adapters/jdbc/
|
63
|
-
db.extend(Sequel::JDBC::
|
62
|
+
Sequel.ts_require 'adapters/jdbc/jtds'
|
63
|
+
db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
|
64
64
|
db.send(:set_mssql_unicode_strings)
|
65
65
|
JDBC.load_gem('jtds')
|
66
66
|
Java::net.sourceforge.jtds.jdbc.Driver
|
@@ -75,6 +75,11 @@ module Sequel
|
|
75
75
|
Sequel.ts_require 'adapters/jdbc/as400'
|
76
76
|
db.extend(Sequel::JDBC::AS400::DatabaseMethods)
|
77
77
|
com.ibm.as400.access.AS400JDBCDriver
|
78
|
+
end,
|
79
|
+
:"informix-sqli"=>proc do |db|
|
80
|
+
Sequel.ts_require 'adapters/jdbc/informix'
|
81
|
+
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
82
|
+
com.informix.jdbc.IfxDriver
|
78
83
|
end
|
79
84
|
}
|
80
85
|
|
@@ -248,12 +253,14 @@ module Sequel
|
|
248
253
|
indexes
|
249
254
|
end
|
250
255
|
|
256
|
+
# Whether or not JNDI is being used for this connection.
|
257
|
+
def jndi?
|
258
|
+
!!(uri =~ JNDI_URI_REGEXP)
|
259
|
+
end
|
260
|
+
|
251
261
|
# All tables in this database
|
252
262
|
def tables(opts={})
|
253
|
-
|
254
|
-
m = output_identifier_meth
|
255
|
-
metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
256
|
-
ts
|
263
|
+
get_tables('TABLE', opts)
|
257
264
|
end
|
258
265
|
|
259
266
|
# The uri for this connection. You can specify the uri
|
@@ -266,11 +273,11 @@ module Sequel
|
|
266
273
|
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
267
274
|
end
|
268
275
|
|
269
|
-
#
|
270
|
-
def
|
271
|
-
|
276
|
+
# All views in this database
|
277
|
+
def views(opts={})
|
278
|
+
get_tables('VIEW', opts)
|
272
279
|
end
|
273
|
-
|
280
|
+
|
274
281
|
private
|
275
282
|
|
276
283
|
# Close given adapter connections
|
@@ -327,6 +334,12 @@ module Sequel
|
|
327
334
|
end
|
328
335
|
end
|
329
336
|
|
337
|
+
# Gets the connection from JNDI.
|
338
|
+
def get_connection_from_jndi
|
339
|
+
jndi_name = JNDI_URI_REGEXP.match(uri)[1]
|
340
|
+
JavaxNaming::InitialContext.new.lookup(jndi_name).connection
|
341
|
+
end
|
342
|
+
|
330
343
|
# Gets the JDBC connection uri from the JNDI resource.
|
331
344
|
def get_uri_from_jndi
|
332
345
|
conn = get_connection_from_jndi
|
@@ -335,12 +348,14 @@ module Sequel
|
|
335
348
|
conn.close if conn
|
336
349
|
end
|
337
350
|
|
338
|
-
#
|
339
|
-
def
|
340
|
-
|
341
|
-
|
351
|
+
# Backbone of the tables and views support.
|
352
|
+
def get_tables(type, opts)
|
353
|
+
ts = []
|
354
|
+
m = output_identifier_meth
|
355
|
+
metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
356
|
+
ts
|
342
357
|
end
|
343
|
-
|
358
|
+
|
344
359
|
# Support Date objects used in bound variables
|
345
360
|
def java_sql_date(date)
|
346
361
|
java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
|
@@ -446,9 +461,11 @@ module Sequel
|
|
446
461
|
table = im.call(table)
|
447
462
|
pks, ts = [], []
|
448
463
|
metadata(:getPrimaryKeys, nil, schema, table) do |h|
|
464
|
+
next if h[:table_schem] == 'INFORMATION_SCHEMA'
|
449
465
|
pks << h[:column_name]
|
450
466
|
end
|
451
467
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
468
|
+
next if h[:table_schem] == 'INFORMATION_SCHEMA'
|
452
469
|
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]}
|
453
470
|
if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
|
454
471
|
s[:type] = :integer
|
@@ -33,6 +33,11 @@ module Sequel
|
|
33
33
|
{:primary_key => true, :type => :identity}
|
34
34
|
end
|
35
35
|
|
36
|
+
# H2 supports CREATE TABLE IF NOT EXISTS syntax.
|
37
|
+
def supports_create_table_if_not_exists?
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
36
41
|
# H2 supports prepared transactions
|
37
42
|
def supports_prepared_transactions?
|
38
43
|
true
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Sequel.require 'adapters/shared/informix'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module JDBC
|
5
|
+
# Database and Dataset instance methods for Informix specific
|
6
|
+
# support via JDBC.
|
7
|
+
module Informix
|
8
|
+
# Database instance methods for Informix databases accessed via JDBC.
|
9
|
+
module DatabaseMethods
|
10
|
+
include Sequel::Informix::DatabaseMethods
|
11
|
+
|
12
|
+
# Return instance of Sequel::JDBC::Informix::Dataset with the given opts.
|
13
|
+
def dataset(opts=nil)
|
14
|
+
Sequel::JDBC::Informix::Dataset.new(self, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# TODO: implement
|
20
|
+
def last_insert_id(conn, opts={})
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Dataset class for Informix datasets accessed via JDBC.
|
26
|
+
class Dataset < JDBC::Dataset
|
27
|
+
include Sequel::Informix::DatasetMethods
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Sequel.require 'adapters/jdbc/mssql'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module JDBC
|
5
|
+
# Database and Dataset instance methods for JTDS specific
|
6
|
+
# support via JDBC.
|
7
|
+
module JTDS
|
8
|
+
# Database instance methods for JTDS databases accessed via JDBC.
|
9
|
+
module DatabaseMethods
|
10
|
+
include Sequel::JDBC::MSSQL::DatabaseMethods
|
11
|
+
|
12
|
+
# Return instance of Sequel::JDBC::JTDS::Dataset with the given opts.
|
13
|
+
def dataset(opts=nil)
|
14
|
+
Sequel::JDBC::JTDS::Dataset.new(self, opts)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Dataset class for JTDS datasets accessed via JDBC.
|
19
|
+
class Dataset < JDBC::Dataset
|
20
|
+
include Sequel::MSSQL::DatasetMethods
|
21
|
+
|
22
|
+
# Handle CLOB types retrieved via JTDS.
|
23
|
+
def convert_type(v)
|
24
|
+
case v
|
25
|
+
when Java::NetSourceforgeJtdsJdbc::ClobImpl
|
26
|
+
convert_type(v.getSubString(1, v.length))
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -16,11 +16,6 @@ module Sequel
|
|
16
16
|
|
17
17
|
include Sequel::MSSQL::DatabaseMethods
|
18
18
|
|
19
|
-
# Return instance of Sequel::JDBC::MSSQL::Dataset with the given opts.
|
20
|
-
def dataset(opts=nil)
|
21
|
-
Sequel::JDBC::MSSQL::Dataset.new(self, opts)
|
22
|
-
end
|
23
|
-
|
24
19
|
private
|
25
20
|
|
26
21
|
# Get the last inserted id using SCOPE_IDENTITY().
|
@@ -43,33 +38,6 @@ module Sequel
|
|
43
38
|
def primary_key_index_re
|
44
39
|
PRIMARY_KEY_INDEX_RE
|
45
40
|
end
|
46
|
-
|
47
|
-
def metadata_dataset
|
48
|
-
ds = super
|
49
|
-
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
50
|
-
# for the getColumns result set specifies an incorrect type for the
|
51
|
-
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
52
|
-
# specified as a short. This causes getObject() to throw a
|
53
|
-
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
54
|
-
# from char to SMALLINT is unsupported." Using getString() rather
|
55
|
-
# than getObject() for this column avoids the problem.
|
56
|
-
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
57
|
-
def ds.result_set_object_getter
|
58
|
-
lambda do |result, n, i|
|
59
|
-
if n == :is_autoincrement
|
60
|
-
@convert_types ? convert_type(result.getString(i)) : result.getString(i)
|
61
|
-
else
|
62
|
-
@convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
ds
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Dataset class for MSSQL datasets accessed via JDBC.
|
71
|
-
class Dataset < JDBC::Dataset
|
72
|
-
include Sequel::MSSQL::DatasetMethods
|
73
41
|
end
|
74
42
|
end
|
75
43
|
end
|
@@ -56,6 +56,15 @@ module Sequel
|
|
56
56
|
def schema_column_type(db_type)
|
57
57
|
db_type == 'tinyint(1)' ? :boolean : super
|
58
58
|
end
|
59
|
+
|
60
|
+
# By default, MySQL 'where id is null' selects the last inserted id.
|
61
|
+
# Turn that off unless explicitly enabled.
|
62
|
+
def setup_connection(conn)
|
63
|
+
super
|
64
|
+
sql = "SET SQL_AUTO_IS_NULL=0"
|
65
|
+
statement(conn){|s| log_yield(sql){s.execute(sql)}} unless opts[:auto_is_null]
|
66
|
+
conn
|
67
|
+
end
|
59
68
|
end
|
60
69
|
|
61
70
|
# Dataset class for MySQL datasets accessed via JDBC.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Sequel.require 'adapters/jdbc/mssql'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module JDBC
|
5
|
+
# Database and Dataset instance methods for SQLServer specific
|
6
|
+
# support via JDBC.
|
7
|
+
module SQLServer
|
8
|
+
# Database instance methods for SQLServer databases accessed via JDBC.
|
9
|
+
module DatabaseMethods
|
10
|
+
include Sequel::JDBC::MSSQL::DatabaseMethods
|
11
|
+
|
12
|
+
# Return instance of Sequel::JDBC::SQLServer::Dataset with the given opts.
|
13
|
+
def dataset(opts=nil)
|
14
|
+
Sequel::JDBC::SQLServer::Dataset.new(self, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
def metadata_dataset
|
18
|
+
ds = super
|
19
|
+
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
20
|
+
# for the getColumns result set specifies an incorrect type for the
|
21
|
+
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
22
|
+
# specified as a short. This causes getObject() to throw a
|
23
|
+
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
24
|
+
# from char to SMALLINT is unsupported." Using getString() rather
|
25
|
+
# than getObject() for this column avoids the problem.
|
26
|
+
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
27
|
+
def ds.result_set_object_getter
|
28
|
+
lambda do |result, n, i|
|
29
|
+
if n == :is_autoincrement
|
30
|
+
@convert_types ? convert_type(result.getString(i)) : result.getString(i)
|
31
|
+
else
|
32
|
+
@convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
ds
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Dataset class for SQLServer datasets accessed via JDBC.
|
41
|
+
class Dataset < JDBC::Dataset
|
42
|
+
include Sequel::MSSQL::DatasetMethods
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -100,6 +100,11 @@ module Sequel
|
|
100
100
|
def timestamp(s) ::Sequel.database_to_application_timestamp(s) end
|
101
101
|
end.new
|
102
102
|
|
103
|
+
# Hash with type name symbols and callable values for converting PostgreSQL types.
|
104
|
+
# Non-builtin types that don't have fixed numbers should use this to register
|
105
|
+
# conversion procs.
|
106
|
+
PG_NAMED_TYPES = {}
|
107
|
+
|
103
108
|
# Hash with integer keys and callable values for converting PostgreSQL types.
|
104
109
|
PG_TYPES = {}
|
105
110
|
{
|
@@ -194,6 +199,10 @@ module Sequel
|
|
194
199
|
include Sequel::Postgres::DatabaseMethods
|
195
200
|
|
196
201
|
set_adapter_scheme :postgres
|
202
|
+
|
203
|
+
# A hash of conversion procs, keyed by type integer (oid) and
|
204
|
+
# having callable values for the conversion proc for that type.
|
205
|
+
attr_reader :conversion_procs
|
197
206
|
|
198
207
|
# Add the primary_keys and primary_key_sequences instance variables,
|
199
208
|
# so we can get the correct return values for inserted rows.
|
@@ -225,6 +234,7 @@ module Sequel
|
|
225
234
|
end
|
226
235
|
conn.db = self
|
227
236
|
conn.apply_connection_settings
|
237
|
+
@conversion_procs ||= get_conversion_procs(conn)
|
228
238
|
conn
|
229
239
|
end
|
230
240
|
|
@@ -305,6 +315,19 @@ module Sequel
|
|
305
315
|
end
|
306
316
|
end
|
307
317
|
end
|
318
|
+
|
319
|
+
# Return the conversion procs hash to use for this database
|
320
|
+
def get_conversion_procs(conn)
|
321
|
+
procs = PG_TYPES.dup
|
322
|
+
conn.execute("SELECT oid, typname FROM pg_type where typtype = 'b'") do |res|
|
323
|
+
res.ntuples.times do |recnum|
|
324
|
+
if pr = PG_NAMED_TYPES[res.getvalue(recnum, 1).to_sym]
|
325
|
+
procs[res.getvalue(recnum, 0).to_i] ||= pr
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
procs
|
330
|
+
end
|
308
331
|
end
|
309
332
|
|
310
333
|
# Dataset class for PostgreSQL datasets that use the pg, postgres, or
|
@@ -372,6 +395,11 @@ module Sequel
|
|
372
395
|
end
|
373
396
|
LiteralString.new("#{prepared_arg_placeholder}#{i}#{"::#{type}" if type}")
|
374
397
|
end
|
398
|
+
|
399
|
+
# Always assume a prepared argument.
|
400
|
+
def prepared_arg?(k)
|
401
|
+
true
|
402
|
+
end
|
375
403
|
end
|
376
404
|
|
377
405
|
# Allow use of bind arguments for PostgreSQL using the pg driver.
|
@@ -483,8 +511,9 @@ module Sequel
|
|
483
511
|
# field numers, type conversion procs, and name symbol arrays.
|
484
512
|
def fetch_rows_set_cols(res)
|
485
513
|
cols = []
|
514
|
+
procs = db.conversion_procs
|
486
515
|
res.nfields.times do |fieldnum|
|
487
|
-
cols << [fieldnum,
|
516
|
+
cols << [fieldnum, procs[res.ftype(fieldnum)], output_identifier(res.fname(fieldnum))]
|
488
517
|
end
|
489
518
|
@columns = cols.map{|c| c.at(2)}
|
490
519
|
cols
|