sequel 2.11.0 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. data/CHANGELOG +168 -0
  2. data/README.rdoc +77 -95
  3. data/Rakefile +100 -80
  4. data/bin/sequel +2 -1
  5. data/doc/advanced_associations.rdoc +23 -32
  6. data/doc/cheat_sheet.rdoc +23 -40
  7. data/doc/dataset_filtering.rdoc +6 -6
  8. data/doc/prepared_statements.rdoc +22 -22
  9. data/doc/release_notes/2.12.0.txt +534 -0
  10. data/doc/schema.rdoc +3 -1
  11. data/doc/sharding.rdoc +8 -8
  12. data/doc/virtual_rows.rdoc +65 -0
  13. data/lib/sequel.rb +1 -1
  14. data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
  15. data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
  16. data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
  17. data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
  18. data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
  19. data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
  20. data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
  21. data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
  22. data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
  23. data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
  24. data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
  25. data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
  26. data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
  27. data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
  28. data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
  30. data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
  31. data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
  32. data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
  33. data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
  34. data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
  35. data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
  36. data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
  37. data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
  38. data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
  39. data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
  40. data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
  41. data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
  42. data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
  43. data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
  44. data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
  45. data/lib/sequel/core.rb +221 -0
  46. data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
  47. data/lib/{sequel_core → sequel}/database.rb +264 -149
  48. data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
  49. data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
  50. data/lib/sequel/database/schema_sql.rb +224 -0
  51. data/lib/{sequel_core → sequel}/dataset.rb +78 -236
  52. data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
  53. data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
  54. data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
  55. data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
  56. data/lib/sequel/deprecated.rb +593 -0
  57. data/lib/sequel/deprecated_migration.rb +91 -0
  58. data/lib/sequel/exceptions.rb +48 -0
  59. data/lib/sequel/extensions/blank.rb +42 -0
  60. data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
  61. data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
  62. data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
  63. data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
  64. data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
  65. data/lib/sequel/extensions/string_date_time.rb +47 -0
  66. data/lib/sequel/metaprogramming.rb +43 -0
  67. data/lib/sequel/model.rb +110 -0
  68. data/lib/sequel/model/associations.rb +1300 -0
  69. data/lib/sequel/model/base.rb +937 -0
  70. data/lib/sequel/model/deprecated.rb +204 -0
  71. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  72. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  73. data/lib/sequel/model/deprecated_validations.rb +388 -0
  74. data/lib/sequel/model/errors.rb +39 -0
  75. data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
  76. data/lib/sequel/model/inflections.rb +208 -0
  77. data/lib/sequel/model/plugins.rb +76 -0
  78. data/lib/sequel/plugins/caching.rb +122 -0
  79. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  80. data/lib/sequel/plugins/schema.rb +53 -0
  81. data/lib/sequel/plugins/serialization.rb +117 -0
  82. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  83. data/lib/sequel/plugins/validation_class_methods.rb +384 -0
  84. data/lib/sequel/plugins/validation_helpers.rb +150 -0
  85. data/lib/{sequel_core → sequel}/sql.rb +125 -190
  86. data/lib/{sequel_core → sequel}/version.rb +2 -1
  87. data/lib/sequel_core.rb +1 -172
  88. data/lib/sequel_model.rb +1 -91
  89. data/spec/adapters/firebird_spec.rb +5 -5
  90. data/spec/adapters/informix_spec.rb +1 -1
  91. data/spec/adapters/mysql_spec.rb +128 -42
  92. data/spec/adapters/oracle_spec.rb +47 -19
  93. data/spec/adapters/postgres_spec.rb +64 -52
  94. data/spec/adapters/spec_helper.rb +1 -1
  95. data/spec/adapters/sqlite_spec.rb +12 -17
  96. data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
  97. data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
  98. data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
  99. data/spec/{sequel_core → core}/database_spec.rb +135 -99
  100. data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
  101. data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
  102. data/spec/core/migration_spec.rb +263 -0
  103. data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
  104. data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
  105. data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
  106. data/spec/{sequel_core → core}/schema_spec.rb +8 -10
  107. data/spec/{sequel_core → core}/spec_helper.rb +29 -2
  108. data/spec/{sequel_core → core}/version_spec.rb +0 -0
  109. data/spec/extensions/blank_spec.rb +67 -0
  110. data/spec/extensions/caching_spec.rb +201 -0
  111. data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
  112. data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
  113. data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
  114. data/spec/extensions/pagination_spec.rb +99 -0
  115. data/spec/extensions/pretty_table_spec.rb +91 -0
  116. data/spec/extensions/query_spec.rb +85 -0
  117. data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
  118. data/spec/extensions/serialization_spec.rb +109 -0
  119. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  120. data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
  121. data/spec/extensions/string_date_time_spec.rb +93 -0
  122. data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
  123. data/spec/extensions/validation_helpers_spec.rb +291 -0
  124. data/spec/integration/dataset_test.rb +31 -0
  125. data/spec/integration/eager_loader_test.rb +17 -30
  126. data/spec/integration/schema_test.rb +8 -5
  127. data/spec/integration/spec_helper.rb +17 -0
  128. data/spec/integration/transaction_test.rb +68 -0
  129. data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
  130. data/spec/{sequel_model → model}/associations_spec.rb +23 -10
  131. data/spec/{sequel_model → model}/base_spec.rb +29 -20
  132. data/spec/{sequel_model → model}/caching_spec.rb +16 -14
  133. data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
  134. data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
  135. data/spec/model/hooks_spec.rb +472 -0
  136. data/spec/model/inflector_spec.rb +126 -0
  137. data/spec/{sequel_model → model}/model_spec.rb +25 -20
  138. data/spec/model/plugins_spec.rb +142 -0
  139. data/spec/{sequel_model → model}/record_spec.rb +121 -62
  140. data/spec/model/schema_spec.rb +92 -0
  141. data/spec/model/spec_helper.rb +124 -0
  142. data/spec/model/validations_spec.rb +1080 -0
  143. metadata +136 -107
  144. data/lib/sequel_core/core_ext.rb +0 -217
  145. data/lib/sequel_core/dataset/callback.rb +0 -13
  146. data/lib/sequel_core/dataset/schema.rb +0 -15
  147. data/lib/sequel_core/deprecated.rb +0 -26
  148. data/lib/sequel_core/exceptions.rb +0 -44
  149. data/lib/sequel_core/schema.rb +0 -2
  150. data/lib/sequel_core/schema/sql.rb +0 -325
  151. data/lib/sequel_model/association_reflection.rb +0 -267
  152. data/lib/sequel_model/associations.rb +0 -499
  153. data/lib/sequel_model/base.rb +0 -539
  154. data/lib/sequel_model/caching.rb +0 -82
  155. data/lib/sequel_model/dataset_methods.rb +0 -26
  156. data/lib/sequel_model/eager_loading.rb +0 -370
  157. data/lib/sequel_model/hooks.rb +0 -101
  158. data/lib/sequel_model/plugins.rb +0 -62
  159. data/lib/sequel_model/record.rb +0 -568
  160. data/lib/sequel_model/schema.rb +0 -49
  161. data/lib/sequel_model/validations.rb +0 -429
  162. data/spec/sequel_model/plugins_spec.rb +0 -80
