sequel 4.45.0 → 4.46.0

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