epugh-sequel 0.0.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 (134) hide show
  1. data/README.rdoc +652 -0
  2. data/VERSION.yml +4 -0
  3. data/bin/sequel +104 -0
  4. data/lib/sequel.rb +1 -0
  5. data/lib/sequel/adapters/ado.rb +85 -0
  6. data/lib/sequel/adapters/db2.rb +132 -0
  7. data/lib/sequel/adapters/dbi.rb +101 -0
  8. data/lib/sequel/adapters/do.rb +197 -0
  9. data/lib/sequel/adapters/do/mysql.rb +38 -0
  10. data/lib/sequel/adapters/do/postgres.rb +92 -0
  11. data/lib/sequel/adapters/do/sqlite.rb +31 -0
  12. data/lib/sequel/adapters/firebird.rb +307 -0
  13. data/lib/sequel/adapters/informix.rb +75 -0
  14. data/lib/sequel/adapters/jdbc.rb +485 -0
  15. data/lib/sequel/adapters/jdbc/h2.rb +62 -0
  16. data/lib/sequel/adapters/jdbc/mysql.rb +56 -0
  17. data/lib/sequel/adapters/jdbc/oracle.rb +23 -0
  18. data/lib/sequel/adapters/jdbc/postgresql.rb +101 -0
  19. data/lib/sequel/adapters/jdbc/sqlite.rb +43 -0
  20. data/lib/sequel/adapters/mysql.rb +370 -0
  21. data/lib/sequel/adapters/odbc.rb +184 -0
  22. data/lib/sequel/adapters/openbase.rb +57 -0
  23. data/lib/sequel/adapters/oracle.rb +140 -0
  24. data/lib/sequel/adapters/postgres.rb +453 -0
  25. data/lib/sequel/adapters/shared/mssql.rb +93 -0
  26. data/lib/sequel/adapters/shared/mysql.rb +341 -0
  27. data/lib/sequel/adapters/shared/oracle.rb +62 -0
  28. data/lib/sequel/adapters/shared/postgres.rb +743 -0
  29. data/lib/sequel/adapters/shared/progress.rb +34 -0
  30. data/lib/sequel/adapters/shared/sqlite.rb +263 -0
  31. data/lib/sequel/adapters/sqlite.rb +243 -0
  32. data/lib/sequel/adapters/utils/date_format.rb +21 -0
  33. data/lib/sequel/adapters/utils/stored_procedures.rb +75 -0
  34. data/lib/sequel/adapters/utils/unsupported.rb +62 -0
  35. data/lib/sequel/connection_pool.rb +258 -0
  36. data/lib/sequel/core.rb +204 -0
  37. data/lib/sequel/core_sql.rb +185 -0
  38. data/lib/sequel/database.rb +687 -0
  39. data/lib/sequel/database/schema_generator.rb +324 -0
  40. data/lib/sequel/database/schema_methods.rb +164 -0
  41. data/lib/sequel/database/schema_sql.rb +324 -0
  42. data/lib/sequel/dataset.rb +422 -0
  43. data/lib/sequel/dataset/convenience.rb +237 -0
  44. data/lib/sequel/dataset/prepared_statements.rb +220 -0
  45. data/lib/sequel/dataset/sql.rb +1105 -0
  46. data/lib/sequel/deprecated.rb +529 -0
  47. data/lib/sequel/exceptions.rb +44 -0
  48. data/lib/sequel/extensions/blank.rb +42 -0
  49. data/lib/sequel/extensions/inflector.rb +288 -0
  50. data/lib/sequel/extensions/pagination.rb +96 -0
  51. data/lib/sequel/extensions/pretty_table.rb +78 -0
  52. data/lib/sequel/extensions/query.rb +48 -0
  53. data/lib/sequel/extensions/string_date_time.rb +47 -0
  54. data/lib/sequel/metaprogramming.rb +44 -0
  55. data/lib/sequel/migration.rb +212 -0
  56. data/lib/sequel/model.rb +142 -0
  57. data/lib/sequel/model/association_reflection.rb +263 -0
  58. data/lib/sequel/model/associations.rb +1024 -0
  59. data/lib/sequel/model/base.rb +911 -0
  60. data/lib/sequel/model/deprecated.rb +188 -0
  61. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  62. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  63. data/lib/sequel/model/deprecated_validations.rb +384 -0
  64. data/lib/sequel/model/errors.rb +37 -0
  65. data/lib/sequel/model/exceptions.rb +7 -0
  66. data/lib/sequel/model/inflections.rb +230 -0
  67. data/lib/sequel/model/plugins.rb +74 -0
  68. data/lib/sequel/object_graph.rb +230 -0
  69. data/lib/sequel/plugins/caching.rb +122 -0
  70. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  71. data/lib/sequel/plugins/schema.rb +53 -0
  72. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  73. data/lib/sequel/plugins/validation_class_methods.rb +373 -0
  74. data/lib/sequel/sql.rb +854 -0
  75. data/lib/sequel/version.rb +11 -0
  76. data/lib/sequel_core.rb +1 -0
  77. data/lib/sequel_model.rb +1 -0
  78. data/spec/adapters/ado_spec.rb +46 -0
  79. data/spec/adapters/firebird_spec.rb +376 -0
  80. data/spec/adapters/informix_spec.rb +96 -0
  81. data/spec/adapters/mysql_spec.rb +875 -0
  82. data/spec/adapters/oracle_spec.rb +272 -0
  83. data/spec/adapters/postgres_spec.rb +692 -0
  84. data/spec/adapters/spec_helper.rb +10 -0
  85. data/spec/adapters/sqlite_spec.rb +550 -0
  86. data/spec/core/connection_pool_spec.rb +526 -0
  87. data/spec/core/core_ext_spec.rb +156 -0
  88. data/spec/core/core_sql_spec.rb +528 -0
  89. data/spec/core/database_spec.rb +1214 -0
  90. data/spec/core/dataset_spec.rb +3513 -0
  91. data/spec/core/expression_filters_spec.rb +363 -0
  92. data/spec/core/migration_spec.rb +261 -0
  93. data/spec/core/object_graph_spec.rb +280 -0
  94. data/spec/core/pretty_table_spec.rb +58 -0
  95. data/spec/core/schema_generator_spec.rb +167 -0
  96. data/spec/core/schema_spec.rb +778 -0
  97. data/spec/core/spec_helper.rb +82 -0
  98. data/spec/core/version_spec.rb +7 -0
  99. data/spec/extensions/blank_spec.rb +67 -0
  100. data/spec/extensions/caching_spec.rb +201 -0
  101. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  102. data/spec/extensions/inflector_spec.rb +122 -0
  103. data/spec/extensions/pagination_spec.rb +99 -0
  104. data/spec/extensions/pretty_table_spec.rb +91 -0
  105. data/spec/extensions/query_spec.rb +85 -0
  106. data/spec/extensions/schema_spec.rb +111 -0
  107. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  108. data/spec/extensions/spec_helper.rb +90 -0
  109. data/spec/extensions/string_date_time_spec.rb +93 -0
  110. data/spec/extensions/validation_class_methods_spec.rb +1054 -0
  111. data/spec/integration/dataset_test.rb +160 -0
  112. data/spec/integration/eager_loader_test.rb +683 -0
  113. data/spec/integration/prepared_statement_test.rb +130 -0
  114. data/spec/integration/schema_test.rb +183 -0
  115. data/spec/integration/spec_helper.rb +75 -0
  116. data/spec/integration/type_test.rb +96 -0
  117. data/spec/model/association_reflection_spec.rb +93 -0
  118. data/spec/model/associations_spec.rb +1780 -0
  119. data/spec/model/base_spec.rb +494 -0
  120. data/spec/model/caching_spec.rb +217 -0
  121. data/spec/model/dataset_methods_spec.rb +78 -0
  122. data/spec/model/eager_loading_spec.rb +1165 -0
  123. data/spec/model/hooks_spec.rb +472 -0
  124. data/spec/model/inflector_spec.rb +126 -0
  125. data/spec/model/model_spec.rb +588 -0
  126. data/spec/model/plugins_spec.rb +142 -0
  127. data/spec/model/record_spec.rb +1243 -0
  128. data/spec/model/schema_spec.rb +92 -0
  129. data/spec/model/spec_helper.rb +124 -0
  130. data/spec/model/validations_spec.rb +1080 -0
  131. data/spec/rcov.opts +6 -0
  132. data/spec/spec.opts +0 -0
  133. data/spec/spec_config.rb.example +10 -0
  134. metadata +202 -0
