sequel 4.45.0 → 4.46.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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +108 -0
  3. data/doc/release_notes/4.46.0.txt +404 -0
  4. data/doc/security.rdoc +9 -0
  5. data/doc/sql.rdoc +2 -2
  6. data/doc/testing.rdoc +1 -1
  7. data/doc/validations.rdoc +1 -2
  8. data/lib/sequel/adapters/ado.rb +8 -3
  9. data/lib/sequel/adapters/ado/access.rb +8 -4
  10. data/lib/sequel/adapters/ado/mssql.rb +3 -1
  11. data/lib/sequel/adapters/amalgalite.rb +5 -0
  12. data/lib/sequel/adapters/cubrid.rb +16 -7
  13. data/lib/sequel/adapters/do.rb +7 -1
  14. data/lib/sequel/adapters/do/mysql.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +10 -5
  16. data/lib/sequel/adapters/jdbc.rb +8 -2
  17. data/lib/sequel/adapters/jdbc/as400.rb +10 -3
  18. data/lib/sequel/adapters/jdbc/db2.rb +27 -16
  19. data/lib/sequel/adapters/jdbc/derby.rb +47 -20
  20. data/lib/sequel/adapters/jdbc/h2.rb +13 -7
  21. data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
  22. data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
  23. data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
  24. data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
  25. data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
  26. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
  27. data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
  28. data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
  29. data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
  30. data/lib/sequel/adapters/mock.rb +5 -0
  31. data/lib/sequel/adapters/mysql.rb +8 -1
  32. data/lib/sequel/adapters/mysql2.rb +6 -1
  33. data/lib/sequel/adapters/odbc.rb +20 -8
  34. data/lib/sequel/adapters/odbc/mssql.rb +6 -3
  35. data/lib/sequel/adapters/oracle.rb +12 -6
  36. data/lib/sequel/adapters/postgres.rb +20 -8
  37. data/lib/sequel/adapters/shared/access.rb +76 -47
  38. data/lib/sequel/adapters/shared/cubrid.rb +16 -11
  39. data/lib/sequel/adapters/shared/db2.rb +46 -19
  40. data/lib/sequel/adapters/shared/firebird.rb +20 -8
  41. data/lib/sequel/adapters/shared/informix.rb +6 -3
  42. data/lib/sequel/adapters/shared/mssql.rb +132 -72
  43. data/lib/sequel/adapters/shared/mysql.rb +112 -65
  44. data/lib/sequel/adapters/shared/oracle.rb +36 -21
  45. data/lib/sequel/adapters/shared/postgres.rb +91 -56
  46. data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
  47. data/lib/sequel/adapters/shared/sqlite.rb +67 -32
  48. data/lib/sequel/adapters/sqlanywhere.rb +9 -1
  49. data/lib/sequel/adapters/sqlite.rb +8 -1
  50. data/lib/sequel/adapters/swift.rb +5 -0
  51. data/lib/sequel/adapters/swift/mysql.rb +4 -2
  52. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  53. data/lib/sequel/adapters/tinytds.rb +10 -3
  54. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  55. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  56. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
  57. data/lib/sequel/adapters/utils/pg_types.rb +14 -6
  58. data/lib/sequel/adapters/utils/replace.rb +4 -2
  59. data/lib/sequel/connection_pool/single.rb +2 -2
  60. data/lib/sequel/core.rb +24 -11
  61. data/lib/sequel/database/connecting.rb +9 -3
  62. data/lib/sequel/database/dataset_defaults.rb +7 -1
  63. data/lib/sequel/database/logging.rb +1 -0
  64. data/lib/sequel/database/misc.rb +5 -2
  65. data/lib/sequel/database/query.rb +7 -5
  66. data/lib/sequel/database/schema_generator.rb +1 -0
  67. data/lib/sequel/database/schema_methods.rb +50 -27
  68. data/lib/sequel/database/transactions.rb +19 -9
  69. data/lib/sequel/dataset/actions.rb +15 -6
  70. data/lib/sequel/dataset/graph.rb +15 -5
  71. data/lib/sequel/dataset/misc.rb +12 -4
  72. data/lib/sequel/dataset/mutation.rb +17 -8
  73. data/lib/sequel/dataset/prepared_statements.rb +3 -2
  74. data/lib/sequel/dataset/query.rb +84 -38
  75. data/lib/sequel/dataset/sql.rb +302 -191
  76. data/lib/sequel/deprecated.rb +26 -17
  77. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
  78. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  79. data/lib/sequel/extensions/from_block.rb +1 -0
  80. data/lib/sequel/extensions/graph_each.rb +1 -1
  81. data/lib/sequel/extensions/identifier_mangling.rb +2 -2
  82. data/lib/sequel/extensions/migration.rb +28 -4
  83. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
  84. data/lib/sequel/extensions/schema_dumper.rb +4 -4
  85. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
  86. data/lib/sequel/extensions/set_overrides.rb +2 -0
  87. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  88. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  89. data/lib/sequel/model.rb +11 -7
  90. data/lib/sequel/model/associations.rb +5 -7
  91. data/lib/sequel/model/base.rb +47 -45
  92. data/lib/sequel/model/dataset_module.rb +9 -14
  93. data/lib/sequel/model/plugins.rb +3 -0
  94. data/lib/sequel/no_core_ext.rb +1 -0
  95. data/lib/sequel/plugins/blacklist_security.rb +1 -1
  96. data/lib/sequel/plugins/boolean_subsets.rb +7 -5
  97. data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
  98. data/lib/sequel/plugins/dataset_associations.rb +1 -1
  99. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  100. data/lib/sequel/plugins/finder.rb +240 -0
  101. data/lib/sequel/plugins/inverted_subsets.rb +19 -12
  102. data/lib/sequel/plugins/many_through_many.rb +1 -1
  103. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  104. data/lib/sequel/plugins/schema.rb +1 -1
  105. data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
  106. data/lib/sequel/plugins/subset_conditions.rb +11 -3
  107. data/lib/sequel/plugins/whitelist_security.rb +118 -0
  108. data/lib/sequel/sql.rb +80 -36
  109. data/lib/sequel/timezones.rb +2 -0
  110. data/lib/sequel/version.rb +1 -1
  111. data/spec/adapters/mssql_spec.rb +20 -0
  112. data/spec/adapters/mysql_spec.rb +1 -1
  113. data/spec/adapters/oracle_spec.rb +12 -8
  114. data/spec/adapters/postgres_spec.rb +1 -1
  115. data/spec/adapters/spec_helper.rb +1 -1
  116. data/spec/adapters/sqlite_spec.rb +36 -34
  117. data/spec/core/connection_pool_spec.rb +2 -1
  118. data/spec/core/database_spec.rb +87 -9
  119. data/spec/core/dataset_spec.rb +501 -129
  120. data/spec/core/deprecated_spec.rb +1 -1
  121. data/spec/core/expression_filters_spec.rb +146 -60
  122. data/spec/core/mock_adapter_spec.rb +1 -1
  123. data/spec/core/object_graph_spec.rb +61 -9
  124. data/spec/core/placeholder_literalizer_spec.rb +20 -2
  125. data/spec/core/schema_generator_spec.rb +6 -6
  126. data/spec/core/schema_spec.rb +54 -5
  127. data/spec/core_extensions_spec.rb +122 -18
  128. data/spec/deprecation_helper.rb +27 -2
  129. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
  130. data/spec/extensions/association_proxies_spec.rb +2 -2
  131. data/spec/extensions/auto_literal_strings_spec.rb +212 -0
  132. data/spec/extensions/blacklist_security_spec.rb +1 -0
  133. data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
  134. data/spec/extensions/column_select_spec.rb +20 -8
  135. data/spec/extensions/columns_introspection_spec.rb +3 -3
  136. data/spec/extensions/core_refinements_spec.rb +29 -12
  137. data/spec/extensions/dataset_associations_spec.rb +12 -12
  138. data/spec/extensions/def_dataset_method_spec.rb +100 -0
  139. data/spec/extensions/error_sql_spec.rb +1 -1
  140. data/spec/extensions/finder_spec.rb +260 -0
  141. data/spec/extensions/graph_each_spec.rb +2 -2
  142. data/spec/extensions/identifier_mangling_spec.rb +14 -8
  143. data/spec/extensions/inverted_subsets_spec.rb +4 -4
  144. data/spec/extensions/lazy_attributes_spec.rb +7 -0
  145. data/spec/extensions/many_through_many_spec.rb +38 -14
  146. data/spec/extensions/nested_attributes_spec.rb +18 -6
  147. data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
  148. data/spec/extensions/pg_enum_spec.rb +16 -1
  149. data/spec/extensions/pg_interval_spec.rb +11 -2
  150. data/spec/extensions/pg_loose_count_spec.rb +5 -0
  151. data/spec/extensions/pg_row_spec.rb +25 -0
  152. data/spec/extensions/prepared_statements_spec.rb +10 -1
  153. data/spec/extensions/query_spec.rb +2 -2
  154. data/spec/extensions/schema_dumper_spec.rb +2 -2
  155. data/spec/extensions/schema_spec.rb +2 -2
  156. data/spec/extensions/set_overrides_spec.rb +7 -3
  157. data/spec/extensions/sql_expr_spec.rb +0 -1
  158. data/spec/extensions/subset_conditions_spec.rb +6 -6
  159. data/spec/extensions/table_select_spec.rb +24 -12
  160. data/spec/extensions/to_dot_spec.rb +4 -4
  161. data/spec/extensions/whitelist_security_spec.rb +131 -0
  162. data/spec/integration/dataset_test.rb +9 -5
  163. data/spec/integration/model_test.rb +2 -0
  164. data/spec/integration/plugin_test.rb +2 -2
  165. data/spec/integration/spec_helper.rb +1 -1
  166. data/spec/model/associations_spec.rb +39 -11
  167. data/spec/model/base_spec.rb +44 -24
  168. data/spec/model/class_dataset_methods_spec.rb +18 -16
  169. data/spec/model/dataset_methods_spec.rb +4 -4
  170. data/spec/model/eager_loading_spec.rb +84 -24
  171. data/spec/model/model_spec.rb +97 -63
  172. data/spec/model/record_spec.rb +21 -13
  173. metadata +13 -2
