sequel 3.21.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.
Files changed (104) hide show
  1. data/CHANGELOG +112 -0
  2. data/README.rdoc +15 -1
  3. data/doc/association_basics.rdoc +159 -40
  4. data/doc/model_hooks.rdoc +64 -27
  5. data/doc/prepared_statements.rdoc +8 -4
  6. data/doc/reflection.rdoc +8 -2
  7. data/doc/release_notes/3.22.0.txt +39 -0
  8. data/doc/release_notes/3.23.0.txt +172 -0
  9. data/doc/release_notes/3.24.0.txt +420 -0
  10. data/doc/virtual_rows.rdoc +2 -2
  11. data/lib/sequel/adapters/ado.rb +2 -1
  12. data/lib/sequel/adapters/db2.rb +8 -1
  13. data/lib/sequel/adapters/firebird.rb +25 -9
  14. data/lib/sequel/adapters/informix.rb +4 -19
  15. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  16. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  17. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  18. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  19. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  20. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  21. data/lib/sequel/adapters/jdbc.rb +39 -20
  22. data/lib/sequel/adapters/odbc.rb +2 -0
  23. data/lib/sequel/adapters/oracle.rb +12 -0
  24. data/lib/sequel/adapters/postgres.rb +30 -1
  25. data/lib/sequel/adapters/shared/access.rb +10 -0
  26. data/lib/sequel/adapters/shared/informix.rb +45 -0
  27. data/lib/sequel/adapters/shared/mssql.rb +106 -11
  28. data/lib/sequel/adapters/shared/mysql.rb +25 -7
  29. data/lib/sequel/adapters/shared/postgres.rb +39 -6
  30. data/lib/sequel/adapters/shared/sqlite.rb +57 -5
  31. data/lib/sequel/adapters/sqlite.rb +8 -3
  32. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  33. data/lib/sequel/adapters/tinytds.rb +4 -3
  34. data/lib/sequel/ast_transformer.rb +190 -0
  35. data/lib/sequel/core.rb +1 -1
  36. data/lib/sequel/database/connecting.rb +1 -1
  37. data/lib/sequel/database/misc.rb +6 -0
  38. data/lib/sequel/database/query.rb +33 -3
  39. data/lib/sequel/database/schema_methods.rb +13 -4
  40. data/lib/sequel/dataset/features.rb +6 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +17 -2
  42. data/lib/sequel/dataset/query.rb +17 -0
  43. data/lib/sequel/dataset/sql.rb +2 -53
  44. data/lib/sequel/exceptions.rb +4 -0
  45. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  46. data/lib/sequel/extensions/migration.rb +4 -3
  47. data/lib/sequel/extensions/to_dot.rb +95 -83
  48. data/lib/sequel/model/associations.rb +234 -32
  49. data/lib/sequel/model/base.rb +187 -60
  50. data/lib/sequel/model/exceptions.rb +3 -1
  51. data/lib/sequel/model.rb +5 -0
  52. data/lib/sequel/plugins/association_pks.rb +6 -4
  53. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  54. data/lib/sequel/plugins/identity_map.rb +2 -2
  55. data/lib/sequel/plugins/many_through_many.rb +33 -3
  56. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  57. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  58. data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
  59. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  60. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  61. data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
  62. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  63. data/lib/sequel/sql.rb +8 -0
  64. data/lib/sequel/version.rb +1 -1
  65. data/spec/adapters/mssql_spec.rb +36 -0
  66. data/spec/adapters/mysql_spec.rb +6 -0
  67. data/spec/adapters/postgres_spec.rb +43 -18
  68. data/spec/adapters/spec_helper.rb +5 -0
  69. data/spec/core/connection_pool_spec.rb +56 -77
  70. data/spec/core/database_spec.rb +33 -0
  71. data/spec/core/dataset_spec.rb +127 -16
  72. data/spec/core/expression_filters_spec.rb +13 -0
  73. data/spec/core/schema_spec.rb +13 -1
  74. data/spec/core/spec_helper.rb +5 -0
  75. data/spec/extensions/association_pks_spec.rb +7 -0
  76. data/spec/extensions/columns_introspection_spec.rb +91 -0
  77. data/spec/extensions/defaults_setter_spec.rb +64 -0
  78. data/spec/extensions/many_through_many_spec.rb +77 -0
  79. data/spec/extensions/migration_spec.rb +17 -17
  80. data/spec/extensions/nested_attributes_spec.rb +1 -0
  81. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  82. data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
  83. data/spec/extensions/prepared_statements_spec.rb +72 -0
  84. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  85. data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
  86. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  87. data/spec/extensions/spec_helper.rb +3 -1
  88. data/spec/extensions/to_dot_spec.rb +3 -5
  89. data/spec/extensions/xml_serializer_spec.rb +12 -0
  90. data/spec/integration/associations_test.rb +212 -0
  91. data/spec/integration/dataset_test.rb +8 -1
  92. data/spec/integration/plugin_test.rb +134 -0
  93. data/spec/integration/prepared_statement_test.rb +72 -1
  94. data/spec/integration/schema_test.rb +66 -8
  95. data/spec/integration/spec_helper.rb +5 -0
  96. data/spec/integration/transaction_test.rb +40 -0
  97. data/spec/integration/type_test.rb +7 -0
  98. data/spec/model/associations_spec.rb +463 -5
  99. data/spec/model/base_spec.rb +59 -0
  100. data/spec/model/eager_loading_spec.rb +269 -1
  101. data/spec/model/hooks_spec.rb +161 -0
  102. data/spec/model/record_spec.rb +30 -0
  103. data/spec/model/spec_helper.rb +5 -0
  104. metadata +29 -4
