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
@@ -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