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
@@ -67,7 +67,7 @@ module Sequel
67
67
  attr_accessor :force_standard_strings
68
68
  end
69
69
 
70
- class CreateTableGenerator < Sequel::Schema::Generator
70
+ class CreateTableGenerator < Sequel::Schema::CreateTableGenerator
71
71
  # Add an exclusion constraint when creating the table. Elements should be
72
72
  # an array of 2 element arrays, with the first element being the column or
73
73
  # expression the exclusion constraint is applied to, and the second element
@@ -111,14 +111,17 @@ module Sequel
111
111
  module DatabaseMethods
112
112
  include UnmodifiedIdentifiers::DatabaseMethods
113
113
 
114
- PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
115
114
  RE_CURRVAL_ERROR = /currval of sequence "(.*)" is not yet defined in this session|relation "(.*)" does not exist/.freeze
116
- FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'.freeze=>:no_action, 'r'.freeze=>:restrict, 'c'.freeze=>:cascade, 'n'.freeze=>:set_null, 'd'.freeze=>:set_default}.freeze
115
+ Sequel::Deprecation.deprecate_constant(self, :RE_CURRVAL_ERROR)
117
116
  POSTGRES_DEFAULT_RE = /\A(?:B?('.*')::[^']+|\((-?\d+(?:\.\d+)?)\))\z/
117
+ Sequel::Deprecation.deprecate_constant(self, :POSTGRES_DEFAULT_RE)
118
118
  UNLOGGED = 'UNLOGGED '.freeze
119
- ON_COMMIT = {
120
- :drop => 'DROP', :delete_rows => 'DELETE ROWS', :preserve_rows => 'PRESERVE ROWS',
121
- }.freeze
119
+ Sequel::Deprecation.deprecate_constant(self, :UNLOGGED)
120
+
121
+ PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
122
+ FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'=>:no_action, 'r'=>:restrict, 'c'=>:cascade, 'n'=>:set_null, 'd'=>:set_default}.freeze
123
+ ON_COMMIT = {:drop => 'DROP', :delete_rows => 'DELETE ROWS', :preserve_rows => 'PRESERVE ROWS'}.freeze
124
+ #ON_COMMIT.each_value(&:freeze) # SEQUEL5
122
125
 
123
126
  # SQL fragment for custom sequences (ones not created by serial primary key),
124
127
  # Returning the schema and literal form of the sequence name, by parsing
@@ -183,7 +186,7 @@ module Sequel
183
186
  # the conversion proc is looked up in the PG_NAMED_TYPES hash.
184
187
  def add_named_conversion_proc(name, &block)
185
188
  unless block
186
- if block = PG_NAMED_TYPES[name]
189
+ if block = PG_NAMED__TYPES[name]
187
190
  Sequel::Deprecation.deprecate("Sequel::PG_NAMED_TYPES", "Call Database#add_named_conversion_proc directly for each database you want to support the #{name} type")
188
191
  end
189
192
  end
@@ -698,7 +701,7 @@ module Sequel
698
701
 
699
702
  # Handle PostgreSQL specific default format.
700
703
  def column_schema_normalize_default(default, type)
701
- if m = POSTGRES_DEFAULT_RE.match(default)
704
+ if m = /\A(?:B?('.*')::[^']+|\((-?\d+(?:\.\d+)?)\))\z/.match(default)
702
705
  default = m[1] || m[2]
703
706
  end
704
707
  super(default, type)
@@ -795,11 +798,13 @@ module Sequel
795
798
  end
796
799
 
797
800
  EXCLUSION_CONSTRAINT_SQL_STATE = '23P01'.freeze
801
+ Sequel::Deprecation.deprecate_constant(self, :EXCLUSION_CONSTRAINT_SQL_STATE)
798
802
  DEADLOCK_SQL_STATE = '40P01'.freeze
803
+ Sequel::Deprecation.deprecate_constant(self, :DEADLOCK_SQL_STATE)
799
804
  def database_specific_error_class_from_sqlstate(sqlstate)
800
- if sqlstate == EXCLUSION_CONSTRAINT_SQL_STATE
805
+ if sqlstate == '23P01'
801
806
  ExclusionConstraintViolation
802
- elsif sqlstate == DEADLOCK_SQL_STATE
807
+ elsif sqlstate == '40P01'
803
808
  SerializationFailure
804
809
  else
805
810
  super
@@ -900,7 +905,7 @@ module Sequel
900
905
  raise(Error, "can't provide both :foreign and :unlogged to create_table") if options[:unlogged]
901
906
  'FOREIGN '
902
907
  elsif options[:unlogged]
903
- UNLOGGED
908
+ 'UNLOGGED '
904
909
  end
905
910
 
906
911
  "CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
@@ -1014,10 +1019,10 @@ module Sequel
1014
1019
  def get_conversion_procs
1015
1020
  procs = PG_TYPES.dup
1016
1021
  procs[1184] = procs[1114] = method(:to_application_timestamp)
1017
- unless PG_NAMED_TYPES.empty?
1018
- Sequel::Deprecation.deprecate("Sequel::PG_NAMED_TYPES", "Call Database#add_named_conversion_proc directly for each Database instance where you want to support the following type(s): #{PG_NAMED_TYPES.keys.join(', ')}")
1022
+ unless PG_NAMED__TYPES.empty?
1023
+ Sequel::Deprecation.deprecate("Sequel::PG_NAMED_TYPES", "Call Database#add_named_conversion_proc directly for each Database instance where you want to support the following type(s): #{PG_NAMED__TYPES.keys.join(', ')}")
1019
1024
  end
1020
- add_named_conversion_procs(procs, PG_NAMED_TYPES)
1025
+ add_named_conversion_procs(procs, PG_NAMED__TYPES)
1021
1026
  procs
1022
1027
  end
1023
1028
 
@@ -1236,43 +1241,71 @@ module Sequel
1236
1241
  include UnmodifiedIdentifiers::DatasetMethods
1237
1242
 
1238
1243
  ACCESS_SHARE = 'ACCESS SHARE'.freeze
1244
+ Sequel::Deprecation.deprecate_constant(self, :ACCESS_SHARE)
1239
1245
  ACCESS_EXCLUSIVE = 'ACCESS EXCLUSIVE'.freeze
1246
+ Sequel::Deprecation.deprecate_constant(self, :ACCESS_EXCLUSIVE)
1240
1247
  BOOL_FALSE = 'false'.freeze
1248
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_FALSE)
1241
1249
  BOOL_TRUE = 'true'.freeze
1250
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_TRUE)
1242
1251
  COMMA_SEPARATOR = ', '.freeze
1252
+ Sequel::Deprecation.deprecate_constant(self, :COMMA_SEPARATOR)
1243
1253
  EXCLUSIVE = 'EXCLUSIVE'.freeze
1254
+ Sequel::Deprecation.deprecate_constant(self, :EXCLUSIVE)
1244
1255
  EXPLAIN = 'EXPLAIN '.freeze
1256
+ Sequel::Deprecation.deprecate_constant(self, :EXPLAIN)
1245
1257
  EXPLAIN_ANALYZE = 'EXPLAIN ANALYZE '.freeze
1258
+ Sequel::Deprecation.deprecate_constant(self, :EXPLAIN_ANALYZE)
1246
1259
  FOR_SHARE = ' FOR SHARE'.freeze
1247
- NULL = LiteralString.new('NULL').freeze
1260
+ Sequel::Deprecation.deprecate_constant(self, :FOR_SHARE)
1248
1261
  PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
1262
+ Sequel::Deprecation.deprecate_constant(self, :PG_TIMESTAMP_FORMAT)
1249
1263
  QUERY_PLAN = 'QUERY PLAN'.to_sym
1264
+ Sequel::Deprecation.deprecate_constant(self, :QUERY_PLAN)
1250
1265
  ROW_EXCLUSIVE = 'ROW EXCLUSIVE'.freeze
1266
+ Sequel::Deprecation.deprecate_constant(self, :ROW_EXCLUSIVE)
1251
1267
  ROW_SHARE = 'ROW SHARE'.freeze
1268
+ Sequel::Deprecation.deprecate_constant(self, :ROW_SHARE)
1252
1269
  SHARE = 'SHARE'.freeze
1270
+ Sequel::Deprecation.deprecate_constant(self, :SHARE)
1253
1271
  SHARE_ROW_EXCLUSIVE = 'SHARE ROW EXCLUSIVE'.freeze
1272
+ Sequel::Deprecation.deprecate_constant(self, :SHARE_ROW_EXCLUSIVE)
1254
1273
  SHARE_UPDATE_EXCLUSIVE = 'SHARE UPDATE EXCLUSIVE'.freeze
1274
+ Sequel::Deprecation.deprecate_constant(self, :SHARE_UPDATE_EXCLUSIVE)
1255
1275
  SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
1256
- SPACE = Dataset::SPACE
1257
- FROM = Dataset::FROM
1258
- APOS = Dataset::APOS
1259
- APOS_RE = Dataset::APOS_RE
1260
- DOUBLE_APOS = Dataset::DOUBLE_APOS
1261
- PAREN_OPEN = Dataset::PAREN_OPEN
1262
- PAREN_CLOSE = Dataset::PAREN_CLOSE
1263
- COMMA = Dataset::COMMA
1264
- ESCAPE = Dataset::ESCAPE
1265
- BACKSLASH = Dataset::BACKSLASH
1266
- AS = Dataset::AS
1276
+ Sequel::Deprecation.deprecate_constant(self, :SQL_WITH_RECURSIVE)
1277
+ SPACE = ' '.freeze
1278
+ Sequel::Deprecation.deprecate_constant(self, :SPACE)
1279
+ FROM = ' FROM '.freeze
1280
+ Sequel::Deprecation.deprecate_constant(self, :FROM)
1281
+ APOS = "'".freeze
1282
+ Sequel::Deprecation.deprecate_constant(self, :APOS)
1283
+ APOS_RE = /'/.freeze
1284
+ Sequel::Deprecation.deprecate_constant(self, :APOS_RE)
1285
+ DOUBLE_APOS = "''".freeze
1286
+ Sequel::Deprecation.deprecate_constant(self, :DOUBLE_APOS)
1287
+ PAREN_CLOSE = ')'.freeze
1288
+ Sequel::Deprecation.deprecate_constant(self, :PAREN_CLOSE)
1289
+ PAREN_OPEN = '('.freeze
1290
+ Sequel::Deprecation.deprecate_constant(self, :PAREN_OPEN)
1291
+ COMMA = ', '.freeze
1292
+ Sequel::Deprecation.deprecate_constant(self, :COMMA)
1293
+ ESCAPE = " ESCAPE ".freeze
1294
+ Sequel::Deprecation.deprecate_constant(self, :ESCAPE)
1295
+ BACKSLASH = "\\".freeze
1296
+ Sequel::Deprecation.deprecate_constant(self, :BACKSLASH)
1297
+ AS = ' AS '.freeze
1298
+ Sequel::Deprecation.deprecate_constant(self, :AS)
1267
1299
  XOR_OP = ' # '.freeze
1268
1300
  CRLF = "\r\n".freeze
1269
1301
  BLOB_RE = /[\000-\037\047\134\177-\377]/n.freeze
1270
1302
  WINDOW = " WINDOW ".freeze
1271
1303
  SELECT_VALUES = "VALUES ".freeze
1272
1304
  EMPTY_STRING = ''.freeze
1273
- LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each(&:freeze)
1274
1305
  SKIP_LOCKED = " SKIP LOCKED".freeze
1275
1306
 
1307
+ NULL = LiteralString.new('NULL').freeze
1308
+ LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each(&:freeze)
1276
1309
  NON_SQL_OPTIONS = (Dataset::NON_SQL_OPTIONS + [:cursor, :insert_conflict]).freeze
1277
1310
 
1278
1311
  Dataset.def_sql_method(self, :delete, [['if server_version >= 90100', %w'with delete from using where returning'], ['else', %w'delete from using where returning']])
@@ -1291,7 +1324,7 @@ module Sequel
1291
1324
  def complex_expression_sql_append(sql, op, args)
1292
1325
  case op
1293
1326
  when :^
1294
- j = XOR_OP
1327
+ j = ' # '
1295
1328
  c = false
1296
1329
  args.each do |a|
1297
1330
  sql << j if c
@@ -1299,13 +1332,13 @@ module Sequel
1299
1332
  c ||= true
1300
1333
  end
1301
1334
  when :ILIKE, :'NOT ILIKE'
1302
- sql << PAREN_OPEN
1303
- literal_append(sql, args.at(0))
1304
- sql << SPACE << op.to_s << SPACE
1305
- literal_append(sql, args.at(1))
1306
- sql << ESCAPE
1307
- literal_append(sql, BACKSLASH)
1308
- sql << PAREN_CLOSE
1335
+ sql << '('
1336
+ literal_append(sql, args[0])
1337
+ sql << ' ' << op.to_s << ' '
1338
+ literal_append(sql, args[1])
1339
+ sql << " ESCAPE "
1340
+ literal_append(sql, "\\")
1341
+ sql << ')'
1309
1342
  else
1310
1343
  super
1311
1344
  end
@@ -1331,7 +1364,7 @@ module Sequel
1331
1364
 
1332
1365
  # Return the results of an EXPLAIN query as a string
1333
1366
  def explain(opts=OPTS)
1334
- with_sql((opts[:analyze] ? EXPLAIN_ANALYZE : EXPLAIN) + select_sql).map(QUERY_PLAN).join(CRLF)
1367
+ with_sql((opts[:analyze] ? 'EXPLAIN ANALYZE ' : 'EXPLAIN ') + select_sql).map(:'QUERY PLAN').join("\r\n")
1335
1368
  end
1336
1369
 
1337
1370
  # Return a cloned dataset which will use FOR SHARE to lock returned rows.
@@ -1379,7 +1412,7 @@ module Sequel
1379
1412
  terms = Sequel.function(query_func, lang, phrase_terms)
1380
1413
  end
1381
1414
 
1382
- ds = where(Sequel.lit(["(", " @@ ", ")"], cols, terms))
1415
+ ds = where(Sequel.lit(["", " @@ ", ""], cols, terms))
1383
1416
 
1384
1417
  if opts[:phrase]
1385
1418
  raise Error, "can't use :phrase with either :tsvector or :tsquery arguments to full_text_search together" if opts[:tsvector] || opts[:tsquery]
@@ -1600,7 +1633,9 @@ module Sequel
1600
1633
  end
1601
1634
  end
1602
1635
 
1603
- # Return a clone of the dataset with an addition named window that can be referenced in window functions.
1636
+ # Return a clone of the dataset with an addition named window that can be
1637
+ # referenced in window functions. See {SQL::Window} for a list of options
1638
+ # that can be passed in.
1604
1639
  def window(name, opts)
1605
1640
  clone(:window=>(@opts[:window]||[]) + [[name, SQL::Window.new(opts)]])
1606
1641
  end
@@ -1640,7 +1675,7 @@ module Sequel
1640
1675
 
1641
1676
  # Only include the primary table in the main delete clause
1642
1677
  def delete_from_sql(sql)
1643
- sql << FROM
1678
+ sql << ' FROM '
1644
1679
  source_list_append(sql, @opts[:from][0..0])
1645
1680
  end
1646
1681
 
@@ -1697,7 +1732,7 @@ module Sequel
1697
1732
  if(from = @opts[:from][1..-1]).empty?
1698
1733
  raise(Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs') if @opts[:join]
1699
1734
  else
1700
- sql << SPACE << type.to_s << SPACE
1735
+ sql << ' ' << type.to_s << ' '
1701
1736
  source_list_append(sql, from)
1702
1737
  select_join_sql(sql)
1703
1738
  end
@@ -1705,12 +1740,12 @@ module Sequel
1705
1740
 
1706
1741
  # Use a generic blob quoting method, hopefully overridden in one of the subadapter methods
1707
1742
  def literal_blob_append(sql, v)
1708
- sql << APOS << v.gsub(BLOB_RE){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"} << APOS
1743
+ sql << "'" << v.gsub(/[\000-\037\047\134\177-\377]/n){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"} << "'"
1709
1744
  end
1710
1745
 
1711
1746
  # PostgreSQL uses FALSE for false values
1712
1747
  def literal_false
1713
- BOOL_FALSE
1748
+ 'false'
1714
1749
  end
1715
1750
 
1716
1751
  # PostgreSQL quotes NaN and Infinity.
@@ -1728,12 +1763,12 @@ module Sequel
1728
1763
 
1729
1764
  # Assume that SQL standard quoting is on, per Sequel's defaults
1730
1765
  def literal_string_append(sql, v)
1731
- sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
1766
+ sql << "'" << v.gsub("'", "''") << "'"
1732
1767
  end
1733
1768
 
1734
1769
  # PostgreSQL uses FALSE for false values
1735
1770
  def literal_true
1736
- BOOL_TRUE
1771
+ 'true'
1737
1772
  end
1738
1773
 
1739
1774
  # PostgreSQL supports multiple rows in INSERT.
@@ -1749,38 +1784,38 @@ module Sequel
1749
1784
  # PostgreSQL requires parentheses around compound datasets if they use
1750
1785
  # CTEs, and using them in other places doesn't hurt.
1751
1786
  def compound_dataset_sql_append(sql, ds)
1752
- sql << PAREN_OPEN
1787
+ sql << '('
1753
1788
  super
1754
- sql << PAREN_CLOSE
1789
+ sql << ')'
1755
1790
  end
1756
1791
 
1757
1792
  # Support FOR SHARE locking when using the :share lock style.
1758
1793
  # Use SKIP LOCKED if skipping locked rows.
1759
1794
  def select_lock_sql(sql)
1760
1795
  if @opts[:lock] == :share
1761
- sql << FOR_SHARE
1796
+ sql << ' FOR SHARE'
1762
1797
  else
1763
1798
  super
1764
1799
  end
1765
1800
 
1766
1801
  if @opts[:skip_locked]
1767
- sql << SKIP_LOCKED
1802
+ sql << " SKIP LOCKED"
1768
1803
  end
1769
1804
  end
1770
1805
 
1771
1806
  # Support VALUES clause instead of the SELECT clause to return rows.
1772
1807
  def select_values_sql(sql)
1773
- sql << SELECT_VALUES
1808
+ sql << "VALUES "
1774
1809
  expression_list_append(sql, opts[:values])
1775
1810
  end
1776
1811
 
1777
1812
  # SQL fragment for named window specifications
1778
1813
  def select_window_sql(sql)
1779
1814
  if ws = @opts[:window]
1780
- sql << WINDOW
1815
+ sql << " WINDOW "
1781
1816
  c = false
1782
- co = COMMA
1783
- as = AS
1817
+ co = ', '
1818
+ as = ' AS '
1784
1819
  ws.map do |name, window|
1785
1820
  sql << co if c
1786
1821
  literal_append(sql, name)
@@ -1793,7 +1828,7 @@ module Sequel
1793
1828
 
1794
1829
  # Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
1795
1830
  def select_with_sql_base
1796
- opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super
1831
+ opts[:with].any?{|w| w[:recursive]} ? "WITH RECURSIVE " : super
1797
1832
  end
1798
1833
 
1799
1834
  # The version of the database server
@@ -1816,8 +1851,8 @@ module Sequel
1816
1851
 
1817
1852
  # Concatenate the expressions with a space in between
1818
1853
  def full_text_string_join(cols)
1819
- cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, EMPTY_STRING)}
1820
- cols = cols.zip([SPACE] * cols.length).flatten
1854
+ cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, '')}
1855
+ cols = cols.zip([' '] * cols.length).flatten
1821
1856
  cols.pop
1822
1857
  SQL::StringExpression.new(:'||', *cols)
1823
1858
  end
@@ -1829,7 +1864,7 @@ module Sequel
1829
1864
 
1830
1865
  # Only include the primary table in the main update clause
1831
1866
  def update_table_sql(sql)
1832
- sql << SPACE
1867
+ sql << ' '
1833
1868
  source_list_append(sql, @opts[:from][0..0])
1834
1869
  end
1835
1870
  end
@@ -19,12 +19,19 @@ module Sequel
19
19
  attr_writer :convert_smallint_to_bool
20
20
 
21
21
  AUTO_INCREMENT = 'IDENTITY'.freeze
22
+ Sequel::Deprecation.deprecate_constant(self, :AUTO_INCREMENT)
22
23
  SQL_BEGIN = "BEGIN TRANSACTION".freeze
24
+ Sequel::Deprecation.deprecate_constant(self, :SQL_BEGIN)
23
25
  SQL_COMMIT = "COMMIT TRANSACTION".freeze
26
+ Sequel::Deprecation.deprecate_constant(self, :SQL_COMMIT)
24
27
  SQL_ROLLBACK = "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION".freeze
28
+ Sequel::Deprecation.deprecate_constant(self, :SQL_ROLLBACK)
25
29
  TEMPORARY = "GLOBAL TEMPORARY ".freeze
30
+ Sequel::Deprecation.deprecate_constant(self, :TEMPORARY)
26
31
  SMALLINT_RE = /smallint/i.freeze
27
- DECIMAL_TYPE_RE = /numeric/io
32
+ Sequel::Deprecation.deprecate_constant(self, :SMALLINT_RE)
33
+ DECIMAL_TYPE_RE = /numeric/i
34
+ Sequel::Deprecation.deprecate_constant(self, :DECIMAL_TYPE_RE)
28
35
 
29
36
  # Whether to convert smallint to boolean arguments for this dataset.
30
37
  # Defaults to the SqlAnywhere module setting.
@@ -49,7 +56,7 @@ module Sequel
49
56
 
50
57
  # Convert smallint type to boolean if convert_smallint_to_bool is true
51
58
  def schema_column_type(db_type)
52
- if convert_smallint_to_bool && db_type =~ SMALLINT_RE
59
+ if convert_smallint_to_bool && db_type =~ /smallint/i
53
60
  :boolean
54
61
  else
55
62
  super
@@ -67,9 +74,9 @@ module Sequel
67
74
  auto_increment = row.delete(:is_autoincrement)
68
75
  row[:auto_increment] = auto_increment == 1 || auto_increment == true
69
76
  row[:primary_key] = row.delete(:pkey) == 'Y'
70
- row[:allow_null] = row[:nulls_allowed].is_a?(Fixnum) ? row.delete(:nulls_allowed) == 1 : row.delete(:nulls_allowed)
77
+ row[:allow_null] = row[:nulls_allowed].is_a?(Integer) ? row.delete(:nulls_allowed) == 1 : row.delete(:nulls_allowed)
71
78
  row[:db_type] = row.delete(:domain_name)
72
- row[:type] = if row[:db_type] =~ DECIMAL_TYPE_RE and (row[:scale].is_a?(Fixnum) ? row[:scale] == 0 : !row[:scale])
79
+ row[:type] = if row[:db_type] =~ /numeric/i and (row[:scale].is_a?(Integer) ? row[:scale] == 0 : !row[:scale])
73
80
  :integer
74
81
  else
75
82
  schema_column_type(row[:db_type])
@@ -114,7 +121,7 @@ module Sequel
114
121
  si[:colnames].as(:columns),
115
122
  fks[:primary_tname].as(:table_name)]}.