@@ -10,6 +10,14 @@ module Sequel
10
10
 
11
11
  # Base class for all SQL fragments
12
12
  class Expression
13
+ # Create a to_s instance method that takes a dataset, and calls
14
+ # the method provided on the dataset with args as the argument (self by default).
15
+ # Used to DRY up some code.
16
+ def self.to_s_method(meth, args=:self) # :nodoc:
17
+ class_eval("def to_s(ds); ds.#{meth}(#{args}) end", __FILE__, __LINE__)
18
+ end
19
+ private_class_method :to_s_method
20
+
13
21
  # Returns self, because SQL::Expression already acts like
14
22
  # LiteralString.
15
23
  def lit
@@ -47,10 +55,13 @@ module Sequel
47
55
  # Hash of ruby operator symbols to SQL operators, used in BooleanMethods
48
56
  BOOLEAN_OPERATOR_METHODS = {:& => :AND, :| =>:OR}
49
57
 
58
+ # Operators that use IS, used for special casing to override literal true/false values
59
+ IS_OPERATORS = [:IS, :'IS NOT']
60
+
50
61
  # Operator symbols that take exactly two arguments
51
- TWO_ARITY_OPERATORS = [:'=', :'!=', :IS, :'IS NOT', :LIKE, :'NOT LIKE', \
62
+ TWO_ARITY_OPERATORS = [:'=', :'!=', :LIKE, :'NOT LIKE', \
52
63
  :~, :'!~', :'~*', :'!~*', :IN, :'NOT IN', :ILIKE, :'NOT ILIKE'] + \
53
- INEQUALITY_OPERATORS + BITWISE_OPERATORS
64
+ INEQUALITY_OPERATORS + BITWISE_OPERATORS + IS_OPERATORS
54
65
 
55
66
  # Operator symbols that take one or more arguments
56
67
  N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS
@@ -65,20 +76,11 @@ module Sequel
65
76
  attr_reader :op
66
77
 
67
78
  # Set the operator symbol and arguments for this object to the ones given.
68
- # Convert all args that are hashes or arrays with all two pairs to ComplexExpressions.
79
+ # Convert all args that are hashes or arrays with all two pairs to BooleanExpressions.
69
80
  # Raise an error if the operator doesn't allow boolean input and a boolean argument is given.
70
81
  # Raise an error if the wrong number of arguments for a given operator is used.
71
82
  def initialize(op, *args)
72
- args.collect! do |a|
73
- case a
74
- when Hash
75
- a.sql_expr
76
- when Array
77
- a.all_two_pairs? ? a.sql_expr : a
78
- else
79
- a
80
- end
81
- end
83
+ args.map!{|a| Sequel.condition_specifier?(a) ? SQL::BooleanExpression.from_value_pairs(a) : a}
82
84
  case op
83
85
  when *N_ARITY_OPERATORS
84
86
  raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
@@ -92,21 +94,15 @@ module Sequel
92
94
  @op = op
93
95
  @args = args
94
96
  end
95
-
96
- # Delegate the creation of the resulting SQL to the given dataset,
97
- # since it may be database dependent.
98
- def to_s(ds)
99
- ds.complex_expression_sql(@op, @args)
100
- end
101
97
 
102
98
  # Returns true if the receiver is the same expression as the
103
99
  # the +other+ expression.
104
- def eql?( other )
105
- return other.is_a?( self.class ) &&
106
- @op.eql?( other.op ) &&
107
- @args.eql?( other.args )
100
+ def eql?(other)
101
+ other.is_a?(self.class) && @op.eql?(other.op) && @args.eql?(other.args)
108
102
  end
109
- alias_method :==, :eql?
103
+ alias == eql?
104
+
105
+ to_s_method :complex_expression_sql, '@op, @args'
110
106
  end
111
107
 
112
108
  # The base class for expressions that can be used in multiple places in
@@ -114,22 +110,17 @@ module Sequel
114
110
  class GenericExpression < Expression
115
111
  end
116
112
 
117
- # The base class for expressions that are specific and can only be used
118
- # in a certain place in the SQL query (ordering, selecting).
119
- class SpecificExpression < Expression
120
- end
121
-
122
113
  ### Modules ###
123
114
 
124
- # Methods the create aliased identifiers
115
+ # Methods that create aliased identifiers
125
116
  module AliasMethods
126
- # Create an SQL column alias of the receiving column to the given alias.
117
+ # Create an SQL column alias of the receiving column or expression to the given alias.
127
118
  def as(aliaz)
128
119
  AliasedExpression.new(self, aliaz)
129
120
  end
130
121
  end
131
122
 
132
- # This defines the bitwise methods &, |, ^, ~, <<, and >>. Because these
123
+ # This defines the bitwise methods: &, |, ^, ~, <<, and >>. Because these
133
124
  # methods overlap with the standard BooleanMethods methods, and they only
134
125
  # make sense for numbers, they are only included in NumericExpression.
135
126
  module BitwiseMethods
@@ -179,19 +170,19 @@ module Sequel
179
170
 
180
171
  # Holds methods that are used to cast objects to differen SQL types.
181
172
  module CastMethods
182
- # Cast the reciever to the given SQL type
173
+ # Cast the reciever to the given SQL type. You can specify a ruby class as a type,
174
+ # and it is handled similarly to using a database independent type in the schema methods.
183
175
  def cast(sql_type)
184
176
  Cast.new(self, sql_type)
185
177
  end
186
- alias_method :cast_as, :cast
187
178
 
188
- # Cast the reciever to the given SQL type (or integer if none given),
179
+ # Cast the reciever to the given SQL type (or the database's default integer type if none given),
189
180
  # and return the result as a NumericExpression.
190
181
  def cast_numeric(sql_type = nil)
191
182
  cast(sql_type || Integer).sql_number
192
183
  end
193
184
 
194
- # Cast the reciever to the given SQL type (or text if none given),
185
+ # Cast the reciever to the given SQL type (or the database's default string type if none given),
195
186
  # and return the result as a StringExpression, so you can use +
196
187
  # directly on the result for SQL string concatenation.
197
188
  def cast_string(sql_type = nil)
@@ -199,6 +190,49 @@ module Sequel
199
190
  end
200
191
  end
201
192
 
193
+ # Adds methods that allow you to treat an object as an instance of a specific
194
+ # ComplexExpression subclass. This is useful if another library
195
+ # overrides the methods defined by Sequel.
196
+ #
197
+ # For example, if Symbol#/ is overridden to produce a string (for
198
+ # example, to make file system path creation easier), the
199
+ # following code will not do what you want:
200
+ #
201
+ # :price/10 > 100
202
+ #
203
+ # In that case, you need to do the following:
204
+ #
205
+ # :price.sql_number/10 > 100
206
+ module ComplexExpressionMethods
207
+ # Extract a datetime_part (e.g. year, month) from self:
208
+ #
209
+ # :date.extract(:year) # SQL: extract(year FROM "date")
210
+ #
211
+ # Also has the benefit of returning the result as a
212
+ # NumericExpression instead of a generic ComplexExpression.
213
+ #
214
+ # The extract function is in the SQL standard, but it doesn't
215
+ # doesn't use the standard function calling convention.
216
+ def extract(datetime_part)
217
+ Function.new(:extract, PlaceholderLiteralString.new("#{datetime_part} FROM ?", [self])).sql_number
218
+ end
219
+
220
+ # Return a BooleanExpression representation of self.
221
+ def sql_boolean
222
+ BooleanExpression.new(:NOOP, self)
223
+ end
224
+
225
+ # Return a NumericExpression representation of self.
226
+ def sql_number
227
+ NumericExpression.new(:NOOP, self)
228
+ end
229
+
230
+ # Return a StringExpression representation of self.
231
+ def sql_string
232
+ StringExpression.new(:NOOP, self)
233
+ end
234
+ end
235
+
202
236
  # Includes a method that returns Identifiers.
203
237
  module IdentifierMethods
204
238
  # Return self wrapped as an identifier.
@@ -208,7 +242,7 @@ module Sequel
208
242
  end
209
243
 
210
244
  # This module includes the methods that are defined on objects that can be
211
- # used in a numeric or string context in SQL (Symbol, LiteralString,
245
+ # used in a numeric or string context in SQL (Symbol (except on ruby 1.9), LiteralString,
212
246
  # SQL::Function, and SQL::StringExpression).
213
247
  #
214
248
  # This defines the >, <, >=, and <= methods.
@@ -287,10 +321,11 @@ module Sequel
287
321
  end
288
322
 
289
323
  # This module includes the methods that are defined on objects that can be
290
- # used in a numeric context in SQL (Symbol, LiteralString, SQL::Function,
324
+ # used in a string context in SQL (Symbol, LiteralString, SQL::Function,
291
325
  # and SQL::StringExpression).
292
326
  #
293
- # This defines the like (LIKE) method, used for pattern matching.
327
+ # This defines the like (LIKE) and ilike methods, used for pattern matching.
328
+ # like is case sensitive, ilike is case insensitive.
294
329
  module StringMethods
295
330
  # Create a BooleanExpression case insensitive pattern match of self
296
331
  # with the given patterns. See StringExpression.like.
@@ -316,50 +351,6 @@ module Sequel
316
351
  end
317
352
  end
318
353
 
319
- ### Modules that include other modules ###
320
-
321
- # This module includes other Sequel::SQL::*Methods modules and is
322
- # included in other classes that are could be either booleans,
323
- # strings, or numbers. It also adds three methods so that
324
- # can specify behavior in case one of the operator methods has
325
- # been overridden (such as Symbol#/).
326
- #
327
- # For example, if Symbol#/ is overridden to produce a string (for
328
- # example, to make file system path creation easier), the
329
- # following code will not do what you want:
330
- #
331
- # :price/10 > 100
332
- #
333
- # In that case, you need to do the following:
334
- #
335
- # :price.sql_number/10 > 100
336
- module ComplexExpressionMethods
337
- # Extract a datetime_part (e.g. year, month) from self:
338
- #
339
- # :date.extract(:year) # SQL: extract(year FROM "date")
340
- #
341
- # Also has the benefit of returning the result as a
342
- # NumericExpression instead of a generic ComplexExpression.
343
- def extract(datetime_part)
344
- Function.new(:extract, PlaceholderLiteralString.new("#{datetime_part} FROM ?", [self])).sql_number
345
- end
346
-
347
- # Return a BooleanExpression representation of self.
348
- def sql_boolean
349
- BooleanExpression.new(:NOOP, self)
350
- end
351
-
352
- # Return a NumericExpression representation of self.
353
- def sql_number
354
- NumericExpression.new(:NOOP, self)
355
- end
356
-
357
- # Return a StringExpression representation of self.
358
- def sql_string
359
- StringExpression.new(:NOOP, self)
360
- end
361
- end
362
-
363
354
  class ComplexExpression
364
355
  include AliasMethods
365
356
  include CastMethods
@@ -380,7 +371,7 @@ module Sequel
380
371
  ### Classes ###
381
372
 
382
373
  # Represents an aliasing of an expression/column to a given name.
383
- class AliasedExpression < SpecificExpression
374
+ class AliasedExpression < Expression
384
375
  # The expression to alias
385
376
  attr_reader :expression
386
377
 
@@ -393,24 +384,17 @@ module Sequel
393
384
  @expression, @aliaz = expression, aliaz
394
385
  end
395
386
 
396
- # Delegate the creation of the resulting SQL to the given dataset,
397
- # since it may be database dependent.
398
- def to_s(ds)
399
- ds.aliased_expression_sql(self)
400
- end
387
+ to_s_method :aliased_expression_sql
401
388
  end
402
389
 
403
390
  # Blob is used to represent binary data in the Ruby environment that is
404
- # stored as a blob type in the database. In PostgreSQL, the blob type is
405
- # called bytea. Sequel represents binary data as a Blob object because
406
- # certain database engines, such as PostgreSQL, require binary data to be
407
- # escaped.
391
+ # stored as a blob type in the database. Sequel represents binary data as a Blob object because
392
+ # certain database engines require binary data to be escaped.
408
393
  class Blob < ::String
409
- # return self.
394
+ # Returns self
410
395
  def to_sequel_blob
411
396
  self
412
397
  end
413
- alias to_blob to_sequel_blob
414
398
  end
415
399
 
416
400
  # Subclass of ComplexExpression where the expression results
@@ -443,7 +427,7 @@ module Sequel
443
427
  new(:AND, new(:>=, l, r.begin), new(r.exclude_end? ? :< : :<=, l, r.end))
444
428
  when Array, ::Sequel::Dataset, SQLArray
445
429
  new(:IN, l, r)
446
- when NilClass
430
+ when NilClass, TrueClass, FalseClass
447
431
  new(:IS, l, r)
448
432
  when Regexp
449
433
  StringExpression.like(l, r)
@@ -457,7 +441,8 @@ module Sequel
457
441
 
458
442
  # Invert the expression, if possible. If the expression cannot
459
443
  # be inverted, raise an error. An inverted expression should match everything that the
460
- # uninverted expression did not match, and vice-versa.
444
+ # uninverted expression did not match, and vice-versa, except for possible issues with
445
+ # SQL NULL (i.e. 1 == NULL is NULL and 1 != NULL is also NULL).
461
446
  def self.invert(ce)
462
447
  case ce
463
448
  when BooleanExpression
@@ -490,15 +475,11 @@ module Sequel
490
475
  # Create an object with the given conditions and
491
476
  # default value.
492
477
  def initialize(conditions, default, expression = nil)
493
- raise(Sequel::Error, 'CaseExpression conditions must be an array with all_two_pairs') unless Array === conditions and conditions.all_two_pairs?
494
- @conditions, @default, @expression = conditions, default, expression
478
+ raise(Sequel::Error, 'CaseExpression conditions must be a hash or array of all two pairs') unless Sequel.condition_specifier?(conditions)
479
+ @conditions, @default, @expression = conditions.to_a, default, expression
495
480
  end
496
481
 
497
- # Delegate the creation of the resulting SQL to the given dataset,
498
- # since it may be database dependent.
499
- def to_s(ds)
500
- ds.case_expression_sql(self)
501
- end
482
+ to_s_method :case_expression_sql
502
483
  end
503
484
 
504
485
  # Represents a cast of an SQL expression to a specific type.
@@ -515,15 +496,11 @@ module Sequel
515
496
  @type = type
516
497
  end
517
498
 
518
- # Delegate the creation of the resulting SQL to the given dataset,
519
- # since it may be database dependent.
520
- def to_s(ds)
521
- ds.cast_sql(expr, type)
522
- end
499
+ to_s_method :cast_sql, '@expr, @type'
523
500
  end
524
501
 
525
502
  # Represents all columns in a given table, table.* in SQL
526
- class ColumnAll < SpecificExpression
503
+ class ColumnAll < Expression
527
504
  # The table containing the columns being selected
528
505
  attr_reader :table
529
506
 
@@ -535,14 +512,10 @@ module Sequel
535
512
  # ColumnAll expressions are considered equivalent if they
536
513
  # have the same class and string representation
537
514
  def ==(x)
538
- x.class == self.class && @table == x.table
515
+ x.class == self.class and @table == x.table
539
516
  end
540
517
 
541
- # Delegate the creation of the resulting SQL to the given dataset,
542
- # since it may be database dependent.
543
- def to_s(ds)
544
- ds.column_all_sql(self)
545
- end
518
+ to_s_method :column_all_sql
546
519
  end
547
520
 
548
521
  # Represents an SQL function call.
@@ -564,11 +537,7 @@ module Sequel
564
537
  x.class == self.class && @f == x.f && @args == x.args
565
538
  end
566
539
 
567
- # Delegate the creation of the resulting SQL to the given dataset,
568
- # since it may be database dependent.
569
- def to_s(ds)
570
- ds.function_sql(self)
571
- end
540
+ to_s_method :function_sql
572
541
  end
573
542
 
574
543
  # Represents an identifier (column or table). Can be used
@@ -585,15 +554,11 @@ module Sequel
585
554
  @value = value
586
555
  end
587
556
 
588
- # Delegate the creation of the resulting SQL to the given dataset,
589
- # since it may be database dependent.
590
- def to_s(ds)
591
- ds.quote_identifier(@value)
592
- end
557
+ to_s_method :quote_identifier, '@value'
593
558
  end
594
559
 
595
560
  # Represents an SQL JOIN clause, used for joining tables.
596
- class JoinClause < SpecificExpression
561
+ class JoinClause < Expression
597
562
  # The type of join to do
598
563
  attr_reader :join_type
599
564
 
@@ -603,17 +568,12 @@ module Sequel
603
568
  # The table alias to use for the join, if any
604
569
  attr_reader :table_alias
605
570
 
606
- # Create an object with the given conditions and
607
- # default value.
571
+ # Create an object with the given join_type, table, and table alias
608
572
  def initialize(join_type, table, table_alias = nil)
609
573
  @join_type, @table, @table_alias = join_type, table, table_alias
610
574
  end
611
575
 
612
- # Delegate the creation of the resulting SQL to the given dataset,
613
- # since it may be database dependent.
614
- def to_s(ds)
615
- ds.join_clause_sql(self)
616
- end
576
+ to_s_method :join_clause_sql
617
577
  end
618
578
 
619
579
  # Represents an SQL JOIN table ON conditions clause.
@@ -621,44 +581,36 @@ module Sequel
621
581
  # The conditions for the join
622
582
  attr_reader :on
623
583
 
624
- # Create an object with the given conditions and
625
- # default value.
584
+ # Create an object with the ON conditions and call super with the
585
+ # remaining args.
626
586
  def initialize(on, *args)
627
587
  @on = on
628
588
  super(*args)
629
589
  end
630
590
 
631
- # Delegate the creation of the resulting SQL to the given dataset,
632
- # since it may be database dependent.
633
- def to_s(ds)
634
- ds.join_on_clause_sql(self)
635
- end
591
+ to_s_method :join_on_clause_sql
636
592
  end
637
593
 
638
594
  # Represents an SQL JOIN table USING (columns) clause.
639
595
  class JoinUsingClause < JoinClause
640
- # The columns that appear both tables that should be equal
596
+ # The columns that appear in both tables that should be equal
641
597
  # for the conditions to match.
642
598
  attr_reader :using
643
599
 
644
- # Create an object with the given conditions and
645
- # default value.
600
+ # Create an object with the given USING conditions and call super
601
+ # with the remaining args.
646
602
  def initialize(using, *args)
647
603
  @using = using
648
604
  super(*args)
649
605
  end
650
606
 
651
- # Delegate the creation of the resulting SQL to the given dataset,
652
- # since it may be database dependent.
653
- def to_s(ds)
654
- ds.join_using_clause_sql(self)
655
- end
607
+ to_s_method :join_using_clause_sql
656
608
  end
657
609
 
658
610
  # Represents a literal string with placeholders and arguments.
659
611
  # This is necessary to ensure delayed literalization of the arguments
660
612
  # required for the prepared statement support
661
- class PlaceholderLiteralString < SpecificExpression
613
+ class PlaceholderLiteralString < Expression
662
614
  # The arguments that will be subsituted into the placeholders.
663
615
  attr_reader :args
664
616
 
@@ -668,19 +620,14 @@ module Sequel
668
620
  # Whether to surround the expression with parantheses
669
621
  attr_reader :parens
670
622
 
671
- # Create an object with the given conditions and
672
- # default value.
623
+ # Create an object with the given string, placeholder arguments, and parens flag.
673
624
  def initialize(str, args, parens=false)
674
625
  @str = str
675
626
  @args = args
676
627
  @parens = parens
677
628
  end
678
629
 
679
- # Delegate the creation of the resulting SQL to the given dataset,
680
- # since it may be database dependent.
681
- def to_s(ds)
682
- ds.placeholder_literal_string_sql(self)
683
- end
630
+ to_s_method :placeholder_literal_string_sql
684
631
  end
685
632
 
686
633
  # Subclass of ComplexExpression where the expression results
@@ -693,7 +640,7 @@ module Sequel
693
640
  end
694
641
 
695
642
  # Represents a column/expression to order the result set by.
696
- class OrderedExpression < SpecificExpression
643
+ class OrderedExpression < Expression
697
644
  # The expression to order the result set by.
698
645
  attr_reader :expression
699
646
 
@@ -705,29 +652,23 @@ module Sequel
705
652
  @expression, @descending = expression, descending
706
653
  end
707
654
 
708
- # Delegate the creation of the resulting SQL to the given dataset,
709
- # since it may be database dependent.
710
- def to_s(ds)
711
- ds.ordered_expression_sql(self)
712
- end
655
+ to_s_method :ordered_expression_sql
713
656
  end
714
657
 
715
- # Represents a qualified (column with table) reference. Used when
716
- # joining tables to disambiguate columns.
658
+ # Represents a qualified (column with table or table with schema) reference.
717
659
  class QualifiedIdentifier < GenericExpression
718
- # The table and column to reference
719
- attr_reader :table, :column
660
+ # The column to reference
661
+ attr_reader :column
720
662
 
721
- # Set the attributes to the given arguments
663
+ # The table to reference
664
+ attr_reader :table
665
+
666
+ # Set the table and column to the given arguments
722
667
  def initialize(table, column)
723
668
  @table, @column = table, column
724
669
  end
725
670
 
726
- # Delegate the creation of the resulting SQL to the given dataset,
727
- # since it may be database dependent.
728
- def to_s(ds)
729
- ds.qualified_identifier_sql(self)
730
- end
671
+ to_s_method :qualified_identifier_sql
731
672
  end
732
673
 
733
674
  # Subclass of ComplexExpression where the expression results
@@ -753,7 +694,7 @@ module Sequel
753
694
  # if a case insensitive regular expression is used (//i), that particular
754
695
  # pattern which will always be case insensitive.
755
696
  def self.like(l, *ces)
756
- case_insensitive = ces.extract_options![:case_insensitive]
697
+ case_insensitive = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive]
757
698
  ces.collect! do |ce|
