sequel 3.12.1 → 3.13.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 (150) hide show
  1. data/CHANGELOG +42 -0
  2. data/README.rdoc +137 -118
  3. data/Rakefile +21 -66
  4. data/doc/active_record.rdoc +9 -9
  5. data/doc/advanced_associations.rdoc +59 -188
  6. data/doc/association_basics.rdoc +15 -2
  7. data/doc/cheat_sheet.rdoc +38 -33
  8. data/doc/dataset_filtering.rdoc +16 -7
  9. data/doc/prepared_statements.rdoc +7 -7
  10. data/doc/querying.rdoc +5 -4
  11. data/doc/release_notes/3.13.0.txt +210 -0
  12. data/doc/sharding.rdoc +1 -1
  13. data/doc/sql.rdoc +5 -5
  14. data/doc/validations.rdoc +11 -11
  15. data/lib/sequel/adapters/ado.rb +1 -1
  16. data/lib/sequel/adapters/do.rb +3 -3
  17. data/lib/sequel/adapters/firebird.rb +3 -3
  18. data/lib/sequel/adapters/jdbc/h2.rb +39 -0
  19. data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
  20. data/lib/sequel/adapters/jdbc/oracle.rb +3 -3
  21. data/lib/sequel/adapters/mysql.rb +7 -4
  22. data/lib/sequel/adapters/oracle.rb +3 -3
  23. data/lib/sequel/adapters/shared/mssql.rb +10 -1
  24. data/lib/sequel/adapters/shared/mysql.rb +63 -0
  25. data/lib/sequel/adapters/shared/postgres.rb +61 -3
  26. data/lib/sequel/adapters/sqlite.rb +105 -18
  27. data/lib/sequel/connection_pool.rb +31 -30
  28. data/lib/sequel/core.rb +58 -58
  29. data/lib/sequel/core_sql.rb +52 -43
  30. data/lib/sequel/database/misc.rb +11 -0
  31. data/lib/sequel/database/query.rb +55 -17
  32. data/lib/sequel/dataset/actions.rb +2 -1
  33. data/lib/sequel/dataset/query.rb +2 -3
  34. data/lib/sequel/dataset/sql.rb +24 -11
  35. data/lib/sequel/extensions/schema_dumper.rb +1 -1
  36. data/lib/sequel/metaprogramming.rb +4 -0
  37. data/lib/sequel/model.rb +37 -19
  38. data/lib/sequel/model/associations.rb +33 -25
  39. data/lib/sequel/model/base.rb +2 -2
  40. data/lib/sequel/model/plugins.rb +7 -2
  41. data/lib/sequel/plugins/active_model.rb +1 -1
  42. data/lib/sequel/plugins/association_pks.rb +2 -2
  43. data/lib/sequel/plugins/association_proxies.rb +1 -1
  44. data/lib/sequel/plugins/boolean_readers.rb +2 -2
  45. data/lib/sequel/plugins/class_table_inheritance.rb +10 -2
  46. data/lib/sequel/plugins/identity_map.rb +3 -3
  47. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  48. data/lib/sequel/plugins/json_serializer.rb +212 -0
  49. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  50. data/lib/sequel/plugins/list.rb +174 -0
  51. data/lib/sequel/plugins/many_through_many.rb +2 -2
  52. data/lib/sequel/plugins/rcte_tree.rb +6 -7
  53. data/lib/sequel/plugins/tree.rb +118 -0
  54. data/lib/sequel/plugins/xml_serializer.rb +321 -0
  55. data/lib/sequel/sql.rb +315 -206
  56. data/lib/sequel/timezones.rb +40 -17
  57. data/lib/sequel/version.rb +8 -2
  58. data/spec/adapters/firebird_spec.rb +2 -2
  59. data/spec/adapters/informix_spec.rb +1 -1
  60. data/spec/adapters/mssql_spec.rb +2 -2
  61. data/spec/adapters/mysql_spec.rb +2 -2
  62. data/spec/adapters/oracle_spec.rb +1 -1
  63. data/spec/adapters/postgres_spec.rb +36 -6
  64. data/spec/adapters/spec_helper.rb +2 -2
  65. data/spec/adapters/sqlite_spec.rb +1 -1
  66. data/spec/core/connection_pool_spec.rb +3 -3
  67. data/spec/core/core_sql_spec.rb +31 -13
  68. data/spec/core/database_spec.rb +39 -2
  69. data/spec/core/dataset_spec.rb +24 -12
  70. data/spec/core/expression_filters_spec.rb +5 -1
  71. data/spec/core/object_graph_spec.rb +1 -1
  72. data/spec/core/schema_generator_spec.rb +1 -1
  73. data/spec/core/schema_spec.rb +1 -1
  74. data/spec/core/spec_helper.rb +1 -1
  75. data/spec/core/version_spec.rb +1 -1
  76. data/spec/extensions/active_model_spec.rb +82 -67
  77. data/spec/extensions/association_dependencies_spec.rb +1 -1
  78. data/spec/extensions/association_pks_spec.rb +1 -1
  79. data/spec/extensions/association_proxies_spec.rb +1 -1
  80. data/spec/extensions/blank_spec.rb +1 -1
  81. data/spec/extensions/boolean_readers_spec.rb +1 -1
  82. data/spec/extensions/caching_spec.rb +1 -1
  83. data/spec/extensions/class_table_inheritance_spec.rb +3 -2
  84. data/spec/extensions/composition_spec.rb +2 -5
  85. data/spec/extensions/force_encoding_spec.rb +3 -1
  86. data/spec/extensions/hook_class_methods_spec.rb +1 -1
  87. data/spec/extensions/identity_map_spec.rb +1 -1
  88. data/spec/extensions/inflector_spec.rb +1 -1
  89. data/spec/extensions/instance_filters_spec.rb +1 -1
  90. data/spec/extensions/instance_hooks_spec.rb +1 -1
  91. data/spec/extensions/json_serializer_spec.rb +154 -0
  92. data/spec/extensions/lazy_attributes_spec.rb +1 -2
  93. data/spec/extensions/list_spec.rb +251 -0
  94. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  95. data/spec/extensions/many_through_many_spec.rb +3 -3
  96. data/spec/extensions/migration_spec.rb +1 -1
  97. data/spec/extensions/named_timezones_spec.rb +5 -6
  98. data/spec/extensions/nested_attributes_spec.rb +1 -1
  99. data/spec/extensions/optimistic_locking_spec.rb +1 -1
  100. data/spec/extensions/pagination_spec.rb +1 -1
  101. data/spec/extensions/pretty_table_spec.rb +1 -1
  102. data/spec/extensions/query_spec.rb +1 -1
  103. data/spec/extensions/rcte_tree_spec.rb +1 -1
  104. data/spec/extensions/schema_dumper_spec.rb +3 -2
  105. data/spec/extensions/schema_spec.rb +1 -1
  106. data/spec/extensions/serialization_spec.rb +6 -2
  107. data/spec/extensions/sharding_spec.rb +1 -1
  108. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  109. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  110. data/spec/extensions/spec_helper.rb +7 -3
  111. data/spec/extensions/sql_expr_spec.rb +1 -1
  112. data/spec/extensions/string_date_time_spec.rb +1 -1
  113. data/spec/extensions/string_stripper_spec.rb +1 -1
  114. data/spec/extensions/subclasses_spec.rb +1 -1
  115. data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
  116. data/spec/extensions/thread_local_timezones_spec.rb +1 -1
  117. data/spec/extensions/timestamps_spec.rb +1 -1
  118. data/spec/extensions/touch_spec.rb +1 -1
  119. data/spec/extensions/tree_spec.rb +119 -0
  120. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  121. data/spec/extensions/update_primary_key_spec.rb +1 -1
  122. data/spec/extensions/validation_class_methods_spec.rb +1 -1
  123. data/spec/extensions/validation_helpers_spec.rb +1 -1
  124. data/spec/extensions/xml_serializer_spec.rb +142 -0
  125. data/spec/integration/associations_test.rb +1 -1
  126. data/spec/integration/database_test.rb +1 -1
  127. data/spec/integration/dataset_test.rb +29 -14
  128. data/spec/integration/eager_loader_test.rb +1 -1
  129. data/spec/integration/migrator_test.rb +1 -1
  130. data/spec/integration/model_test.rb +1 -1
  131. data/spec/integration/plugin_test.rb +316 -1
  132. data/spec/integration/prepared_statement_test.rb +1 -1
  133. data/spec/integration/schema_test.rb +8 -8
  134. data/spec/integration/spec_helper.rb +1 -1
  135. data/spec/integration/timezone_test.rb +1 -1
  136. data/spec/integration/transaction_test.rb +35 -20
  137. data/spec/integration/type_test.rb +1 -1
  138. data/spec/model/association_reflection_spec.rb +1 -1
  139. data/spec/model/associations_spec.rb +49 -34
  140. data/spec/model/base_spec.rb +1 -1
  141. data/spec/model/dataset_methods_spec.rb +4 -4
  142. data/spec/model/eager_loading_spec.rb +1 -1
  143. data/spec/model/hooks_spec.rb +1 -1
  144. data/spec/model/inflector_spec.rb +1 -1
  145. data/spec/model/model_spec.rb +7 -1
  146. data/spec/model/plugins_spec.rb +1 -1
  147. data/spec/model/record_spec.rb +1 -3
  148. data/spec/model/spec_helper.rb +2 -2
  149. data/spec/model/validations_spec.rb +1 -1
  150. metadata +29 -5