116
123
  join(Sequel[:sys][:sysforeignkeys].as(:fks), :role => :role).
117
- join(Sequel[:sys][:sysindexes].as(:si), [:iname=> Sequel[:fk][:role]], {:implicit_qualifier => :fk}).
124
+ join(Sequel[:sys][:sysindexes].as(:si), {:iname => Sequel[:fk][:role]}, {:implicit_qualifier => :fk}).
118
125
  where{{fks[:foreign_tname]=>im.call(table)}}.
119
126
  each do |r|
120
127
  unless r[:type].downcase == 'primary key'
@@ -152,7 +159,7 @@ module Sequel
152
159
 
153
160
  # Sybase uses the IDENTITY column for autoincrementing columns.
154
161
  def auto_increment_sql
155
- AUTO_INCREMENT
162
+ 'IDENTITY'
156
163
  end
157
164
 
158
165
  # Sybase does not allow adding primary key constraints to NULLable columns.
@@ -162,22 +169,22 @@ module Sequel
162
169
 
163
170
  # SQL fragment for marking a table as temporary
164
171
  def temporary_table_sql
165
- TEMPORARY
172
+ "GLOBAL TEMPORARY "
166
173
  end
167
174
 
168
175
  # SQL to BEGIN a transaction.
169
176
  def begin_transaction_sql