758
699
  op, expr = Regexp === ce ? [ce.casefold? || case_insensitive ? :'~*' : :~, ce.source] : [case_insensitive ? :ILIKE : :LIKE, ce]
759
700
  BooleanExpression.new(op, l, expr)
@@ -771,11 +712,7 @@ module Sequel
771
712
  @array = array
772
713
  end
773
714
 
774
- # Delegate the creation of the resulting SQL to the given dataset,
775
- # since it may be database dependent.
776
- def to_s(ds)
777
- ds.array_sql(@array)
778
- end
715
+ to_s_method :array_sql, '@array'
779
716
  end
780
717
 
781
718
  # Represents an SQL array access, with multiple possible arguments.
@@ -786,7 +723,7 @@ module Sequel
786
723
  # The array of subscripts to use (should be an array of numbers)
787
724
  attr_reader :sub
788
725
 
789
- # Set the attributes to the given arguments
726
+ # Set the array column and subscripts to the given arguments
790
727
  def initialize(f, sub)
791
728
  @f, @sub = f, sub
792
729
  end
@@ -797,11 +734,7 @@ module Sequel
797
734
  Subscript.new(@f, @sub + Array(sub))
798
735
  end
799
736
 
800
- # Delegate the creation of the resulting SQL to the given dataset,
801
- # since it may be database dependent.
802
- def to_s(ds)
803
- ds.subscript_sql(self)
804
- end
737
+ to_s_method :subscript_sql
805
738
  end