@@ -8,7 +8,9 @@ module Sequel
8
8
 
9
9
  module DatabaseMethods
10
10
  AUTO_INCREMENT = ''.freeze
11
+ Sequel::Deprecation.deprecate_constant(self, :AUTO_INCREMENT)
11
12
  TEMPORARY = 'GLOBAL TEMPORARY '.freeze
13
+ Sequel::Deprecation.deprecate_constant(self, :TEMPORARY)
12
14
 
13
15
  def clear_primary_key(*tables)
14
16
  tables.each{|t| @primary_keys.delete(dataset.send(:input_identifier, t))}
@@ -54,6 +56,10 @@ module Sequel
54
56
 
55
57
  private
56
58
 
59
+ def temporary_table_sql
60
+ 'GLOBAL TEMPORARY '
61
+ end
62
+
57
63
  # Use Firebird specific syntax for add column
58
64
  def alter_table_sql(table, op)
59
65
  case op[:op]
@@ -70,8 +76,8 @@ module Sequel
70
76
  end
71
77
  end
72
78
 
73
- def auto_increment_sql()
74
- AUTO_INCREMENT
79
+ def auto_increment_sql
80
+ ''
75
81
  end
76
82
 
77
83
  def create_sequence_sql(name, opts=OPTS)
@@ -158,12 +164,18 @@ module Sequel
158
164
  end