data/lib/sequel/sql.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  if RUBY_VERSION < '1.9.0'
3
- # If on Ruby 1.8, create a Sequel::BasicObject class that is similar to the
4
- # the Ruby 1.9 BasicObject class. This is used in a few places where proxy
3
+ # If on Ruby 1.8, create a <tt>Sequel::BasicObject</tt> class that is similar to the
4
+ # the Ruby 1.9 +BasicObject+ class. This is used in a few places where proxy
5
5
  # objects are needed that respond to any method call.
6
6
  class BasicObject
7
7
  # The instance methods to not remove from the class when removing
@@ -10,26 +10,26 @@ module Sequel
10
10
 
11
11
  # Remove all but the most basic instance methods from the class. A separate
12
12
  # method so that it can be called again if necessary if you load libraries
13
- # after Sequel that add instance methods to Object.
13
+ # after Sequel that add instance methods to +Object+.
14
14
  def self.remove_methods!
15
15
  ((private_instance_methods + instance_methods) - KEEP_METHODS).each{|m| undef_method(m)}
16
16
  end
17
17
  remove_methods!
18
18
  end
19
19
  else
20
- # If on 1.9, create a Sequel::BasicObject class that is just like the
21
- # default BasicObject class, except that missing constants are resolved in
22
- # Object. This allows the virtual row support to work with classes
20
+ # If on 1.9, create a <tt>Sequel::BasicObject</tt> class that is just like the
21
+ # default +BasicObject+ class, except that missing constants are resolved in
22
+ # +Object+. This allows the virtual row support to work with classes
23
23
  # without prefixing them with ::, such as:
24
24
  #
25
25
  # DB[:bonds].filter{maturity_date > Time.now}
26
26
  class BasicObject < ::BasicObject
27
- # Lookup missing constants in ::Object
27
+ # Lookup missing constants in <tt>::Object</tt>
28
28
  def self.const_missing(name)
29
29
  ::Object.const_get(name)
30
30
  end
31
31
 
32
- # No-op method on ruby 1.9, which has a real BasicObject class.
32
+ # No-op method on ruby 1.9, which has a real +BasicObject+ class.
33
33
  def self.remove_methods!
34
34
  end
35
35
  end
@@ -45,17 +45,22 @@ module Sequel
45
45
 
46
46
  ### Parent Classes ###
47
47
 
48
- # Classes/Modules aren't an alphabetical order due to the fact that
48
+ # Classes/Modules aren't in alphabetical order due to the fact that
49
49
  # some reference constants defined in others at load time.
50
50
 
51
- # Base class for all SQL fragments
51
+ # Base class for all SQL expression objects.
52
52
  class Expression
53
- # all instance variables declared to be readers are to be used for comparison.
53
+ # Expression objects are assumed to be value objects, where their
54
+ # attribute values can't change after assignment. In order to make
55
+ # it easy to define equality and hash methods, subclass
56
+ # instances assume that the only values that affect the results of
57
+ # such methods are the values of the object's attributes.
54
58
  def self.attr_reader(*args)
55
59
  super
56
60
  comparison_attrs.concat args
57
61
  end
58
62
 
63
+ # All attributes used for equality and hash methods.
59
64
  def self.comparison_attrs
60
65
  @comparison_attrs ||= self == Expression ? [] : superclass.comparison_attrs.clone
61
66
  end
@@ -68,7 +73,7 @@ module Sequel
68
73
  end
69
74
  private_class_method :to_s_method
70
75
 
71
- # Alias of eql?
76
+ # Alias of <tt>eql?</tt>
72
77
  def ==(other)
73
78
  eql?(other)
74
79
  end
@@ -76,7 +81,7 @@ module Sequel
76
81
  # Returns true if the receiver is the same expression as the
77
82
  # the +other+ expression.
78
83
  def eql?(other)
79
- other.is_a?(self.class) && !self.class.comparison_attrs.find {|a| send(a) != other.send(a)}
84
+ other.is_a?(self.class) && !self.class.comparison_attrs.find{|a| send(a) != other.send(a)}
80
85
  end
81
86
 
82
87
  # Make sure that the hash value is the same if the attributes are the same.
@@ -84,13 +89,18 @@ module Sequel
84
89
  ([self.class] + self.class.comparison_attrs.map{|x| send(x)}).hash
85
90
  end
86
91
 
87
- # Returns self, because SQL::Expression already acts like
88
- # LiteralString.
92
+ # Show the class name and instance variables for the object, necessary
93
+ # for correct operation on ruby 1.9.2.
94
+ def inspect
95
+ "#<#{self.class} #{instance_variables.map{|iv| "#{iv}=>#{instance_variable_get(iv).inspect}"}.join(', ')}>"
96
+ end
97
+
98
+ # Returns +self+, because <tt>SQL::Expression</tt> already acts like +LiteralString+.
89
99
  def lit
90
100
  self
91
101
  end
92
102
 
93
- # Alias of to_s
103
+ # Alias of +to_s+
94
104
  def sql_literal(ds)
95
105
  to_s(ds)
96
106
  end
@@ -98,11 +108,10 @@ module Sequel
98
108
 
99
109
  # Represents a complex SQL expression, with a given operator and one
100
110
  # or more attributes (which may also be ComplexExpressions, forming
101
- # a tree). This class is the backbone of the blockless filter support in
102
- # Sequel.
111
+ # a tree). This class is the backbone of Sequel's ruby expression DSL.
103
112
  #
104
113
  # This is an abstract class that is not that useful by itself. The
105
- # subclasses BooleanExpression, NumericExpression, and StringExpression
114
+ # subclasses +BooleanExpression+, +NumericExpression+, and +StringExpression+
106
115
  # define the behavior of the DSL via operators.