170
- SQL_BEGIN
177
+ "BEGIN TRANSACTION"
171
178
  end
172
179
 
173
180
  # SQL to ROLLBACK a transaction.
174
181
  def rollback_transaction_sql
175
- SQL_ROLLBACK
182
+ "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
176
183
  end
177
184
 
178
185
  # SQL to COMMIT a transaction.
179
186
  def commit_transaction_sql
180
- SQL_COMMIT
187
+ "COMMIT TRANSACTION"
181
188
  end
182
189
 
183
190
  # Sybase has both datetime and timestamp classes, most people are going
@@ -267,26 +274,47 @@ module Sequel
267
274
 
268
275
  module DatasetMethods
269
276
  BOOL_TRUE = '1'.freeze
277
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_TRUE)
270
278
  BOOL_FALSE = '0'.freeze
279
+ Sequel::Deprecation.deprecate_constant(self, :BOOL_FALSE)
271
280
  WILDCARD = LiteralString.new('%').freeze
281
+ Sequel::Deprecation.deprecate_constant(self, :WILDCARD)
272
282
  TOP = " TOP ".freeze
283
+ Sequel::Deprecation.deprecate_constant(self, :TOP)
273
284
  START_AT = " START AT ".freeze
285
+ Sequel::Deprecation.deprecate_constant(self, :START_AT)
274
286
  SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