159
165
 
160
166
  module DatasetMethods
167
+ NULL = LiteralString.new('NULL').freeze
168
+
161
169
  BOOL_TRUE = '1'.freeze
170
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_TRUE)
162
171
  BOOL_FALSE = '0'.freeze
163
- NULL = LiteralString.new('NULL').freeze
172
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_FALSE)
164
173
  FIRST = " FIRST ".freeze
174
+ Sequel::Deprecation.deprecate_constant(self, :FIRST)
165
175
  SKIP = " SKIP ".freeze
176
+ Sequel::Deprecation.deprecate_constant(self, :SKIP)
166
177
  DEFAULT_FROM = " FROM RDB$DATABASE"
178
+ Sequel::Deprecation.deprecate_constant(self, :DEFAULT_FROM)
167
179
 
168
180
  Dataset.def_sql_method(self, :select, %w'with select distinct limit columns from join where group having compounds order')
169
181
  Dataset.def_sql_method(self, :insert, %w'insert into columns values returning')
@@ -213,7 +225,7 @@ module Sequel
213
225
  private
214
226
 
215
227
  def empty_from_sql
216
- DEFAULT_FROM
228
+ " FROM RDB$DATABASE"
217
229
  end
218
230
 
219
231
  def insert_pk(*values)
@@ -222,11 +234,11 @@ module Sequel
222
234
  end
223
235
 
224
236
  def literal_false
225
- BOOL_FALSE
237
+ '0'
226
238
  end
227
239
 
228
240
  def literal_true
229
- BOOL_TRUE
241
+ '1'
230
242
  end
231
243
 
232
244
  # Firebird can insert multiple rows using a UNION
@@ -236,11 +248,11 @@ module Sequel
236
248
 
237
249
  def select_limit_sql(sql)
238
250
  if l = @opts[:limit]
239
- sql << FIRST
251
+ sql << " FIRST "
240
252
  literal_append(sql, l)
241
253
  end
242
254
  if o = @opts[:offset]
243
- sql << SKIP
255
+ sql << " SKIP "
244
256
  literal_append(sql, o)
245
257
  end
246
258
  end
@@ -8,6 +8,7 @@ module Sequel
8
8
 
9
9
  module DatabaseMethods
10
10
  TEMPORARY = 'TEMP '.freeze
11
+ Sequel::Deprecation.deprecate_constant(self, :TEMPORARY)
11
12
 
12
13
  # Informix uses the :informix database type
13
14
  def database_type
@@ -24,13 +25,15 @@ module Sequel
24
25
 
25
26
  # SQL fragment for showing a table is temporary
26
27
  def temporary_table_sql
27
- TEMPORARY
28
+ 'TEMP '
28
29
  end
29
30
  end
30
31
 
31
32
  module DatasetMethods
32
33
  FIRST = " FIRST ".freeze
34
+ Sequel::Deprecation.deprecate_constant(self, :FIRST)
33
35
  SKIP = " SKIP ".freeze
36
+ Sequel::Deprecation.deprecate_constant(self, :SKIP)
34
37
 
35
38
  Dataset.def_sql_method(self, :select, %w'select limit distinct columns from join where having group compounds order')
36
39
 
@@ -47,11 +50,11 @@ module Sequel
47
50
 
48
51
  def select_limit_sql(sql)
49
52
  if o = @opts[:offset]
50
- sql << SKIP
53
+ sql << " SKIP "
51
54
  literal_append(sql, o)
52
55
  end
53
56
  if l = @opts[:limit]