107
116
  class ComplexExpression < Expression
108
117
  # A hash of the opposite for each operator symbol, used for inverting
@@ -114,30 +123,33 @@ module Sequel
114
123
  :'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
115
124
  :'NOT ILIKE'=>:ILIKE}
116
125
 
117
- # Standard Mathematical Operators used in NumericMethods
126
+ # Standard mathematical operators used in +NumericMethods+
118
127
  MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
119
128
 
120
- # Bitwise Mathematical Operators used in NumericMethods
129
+ # Bitwise mathematical operators used in +NumericMethods+
121
130
  BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>]
122
131
 
123
- # Inequality Operators used in InequalityMethods
132
+ # Inequality operators used in +InequalityMethods+
124
133
  INEQUALITY_OPERATORS = [:<, :>, :<=, :>=]
125
134
 
126
- # Hash of ruby operator symbols to SQL operators, used in BooleanMethods
135
+ # Hash of ruby operator symbols to SQL operators, used in +BooleanMethods+
127
136
  BOOLEAN_OPERATOR_METHODS = {:& => :AND, :| =>:OR}
128
137
 
138
+ # Operators that use IN/NOT IN for inclusion/exclusion
139
+ IN_OPERATORS = [:IN, :'NOT IN']
140
+
129
141
  # Operators that use IS, used for special casing to override literal true/false values
130
142
  IS_OPERATORS = [:IS, :'IS NOT']
131
143
 
132
144
  # Operator symbols that take exactly two arguments
133
145
  TWO_ARITY_OPERATORS = [:'=', :'!=', :LIKE, :'NOT LIKE', \
134
- :~, :'!~', :'~*', :'!~*', :IN, :'NOT IN', :ILIKE, :'NOT ILIKE'] + \
135
- INEQUALITY_OPERATORS + BITWISE_OPERATORS + IS_OPERATORS
146
+ :~, :'!~', :'~*', :'!~*', :ILIKE, :'NOT ILIKE'] + \
147
+ INEQUALITY_OPERATORS + BITWISE_OPERATORS + IS_OPERATORS + IN_OPERATORS
136
148
 
137
149
  # Operator symbols that take one or more arguments
138
150
  N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS
139
151
 
140
- # Operator symbols that take one argument
152
+ # Operator symbols that take only a single argument
141
153
  ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~']
142
154
 
143
155
  # An array of args for this object
@@ -147,11 +159,13 @@ module Sequel
147
159
  attr_reader :op
148
160
 
149
161
  # Set the operator symbol and arguments for this object to the ones given.
150
- # Convert all args that are hashes or arrays with all two pairs to BooleanExpressions.
151
- # Raise an error if the operator doesn't allow boolean input and a boolean argument is given.
152
- # Raise an error if the wrong number of arguments for a given operator is used.
162
+ # Convert all args that are hashes or arrays of two element arrays to +BooleanExpressions+,
163
+ # other than the second arg for an IN/NOT IN operator.
164
+ # Raise an +Error+ if the operator doesn't allow boolean input and a boolean argument is given.
165
+ # Raise an +Error+ if the wrong number of arguments for a given operator is used.
153
166
  def initialize(op, *args)
154
- args.map!{|a| Sequel.condition_specifier?(a) ? SQL::BooleanExpression.from_value_pairs(a) : a}
167
+ orig_args = args
168
+ args = args.map{|a| Sequel.condition_specifier?(a) ? SQL::BooleanExpression.from_value_pairs(a) : a}
155
169
  case op
156
170
  when *N_ARITY_OPERATORS
157
171
  raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
@@ -160,6 +174,10 @@ module Sequel
160
174
  old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
161
175
  when *TWO_ARITY_OPERATORS
162
176
  raise(Error, "The #{op} operator requires precisely 2 arguments") unless args.length == 2
177
+ # With IN/NOT IN, even if the second argument is an array of two element arrays,
178
+ # don't convert it into a boolean expression, since it's definitely being used
179
+ # as a value list.
180
+ args[1] = orig_args[1] if IN_OPERATORS.include?(op)
163
181
  when *ONE_ARITY_OPERATORS
164
182
  raise(Error, "The #{op} operator requires a single argument") unless args.length == 1
165
183
  else
@@ -173,23 +191,32 @@ module Sequel
173
191
  end
174
192
 
175
193
  # The base class for expressions that can be used in multiple places in
176
- # the SQL query.
194
+ # an SQL query.
177
195
  class GenericExpression < Expression
178
196
  end
179
197
 
180
198
  ### Modules ###
181
199
 
182
- # Methods that create aliased identifiers
200
+ # Includes an +as+ method that creates an SQL alias.
183
201
  module AliasMethods
184
- # Create an SQL column alias of the receiving column or expression to the given alias.
202
+ # Create an SQL alias (+AliasedExpression+) of the receiving column or expression to the given alias.
203
+ #
204
+ # :column.as(:alias) # "column" AS "alias"
185
205
  def as(aliaz)
186
206
  AliasedExpression.new(self, aliaz)
187
207
  end
188
208
  end
189
209
 
190
210
  # This defines the bitwise methods: &, |, ^, ~, <<, and >>. Because these
191
- # methods overlap with the standard BooleanMethods methods, and they only
192
- # make sense for numbers, they are only included in NumericExpression.
211
+ # methods overlap with the standard +BooleanMethods methods+, and they only
212
+ # make sense for integers, they are only included in +NumericExpression+.
213
+ #
214
+ # :a.sql_number & :b # "a" & "b"
215
+ # :a.sql_number | :b # "a" | "b"
216
+ # :a.sql_number ^ :b # "a" ^ "b"
217
+ # :a.sql_number << :b # "a" << "b"
218
+ # :a.sql_number >> :b # "a" >> "b"
219
+ # ~:a.sql_number # ~"a"
193
220
  module BitwiseMethods
194
221
  ComplexExpression::BITWISE_OPERATORS.each do |o|
195
222
  define_method(o) do |ce|
@@ -203,22 +230,21 @@ module Sequel
203
230
  end
204
231
 
205
232
  # Do the bitwise compliment of the self
233
+ #
234
+ # ~:a.sql_number # ~"a"
206
235
  def ~
207
236
  NumericExpression.new(:'B~', self)
208
237
  end
209
238
  end
210
239
 
211
- # This module includes the methods that are defined on objects that can be
212
- # used in a boolean context in SQL (Symbol, LiteralString, SQL::Function,
213
- # and SQL::BooleanExpression).
240
+ # This module includes the boolean/logical AND (&), OR (|) and NOT (~) operators
241
+ # that are defined on objects that can be used in a boolean context in SQL
242
+ # (+Symbol+, +LiteralString+, and <tt>SQL::GenericExpression</tt>).
214
243
  #
215
- # This defines the ~ (NOT), & (AND), and | (OR) methods.
244
+ # :a & :b # "a" AND "b"
245
+ # :a | :b # "a" OR "b"
246
+ # ~:a # NOT "a"
216
247
  module BooleanMethods
217
- # Create a new BooleanExpression with NOT, representing the inversion of whatever self represents.
218
- def ~
219
- BooleanExpression.invert(self)
220
- end
221
-
222
248
  ComplexExpression::BOOLEAN_OPERATOR_METHODS.each do |m, o|
223
249
  define_method(m) do |ce|
224
250
  case ce
@@ -229,35 +255,52 @@ module Sequel
229
255
  end
230
256
  end
231
257
  end