@@ -0,0 +1,854 @@
1
+ module Sequel
2
+ # The SQL module holds classes whose instances represent SQL fragments.
3
+ # It also holds modules that are included in core ruby classes that
4
+ # make Sequel a friendly DSL.
5
+ module SQL
6
+ ### Parent Classes ###
7
+
8
+ # Classes/Modules aren't an alphabetical order due to the fact that
9
+ # some reference constants defined in others at load time.
10
+
11
+ # Base class for all SQL fragments
12
+ class Expression
13
+ # Returns self, because SQL::Expression already acts like
14
+ # LiteralString.
15
+ def lit
16
+ self
17
+ end
18
+ end
19
+
20
+ # Represents a complex SQL expression, with a given operator and one
21
+ # or more attributes (which may also be ComplexExpressions, forming
22
+ # a tree). This class is the backbone of the blockless filter support in
23
+ # Sequel.
24
+ #
25
+ # This is an abstract class that is not that useful by itself. The
26
+ # subclasses BooleanExpression, NumericExpression, and StringExpression
27
+ # define the behavior of the DSL via operators.
28
+ class ComplexExpression < Expression
29
+ # A hash of the opposite for each operator symbol, used for inverting
30
+ # objects.
31
+ OPERTATOR_INVERSIONS = {:AND => :OR, :OR => :AND, :< => :>=, :> => :<=,
32
+ :<= => :>, :>= => :<, :'=' => :'!=' , :'!=' => :'=', :LIKE => :'NOT LIKE',
33
+ :'NOT LIKE' => :LIKE, :~ => :'!~', :'!~' => :~, :IN => :'NOT IN',
34
+ :'NOT IN' => :IN, :IS => :'IS NOT', :'IS NOT' => :IS, :'~*' => :'!~*',
35
+ :'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
36
+ :'NOT ILIKE'=>:ILIKE}
37
+
38
+ # Mathematical Operators used in NumericMethods
39
+ MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
40
+
41
+ # Mathematical Operators used in NumericMethods
42
+ BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>]
43
+
44
+ # Inequality Operators used in InequalityMethods
45
+ INEQUALITY_OPERATORS = [:<, :>, :<=, :>=]
46
+
47
+ # Hash of ruby operator symbols to SQL operators, used in BooleanMethods
48
+ BOOLEAN_OPERATOR_METHODS = {:& => :AND, :| =>:OR}
49
+
50
+ # Operators that use IS, used for special casing to override literal true/false values
51
+ IS_OPERATORS = [:IS, :'IS NOT']
52
+
53
+ # Operator symbols that take exactly two arguments
54
+ TWO_ARITY_OPERATORS = [:'=', :'!=', :LIKE, :'NOT LIKE', \
55
+ :~, :'!~', :'~*', :'!~*', :IN, :'NOT IN', :ILIKE, :'NOT ILIKE'] + \
56
+ INEQUALITY_OPERATORS + BITWISE_OPERATORS + IS_OPERATORS
57
+
58
+ # Operator symbols that take one or more arguments
59
+ N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS
60
+
61
+ # Operator symbols that take one argument
62
+ ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~']
63
+
64
+ # An array of args for this object
65
+ attr_reader :args
66
+
67
+ # The operator symbol for this object
68
+ attr_reader :op
69
+
70
+ # Set the operator symbol and arguments for this object to the ones given.
71
+ # Convert all args that are hashes or arrays with all two pairs to ComplexExpressions.
72
+ # Raise an error if the operator doesn't allow boolean input and a boolean argument is given.
73
+ # Raise an error if the wrong number of arguments for a given operator is used.
74
+ def initialize(op, *args)
75
+ args.collect! do |a|
76
+ case a
77
+ when Hash
78
+ a.sql_expr
79
+ when Array
80
+ a.all_two_pairs? ? a.sql_expr : a
81
+ else
82
+ a
83
+ end
84
+ end
85
+ case op
86
+ when *N_ARITY_OPERATORS
87
+ raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
88
+ when *TWO_ARITY_OPERATORS
89
+ raise(Error, "The #{op} operator requires precisely 2 arguments") unless args.length == 2
90
+ when *ONE_ARITY_OPERATORS
91
+ raise(Error, "The #{op} operator requires a single argument") unless args.length == 1
92
+ else
93
+ raise(Error, "Invalid operator #{op}")
94
+ end
95
+ @op = op
96
+ @args = args
97
+ end
98
+
99
+ # Delegate the creation of the resulting SQL to the given dataset,
100
+ # since it may be database dependent.
101
+ def to_s(ds)
102
+ ds.complex_expression_sql(@op, @args)
103
+ end
104
+
105
+ # Returns true if the receiver is the same expression as the
106
+ # the +other+ expression.
107
+ def eql?( other )
108
+ return other.is_a?( self.class ) &&
109
+ @op.eql?( other.op ) &&
110
+ @args.eql?( other.args )
111
+ end
112
+ alias_method :==, :eql?
113
+ end
114
+
115
+ # The base class for expressions that can be used in multiple places in
116
+ # the SQL query.
117
+ class GenericExpression < Expression
118
+ end
119
+
120
+ ### Modules ###
121
+
122
+ # Methods the create aliased identifiers
123
+ module AliasMethods
124
+ # Create an SQL column alias of the receiving column to the given alias.
125
+ def as(aliaz)
126
+ AliasedExpression.new(self, aliaz)
127
+ end
128
+ end
129
+
130
+ # This defines the bitwise methods &, |, ^, ~, <<, and >>. Because these
131
+ # methods overlap with the standard BooleanMethods methods, and they only
132
+ # make sense for numbers, they are only included in NumericExpression.
133
+ module BitwiseMethods
134
+ ComplexExpression::BITWISE_OPERATORS.each do |o|
135
+ define_method(o) do |ce|
136
+ case ce
137
+ when NumericExpression
138
+ NumericExpression.new(o, self, ce)
139
+ when ComplexExpression
140
+ raise(Sequel::Error, "cannot apply #{o} to a non-numeric expression")
141
+ else
142
+ NumericExpression.new(o, self, ce)
143
+ end
144
+ end
145
+ end
146
+
147
+ # Do the bitwise compliment of the self
148
+ def ~
149
+ NumericExpression.new(:'B~', self)
150
+ end
151
+ end
152
+
153
+ # This module includes the methods that are defined on objects that can be
154
+ # used in a boolean context in SQL (Symbol, LiteralString, SQL::Function,
155
+ # and SQL::BooleanExpression).
156
+ #
157
+ # This defines the ~ (NOT), & (AND), and | (OR) methods.
158
+ module BooleanMethods
159
+ # Create a new BooleanExpression with NOT, representing the inversion of whatever self represents.
160
+ def ~
161
+ BooleanExpression.invert(self)
162
+ end
163
+
164
+ ComplexExpression::BOOLEAN_OPERATOR_METHODS.each do |m, o|
165
+ define_method(m) do |ce|
166
+ case ce
167
+ when BooleanExpression
168
+ BooleanExpression.new(o, self, ce)
169
+ when ComplexExpression
170
+ raise(Sequel::Error, "cannot apply #{o} to a non-boolean expression")
171
+ else
172
+ BooleanExpression.new(o, self, ce)
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ # Holds methods that are used to cast objects to differen SQL types.
179
+ module CastMethods
180
+ # Cast the reciever to the given SQL type
181
+ def cast(sql_type)
182
+ Cast.new(self, sql_type)
183
+ end
184
+
185
+ # Cast the reciever to the given SQL type (or integer if none given),
186
+ # and return the result as a NumericExpression.
187
+ def cast_numeric(sql_type = nil)
188
+ cast(sql_type || Integer).sql_number
189
+ end
190
+
191
+ # Cast the reciever to the given SQL type (or text if none given),
192
+ # and return the result as a StringExpression, so you can use +
193
+ # directly on the result for SQL string concatenation.
194
+ def cast_string(sql_type = nil)
195
+ cast(sql_type || String).sql_string
196
+ end
197
+ end
198
+
199
+ # Includes a method that returns Identifiers.
200
+ module IdentifierMethods
201
+ # Return self wrapped as an identifier.
202
+ def identifier
203
+ Identifier.new(self)
204
+ end
205
+ end
206
+
207
+ # This module includes the methods that are defined on objects that can be
208
+ # used in a numeric or string context in SQL (Symbol, LiteralString,
209
+ # SQL::Function, and SQL::StringExpression).
210
+ #
211
+ # This defines the >, <, >=, and <= methods.
212
+ module InequalityMethods
213
+ ComplexExpression::INEQUALITY_OPERATORS.each do |o|
214
+ define_method(o) do |ce|
215
+ case ce
216
+ when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, Array
217
+ raise(Error, "cannot apply #{o} to a boolean expression")
218
+ else
219
+ BooleanExpression.new(o, self, ce)
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ # This module augments the default initalize method for the
226
+ # ComplexExpression subclass it is included in, so that
227
+ # attempting to use boolean input when initializing a NumericExpression
228
+ # or StringExpression results in an error.
229
+ module NoBooleanInputMethods
230
+ # Raise an Error if one of the args would be boolean in an SQL
231
+ # context, otherwise call super.
232
+ def initialize(op, *args)
233
+ args.each do |a|
234
+ case a
235
+ when BooleanExpression, TrueClass, FalseClass, NilClass, Hash, Array
236
+ raise(Error, "cannot apply #{op} to a boolean expression")
237
+ end
238
+ end
239
+ super
240
+ end
241
+ end
242
+
243
+ # This module includes the methods that are defined on objects that can be
244
+ # used in a numeric context in SQL (Symbol, LiteralString, SQL::Function,
245
+ # and SQL::NumericExpression).
246
+ #
247
+ # This defines the +, -, *, and / methods.
248
+ module NumericMethods
249
+ ComplexExpression::MATHEMATICAL_OPERATORS.each do |o|
250
+ define_method(o) do |ce|
251
+ case ce
252
+ when NumericExpression
253
+ NumericExpression.new(o, self, ce)
254
+ when ComplexExpression
255
+ raise(Sequel::Error, "cannot apply #{o} to a non-numeric expression")
256
+ else
257
+ NumericExpression.new(o, self, ce)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ # Methods that create OrderedExpressions, used for sorting by columns
264
+ # or more complex expressions.
265
+ module OrderMethods
266
+ # Mark the receiving SQL column as sorting in a descending fashion.
267
+ def desc
268
+ OrderedExpression.new(self)
269
+ end
270
+
271
+ # Mark the receiving SQL column as sorting in an ascending fashion (generally a no-op).
272
+ def asc
273
+ OrderedExpression.new(self, false)
274
+ end
275
+ end
276
+
277
+ # Methods that created QualifiedIdentifiers, used for qualifying column
278
+ # names with a table or table names with a schema.
279
+ module QualifyingMethods
280
+ # Qualify the current object with the given table/schema.
281
+ def qualify(ts)
282
+ QualifiedIdentifier.new(ts, self)
283
+ end
284
+ end
285
+
286
+ # This module includes the methods that are defined on objects that can be
287
+ # used in a numeric context in SQL (Symbol, LiteralString, SQL::Function,
288
+ # and SQL::StringExpression).
289
+ #
290
+ # This defines the like (LIKE) method, used for pattern matching.
291
+ module StringMethods
292
+ # Create a BooleanExpression case insensitive pattern match of self
293
+ # with the given patterns. See StringExpression.like.
294
+ def ilike(*ces)
295
+ StringExpression.like(self, *(ces << {:case_insensitive=>true}))
296
+ end
297
+
298
+ # Create a BooleanExpression case sensitive pattern match of self with
299
+ # the given patterns. See StringExpression.like.
300
+ def like(*ces)
301
+ StringExpression.like(self, *ces)
302
+ end
303
+ end
304
+
305
+ # This module is included in StringExpression and can be included elsewhere
306
+ # to allow the use of the + operator to represent concatenation of SQL
307
+ # Strings:
308
+ #
309
+ # :x.sql_string + :y => # SQL: x || y
310
+ module StringConcatenationMethods
311
+ def +(ce)
312
+ StringExpression.new(:'||', self, ce)
313
+ end
314
+ end
315
+
316
+ ### Modules that include other modules ###
317
+
318
+ # This module includes other Sequel::SQL::*Methods modules and is
319
+ # included in other classes that are could be either booleans,
320
+ # strings, or numbers. It also adds three methods so that
321
+ # can specify behavior in case one of the operator methods has
322
+ # been overridden (such as Symbol#/).
323
+ #
324
+ # For example, if Symbol#/ is overridden to produce a string (for
325
+ # example, to make file system path creation easier), the
326
+ # following code will not do what you want:
327
+ #
328
+ # :price/10 > 100
329
+ #
330
+ # In that case, you need to do the following:
331
+ #
332
+ # :price.sql_number/10 > 100
333
+ module ComplexExpressionMethods
334
+ # Extract a datetime_part (e.g. year, month) from self:
335
+ #
336
+ # :date.extract(:year) # SQL: extract(year FROM "date")
337
+ #
338
+ # Also has the benefit of returning the result as a
339
+ # NumericExpression instead of a generic ComplexExpression.
340
+ def extract(datetime_part)
341
+ Function.new(:extract, PlaceholderLiteralString.new("#{datetime_part} FROM ?", [self])).sql_number
342
+ end
343
+
344
+ # Return a BooleanExpression representation of self.
345
+ def sql_boolean
346
+ BooleanExpression.new(:NOOP, self)
347
+ end
348
+
349
+ # Return a NumericExpression representation of self.
350
+ def sql_number
351
+ NumericExpression.new(:NOOP, self)
352
+ end
353
+
354
+ # Return a StringExpression representation of self.
355
+ def sql_string
356
+ StringExpression.new(:NOOP, self)
357
+ end
358
+ end
359
+
360
+ class ComplexExpression
361
+ include AliasMethods
362
+ include CastMethods
363
+ include OrderMethods
364
+ end
365
+
366
+ class GenericExpression
367
+ include AliasMethods
368
+ include CastMethods
369
+ include OrderMethods
370
+ include ComplexExpressionMethods
371
+ include BooleanMethods
372
+ include NumericMethods
373
+ include StringMethods
374
+ include InequalityMethods
375
+ end
376
+
377
+ ### Classes ###
378
+
379
+ # Represents an aliasing of an expression/column to a given name.
380
+ class AliasedExpression < Expression
381
+ # The expression to alias
382
+ attr_reader :expression
383
+
384
+ # The alias to use for the expression, not alias since that is
385
+ # a keyword in ruby.
386
+ attr_reader :aliaz
387
+
388
+ # Create an object with the given expression and alias.
389
+ def initialize(expression, aliaz)
390
+ @expression, @aliaz = expression, aliaz
391
+ end
392
+
393
+ # Delegate the creation of the resulting SQL to the given dataset,
394
+ # since it may be database dependent.
395
+ def to_s(ds)
396
+ ds.aliased_expression_sql(self)
397
+ end
398
+ end
399
+
400
+ # Blob is used to represent binary data in the Ruby environment that is
401
+ # stored as a blob type in the database. In PostgreSQL, the blob type is
402
+ # called bytea. Sequel represents binary data as a Blob object because
403
+ # certain database engines, such as PostgreSQL, require binary data to be
404
+ # escaped.
405
+ class Blob < ::String
406
+ # Returns self
407
+ def to_sequel_blob
408
+ self
409
+ end
410
+ end
411
+
412
+ # Subclass of ComplexExpression where the expression results
413
+ # in a boolean value in SQL.
414
+ class BooleanExpression < ComplexExpression
415
+ include BooleanMethods
416
+
417
+ # Take pairs of values (e.g. a hash or array of arrays of two pairs)
418
+ # and converts it to a BooleanExpression. The operator and args
419
+ # used depends on the case of the right (2nd) argument:
420
+ #
421
+ # * 0..10 - left >= 0 AND left <= 10
422
+ # * [1,2] - left IN (1,2)
423
+ # * nil - left IS NULL
424
+ # * /as/ - left ~ 'as'
425
+ # * :blah - left = blah
426
+ # * 'blah' - left = 'blah'
427
+ #
428
+ # If multiple arguments are given, they are joined with the op given (AND
429
+ # by default, OR possible). If negate is set to true,
430
+ # all subexpressions are inverted before used. Therefore, the following
431
+ # expressions are equivalent:
432
+ #
433
+ # ~from_value_pairs(hash)
434
+ # from_value_pairs(hash, :OR, true)
435
+ def self.from_value_pairs(pairs, op=:AND, negate=false)
436
+ pairs = pairs.collect do |l,r|
437
+ ce = case r
438
+ when Range
439
+ new(:AND, new(:>=, l, r.begin), new(r.exclude_end? ? :< : :<=, l, r.end))
440
+ when Array, ::Sequel::Dataset, SQLArray
441
+ new(:IN, l, r)
442
+ when NilClass, TrueClass, FalseClass
443
+ new(:IS, l, r)
444
+ when Regexp
445
+ StringExpression.like(l, r)
446
+ else
447
+ new(:'=', l, r)
448
+ end
449
+ negate ? invert(ce) : ce
450
+ end
451
+ pairs.length == 1 ? pairs.at(0) : new(op, *pairs)
452
+ end
453
+
454
+ # Invert the expression, if possible. If the expression cannot
455
+ # be inverted, raise an error. An inverted expression should match everything that the
456
+ # uninverted expression did not match, and vice-versa.
457
+ def self.invert(ce)
458
+ case ce
459
+ when BooleanExpression
460
+ case op = ce.op
461
+ when :AND, :OR
462
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.collect{|a| BooleanExpression.invert(a)})
463
+ else
464
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup)
465
+ end
466
+ when ComplexExpression
467
+ raise(Sequel::Error, "operator #{ce.op} cannot be inverted")
468
+ else
469
+ BooleanExpression.new(:NOT, ce)
470
+ end
471
+ end
472
+ end
473
+
474
+ # Represents an SQL CASE expression, used for conditions.
475
+ class CaseExpression < GenericExpression
476
+ # An array of all two pairs with the first element specifying the
477
+ # condition and the second element specifying the result.
478
+ attr_reader :conditions
479
+
480
+ # The default value if no conditions are true
481
+ attr_reader :default
482
+
483
+ # The expression to test the conditions against
484
+ attr_reader :expression
485
+
486
+ # Create an object with the given conditions and
487
+ # default value.
488
+ def initialize(conditions, default, expression = nil)
489
+ raise(Sequel::Error, 'CaseExpression conditions must be an array with all_two_pairs') unless Array === conditions and conditions.all_two_pairs?
490
+ @conditions, @default, @expression = conditions, default, expression
491
+ end
492
+
493
+ # Delegate the creation of the resulting SQL to the given dataset,
494
+ # since it may be database dependent.
495
+ def to_s(ds)
496
+ ds.case_expression_sql(self)
497
+ end
498
+ end
499
+
500
+ # Represents a cast of an SQL expression to a specific type.
501
+ class Cast < GenericExpression
502
+ # The expression to cast
503
+ attr_reader :expr
504
+
505
+ # The type to which to cast the expression
506
+ attr_reader :type
507
+
508
+ # Set the attributes to the given arguments
509
+ def initialize(expr, type)
510
+ @expr = expr
511
+ @type = type
512
+ end
513
+
514
+ # Delegate the creation of the resulting SQL to the given dataset,
515
+ # since it may be database dependent.
516
+ def to_s(ds)
517
+ ds.cast_sql(expr, type)
518
+ end
519
+ end
520
+
521
+ # Represents all columns in a given table, table.* in SQL
522
+ class ColumnAll < Expression
523
+ # The table containing the columns being selected
524
+ attr_reader :table
525
+
526
+ # Create an object with the given table
527
+ def initialize(table)
528
+ @table = table
529
+ end
530
+
531
+ # ColumnAll expressions are considered equivalent if they
532
+ # have the same class and string representation
533
+ def ==(x)
534
+ x.class == self.class && @table == x.table
535
+ end
536
+
537
+ # Delegate the creation of the resulting SQL to the given dataset,
538
+ # since it may be database dependent.
539
+ def to_s(ds)
540
+ ds.column_all_sql(self)
541
+ end
542
+ end
543
+
544
+ # Represents an SQL function call.
545
+ class Function < GenericExpression
546
+ # The array of arguments to pass to the function (may be blank)
547
+ attr_reader :args
548
+
549
+ # The SQL function to call
550
+ attr_reader :f
551
+
552
+ # Set the attributes to the given arguments
553
+ def initialize(f, *args)
554
+ @f, @args = f, args
555
+ end
556
+
557
+ # Functions are considered equivalent if they
558
+ # have the same class, function, and arguments.
559
+ def ==(x)
560
+ x.class == self.class && @f == x.f && @args == x.args
561
+ end
562
+
563
+ # Delegate the creation of the resulting SQL to the given dataset,
564
+ # since it may be database dependent.
565
+ def to_s(ds)
566
+ ds.function_sql(self)
567
+ end
568
+ end
569
+
570
+ # Represents an identifier (column or table). Can be used
571
+ # to specify a Symbol with multiple underscores should not be
572
+ # split, or for creating an identifier without using a symbol.
573
+ class Identifier < GenericExpression
574
+ include QualifyingMethods
575
+
576
+ # The table and column to reference
577
+ attr_reader :value
578
+
579
+ # Set the value to the given argument
580
+ def initialize(value)
581
+ @value = value
582
+ end
583
+
584
+ # Delegate the creation of the resulting SQL to the given dataset,
585
+ # since it may be database dependent.
586
+ def to_s(ds)
587
+ ds.quote_identifier(@value)
588
+ end
589
+ end
590
+
591
+ # Represents an SQL JOIN clause, used for joining tables.
592
+ class JoinClause < Expression
593
+ # The type of join to do
594
+ attr_reader :join_type
595
+
596
+ # The actual table to join
597
+ attr_reader :table
598
+
599
+ # The table alias to use for the join, if any
600
+ attr_reader :table_alias
601
+
602
+ # Create an object with the given conditions and
603
+ # default value.
604
+ def initialize(join_type, table, table_alias = nil)
605
+ @join_type, @table, @table_alias = join_type, table, table_alias
606
+ end
607
+
608
+ # Delegate the creation of the resulting SQL to the given dataset,
609
+ # since it may be database dependent.
610
+ def to_s(ds)
611
+ ds.join_clause_sql(self)
612
+ end
613
+ end
614
+
615
+ # Represents an SQL JOIN table ON conditions clause.
616
+ class JoinOnClause < JoinClause
617
+ # The conditions for the join
618
+ attr_reader :on
619
+
620
+ # Create an object with the given conditions and
621
+ # default value.
622
+ def initialize(on, *args)
623
+ @on = on
624
+ super(*args)
625
+ end
626
+
627
+ # Delegate the creation of the resulting SQL to the given dataset,
628
+ # since it may be database dependent.
629
+ def to_s(ds)
630
+ ds.join_on_clause_sql(self)
631
+ end
632
+ end
633
+
634
+ # Represents an SQL JOIN table USING (columns) clause.
635
+ class JoinUsingClause < JoinClause
636
+ # The columns that appear both tables that should be equal
637
+ # for the conditions to match.
638
+ attr_reader :using
639
+
640
+ # Create an object with the given conditions and
641
+ # default value.
642
+ def initialize(using, *args)
643
+ @using = using
644
+ super(*args)
645
+ end
646
+
647
+ # Delegate the creation of the resulting SQL to the given dataset,
648
+ # since it may be database dependent.
649
+ def to_s(ds)
650
+ ds.join_using_clause_sql(self)
651
+ end
652
+ end
653
+
654
+ # Represents a literal string with placeholders and arguments.
655
+ # This is necessary to ensure delayed literalization of the arguments
656
+ # required for the prepared statement support
657
+ class PlaceholderLiteralString < Expression
658
+ # The arguments that will be subsituted into the placeholders.
659
+ attr_reader :args
660
+
661
+ # The literal string containing placeholders
662
+ attr_reader :str
663
+
664
+ # Whether to surround the expression with parantheses
665
+ attr_reader :parens
666
+
667
+ # Create an object with the given conditions and
668
+ # default value.
669
+ def initialize(str, args, parens=false)
670
+ @str = str
671
+ @args = args
672
+ @parens = parens
673
+ end
674
+
675
+ # Delegate the creation of the resulting SQL to the given dataset,
676
+ # since it may be database dependent.
677
+ def to_s(ds)
678
+ ds.placeholder_literal_string_sql(self)
679
+ end
680
+ end
681
+
682
+ # Subclass of ComplexExpression where the expression results
683
+ # in a numeric value in SQL.
684
+ class NumericExpression < ComplexExpression
685
+ include BitwiseMethods
686
+ include NumericMethods
687
+ include InequalityMethods
688
+ include NoBooleanInputMethods
689
+ end
690
+
691
+ # Represents a column/expression to order the result set by.
692
+ class OrderedExpression < Expression
693
+ # The expression to order the result set by.
694
+ attr_reader :expression
695
+
696
+ # Whether the expression should order the result set in a descending manner
697
+ attr_reader :descending
698
+
699
+ # Set the expression and descending attributes to the given values.
700
+ def initialize(expression, descending = true)
701
+ @expression, @descending = expression, descending
702
+ end
703
+
704
+ # Delegate the creation of the resulting SQL to the given dataset,
705
+ # since it may be database dependent.
706
+ def to_s(ds)
707
+ ds.ordered_expression_sql(self)
708
+ end
709
+ end
710
+
711
+ # Represents a qualified (column with table) reference. Used when
712
+ # joining tables to disambiguate columns.
713
+ class QualifiedIdentifier < GenericExpression
714
+ # The table and column to reference
715
+ attr_reader :table, :column
716
+
717
+ # Set the attributes to the given arguments
718
+ def initialize(table, column)
719
+ @table, @column = table, column
720
+ end
721
+
722
+ # Delegate the creation of the resulting SQL to the given dataset,
723
+ # since it may be database dependent.
724
+ def to_s(ds)
725
+ ds.qualified_identifier_sql(self)
726
+ end
727
+ end
728
+
729
+ # Subclass of ComplexExpression where the expression results
730
+ # in a text/string/varchar value in SQL.
731
+ class StringExpression < ComplexExpression
732
+ include StringMethods
733
+ include StringConcatenationMethods
734
+ include InequalityMethods
735
+ include NoBooleanInputMethods
736
+
737
+ # Creates a SQL pattern match exprssion. left (l) is the SQL string we
738
+ # are matching against, and ces are the patterns we are matching.
739
+ # The match succeeds if any of the patterns match (SQL OR). Patterns
740
+ # can be given as strings or regular expressions. Strings will cause
741
+ # the SQL LIKE operator to be used, and should be supported by most
742
+ # databases. Regular expressions will probably only work on MySQL
743
+ # and PostgreSQL, and SQL regular expression syntax is not fully compatible
744
+ # with ruby regular expression syntax, so be careful if using regular
745
+ # expressions.
746
+ #
747
+ # The pattern match will be case insensitive if the last argument is a hash
748
+ # with a key of :case_insensitive that is not false or nil. Also,
749
+ # if a case insensitive regular expression is used (//i), that particular
750
+ # pattern which will always be case insensitive.
751
+ def self.like(l, *ces)
752
+ case_insensitive = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive]
753
+ ces.collect! do |ce|
754
+ op, expr = Regexp === ce ? [ce.casefold? || case_insensitive ? :'~*' : :~, ce.source] : [case_insensitive ? :ILIKE : :LIKE, ce]
755
+ BooleanExpression.new(op, l, expr)
756
+ end
757
+ ces.length == 1 ? ces.at(0) : BooleanExpression.new(:OR, *ces)
758
+ end
759
+ end
760
+
761
+ # Represents an SQL array. Added so it is possible to deal with a
762
+ # ruby array of all two pairs as an SQL array instead of an ordered
763
+ # hash-like conditions specifier.
764
+ class SQLArray < Expression
765
+ # Create an object with the given array.
766
+ def initialize(array)
767
+ @array = array
768
+ end
769
+
770
+ # Delegate the creation of the resulting SQL to the given dataset,
771
+ # since it may be database dependent.
772
+ def to_s(ds)
773
+ ds.array_sql(@array)
774
+ end
775
+ end
776
+
777
+ # Represents an SQL array access, with multiple possible arguments.
778
+ class Subscript < GenericExpression
779
+ # The SQL array column
780
+ attr_reader :f
781
+
782
+ # The array of subscripts to use (should be an array of numbers)
783
+ attr_reader :sub
784
+
785
+ # Set the attributes to the given arguments
786
+ def initialize(f, sub)
787
+ @f, @sub = f, sub
788
+ end
789
+
790
+ # Create a new subscript appending the given subscript(s)
791
+ # the the current array of subscripts.
792
+ def |(sub)
793
+ Subscript.new(@f, @sub + Array(sub))
794
+ end
795
+
796
+ # Delegate the creation of the resulting SQL to the given dataset,
797
+ # since it may be database dependent.
798
+ def to_s(ds)
799
+ ds.subscript_sql(self)
800
+ end
801
+ end
802
+
803
+ if RUBY_VERSION >= '1.9.0'
804
+ class VirtualRow < BasicObject
805
+ end
806
+ else
807
+ class VirtualRow
808
+ (instance_methods - %w"__id__ __send__ instance_eval == equal?").each{|m| undef_method(m)}
809
+ end
810
+ end
811
+
812
+ # An instance of this class is yielded to the block supplied to filter.
813
+ # Useful if another library also defines the operator methods that
814
+ # Sequel defines for symbols.
815
+ #
816
+ # Examples:
817
+ #
818
+ # ds = DB[:t]
819
+ # ds.filter{|r| r.name < 2} # SELECT * FROM t WHERE (name < 2)
820
+ # ds.filter{|r| r.table__column + 1 < 2} # SELECT * FROM t WHERE ((table.column + 1) < 2)
821
+ # ds.filter{|r| r.is_active(1, 'arg2')} # SELECT * FROM t WHERE is_active(1, 'arg2')
822
+ class VirtualRow
823
+ # Can return Identifiers, QualifiedIdentifiers, or Functions:
824
+ #
825
+ # * Function - returned if any arguments are supplied, using the method name
826
+ # as the function name, and the arguments as the function arguments.
827
+ # * QualifiedIdentifier - returned if the method name contains __, with the
828
+ # table being the part before __, and the column being the part after.
829
+ # * Identifier - returned otherwise, using the method name.
830
+ def method_missing(m, *args)
831
+ if args.empty?
832
+ table, column = m.to_s.split('__', 2)
833
+ column ? QualifiedIdentifier.new(table, column) : Identifier.new(m)
834
+ else
835
+ Function.new(m, *args)
836
+ end
837
+ end
838
+ end
839
+ end
840
+
841
+ # LiteralString is used to represent literal SQL expressions. A
842
+ # LiteralString is copied verbatim into an SQL statement. Instances of
843
+ # LiteralString can be created by calling String#lit.
844
+ # LiteralStrings can also use all of the SQL::OrderMethods and the
845
+ # SQL::ComplexExpressionMethods.
846
+ class LiteralString < ::String
847
+ include SQL::OrderMethods
848
+ include SQL::ComplexExpressionMethods
849
+ include SQL::BooleanMethods
850
+ include SQL::NumericMethods
851
+ include SQL::StringMethods
852
+ include SQL::InequalityMethods
853
+ end
854
+ end