54
- sql << FIRST
57
+ sql << " FIRST "
55
58
  literal_append(sql, l)
56
59
  end
57
60
  end
@@ -14,14 +14,26 @@ module Sequel
14
14
 
15
15
  module DatabaseMethods
16
16
  AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
17
+ Sequel::Deprecation.deprecate_constant(self, :AUTO_INCREMENT)
17
18
  SERVER_VERSION_RE = /^(\d+)\.(\d+)\.(\d+)/.freeze
19
+ Sequel::Deprecation.deprecate_constant(self, :SERVER_VERSION_RE)
18
20
  SERVER_VERSION_SQL = "SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)".freeze
21
+ Sequel::Deprecation.deprecate_constant(self, :SERVER_VERSION_SQL)
19
22
  SQL_BEGIN = "BEGIN TRANSACTION".freeze
23
+ Sequel::Deprecation.deprecate_constant(self, :SQL_BEGIN)
20
24
  SQL_COMMIT = "COMMIT TRANSACTION".freeze
25
+ Sequel::Deprecation.deprecate_constant(self, :SQL_COMMIT)
21
26
  SQL_ROLLBACK = "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION".freeze
27
+ Sequel::Deprecation.deprecate_constant(self, :SQL_ROLLBACK)
22
28
  SQL_ROLLBACK_TO_SAVEPOINT = 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_%d'.freeze
29
+ Sequel::Deprecation.deprecate_constant(self, :SQL_ROLLBACK_TO_SAVEPOINT)
23
30
  SQL_SAVEPOINT = 'SAVE TRANSACTION autopoint_%d'.freeze
31
+ Sequel::Deprecation.deprecate_constant(self, :SQL_SAVEPOINT)
24
32
  MSSQL_DEFAULT_RE = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/
33
+ Sequel::Deprecation.deprecate_constant(self, :MSSQL_DEFAULT_RE)
34
+ DECIMAL_TYPE_RE = /number|numeric|decimal/io
35
+ Sequel::Deprecation.deprecate_constant(self, :DECIMAL_TYPE_RE)
36
+
25
37
  FOREIGN_KEY_ACTION_MAP = {0 => :no_action, 1 => :cascade, 2 => :set_null, 3 => :set_default}.freeze
26
38
 
27
39
  include Sequel::Database::SplitAlterTable
@@ -37,10 +49,6 @@ module Sequel
37
49
  reset_default_dataset
38
50
  end
39
51
 
40
- # The types to check for 0 scale to transform :decimal types
41
- # to :integer.
42
- DECIMAL_TYPE_RE = /number|numeric|decimal/io
43
-
44
52
  # Execute the given stored procedure with the given name.
45
53
  #
46
54
  # Options:
@@ -215,7 +223,7 @@ module Sequel
215
223
  (conn.server_version rescue nil) if conn.respond_to?(:server_version)
216
224
  end
217
225
  unless @server_version
218
- m = SERVER_VERSION_RE.match(fetch(SERVER_VERSION_SQL).single_value.to_s)
226
+ m = /^(\d+)\.(\d+)\.(\d+)/.match(fetch("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)").single_value.to_s)
219
227
  @server_version = (m[1].to_i * 1000000) + (m[2].to_i * 10000) + m[3].to_i
220
228
  end
221
229
  @server_version
@@ -265,7 +273,7 @@ module Sequel
265
273
 
266
274
  # MSSQL uses the IDENTITY(1,1) column for autoincrementing columns.
267
275
  def auto_increment_sql
268
- AUTO_INCREMENT
276
+ 'IDENTITY(1,1)'
269
277
  end
270
278
 
271
279
  # MSSQL specific syntax for altering tables.
@@ -310,12 +318,12 @@ module Sequel
310
318
 
311
319
  # SQL to start a new savepoint
312
320
  def begin_savepoint_sql(depth)
313
- SQL_SAVEPOINT % depth
321
+ "SAVE TRANSACTION autopoint_#{depth}"
314
322
  end
315
323
 
316
324
  # SQL to BEGIN a transaction.
317
325
  def begin_transaction_sql
318
- SQL_BEGIN
326
+ "BEGIN TRANSACTION"
319
327
  end
320
328
 
321
329
  # MSSQL does not allow adding primary key constraints to NULLable columns.
@@ -325,7 +333,7 @@ module Sequel
325
333
 
326
334
  # Handle MSSQL specific default format.
327
335
  def column_schema_normalize_default(default, type)
328
- if m = MSSQL_DEFAULT_RE.match(default)
336
+ if m = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/.match(default)
329
337
  default = m[1] || m[2]
330
338
  end
331
339
  super(default, type)
@@ -339,7 +347,7 @@ module Sequel
339
347
 
340
348
  # SQL to COMMIT a transaction.
341
349
  def commit_transaction_sql
342
- SQL_COMMIT
350
+ "COMMIT TRANSACTION"
343
351
  end
344
352
 
345
353
  # MSSQL uses the name of the table to decide the difference between
@@ -418,12 +426,12 @@ module Sequel
418
426
 
419
427
  # SQL to rollback to a savepoint
