sequel 3.23.0 → 3.24.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|