258
+
259
+ # Create a new BooleanExpression with NOT, representing the inversion of whatever self represents.
260
+ #
261
+ # ~:a # NOT :a
262
+ def ~
263
+ BooleanExpression.invert(self)
264
+ end
232
265
  end
233
266
 
234
- # Holds methods that are used to cast objects to differen SQL types.
267
+ # Holds methods that are used to cast objects to different SQL types.
235
268
  module CastMethods
236
269
  # Cast the reciever to the given SQL type. You can specify a ruby class as a type,
237
270
  # and it is handled similarly to using a database independent type in the schema methods.
271
+ #
272
+ # :a.cast(:integer) # CAST(a AS integer)
273
+ # :a.cast(String) # CAST(a AS varchar(255))
238
274
  def cast(sql_type)
239
275
  Cast.new(self, sql_type)
240
276
  end
241
277
 
242
- # Cast the reciever to the given SQL type (or the database's default integer type if none given),
243
- # and return the result as a NumericExpression.
278
+ # Cast the reciever to the given SQL type (or the database's default Integer type if none given),
279
+ # and return the result as a +NumericExpression+, so you can use the bitwise operators
280
+ # on the result.
281
+ #
282
+ # :a.cast_numeric # CAST(a AS integer)
283
+ # :a.cast_numeric(Float) # CAST(a AS double precision)
244
284
  def cast_numeric(sql_type = nil)
245
285
  cast(sql_type || Integer).sql_number
246
286
  end
247
287
 
248
- # Cast the reciever to the given SQL type (or the database's default string type if none given),
249
- # and return the result as a StringExpression, so you can use +
288
+ # Cast the reciever to the given SQL type (or the database's default String type if none given),
289
+ # and return the result as a +StringExpression+, so you can use +
250
290
  # directly on the result for SQL string concatenation.
291
+ #
292
+ # :a.cast_string # CAST(a AS varchar(255))
293
+ # :a.cast_string(:text) # CAST(a AS text)
251
294
  def cast_string(sql_type = nil)
252
295
  cast(sql_type || String).sql_string
253
296
  end
254
297
  end
255
298
 
256
299
  # Adds methods that allow you to treat an object as an instance of a specific
257
- # ComplexExpression subclass. This is useful if another library
300
+ # +ComplexExpression+ subclass. This is useful if another library
258
301
  # overrides the methods defined by Sequel.
259
302
  #
260
- # For example, if Symbol#/ is overridden to produce a string (for
303
+ # For example, if <tt>Symbol#/</tt> is overridden to produce a string (for
261
304
  # example, to make file system path creation easier), the
262
305
  # following code will not do what you want:
263
306
  #
@@ -269,51 +312,64 @@ module Sequel
269
312
  module ComplexExpressionMethods
270
313
  # Extract a datetime_part (e.g. year, month) from self:
271
314
  #
272
- # :date.extract(:year) # SQL: extract(year FROM "date")
315
+ # :date.extract(:year) # extract(year FROM "date")
273
316
  #
274
317
  # Also has the benefit of returning the result as a
275
318
  # NumericExpression instead of a generic ComplexExpression.
276
319
  #
277
320
  # The extract function is in the SQL standard, but it doesn't
278
- # doesn't use the standard function calling convention.
321
+ # doesn't use the standard function calling convention, and it
322
+ # doesn't work on all databases.
279
323
  def extract(datetime_part)
280
324
  Function.new(:extract, PlaceholderLiteralString.new("#{datetime_part} FROM ?", [self])).sql_number
281
325
  end
282
326
 
283
- # Return a BooleanExpression representation of self.
327
+ # Return a BooleanExpression representation of +self+.
284
328
  def sql_boolean
285
329
  BooleanExpression.new(:NOOP, self)
286
330
  end
287
331
 
288
- # Return a NumericExpression representation of self.
332
+ # Return a NumericExpression representation of +self+.
333
+ #
334
+ # ~:a # NOT "a"
335
+ # ~:a.sql_number # ~"a"
289
336
  def sql_number
290
337
  NumericExpression.new(:NOOP, self)
291
338
  end
292
339
 
293
- # Return a StringExpression representation of self.
340
+ # Return a StringExpression representation of +self+.
341
+ #
342
+ # :a + :b # "a" + "b"
343
+ # :a.sql_string + :b # "a" || "b"
294
344
  def sql_string
295
345
  StringExpression.new(:NOOP, self)
296
346
  end
297
347
  end
298
348
 
299
- # Includes a method that returns Identifiers.
349
+ # Includes an +identifier+ method that returns <tt>Identifier</tt>s.
300
350
  module IdentifierMethods
301
- # Return self wrapped as an identifier.
351
+ # Return self wrapped as an <tt>SQL::Identifier</tt>.
352
+ #
353
+ # :a__b # "a"."b"
354
+ # :a__b.identifier # "a__b"
302
355
  def identifier
303
356
  Identifier.new(self)
304
357
  end
305
358
  end
306
359
 
307
- # This module includes the methods that are defined on objects that can be
308
- # used in a numeric or string context in SQL (Symbol (except on ruby 1.9), LiteralString,
309
- # SQL::Function, and SQL::StringExpression).
360
+ # This module includes the inequality methods (>, <, >=, <=) that are defined on objects that can be
361
+ # used in a numeric or string context in SQL (+Symbol+ (except on ruby 1.9), +LiteralString+,
362
+ # <tt>SQL::GenericExpression</tt>).
310
363
  #
311
- # This defines the >, <, >=, and <= methods.
364
+ # 'a'.lit > :b # a > "b"
365
+ # 'a'.lit < :b # a > "b"
366
+ # 'a'.lit >= :b # a >= "b"
367
+ # 'a'.lit <= :b # a <= "b"
312
368
  module InequalityMethods
313
369
  ComplexExpression::INEQUALITY_OPERATORS.each do |o|
314
370
  define_method(o) do |ce|
315
371
  case ce
316
- when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, Array
372
+ when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, ::Array
317
373
  raise(Error, "cannot apply #{o} to a boolean expression")
318
374
  else
319
375
  BooleanExpression.new(o, self, ce)
@@ -323,16 +379,17 @@ module Sequel
323
379
  end
324
380
 
325
381
  # This module augments the default initalize method for the
326
- # ComplexExpression subclass it is included in, so that
327
- # attempting to use boolean input when initializing a NumericExpression
328
- # or StringExpression results in an error.
382
+ # +ComplexExpression+ subclass it is included in, so that
383
+ # attempting to use boolean input when initializing a +NumericExpression+
384
+ # or +StringExpression+ results in an error. It is not expected to be
385
+ # used directly.
329
386
  module NoBooleanInputMethods
330
- # Raise an Error if one of the args would be boolean in an SQL
387
+ # Raise an +Error+ if one of the args would be boolean in an SQL
331
388
  # context, otherwise call super.
332
389
  def initialize(op, *args)
333
390
  args.each do |a|
334
391
  case a
335
- when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, Array
392
+ when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, ::Array
336
393
  raise(Error, "cannot apply #{op} to a boolean expression")
337
394
  end
338
395
  end
@@ -340,11 +397,14 @@ module Sequel
340
397
  end
341
398
  end
342
399
 
343
- # This module includes the methods that are defined on objects that can be
344
- # used in a numeric context in SQL (Symbol, LiteralString, SQL::Function,
345
- # and SQL::NumericExpression).
400
+ # This module includes the standard mathematical methods (+, -, *, and /)
401
+ # that are defined on objects that can be used in a numeric context in SQL
402
+ # (+Symbol+, +LiteralString+, and +SQL::GenericExpression+).
346
403
  #