420
428
  def rollback_savepoint_sql(depth)
421
- SQL_ROLLBACK_TO_SAVEPOINT % depth
429
+ "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_#{depth}"
422
430
  end
423
431
 
424
432
  # SQL to ROLLBACK a transaction.
425
433
  def rollback_transaction_sql
426
- SQL_ROLLBACK
434
+ "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
427
435
  end
428
436
 
429
437
  # The closest MSSQL equivalent of a boolean datatype is the bit type.
@@ -480,7 +488,7 @@ module Sequel
480
488
  end
481
489
  row[:allow_null] = row[:allow_null] == 'YES' ? true : false
482
490
  row[:default] = nil if blank_object?(row[:default])
483
- row[:type] = if row[:db_type] =~ DECIMAL_TYPE_RE && row[:scale] == 0
491
+ row[:type] = if row[:db_type] =~ /number|numeric|decimal/i && row[:scale] == 0
484
492
  :integer
485
493
  else
486
494
  schema_column_type(row[:db_type])
@@ -529,54 +537,98 @@ module Sequel
529
537
  end)
530
538
  include EmulateOffsetWithRowNumber
531
539
 
540
+ CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}#.freeze # SEQUEL5
541
+ EXTRACT_MAP = {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}#.freeze # SEQUEL5
542
+ #EXTRACT_MAP.each_value(&:freeze) # SEQUEL5
543
+ NON_SQL_OPTIONS = (Dataset::NON_SQL_OPTIONS + [:disable_insert_output, :mssql_unicode_strings]).freeze
544
+ LIMIT_ALL = Object.new.freeze
545
+
532
546
  BOOL_TRUE = '1'.freeze
547
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_TRUE)
533
548
  BOOL_FALSE = '0'.freeze
549
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_FALSE)
534
550
  COMMA_SEPARATOR = ', '.freeze
551
+ Sequel::Deprecation.deprecate_constant(self, :COMMA_SEPARATOR)
535
552
  TABLE_HINT = " WITH (".freeze
553
+ Sequel::Deprecation.deprecate_constant(self, :TABLE_HINT)
536
554
  READPAST = "READPAST".freeze
555
+ Sequel::Deprecation.deprecate_constant(self, :READPAST)
537
556
  NOLOCK = 'NOLOCK'.freeze
557
+ Sequel::Deprecation.deprecate_constant(self, :NOLOCK)
538
558
  UPDLOCK = 'UPDLOCK'.freeze
559
+ Sequel::Deprecation.deprecate_constant(self, :UPDLOCK)
539
560
  WILDCARD = LiteralString.new('*').freeze
540
- CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}
541
- EXTRACT_MAP = {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}
542
- BRACKET_CLOSE = Dataset::BRACKET_CLOSE
543
- BRACKET_OPEN = Dataset::BRACKET_OPEN
544
- COMMA = Dataset::COMMA
545
- PAREN_CLOSE = Dataset::PAREN_CLOSE
546
- PAREN_SPACE_OPEN = Dataset::PAREN_SPACE_OPEN
547
- SPACE = Dataset::SPACE
548
- FROM = Dataset::FROM
549
- APOS = Dataset::APOS
550
- APOS_RE = Dataset::APOS_RE
551
- DOUBLE_APOS = Dataset::DOUBLE_APOS
552
- INTO = Dataset::INTO
561
+ Sequel::Deprecation.deprecate_constant(self, :WILDCARD)
562
+ BRACKET_CLOSE = ']'.freeze
563
+ Sequel::Deprecation.deprecate_constant(self, :BRACKET_CLOSE)
564
+ BRACKET_OPEN = '['.freeze
565
+ Sequel::Deprecation.deprecate_constant(self, :BRACKET_OPEN)
566
+ COMMA = ', '.freeze
567
+ Sequel::Deprecation.deprecate_constant(self, :COMMA)
568
+ PAREN_CLOSE = ')'.freeze
569
+ Sequel::Deprecation.deprecate_constant(self, :PAREN_CLOSE)
570
+ PAREN_SPACE_OPEN = ' ('.freeze
571
+ Sequel::Deprecation.deprecate_constant(self, :PAREN_SPACE_OPEN)
572
+ SPACE = ' '.freeze
573
+ Sequel::Deprecation.deprecate_constant(self, :SPACE)
574
+ FROM = ' FROM '.freeze
575
+ Sequel::Deprecation.deprecate_constant(self, :FROM)
576
+ APOS = "'".freeze
577
+ Sequel::Deprecation.deprecate_constant(self, :APOS)
578
+ APOS_RE = /'/.freeze
579
+ Sequel::Deprecation.deprecate_constant(self, :APOS_RE)
580
+ DOUBLE_APOS = "''".freeze
581
+ Sequel::Deprecation.deprecate_constant(self, :DOUBLE_APOS)
582
+ INTO = " INTO ".freeze
583
+ Sequel::Deprecation.deprecate_constant(self, :INTO)
553
584
  DOUBLE_BRACKET_CLOSE = ']]'.freeze