287
+ Sequel::Deprecation.deprecate_constant(self, :SQL_WITH_RECURSIVE)
275
288
  DATE_FUNCTION = 'today()'.freeze
289
+ Sequel::Deprecation.deprecate_constant(self, :DATE_FUNCTION)
276
290
  NOW_FUNCTION = 'now()'.freeze
291
+ Sequel::Deprecation.deprecate_constant(self, :NOW_FUNCTION)
277
292
  DATEPART = 'datepart'.freeze
293
+ Sequel::Deprecation.deprecate_constant(self, :DATEPART)
278
294
  REGEXP = 'REGEXP'.freeze
295
+ Sequel::Deprecation.deprecate_constant(self, :REGEXP)
279
296
  NOT_REGEXP = 'NOT REGEXP'.freeze
280
- APOS = Dataset::APOS
281
- APOS_RE = Dataset::APOS_RE
282
- DOUBLE_APOS = Dataset::DOUBLE_APOS
297
+ Sequel::Deprecation.deprecate_constant(self, :NOT_REGEXP)
298
+ APOS = "'".freeze
299
+ Sequel::Deprecation.deprecate_constant(self, :APOS)
300
+ APOS_RE = /'/.freeze
301
+ Sequel::Deprecation.deprecate_constant(self, :APOS_RE)
302
+ DOUBLE_APOS = "''".freeze
303
+ Sequel::Deprecation.deprecate_constant(self, :DOUBLE_APOS)
283
304
  BACKSLASH_RE = /\\/.freeze