347
- # This defines the +, -, *, and / methods.
404
+ # :a + :b # "a" + "b"
405
+ # :a - :b # "a" - "b"
406
+ # :a * :b # "a" * "b"
407
+ # :a / :b # "a" / "b"
348
408
  module NumericMethods
349
409
  ComplexExpression::MATHEMATICAL_OPERATORS.each do |o|
350
410
  define_method(o) do |ce|
@@ -358,66 +418,83 @@ module Sequel
358
418
  end
359
419
  end
360
420
 
361
- # Methods that create OrderedExpressions, used for sorting by columns
421
+ # Methods that create +OrderedExpressions+, used for sorting by columns
362
422
  # or more complex expressions.
363
423
  module OrderMethods
364
- # Mark the receiving SQL column as sorting in a descending fashion.
365
- def desc
366
- OrderedExpression.new(self)
424
+ # Mark the receiving SQL column as sorting in an ascending fashion (generally a no-op).
425
+ # Options:
426
+ #
427
+ # :nulls :: Set to :first to use NULLS FIRST (so NULL values are ordered
428
+ # before other values), or :last to use NULLS LAST (so NULL values
429
+ # are ordered after other values).
430
+ def asc(opts={})
431
+ OrderedExpression.new(self, false, opts)
367
432
  end
368
433
 
369
- # Mark the receiving SQL column as sorting in an ascending fashion (generally a no-op).
370
- def asc
371
- OrderedExpression.new(self, false)
434
+ # Mark the receiving SQL column as sorting in a descending fashion.
435
+ # Options:
436
+ #
437
+ # :nulls :: Set to :first to use NULLS FIRST (so NULL values are ordered
438
+ # before other values), or :last to use NULLS LAST (so NULL values
439
+ # are ordered after other values).
440
+ def desc(opts={})
441
+ OrderedExpression.new(self, true, opts)
372
442
  end
373
443
  end
374
444
 
375
- # Methods that created QualifiedIdentifiers, used for qualifying column
445
+ # Includes a +qualify+ method that created <tt>QualifiedIdentifier</tt>s, used for qualifying column
376
446
  # names with a table or table names with a schema.
377
447
  module QualifyingMethods
378
- # Qualify the current object with the given table/schema.
379
- def qualify(ts)
380
- QualifiedIdentifier.new(ts, self)
448
+ # Qualify the receiver with the given +qualifier+ (table for column/schema for table).
449
+ #
450
+ # :column.qualify(:table) # "table"."column"
451
+ # :table.qualify(:schema) # "schema"."table"
452
+ # :column.qualify(:table).qualify(:schema) # "schema"."table"."column"
453
+ def qualify(qualifier)
454
+ QualifiedIdentifier.new(qualifier, self)
381
455
  end
382
456
  end
383
457
 
384
- # This module includes the methods that are defined on objects that can be
385
- # used in a string context in SQL (Symbol, LiteralString, SQL::Function,
386
- # and SQL::StringExpression).
387
- #
388
- # This defines the like (LIKE) and ilike methods, used for pattern matching.
389
- # like is case sensitive (if the database supports it), ilike is case insensitive.
458
+ # This module includes the +like+ and +ilike+ methods used for pattern matching that are defined on objects that can be
459
+ # used in a string context in SQL (+Symbol+, +LiteralString+, <tt>SQL::GenericExpression</tt>).
390
460
  module StringMethods
391
- # Create a BooleanExpression case insensitive pattern match of self
392
- # with the given patterns. See StringExpression.like.
461
+ # Create a +BooleanExpression+ case insensitive pattern match of the receiver
462
+ # with the given patterns. See <tt>StringExpression.like</tt>.
463
+ #
464
+ # :a.ilike('A%') # "a" ILIKE 'A%'
393
465
  def ilike(*ces)
394
466
  StringExpression.like(self, *(ces << {:case_insensitive=>true}))
395
467
  end
396
468
 
397
- # Create a BooleanExpression case sensitive (if the database supports it) pattern match of self with
398
- # the given patterns. See StringExpression.like.
469
+ # Create a +BooleanExpression+ case sensitive (if the database supports it) pattern match of the receiver with
470
+ # the given patterns. See <tt>StringExpression.like</tt>.
471
+ #
472
+ # :a.like('A%') # "a" LIKE 'A%'
399
473
  def like(*ces)
400
474
  StringExpression.like(self, *ces)
401
475
  end
402
476
  end
403
477
 
404
- # This module is included in StringExpression and can be included elsewhere
405
- # to allow the use of the + operator to represent concatenation of SQL
406
- # Strings:
407
- #
408
- # :x.sql_string + :y => # SQL: x || y
478
+ # This module includes the <tt>+</tt> method. It is included in +StringExpression+ and can be included elsewhere
479
+ # to allow the use of the + operator to represent concatenation of SQL Strings:
409
480
  module StringConcatenationMethods
481
+ # Return a +StringExpression+ representing the concatenation of the receiver
482
+ # with the given argument.
483
+ #
484
+ # :x.sql_string + :y => # "x" || "y"
410
485
  def +(ce)
411
486
  StringExpression.new(:'||', self, ce)
412
487
  end
413
488
  end
414
489
 
415
- # Methods that create Subscripts (SQL array accesses).
490
+ # This module includes the +sql_subscript+ method, representing SQL array accesses.
416
491
  module SubscriptMethods
417
- # Return an SQL array subscript with the given arguments.
492
+ # Return a <tt>Subscript</tt> with the given arguments, representing an
493
+ # SQL array access.
418
494
  #
419
- # :array.sql_subscript(1) # SQL: array[1]
420
- # :array.sql_subscript(1, 2) # SQL: array[1, 2]
495
+ # :array.sql_subscript(1) # array[1]
496
+ # :array.sql_subscript(1, 2) # array[1, 2]
497
+ # :array.sql_subscript([1, 2]) # array[1, 2]
421
498
  def sql_subscript(*sub)
422
499
  Subscript.new(self, sub.flatten)
423
500
  end
@@ -425,12 +502,12 @@ module Sequel
425
502
 
426
503
  ### Classes ###
427
504
 
428
- # Represents an aliasing of an expression/column to a given name.
505
+ # Represents an aliasing of an expression to a given alias.
429
506
  class AliasedExpression < Expression
430
507
  # The expression to alias
431
508
  attr_reader :expression
432
509
 
433
- # The alias to use for the expression, not alias since that is
510
+ # The alias to use for the expression, not +alias+ since that is
434
511
  # a keyword in ruby.
435
512
  attr_reader :aliaz
436
513
 
@@ -442,28 +519,31 @@ module Sequel
442
519
  to_s_method :aliased_expression_sql
443
520
  end
444
521
 
445
- # Blob is used to represent binary data in the Ruby environment that is
522
+ # +Blob+ is used to represent binary data in the Ruby environment that is
446
523
  # stored as a blob type in the database. Sequel represents binary data as a Blob object because
447
- # certain database engines require binary data to be escaped.
524
+ # most database engines require binary data to be escaped differently than regular strings.
448
525
  class Blob < ::String
449
- # Returns self
526
+ # Returns +self+, used so that Blobs don't get wrapped in multiple
527
+ # levels.
450
528
  def to_sequel_blob
451
529
  self
452
530
  end
453
531
  end
454
532
 
455
- # Subclass of ComplexExpression where the expression results
533
+ # Subclass of +ComplexExpression+ where the expression results
456
534
  # in a boolean value in SQL.
457
535
  class BooleanExpression < ComplexExpression
458
536
  include BooleanMethods
459
537
 