585
+ Sequel::Deprecation.deprecate_constant(self, :DOUBLE_BRACKET_CLOSE)
554
586
  DATEPART_SECOND_OPEN = "CAST((datepart(".freeze
587
+ Sequel::Deprecation.deprecate_constant(self, :DATEPART_SECOND_OPEN)
555
588
  DATEPART_SECOND_MIDDLE = ') + datepart(ns, '.freeze
589
+ Sequel::Deprecation.deprecate_constant(self, :DATEPART_SECOND_MIDDLE)
556
590
  DATEPART_SECOND_CLOSE = ")/1000000000.0) AS double precision)".freeze
591
+ Sequel::Deprecation.deprecate_constant(self, :DATEPART_SECOND_CLOSE)
557
592
  DATEPART_OPEN = "datepart(".freeze
593
+ Sequel::Deprecation.deprecate_constant(self, :DATEPART_OPEN)
558
594
  OUTPUT_INSERTED = " OUTPUT INSERTED.*".freeze
595
+ Sequel::Deprecation.deprecate_constant(self, :OUTPUT_INSERTED)
559
596
  HEX_START = '0x'.freeze
597
+ Sequel::Deprecation.deprecate_constant(self, :HEX_START)
560
598
  UNICODE_STRING_START = "N'".freeze
599
+ Sequel::Deprecation.deprecate_constant(self, :UNICODE_STRING_START)
561
600
  BACKSLASH_CRLF_RE = /\\((?:\r\n)|\n)/.freeze
601
+ Sequel::Deprecation.deprecate_constant(self, :BACKSLASH_CRLF_RE)
562
602
  BACKSLASH_CRLF_REPLACE = '\\\\\\\\\\1\\1'.freeze
603
+ Sequel::Deprecation.deprecate_constant(self, :BACKSLASH_CRLF_REPLACE)
563
604
  TOP_PAREN = " TOP (".freeze
605
+ Sequel::Deprecation.deprecate_constant(self, :TOP_PAREN)
564
606
  TOP = " TOP ".freeze
607
+ Sequel::Deprecation.deprecate_constant(self, :TOP)
565
608
  OUTPUT = " OUTPUT ".freeze
609
+ Sequel::Deprecation.deprecate_constant(self, :OUTPUT)
566
610
  HSTAR = "H*".freeze
611
+ Sequel::Deprecation.deprecate_constant(self, :HSTAR)
567
612
  CASE_SENSITIVE_COLLATION = 'Latin1_General_CS_AS'.freeze
613
+ Sequel::Deprecation.deprecate_constant(self, :CASE_SENSITIVE_COLLATION)
568
614
  CASE_INSENSITIVE_COLLATION = 'Latin1_General_CI_AS'.freeze
615
+ Sequel::Deprecation.deprecate_constant(self, :CASE_INSENSITIVE_COLLATION)
569
616
  DEFAULT_TIMESTAMP_FORMAT = "'%Y-%m-%dT%H:%M:%S%N%z'".freeze
617
+ Sequel::Deprecation.deprecate_constant(self, :DEFAULT_TIMESTAMP_FORMAT)
570
618
  FORMAT_DATE = "'%Y%m%d'".freeze
619
+ Sequel::Deprecation.deprecate_constant(self, :FORMAT_DATE)
571
620
  CROSS_APPLY = 'CROSS APPLY'.freeze
621
+ Sequel::Deprecation.deprecate_constant(self, :CROSS_APPLY)
572
622
  OUTER_APPLY = 'OUTER APPLY'.freeze
623
+ Sequel::Deprecation.deprecate_constant(self, :OUTER_APPLY)
573
624
  OFFSET = " OFFSET ".freeze
625
+ Sequel::Deprecation.deprecate_constant(self, :OFFSET)
574
626
  ROWS = " ROWS".freeze
627
+ Sequel::Deprecation.deprecate_constant(self, :ROWS)
575
628
  ROWS_ONLY = " ROWS ONLY".freeze
629
+ Sequel::Deprecation.deprecate_constant(self, :ROWS_ONLY)
576
630
  FETCH_NEXT = " FETCH NEXT ".freeze
577
-
578
- NON_SQL_OPTIONS = (Dataset::NON_SQL_OPTIONS + [:disable_insert_output, :mssql_unicode_strings]).freeze
579
- LIMIT_ALL = Object.new.freeze
631
+ Sequel::Deprecation.deprecate_constant(self, :FETCH_NEXT)
580
632
 
581
633
  Dataset.def_mutation_method(:disable_insert_output, :output, :module=>self)
582
634
  Dataset.def_sql_method(self, :delete, %w'with delete limit from output from2 where')
@@ -604,25 +656,25 @@ module Sequel
604
656
  when :'||'
605
657
  super(sql, :+, args)
606
658
  when :LIKE, :"NOT LIKE"
607
- super(sql, op, args.map{|a| Sequel.lit(["(", " COLLATE #{CASE_SENSITIVE_COLLATION})"], a)})
659
+ super(sql, op, args.map{|a| Sequel.lit(["(", " COLLATE Latin1_General_CS_AS)"], a)})
608
660
  when :ILIKE, :"NOT ILIKE"