@@ -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
@@ -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
@@ -53,13 +53,15 @@ 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
+ db.send(:set_mssql_unicode_strings)
58
59
  com.microsoft.sqlserver.jdbc.SQLServerDriver
59
60
  end,
60
61
  :jtds=>proc do |db|
61
- Sequel.ts_require 'adapters/jdbc/mssql'
62
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
62
+ Sequel.ts_require 'adapters/jdbc/jtds'
63
+ db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
64
+ db.send(:set_mssql_unicode_strings)
63
65
  JDBC.load_gem('jtds')
64
66
  Java::net.sourceforge.jtds.jdbc.Driver
65
67
  end,
@@ -73,6 +75,11 @@ module Sequel
73
75
  Sequel.ts_require 'adapters/jdbc/as400'
74
76
  db.extend(Sequel::JDBC::AS400::DatabaseMethods)
75
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
76
83
  end
77
84
  }
78
85
 
@@ -101,7 +108,7 @@ module Sequel
101
108
  # True by default, can be set to false to roughly double performance when
102
109
  # fetching rows.
103
110
  attr_accessor :convert_types
104
-
111
+
105
112
  # Call the DATABASE_SETUP proc directly after initialization,
106
113
  # so the object always uses sub adapter specific code. Also,
107
114
  # raise an error immediately if the connection doesn't have a
@@ -246,12 +253,14 @@ module Sequel
246
253
  indexes
247
254
  end
248
255
 
256
+ # Whether or not JNDI is being used for this connection.
257
+ def jndi?
258
+ !!(uri =~ JNDI_URI_REGEXP)
259
+ end
260
+
249
261
  # All tables in this database
250
262
  def tables(opts={})
251
- ts = []
252
- m = output_identifier_meth
253
- metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
254
- ts
263
+ get_tables('TABLE', opts)
255
264
  end
256
265
 
257
266
  # The uri for this connection. You can specify the uri
@@ -264,11 +273,11 @@ module Sequel
264
273
  ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
265
274
  end
266
275
 
267
- # Whether or not JNDI is being used for this connection.
268
- def jndi?
269
- !!(uri =~ JNDI_URI_REGEXP)
276
+ # All views in this database
277
+ def views(opts={})
278
+ get_tables('VIEW', opts)
270
279
  end
271
-
280
+
272
281
  private
273
282
 
274
283
  # Close given adapter connections
@@ -325,6 +334,12 @@ module Sequel
325
334
  end
326
335
  end
327
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
+
328
343
  # Gets the JDBC connection uri from the JNDI resource.
329
344
  def get_uri_from_jndi
330
345
  conn = get_connection_from_jndi
@@ -333,12 +348,14 @@ module Sequel
333
348
  conn.close if conn
334
349
  end
335
350
 
336
- # Gets the connection from JNDI.
337
- def get_connection_from_jndi
338
- jndi_name = JNDI_URI_REGEXP.match(uri)[1]
339
- 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
340
357
  end
341
-
358
+
342
359
  # Support Date objects used in bound variables
343
360
  def java_sql_date(date)
344
361
  java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
@@ -444,9 +461,11 @@ module Sequel
444
461
  table = im.call(table)
445
462
  pks, ts = [], []
446
463
  metadata(:getPrimaryKeys, nil, schema, table) do |h|
464
+ next if h[:table_schem] == 'INFORMATION_SCHEMA'
447
465
  pks << h[:column_name]
448
466
  end
449
467
  metadata(:getColumns, nil, schema, table, nil) do |h|
468
+ next if h[:table_schem] == 'INFORMATION_SCHEMA'
450
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]}
451
470
  if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
452
471
  s[:type] = :integer
@@ -530,8 +549,8 @@ module Sequel
530
549
  # Uses the database's setting by default, can be set to false to roughly