460
- # Take pairs of values (e.g. a hash or array of arrays of two pairs)
461
- # and converts it to a BooleanExpression. The operator and args
538
+ # Take pairs of values (e.g. a hash or array of two element arrays)
539
+ # and converts it to a +BooleanExpression+. The operator and args
462
540
  # used depends on the case of the right (2nd) argument:
463
541
  #
464
542
  # * 0..10 - left >= 0 AND left <= 10
465
543
  # * [1,2] - left IN (1,2)
466
544
  # * nil - left IS NULL
545
+ # * true - left IS TRUE
546
+ # * false - left IS FALSE
467
547
  # * /as/ - left ~ 'as'
468
548
  # * :blah - left = blah
469
549
  # * 'blah' - left = 'blah'
@@ -480,7 +560,7 @@ module Sequel
480
560
  ce = case r
481
561
  when Range
482
562
  new(:AND, new(:>=, l, r.begin), new(r.exclude_end? ? :< : :<=, l, r.end))
483
- when Array, ::Sequel::Dataset, SQLArray
563
+ when ::Array, ::Sequel::Dataset
484
564
  new(:IN, l, r)
485
565
  when NegativeBooleanConstant
486
566
  new(:"IS NOT", l, r.constant)
@@ -502,6 +582,8 @@ module Sequel
502
582
  # be inverted, raise an error. An inverted expression should match everything that the
503
583
  # uninverted expression did not match, and vice-versa, except for possible issues with
504
584
  # SQL NULL (i.e. 1 == NULL is NULL and 1 != NULL is also NULL).
585
+ #
586
+ # BooleanExpression.invert(:a) # NOT "a"
505
587
  def self.invert(ce)
506
588
  case ce
507
589
  when BooleanExpression
@@ -519,23 +601,31 @@ module Sequel
519
601
  end
520
602
  end
521
603
 
522
- # Represents an SQL CASE expression, used for conditions.
604
+ # Represents an SQL CASE expression, used for conditional branching in SQL.
523
605
  class CaseExpression < GenericExpression
524
606
  # An array of all two pairs with the first element specifying the
525
- # condition and the second element specifying the result.
607
+ # condition and the second element specifying the result if the
608
+ # condition matches.
526
609
  attr_reader :conditions
527
610
 
528
- # The default value if no conditions are true
611
+ # The default value if no conditions match.
529
612
  attr_reader :default
530
613
 
531
614
  # The expression to test the conditions against
532
615
  attr_reader :expression
533
616
 
534
617
  # Create an object with the given conditions and
535
- # default value.
536
- def initialize(conditions, default, expression = nil)
618
+ # default value. An expression can be provided to
619
+ # test each condition against, instead of having
620
+ # all conditions represent their own boolean expression.
621
+ def initialize(conditions, default, expression=(no_expression=true; nil))
537
622
  raise(Sequel::Error, 'CaseExpression conditions must be a hash or array of all two pairs') unless Sequel.condition_specifier?(conditions)
538
- @conditions, @default, @expression = conditions.to_a, default, expression
623
+ @conditions, @default, @expression, @no_expression = conditions.to_a, default, expression, no_expression
624
+ end
625
+
626
+ # Whether to use an expression for this CASE expression.
627
+ def expression?
628
+ !@no_expression
539
629
  end
540
630
 
541
631
  to_s_method :case_expression_sql
@@ -578,9 +668,12 @@ module Sequel
578
668
  include SubscriptMethods
579
669
  end
580
670
 
581
- # Represents constants or psuedo-constants (e.g. CURRENT_DATE) in SQL.
671
+ # Represents constants or psuedo-constants (e.g. +CURRENT_DATE+) in SQL.
582
672
  class Constant < GenericExpression
583
- # Create an object with the given table
673
+ # The underlying constant related to this object.
674
+ attr_reader :constant
675
+
676
+ # Create an constant with the given value
584
677
  def initialize(constant)
585
678
  @constant = constant
586
679
  end
@@ -588,15 +681,12 @@ module Sequel
588
681
  to_s_method :constant_sql, '@constant'
589
682
  end
590
683
 
591
- # Represents boolean constants such as NULL, NOTNULL, TRUE, and FALSE.
684
+ # Represents boolean constants such as +NULL+, +NOTNULL+, +TRUE+, and +FALSE+.
592
685
  class BooleanConstant < Constant
593
- # The underlying constant related for this object.
594
- attr_reader :constant
595
-
596
686
  to_s_method :boolean_constant_sql, '@constant'
597
687
  end
598
688
 
599
- # Represents inverse boolean constants (currently only NOTNULL). A
689
+ # Represents inverse boolean constants (currently only +NOTNULL+). A
600
690
  # special class to allow for special behavior.
601
691
  class NegativeBooleanConstant < BooleanConstant
602
692
  to_s_method :negative_boolean_constant_sql, '@constant'
@@ -624,7 +714,7 @@ module Sequel
624
714
  # The SQL function to call
625
715
  attr_reader :f
626
716
 
627
- # Set the attributes to the given arguments
717
+ # Set the functions and args to the given arguments
628
718
  def initialize(f, *args)
629
719
  @f, @args = f, args
630
720
  end
@@ -645,12 +735,12 @@ module Sequel
645
735
  end
646
736
 
647
737
  # Represents an identifier (column or table). Can be used
648
- # to specify a Symbol with multiple underscores should not be
738
+ # to specify a +Symbol+ with multiple underscores should not be
649
739
  # split, or for creating an identifier without using a symbol.
650
740
  class Identifier < GenericExpression
651
741
  include QualifyingMethods
652
742
 
653
- # The table and column to reference
743
+ # The table or column to reference
654
744
  attr_reader :value
655
745
 
656
746
  # Set the value to the given argument
@@ -680,7 +770,7 @@ module Sequel
680
770
  to_s_method :join_clause_sql
681
771
  end
682
772
 
683
- # Represents an SQL JOIN table ON conditions clause.
773
+ # Represents an SQL JOIN clause with ON conditions.
684
774
  class JoinOnClause < JoinClause
685
775
  # The conditions for the join
686
776
  attr_reader :on
@@ -695,7 +785,7 @@ module Sequel
695
785
  to_s_method :join_on_clause_sql
696
786
  end
697
787
 
698
- # Represents an SQL JOIN table USING (columns) clause.
788
+ # Represents an SQL JOIN clause with USING conditions.
699
789
  class JoinUsingClause < JoinClause
700
790
  # The columns that appear in both tables that should be equal
701
791
  # for the conditions to match.
@@ -713,8 +803,9 @@ module Sequel
713
803
 
714
804
  # Represents a literal string with placeholders and arguments.
715
805
  # This is necessary to ensure delayed literalization of the arguments
716
- # required for the prepared statement support
717
- class PlaceholderLiteralString < Expression
806
+ # required for the prepared statement support and for database-specific
807
+ # literalization.
808
+ class PlaceholderLiteralString < GenericExpression
718
809
  # The arguments that will be subsituted into the placeholders.
719
810
  # Either an array of unnamed placeholders (which will be substituted in
720
811
  # order for ? characters), or a hash of named placeholders (which will be
@@ -737,7 +828,7 @@ module Sequel
737
828
  to_s_method :placeholder_literal_string_sql
738
829
  end
739
830
 
740
- # Subclass of ComplexExpression where the expression results
831
+ # Subclass of +ComplexExpression+ where the expression results
741
832
  # in a numeric value in SQL.
742
833
  class NumericExpression < ComplexExpression
743
834
  include BitwiseMethods
@@ -748,43 +839,51 @@ module Sequel
748
839
 
749
840
  # Represents a column/expression to order the result set by.
750
841
  class OrderedExpression < Expression