305
+ Sequel::Deprecation.deprecate_constant(self, :BACKSLASH_RE)
284
306
  QUAD_BACKSLASH = "\\\\\\\\".freeze
307
+ Sequel::Deprecation.deprecate_constant(self, :QUAD_BACKSLASH)
285
308
  BLOB_START = "0x".freeze
309
+ Sequel::Deprecation.deprecate_constant(self, :BLOB_START)
286
310
  HSTAR = "H*".freeze
311
+ Sequel::Deprecation.deprecate_constant(self, :HSTAR)
287
312
  CROSS_APPLY = 'CROSS APPLY'.freeze
313
+ Sequel::Deprecation.deprecate_constant(self, :CROSS_APPLY)
288
314
  OUTER_APPLY = 'OUTER APPLY'.freeze
315
+ Sequel::Deprecation.deprecate_constant(self, :OUTER_APPLY)
289
316
  ONLY_OFFSET = " TOP 2147483647".freeze
317
+ Sequel::Deprecation.deprecate_constant(self, :ONLY_OFFSET)
290
318
 
291
319
  Dataset.def_sql_method(self, :insert, %w'with insert into columns values')
292
320
  Dataset.def_sql_method(self, :select, %w'with select distinct limit columns into from join where group having compounds order lock')
@@ -347,12 +375,12 @@ module Sequel
347
375
  when :<<, :>>