806
739
 
807
740
  if RUBY_VERSION >= '1.9.0'
@@ -813,9 +746,13 @@ module Sequel
813
746
  end
814
747
  end
815
748
 
816
- # An instance of this class is yielded to the block supplied to filter.
817
- # Useful if another library also defines the operator methods that
818
- # Sequel defines for symbols.
749
+ # The purpose of this class is to allow the easy creation of SQL identifiers and functions
750
+ # without relying on methods defined on Symbol. This is useful if another library defines
751
+ # the methods defined by Sequel, or if you are running on ruby 1.9.
752
+ #
753
+ # An instance of this class is yielded to the block supplied to filter, order, and select.
754
+ # If Sequel.virtual_row_instance_eval is true and the block doesn't take an argument,
755
+ # the block is instance_evaled in the context of a new instance of this class.
819
756
  #
820
757
  # Examples:
821
758
  #
@@ -845,8 +782,6 @@ module Sequel
845
782
  # LiteralString is used to represent literal SQL expressions. A
846
783
  # LiteralString is copied verbatim into an SQL statement. Instances of
847
784
  # LiteralString can be created by calling String#lit.
848
- # LiteralStrings can also use all of the SQL::OrderMethods and the
849
- # SQL::ComplexExpressionMethods.
850
785
  class LiteralString < ::String
851
786
  include SQL::OrderMethods
852
787
  include SQL::ComplexExpressionMethods