609
- super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|a| Sequel.lit(["(", " COLLATE #{CASE_INSENSITIVE_COLLATION})"], a)})
661
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|a| Sequel.lit(["(", " COLLATE Latin1_General_CI_AS)"], a)})
610
662
  when :<<, :>>
611
663
  complex_expression_emulate_append(sql, op, args)
612
664
  when :extract
613
- part = args.at(0)
665
+ part = args[0]
614
666
  raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
615
667
  if part == :second
616
- expr = args.at(1)
617
- sql << DATEPART_SECOND_OPEN << format.to_s << COMMA
668
+ expr = args[1]
669
+ sql << "CAST((datepart(" << format.to_s << ', '
618
670
  literal_append(sql, expr)
619
- sql << DATEPART_SECOND_MIDDLE
671
+ sql << ') + datepart(ns, '
620
672
  literal_append(sql, expr)
621
- sql << DATEPART_SECOND_CLOSE
673
+ sql << ")/1000000000.0) AS double precision)"
622
674
  else
623
- sql << DATEPART_OPEN << format.to_s << COMMA
624
- literal_append(sql, args.at(1))
625
- sql << PAREN_CLOSE
675
+ sql << "datepart(" << format.to_s << ', '
676
+ literal_append(sql, args[1])
677
+ sql << ')'
626
678
  end
627
679
  else
628
680
  super
@@ -656,7 +708,7 @@ module Sequel
656
708
  # MSSQL uses the CONTAINS keyword for full text search
657
709
  def full_text_search(cols, terms, opts = OPTS)
658
710
  terms = "\"#{terms.join('" OR "')}\"" if terms.is_a?(Array)
659
- where("CONTAINS (?, ?)", cols, terms)
711
+ where(Sequel.lit("CONTAINS (?, ?)", cols, terms))
660
712
  end
661
713
 
662
714
  # Use the OUTPUT clause to get the value of all columns for the newly inserted record.
@@ -714,7 +766,7 @@ module Sequel
714
766
 
715
767
  # MSSQL uses [] to quote identifiers.
716
768
  def quoted_identifier_append(sql, name)
717
- sql << BRACKET_OPEN << name.to_s.gsub(/\]/, DOUBLE_BRACKET_CLOSE) << BRACKET_CLOSE
769
+ sql << '[' << name.to_s.gsub(/\]/, ']]') << ']'
718
770
  end
719
771
 
720
772
  # Emulate RETURNING using the output clause. This only handles values that are simple column references.
@@ -895,12 +947,12 @@ module Sequel
895
947
  # since that is the format that is multilanguage and not
896
948
  # DATEFORMAT dependent.
897
949
  def default_timestamp_format
898
- DEFAULT_TIMESTAMP_FORMAT
950
+ "'%Y-%m-%dT%H:%M:%S%N%z'"
899
951
  end
900
952
 
901
953
  # Only include the primary table in the main delete clause
902
954
  def delete_from_sql(sql)
903
- sql << FROM
955
+ sql << ' FROM '
904
956
  source_list_append(sql, @opts[:from][0..0])
905
957
  end
906
958
 
@@ -954,9 +1006,9 @@ module Sequel
954
1006
  def join_type_sql(join_type)
955
1007
  case join_type
956
1008
  when :cross_apply
957
- CROSS_APPLY
1009
+ 'CROSS APPLY'
958
1010
  when :outer_apply
959
- OUTER_APPLY
1011
+ 'OUTER APPLY'
960
1012
  else
961
1013
  super
962
1014
  end
@@ -964,30 +1016,30 @@ module Sequel
964
1016
 
965
1017
  # MSSQL uses a literal hexidecimal number for blob strings
966
1018
  def literal_blob_append(sql, v)
967
- sql << HEX_START << v.unpack(HSTAR).first
1019
+ sql << '0x' << v.unpack("H*").first
968
1020
  end
969
1021
 
970
1022
  # Use YYYYmmdd format, since that's the only want that is
971
1023
  # multilanguage and not DATEFORMAT dependent.
972
1024
  def literal_date(v)
973
- v.strftime(FORMAT_DATE)
1025
+ v.strftime("'%Y%m%d'")
974
1026
  end
975
1027
 
976
1028
  # Use 0 for false on MSSQL
977
1029
  def literal_false
978
- BOOL_FALSE
1030
+ '0'
979
1031
  end
980
1032
 
981
1033
  # Optionally use unicode string syntax for all strings. Don't double
982
1034
  # backslashes.
983
1035
  def literal_string_append(sql, v)
984
- sql << (mssql_unicode_strings ? UNICODE_STRING_START : APOS)
985
- sql << v.gsub(APOS_RE, DOUBLE_APOS).gsub(BACKSLASH_CRLF_RE, BACKSLASH_CRLF_REPLACE) << APOS
1036
+ sql << (mssql_unicode_strings ? "N'" : "'")
1037
+ sql << v.gsub("'", "''").gsub(/\\((?:\r\n)|\n)/, '\\\\\\\\\\1\\1') << "'"
986
1038
  end