531
550
  # double performance when fetching rows.
532
551
  attr_accessor :convert_types
533
-
534
- # Use the convert_types default setting from the database
552
+
553
+ # Use the convert_types default setting from the database.
535
554
  def initialize(db, opts={})
536
555
  @convert_types = db.convert_types
537
556
  super
@@ -15,6 +15,7 @@ module Sequel
15
15
  when 'mssql'
16
16
  Sequel.ts_require 'adapters/odbc/mssql'
17
17
  extend Sequel::ODBC::MSSQL::DatabaseMethods
18
+ set_mssql_unicode_strings
18
19
  when 'progress'
19
20
  Sequel.ts_require 'adapters/shared/progress'
20
21
  extend Sequel::Progress::DatabaseMethods
@@ -116,6 +117,7 @@ module Sequel
116
117
  when ::ODBC::TimeStamp
117
118
  Sequel.database_to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
118
119
  when ::ODBC::Time
120
+ now = ::Time.now
119
121
  Sequel.database_to_application_timestamp([now.year, now.month, now.day, v.hour, v.minute, v.second])
120
122
  when ::ODBC::Date
121
123
  Date.new(v.year, v.month, v.day)
@@ -24,6 +24,18 @@ module Sequel
24
24
  conn = OCI8.new(opts[:user], opts[:password], dbname, opts[:privilege])
25
25
  conn.autocommit = true
26
26
  conn.non_blocking = true
27
+
28
+ # The ruby-oci8 gem which retrieves oracle columns with a type of
29
+ # DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE is complex based on the
30
+ # ruby version (1.9.2 or later) and Oracle version (9 or later)
31
+ # In the now standard case of 1.9.2 and Oracle 9 or later, the timezone
32
+ # is determined by the Oracle session timezone. Thus if the user
33
+ # requests Sequel provide UTC timezone to the application,
34
+ # we need to alter the session timezone to be UTC
35
+ if Sequel.application_timezone == :utc
36
+ conn.exec("ALTER SESSION SET TIME_ZONE='-00:00'")
37
+ end
38
+
27
39
  conn
28
40
  end
29
41
 
@@ -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
@@ -1,6 +1,7 @@
1
1
  module Sequel
2
2
  module Access
3
3
  module DatabaseMethods
4
+ # Access uses type :access as the database_type
4
5
  def database_type
5
6
  :access
6
7
  end
@@ -16,6 +17,7 @@ module Sequel
16
17
  from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
17
18
  end
18
19
 
20
+ # Access uses type Counter for an autoincrementing keys
19
21
  def serial_primary_key_options
20
22
  {:primary_key => true, :type=>:Counter}
21
23
  end
@@ -34,16 +36,24 @@ module Sequel
34
36
  module DatasetMethods
35
37
  SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where group order having compounds')
36
38
 
39
+ # Access doesn't support INTERSECT or EXCEPT
37
40
  def supports_intersect_except?
38
41
  false
39
42
  end
40
43
 
41
44
  private
42
45
 
46
+ # Access uses TOP for limits
47
+ def select_limit_sql(sql)
48
+ sql << " TOP #{@opts[:limit]}" if @opts[:limit]
49
+ end
50
+
51
+ # Access uses [] for quoting identifiers
43
52
  def quoted_identifier(v)
44
53
  "[#{v}]"
45
54
  end
46
55
 
56
+ # Access requires the limit clause come before other clauses
47
57
  def select_clause_methods
48
58
  SELECT_CLAUSE_METHODS
49
59
  end
@@ -0,0 +1,45 @@
1
+ module Sequel
2
+ module Informix
3
+ module DatabaseMethods
4
+ TEMPORARY = 'TEMP '.freeze
5
+
6
+ # Informix uses the :informix database type
7
+ def database_type
8
+ :informix
9
+ end
10
+
11
+ private
12
+
13
+ # Informix has issues with quoted identifiers, so
14
+ # turn off database quoting by default.
15
+ def quote_identifiers_default
16
+ false
17
+ end
18
+
19
+ # SQL fragment for showing a table is temporary
20
+ def temporary_table_sql
21
+ TEMPORARY
22
+ end
23
+ end
24
+
25
+ module DatasetMethods
26
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where having group compounds order')
27
+
28
+ private
29
+
30
+ # Informix does not support INTERSECT or EXCEPT
31
+ def supports_intersect_except?
32
+ false
33
+ end
34
+
35
+ def select_clause_methods
36
+ SELECT_CLAUSE_METHODS
37
+ end
38
+
39
+ def select_limit_sql(sql)
40
+ sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
41
+ sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
42
+ end
43
+ end
44
+ end
45
+ end