348
376
  complex_expression_emulate_append(sql, op, args)
349
377
  when :LIKE, :"NOT LIKE"
350
- sql << Sequel::Dataset::PAREN_OPEN
351
- literal_append(sql, args.at(0))
352
- sql << Sequel::Dataset::SPACE << (op == :LIKE ? REGEXP : NOT_REGEXP) << Sequel::Dataset::SPACE
378
+ sql << '('
379
+ literal_append(sql, args[0])
380
+ sql << (op == :LIKE ? ' REGEXP ' : ' NOT REGEXP ')
353
381
  pattern = String.new
354
382
  last_c = ''
355
- args.at(1).each_char do |c|
383
+ args[1].each_char do |c|
356
384
  if c == '_' and not pattern.end_with?('\\') and last_c != '\\'
357
385
  pattern << '.'
358
386
  elsif c == '%' and not pattern.end_with?('\\') and last_c != '\\'
@@ -375,17 +403,17 @@ module Sequel
375
403
  end
376
404
  end
377
405
  literal_append(sql, pattern)
378
- sql << Sequel::Dataset::ESCAPE
379
- literal_append(sql, Sequel::Dataset::BACKSLASH)
380
- sql << Sequel::Dataset::PAREN_CLOSE
406
+ sql << " ESCAPE "
407
+ literal_append(sql, "\\")
408
+ sql << ')'
381
409
  when :ILIKE, :"NOT ILIKE"