987
1039
 
988
1040
  # Use 1 for true on MSSQL
989
1041
  def literal_true
990
- BOOL_TRUE
1042
+ '1'
991
1043
  end
992
1044
 
993
1045
  # MSSQL 2008+ supports multiple rows in the VALUES clause, older versions
@@ -1003,7 +1055,7 @@ module Sequel
1003
1055
 
1004
1056
  def select_into_sql(sql)
1005
1057
  if i = @opts[:into]
1006
- sql << INTO
1058
+ sql << " INTO "
1007
1059
  identifier_append(sql, i)
1008
1060
  end
1009
1061
  end
@@ -1022,12 +1074,12 @@ module Sequel
1022
1074
  if l == LIMIT_ALL
1023
1075
  sql << " TOP (100) PERCENT"
1024
1076
  else
1025
- sql << TOP_PAREN
1077
+ sql << " TOP ("
1026
1078
  literal_append(sql, l)
1027
- sql << PAREN_CLOSE
1079
+ sql << ')'
1028
1080
  end
1029
1081
  else
1030
- sql << TOP
1082
+ sql << " TOP "
1031
1083
  literal_append(sql, l)
1032
1084
  end
1033
1085
  end
@@ -1048,25 +1100,25 @@ module Sequel
1048
1100
  lock_hint = for_update || dirty
1049
1101
 
1050
1102
  if lock_hint || skip_locked
1051
- sql << TABLE_HINT
1103
+ sql << " WITH ("
1052
1104
 
1053
1105
  if lock_hint
1054
1106
  sql << if for_update
1055
- UPDLOCK
1107
+ 'UPDLOCK'
1056
1108
  else
1057
- NOLOCK
1109
+ 'NOLOCK'
1058
1110
  end
1059
1111
  end
1060
1112
 
1061
1113
  if lock_hint && skip_locked
1062
- sql << COMMA_SEPARATOR
1114
+ sql << ', '
1063
1115
  end
1064
1116
 
1065
1117
  if skip_locked
1066
- sql << READPAST
1118
+ sql << "READPAST"
1067
1119
  end
1068
1120
 
1069
- sql << PAREN_CLOSE
1121
+ sql << ')'
1070
1122
  else
1071
1123
  super
1072
1124
  end
@@ -1078,14 +1130,14 @@ module Sequel
1078
1130
  super
1079
1131
  if is_2012_or_later? && @opts[:order]
1080
1132
  if o = @opts[:offset]
1081
- sql << OFFSET
1133
+ sql << " OFFSET "
1082
1134
  literal_append(sql, o)
1083
- sql << ROWS
1135
+ sql << " ROWS"
1084
1136
 
1085
1137
  if l = @opts[:limit]
1086
- sql << FETCH_NEXT
1138
+ sql << " FETCH NEXT "
1087
1139
  literal_append(sql, l)
1088
- sql << ROWS_ONLY
1140
+ sql << " ROWS ONLY"
1089
1141
  end
1090
1142
  end
1091
1143
  end
@@ -1102,21 +1154,21 @@ module Sequel
1102
1154
  end
1103
1155
 
1104
1156
  def output_list_sql(sql, output)
1105
- sql << OUTPUT
1157
+ sql << " OUTPUT "
1106
1158
  column_list_append(sql, output[:select_list])
1107
1159
  if into = output[:into]
1108
- sql << INTO
1160
+ sql << " INTO "
1109
1161
  identifier_append(sql, into)
1110
1162
  if column_list = output[:column_list]
1111
- sql << PAREN_SPACE_OPEN
1163
+ sql << ' ('
1112
1164
  source_list_append(sql, column_list)
1113
- sql << PAREN_CLOSE
1165
+ sql << ')'
1114
1166
  end
1115
1167
  end
1116
1168
  end
1117
1169
 
1118
1170
  def output_returning_sql(sql, type, values)
1119
- sql << OUTPUT
1171
+ sql << " OUTPUT "
1120
1172
  if values.empty?
1121
1173
  literal_append(sql, SQL::ColumnAll.new(type))
1122
1174
  else
@@ -1132,14 +1184,22 @@ module Sequel
1132
1184
  end
1133
1185
  end
1134
1186
 
1135
- # MSSQL supports millisecond timestamp precision.
1187
+ # MSSQL supports 100-nsec precision for time columns, but ruby by
1188
+ # default only supports usec precision.
1189
+ def sqltime_precision
1190
+ 6
1191
+ end
1192
+
1193
+ # MSSQL supports millisecond timestamp precision for datetime columns.
1194
+ # 100-nsec precision is supported for datetime2 columns, but Sequel does
1195
+ # not know what the column type is when formatting values.
1136
1196
  def timestamp_precision
1137
1197
  3
1138
1198
  end
1139
1199
 
1140
1200
  # Only include the primary table in the main update clause
1141
1201
  def update_table_sql(sql)
1142
- sql << SPACE
1202
+ sql << ' '
1143
1203
  source_list_append(sql, @opts[:from][0..0])
1144
1204
  end
1145
1205