sequel 3.23.0 → 3.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/CHANGELOG +64 -0
  2. data/doc/association_basics.rdoc +43 -5
  3. data/doc/model_hooks.rdoc +64 -27
  4. data/doc/prepared_statements.rdoc +8 -4
  5. data/doc/reflection.rdoc +8 -2
  6. data/doc/release_notes/3.23.0.txt +1 -1
  7. data/doc/release_notes/3.24.0.txt +420 -0
  8. data/lib/sequel/adapters/db2.rb +8 -1
  9. data/lib/sequel/adapters/firebird.rb +25 -9
  10. data/lib/sequel/adapters/informix.rb +4 -19
  11. data/lib/sequel/adapters/jdbc.rb +34 -17
  12. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  13. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  14. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  15. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  16. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  17. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  18. data/lib/sequel/adapters/postgres.rb +30 -1
  19. data/lib/sequel/adapters/shared/access.rb +10 -0
  20. data/lib/sequel/adapters/shared/informix.rb +45 -0
  21. data/lib/sequel/adapters/shared/mssql.rb +82 -8
  22. data/lib/sequel/adapters/shared/mysql.rb +25 -7
  23. data/lib/sequel/adapters/shared/postgres.rb +39 -6
  24. data/lib/sequel/adapters/shared/sqlite.rb +57 -5
  25. data/lib/sequel/adapters/sqlite.rb +8 -3
  26. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  27. data/lib/sequel/ast_transformer.rb +190 -0
  28. data/lib/sequel/core.rb +1 -1
  29. data/lib/sequel/database/misc.rb +6 -0
  30. data/lib/sequel/database/query.rb +33 -3
  31. data/lib/sequel/database/schema_methods.rb +6 -2
  32. data/lib/sequel/dataset/features.rb +6 -0
  33. data/lib/sequel/dataset/prepared_statements.rb +17 -2
  34. data/lib/sequel/dataset/query.rb +17 -0
  35. data/lib/sequel/dataset/sql.rb +2 -53
  36. data/lib/sequel/exceptions.rb +4 -0
  37. data/lib/sequel/extensions/to_dot.rb +95 -83
  38. data/lib/sequel/model.rb +5 -0
  39. data/lib/sequel/model/associations.rb +80 -14
  40. data/lib/sequel/model/base.rb +182 -55
  41. data/lib/sequel/model/exceptions.rb +3 -1
  42. data/lib/sequel/plugins/association_pks.rb +6 -4
  43. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  44. data/lib/sequel/plugins/many_through_many.rb +8 -3
  45. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  46. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  47. data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
  48. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  49. data/lib/sequel/sql.rb +8 -0
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/postgres_spec.rb +43 -18
  52. data/spec/core/connection_pool_spec.rb +56 -77
  53. data/spec/core/database_spec.rb +25 -0
  54. data/spec/core/dataset_spec.rb +127 -16
  55. data/spec/core/expression_filters_spec.rb +13 -0
  56. data/spec/core/schema_spec.rb +6 -1
  57. data/spec/extensions/association_pks_spec.rb +7 -0
  58. data/spec/extensions/defaults_setter_spec.rb +64 -0
  59. data/spec/extensions/many_through_many_spec.rb +60 -4
  60. data/spec/extensions/nested_attributes_spec.rb +1 -0
  61. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  62. data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
  63. data/spec/extensions/prepared_statements_spec.rb +72 -0
  64. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  65. data/spec/extensions/to_dot_spec.rb +3 -5
  66. data/spec/integration/associations_test.rb +155 -1
  67. data/spec/integration/dataset_test.rb +8 -1
  68. data/spec/integration/plugin_test.rb +119 -0
  69. data/spec/integration/prepared_statement_test.rb +72 -1
  70. data/spec/integration/schema_test.rb +66 -8
  71. data/spec/integration/transaction_test.rb +40 -0
  72. data/spec/model/associations_spec.rb +349 -8
  73. data/spec/model/base_spec.rb +59 -0
  74. data/spec/model/hooks_spec.rb +161 -0
  75. data/spec/model/record_spec.rb +24 -0
  76. metadata +21 -4
@@ -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
- # The order of clauses in the SELECT SQL statement
251
- def select_clause_methods
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
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'limit distinct columns from join where having group compounds order')
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
@@ -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/mssql'
57
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
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/mssql'
63
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
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
- ts = []
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
- # Whether or not JNDI is being used for this connection.
270
- def jndi?
271
- !!(uri =~ JNDI_URI_REGEXP)
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
- # Gets the connection from JNDI.
339
- def get_connection_from_jndi
340
- jndi_name = JNDI_URI_REGEXP.match(uri)[1]
341
- JavaxNaming::InitialContext.new.lookup(jndi_name).connection
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, PG_TYPES[res.ftype(fieldnum)], output_identifier(res.fname(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