382
410
  super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args)
383
411
  when :extract
384
- sql << DATEPART + Sequel::Dataset::PAREN_OPEN
385
- literal_append(sql, args.at(0))
412
+ sql << 'datepart('
413
+ literal_append(sql, args[0])
386
414
  sql << ','
387
- literal_append(sql, args.at(1))
388
- sql << Sequel::Dataset::PAREN_CLOSE
415
+ literal_append(sql, args[1])
416
+ sql << ')'
389
417
  else
390
418
  super
391
419
  end
@@ -400,9 +428,9 @@ module Sequel
400
428
  def constant_sql_append(sql, constant)
401
429
  case constant
402
430
  when :CURRENT_DATE
403
- sql << DATE_FUNCTION
431
+ sql << 'today()'
404
432
  when :CURRENT_TIMESTAMP, :CURRENT_TIME
405
- sql << NOW_FUNCTION
433
+ sql << 'now()'
406
434
  else
407
435
  super
408
436
  end
@@ -417,17 +445,17 @@ module Sequel
417
445
 
418
446
  # Use 1 for true on Sybase
419
447
  def literal_true
420
- BOOL_TRUE
448
+ '1'
421
449
  end
422
450
 
423
451
  # Use 0 for false on Sybase
424
452
  def literal_false
425
- BOOL_FALSE
453
+ '0'
426
454
  end