842
+ INVERT_NULLS = {:first=>:last, :last=>:first}.freeze
843
+
751
844
  # The expression to order the result set by.
752
845
  attr_reader :expression
753
846
 
754
847
  # Whether the expression should order the result set in a descending manner
755
848
  attr_reader :descending
756
849
 
850
+ # Whether to sort NULLS FIRST/LAST
851
+ attr_reader :nulls
852
+
757
853
  # Set the expression and descending attributes to the given values.
758
- def initialize(expression, descending = true)
759
- @expression, @descending = expression, descending
854
+ # Options:
855
+ #
856
+ # :nulls :: Can be :first/:last for NULLS FIRST/LAST.
857
+ def initialize(expression, descending = true, opts={})
858
+ @expression, @descending, @nulls = expression, descending, opts[:nulls]
760
859
  end
761
860
 
762
- # Return a copy that is ASC
861
+ # Return a copy that is ordered ASC
763
862
  def asc
764
- OrderedExpression.new(@expression, false)
863
+ OrderedExpression.new(@expression, false, :nulls=>@nulls)
765
864
  end
766
865
 
767
- # Return a copy that is DESC
866
+ # Return a copy that is ordered DESC
768
867
  def desc
769
- OrderedExpression.new(@expression)
868
+ OrderedExpression.new(@expression, true, :nulls=>@nulls)
770
869
  end
771
870
 
772
- # Return an inverted expression, changing ASC to DESC and vice versa
871
+ # Return an inverted expression, changing ASC to DESC and NULLS FIRST to NULLS LAST.
773
872
  def invert
774
- OrderedExpression.new(@expression, !@descending)
873
+ OrderedExpression.new(@expression, !@descending, :nulls=>INVERT_NULLS.fetch(@nulls, @nulls))
775
874
  end
776
875
 
777
876
  to_s_method :ordered_expression_sql
778
877
  end
779
878
 
780
- # Represents a qualified (column with table or table with schema) reference.
879
+ # Represents a qualified identifier (column with table or table with schema).
781
880
  class QualifiedIdentifier < GenericExpression
782
881
  include QualifyingMethods
783
882
 
784
- # The column to reference
883
+ # The column/table referenced
785
884
  attr_reader :column
786
885
 
787
- # The table to reference
886
+ # The table/schema qualifying the reference
788
887
  attr_reader :table
789
888
 
790
889
  # Set the table and column to the given arguments
@@ -795,7 +894,7 @@ module Sequel
795
894
  to_s_method :qualified_identifier_sql
796
895
  end
797
896
 
798
- # Subclass of ComplexExpression where the expression results
897
+ # Subclass of +ComplexExpression+ where the expression results
799
898
  # in a text/string/varchar value in SQL.
800
899
  class StringExpression < ComplexExpression
801
900
  include StringMethods
@@ -803,23 +902,31 @@ module Sequel
803
902
  include InequalityMethods
804
903
  include NoBooleanInputMethods
805
904
 
806
- # Map of [regexp, case_insenstive] to ComplexExpression operator
905
+ # Map of [regexp, case_insenstive] to +ComplexExpression+ operator symbol
807
906
  LIKE_MAP = {[true, true]=>:'~*', [true, false]=>:~, [false, true]=>:ILIKE, [false, false]=>:LIKE}
808
907
 
809
908
  # Creates a SQL pattern match exprssion. left (l) is the SQL string we
810
909
  # are matching against, and ces are the patterns we are matching.
811
- # The match succeeds if any of the patterns match (SQL OR). Patterns
812
- # can be given as strings or regular expressions. Strings will cause
813
- # the SQL LIKE operator to be used, and should be supported by most
814
- # databases. Regular expressions will probably only work on MySQL
815
- # and PostgreSQL, and SQL regular expression syntax is not fully compatible
816
- # with ruby regular expression syntax, so be careful if using regular
817
- # expressions.
910
+ # The match succeeds if any of the patterns match (SQL OR).
911
+ #
912
+ # If a regular expression is used as a pattern, an SQL regular expression will be
913
+ # used, which is currently only supported on MySQL and PostgreSQL. Be aware
914
+ # that MySQL and PostgreSQL regular expression syntax is similar to ruby
915
+ # regular expression syntax, but it not exactly the same, especially for
916
+ # advanced regular expression features. Sequel just uses the source of the
917
+ # ruby regular expression verbatim as the SQL regular expression string.
918
+ #
919
+ # If any other object is used as a regular expression, the SQL LIKE operator will
920
+ # be used, and should be supported by most databases.
818
921
  #
819
922
  # The pattern match will be case insensitive if the last argument is a hash
820
923
  # with a key of :case_insensitive that is not false or nil. Also,
821
924
  # if a case insensitive regular expression is used (//i), that particular
822
925
  # pattern which will always be case insensitive.
926
+ #
927
+ # StringExpression.like(:a, 'a%') # "a" LIKE 'a%'
928
+ # StringExpression.like(:a, 'a%', :case_insensitive=>true) # "a" ILIKE 'a%'
929
+ # StringExpression.like(:a, 'a%', /^a/i) # "a" LIKE 'a%' OR "a" ~* '^a'
823
930
  def self.like(l, *ces)
824
931
  l, lre, lci = like_element(l)
825
932
  lci = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive] ? true : lci
@@ -830,7 +937,7 @@ module Sequel
830
937
  ces.length == 1 ? ces.at(0) : BooleanExpression.new(:OR, *ces)
831
938
  end
832
939
 
833
- # An array of three parts:
940
+ # Returns a three element array, made up of:
834
941
  # * The object to use
835
942
  # * Whether it is a regular expression
836
943
  # * Whether it is case insensitive
@@ -844,22 +951,6 @@ module Sequel
844
951
  private_class_method :like_element
845
952
  end
846
953
 
847
- # Represents an SQL array. Added so it is possible to deal with a
848
- # ruby array of all two pairs as an SQL array instead of an ordered
849
- # hash-like conditions specifier.
850
- class SQLArray < Expression
851
- # The array of objects this SQLArray wraps
852
- attr_reader :array
853
- alias to_a array
854
-
855
- # Create an object with the given array.
856
- def initialize(array)
857
- @array = array
858
- end
859
-
860
- to_s_method :array_sql, '@array'
861
- end
862
-
863
954
  # Represents an SQL array access, with multiple possible arguments.
864
955
  class Subscript < GenericExpression
865
956
  # The SQL array column
@@ -873,7 +964,7 @@ module Sequel
873
964
  @f, @sub = f, sub
874
965
  end
875
966
 
876
- # Create a new subscript appending the given subscript(s)
967
+ # Create a new +Subscript+ appending the given subscript(s)
877
968
  # the the current array of subscripts.
878
969
  def |(sub)
879
970
  Subscript.new(@f, @sub + Array(sub))
@@ -882,32 +973,48 @@ module Sequel
882
973
  to_s_method :subscript_sql
883
974
  end
884
975
 
885
- # The purpose of this class is to allow the easy creation of SQL identifiers and functions
886
- # without relying on methods defined on Symbol. This is useful if another library defines
887
- # the methods defined by Sequel, or if you are running on ruby 1.9.
976
+ # Represents an SQL value list (IN/NOT IN predicate value). Added so it is possible to deal with a
977
+ # ruby array of two element arrays as an SQL value list instead of an ordered
978
+ # hash-like conditions specifier.
979
+ class ValueList < ::Array
980
+ end
981
+
982
+ # Deprecated name for +ValueList+, used for backwards compatibility
983
+ SQLArray = ValueList
984
+
985
+ # The purpose of the +VirtualRow+ class is to allow the easy creation of SQL identifiers and functions
986
+ # without relying on methods defined on +Symbol+. This is useful if another library defines
987
+ # the methods defined by Sequel, if you are running on ruby 1.9, or if you are not using the
988
+ # core extensions.
888
989
  #
889
- # An instance of this class is yielded to the block supplied to filter, order, and select.
990
+ # An instance of this class is yielded to the block supplied to <tt>Dataset#filter</tt>, <tt>Dataset#order</tt>, and <tt>Dataset#select</tt>
991
+ # (and the other methods that accept a block and pass it to one of those methods).
890
992
  # If the block doesn't take an argument, the block is instance_evaled in the context of
891
993
  # a new instance of this class.
892
994
  #
893
- # VirtualRow uses method_missing to return Identifiers, QualifiedIdentifiers, Functions, or WindowFunctions,
894
- # depending on how it is called. If a block is not given, creates one of the following objects:
895
- # * Function - returned if any arguments are supplied, using the method name
896
- # as the function name, and the arguments as the function arguments.
897
- # * QualifiedIdentifier - returned if the method name contains __, with the
898
- # table being the part before __, and the column being the part after.
899
- # * Identifier - returned otherwise, using the method name.
900
- # If a block is given, it returns either a Function or WindowFunction, depending on the first
995
+ # +VirtualRow+ uses +method_missing+ to return either an +Identifier+, +QualifiedIdentifier+, +Function+, or +WindowFunction+,
996
+ # depending on how it is called.
997
+ #
998
+ # If a block is _not_ given, creates one of the following objects:
999
+ #
1000
+ # +Function+ :: Returned if any arguments are supplied, using the method name
1001
+ # as the function name, and the arguments as the function arguments.
1002
+ # +QualifiedIdentifier+ :: Returned if the method name contains __, with the
1003
+ # table being the part before __, and the column being the part after.
1004
+ # +Identifier+ :: Returned otherwise, using the method name.
1005
+ #
1006
+ # If a block is given, it returns either a +Function+ or +WindowFunction+, depending on the first
901
1007
  # argument to the method. Note that the block is currently not called by the code, though
902
1008
  # this may change in a future version. If the first argument is:
903
- # * no arguments given - uses a Function with no arguments.
904
- # * :* - uses a Function with a literal wildcard argument (*), mostly useful for COUNT.
905
- # * :distinct - uses a Function that prepends DISTINCT to the rest of the arguments, mostly
906
- # useful for aggregate functions.
907
- # * :over - uses a WindowFunction. If a second argument is provided, it should be a hash
908
- # of options which are passed to Window (e.g. :window, :partition, :order, :frame). The
909
- # arguments to the function itself should be specified as :*=>true for a wildcard, or via
910
- # the :args option.
1009
+ #
1010
+ # no arguments given :: creates a +Function+ with no arguments.
1011
+ # :* :: creates a +Function+ with a literal wildcard argument (*), mostly useful for COUNT.
1012
+ # :distinct :: creates a +Function+ that prepends DISTINCT to the rest of the arguments, mostly
1013
+ # useful for aggregate functions.
1014
+ # :over :: creates a +WindowFunction+. If a second argument is provided, it should be a hash
1015
+ # of options which are passed to Window (with possible keys :window, :partition, :order, and :frame). The
1016
+ # arguments to the function itself should be specified as <tt>:*=>true</tt> for a wildcard, or via
1017
+ # the <tt>:args</tt> option.
911
1018
  #
912
1019
  # Examples:
913
1020
  #
@@ -927,13 +1034,15 @@ module Sequel
927
1034
  # ds.select{rank(:over){}} # SELECT rank() OVER () FROM t
928
1035
  # ds.select{count(:over, :*=>true){}} # SELECT count(*) OVER () FROM t
929
1036
  # ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}} # SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3) FROM t
1037
+ #
1038
+ # For a more detailed explanation, see the {Virtual Rows guide}[link:files/doc/virtual_rows_rdoc.html].
930
1039
  class VirtualRow < BasicObject
931
1040
  WILDCARD = LiteralString.new('*').freeze
932
1041
  QUESTION_MARK = LiteralString.new('?').freeze
933
1042
  COMMA_SEPARATOR = LiteralString.new(', ').freeze
934
1043
  DOUBLE_UNDERSCORE = '__'.freeze
935
1044
 
936
- # Return Identifiers, QualifiedIdentifiers, Functions, or WindowFunctions, depending
1045
+ # Return an +Identifier+, +QualifiedIdentifier+, +Function+, or +WindowFunction+, depending
937
1046
  # on arguments and whether a block is provided. Does not currently call the block.
938
1047
  # See the class level documentation.
939
1048
  def method_missing(m, *args, &block)
@@ -963,17 +1072,17 @@ module Sequel
963
1072
  end
964
1073
  end
965
1074
 
966
- # A window is part of a window function specifying the window over which the function operates.
967
- # It is separated from the WindowFunction class because it also can be used separately on
1075
+ # A +Window+ is part of a window function specifying the window over which the function operates.
1076
+ # It is separated from the +WindowFunction+ class because it also can be used separately on
968
1077
  # some databases.
969
1078
  class Window < Expression
970
- # The options for this window. Options currently used are:
971
- # * :frame - if specified, should be :all or :rows. :all always operates over all rows in the
972
- # partition, while :rows excludes the current row's later peers. The default is to include
973
- # all previous rows in the partition up to the current row's last peer.
974
- # * :order - order on the column(s) given
975
- # * :partition - partition/group on the column(s) given
976
- # * :window - base results on a previously specified named window
1079
+ # The options for this window. Options currently supported:
1080
+ # :frame :: if specified, should be :all, :rows, or a String that is used literally. :all always operates over all rows in the
1081
+ # partition, while :rows excludes the current row's later peers. The default is to include
1082
+ # all previous rows in the partition up to the current row's last peer.
1083
+ # :order :: order on the column(s) given
1084
+ # :partition :: partition/group on the column(s) given
1085
+ # :window :: base results on a previously specified named window
977
1086
  attr_reader :opts
978
1087
 
979
1088
  # Set the options to the options given
@@ -984,12 +1093,12 @@ module Sequel
984
1093
  to_s_method :window_sql, '@opts'
985
1094
  end
986
1095
 
987
- # A WindowFunction is a grouping of a function with a window over which it operates.
1096
+ # A +WindowFunction+ is a grouping of a +Function+ with a +Window+ over which it operates.
988
1097
  class WindowFunction < GenericExpression
989
- # The function to use, should be an SQL::Function.
1098
+ # The function to use, should be an <tt>SQL::Function</tt>.
990
1099
  attr_reader :function
991
1100
 
992
- # The window to use, should be an SQL::Window.
1101
+ # The window to use, should be an <tt>SQL::Window</tt>.
993
1102
  attr_reader :window
994
1103
 
995
1104
  # Set the function and window.
@@ -1001,9 +1110,9 @@ module Sequel
1001
1110
  end
1002
1111
  end
1003
1112
 
1004
- # LiteralString is used to represent literal SQL expressions. A
1005
- # LiteralString is copied verbatim into an SQL statement. Instances of
1006
- # LiteralString can be created by calling String#lit.
1113
+ # +LiteralString+ is used to represent literal SQL expressions. A
1114
+ # +LiteralString+ is copied verbatim into an SQL statement. Instances of
1115
+ # +LiteralString+ can be created by calling <tt>String#lit</tt>.
1007
1116
  class LiteralString
1008
1117
  include SQL::OrderMethods
1009
1118
  include SQL::ComplexExpressionMethods