427
455
 
428
456
  # SQL fragment for String. Doubles \ and ' by default.
429
457
  def literal_string_append(sql, v)
430
- sql << APOS << v.gsub(BACKSLASH_RE, QUAD_BACKSLASH).gsub(APOS_RE, DOUBLE_APOS) << APOS
458
+ sql << "'" << v.gsub("\\", "\\\\\\\\").gsub("'", "''") << "'"
431
459
  end
432
460
 
433
461
  # SqlAnywhere uses a preceding X for hex escaping strings
@@ -435,7 +463,7 @@ module Sequel
435
463
  if v.empty?
436
464
  literal_append(sql, "")
437
465
  else
438
- sql << BLOB_START << v.unpack(HSTAR).first
466
+ sql << "0x" << v.unpack("H*").first
439
467
  end
440
468
  end
441
469
 
@@ -446,7 +474,7 @@ module Sequel
446
474
 
447
475
  def select_into_sql(sql)
448
476
  if i = @opts[:into]
449
- sql << Sequel::Dataset::INTO
477
+ sql << " INTO "
450
478
  identifier_append(sql, i)
451
479
  end
452
480
  end
@@ -458,14 +486,14 @@ module Sequel
458
486
  o = @opts[:offset]
459
487
  if l || o
460
488
  if l
461
- sql << TOP
489
+ sql << " TOP "
462
490
  literal_append(sql, l)
463
491
  else
464
- sql << ONLY_OFFSET
492
+ sql << " TOP 2147483647"
465
493
  end
466
494
 
467
495
  if o
468
- sql << START_AT + "("
496
+ sql << " START AT ("
469
497
  literal_append(sql, o)
470
498
  sql << " + 1)"
471
499
  end
@@ -474,15 +502,15 @@ module Sequel
474
502
 
475
503
  # Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
476
504
  def select_with_sql_base
477
- opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super
505
+ opts[:with].any?{|w| w[:recursive]} ? "WITH RECURSIVE " : super
478
506
  end
479
507
 
480
508
  def join_type_sql(join_type)
481
509
  case join_type
482
510
  when :cross_apply
483
- CROSS_APPLY
511
+ 'CROSS APPLY'
484
512
  when :outer_apply
485
- OUTER_APPLY
513
+ 'OUTER APPLY'
486
514
  else
487
515
  super
488
516
  end