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.
- data/CHANGELOG +42 -0
- data/README.rdoc +137 -118
- data/Rakefile +21 -66
- data/doc/active_record.rdoc +9 -9
- data/doc/advanced_associations.rdoc +59 -188
- data/doc/association_basics.rdoc +15 -2
- data/doc/cheat_sheet.rdoc +38 -33
- data/doc/dataset_filtering.rdoc +16 -7
- data/doc/prepared_statements.rdoc +7 -7
- data/doc/querying.rdoc +5 -4
- data/doc/release_notes/3.13.0.txt +210 -0
- data/doc/sharding.rdoc +1 -1
- data/doc/sql.rdoc +5 -5
- data/doc/validations.rdoc +11 -11
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/do.rb +3 -3
- data/lib/sequel/adapters/firebird.rb +3 -3
- data/lib/sequel/adapters/jdbc/h2.rb +39 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -4
- data/lib/sequel/adapters/oracle.rb +3 -3
- data/lib/sequel/adapters/shared/mssql.rb +10 -1
- data/lib/sequel/adapters/shared/mysql.rb +63 -0
- data/lib/sequel/adapters/shared/postgres.rb +61 -3
- data/lib/sequel/adapters/sqlite.rb +105 -18
- data/lib/sequel/connection_pool.rb +31 -30
- data/lib/sequel/core.rb +58 -58
- data/lib/sequel/core_sql.rb +52 -43
- data/lib/sequel/database/misc.rb +11 -0
- data/lib/sequel/database/query.rb +55 -17
- data/lib/sequel/dataset/actions.rb +2 -1
- data/lib/sequel/dataset/query.rb +2 -3
- data/lib/sequel/dataset/sql.rb +24 -11
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/metaprogramming.rb +4 -0
- data/lib/sequel/model.rb +37 -19
- data/lib/sequel/model/associations.rb +33 -25
- data/lib/sequel/model/base.rb +2 -2
- data/lib/sequel/model/plugins.rb +7 -2
- data/lib/sequel/plugins/active_model.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +2 -2
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/boolean_readers.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +10 -2
- data/lib/sequel/plugins/identity_map.rb +3 -3
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +212 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/list.rb +174 -0
- data/lib/sequel/plugins/many_through_many.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +6 -7
- data/lib/sequel/plugins/tree.rb +118 -0
- data/lib/sequel/plugins/xml_serializer.rb +321 -0
- data/lib/sequel/sql.rb +315 -206
- data/lib/sequel/timezones.rb +40 -17
- data/lib/sequel/version.rb +8 -2
- data/spec/adapters/firebird_spec.rb +2 -2
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +2 -2
- data/spec/adapters/mysql_spec.rb +2 -2
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +36 -6
- data/spec/adapters/spec_helper.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +3 -3
- data/spec/core/core_sql_spec.rb +31 -13
- data/spec/core/database_spec.rb +39 -2
- data/spec/core/dataset_spec.rb +24 -12
- data/spec/core/expression_filters_spec.rb +5 -1
- data/spec/core/object_graph_spec.rb +1 -1
- data/spec/core/schema_generator_spec.rb +1 -1
- data/spec/core/schema_spec.rb +1 -1
- data/spec/core/spec_helper.rb +1 -1
- data/spec/core/version_spec.rb +1 -1
- data/spec/extensions/active_model_spec.rb +82 -67
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/blank_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/caching_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +3 -2
- data/spec/extensions/composition_spec.rb +2 -5
- data/spec/extensions/force_encoding_spec.rb +3 -1
- data/spec/extensions/hook_class_methods_spec.rb +1 -1
- data/spec/extensions/identity_map_spec.rb +1 -1
- data/spec/extensions/inflector_spec.rb +1 -1
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/instance_hooks_spec.rb +1 -1
- data/spec/extensions/json_serializer_spec.rb +154 -0
- data/spec/extensions/lazy_attributes_spec.rb +1 -2
- data/spec/extensions/list_spec.rb +251 -0
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -3
- data/spec/extensions/migration_spec.rb +1 -1
- data/spec/extensions/named_timezones_spec.rb +5 -6
- data/spec/extensions/nested_attributes_spec.rb +1 -1
- data/spec/extensions/optimistic_locking_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +3 -2
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +6 -2
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/string_date_time_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +1 -1
- data/spec/extensions/subclasses_spec.rb +1 -1
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
- data/spec/extensions/thread_local_timezones_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +119 -0
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/update_primary_key_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +1 -1
- data/spec/extensions/validation_helpers_spec.rb +1 -1
- data/spec/extensions/xml_serializer_spec.rb +142 -0
- data/spec/integration/associations_test.rb +1 -1
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +29 -14
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +1 -1
- data/spec/integration/plugin_test.rb +316 -1
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +8 -8
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +35 -20
- data/spec/integration/type_test.rb +1 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +49 -34
- data/spec/model/base_spec.rb +1 -1
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +1 -1
- data/spec/model/hooks_spec.rb +1 -1
- data/spec/model/inflector_spec.rb +1 -1
- data/spec/model/model_spec.rb +7 -1
- data/spec/model/plugins_spec.rb +1 -1
- data/spec/model/record_spec.rb +1 -3
- data/spec/model/spec_helper.rb +2 -2
- data/spec/model/validations_spec.rb +1 -1
- 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
|
|
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
|
|
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
|
|
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
|
|
51
|
+
# Base class for all SQL expression objects.
|
|
52
52
|
class Expression
|
|
53
|
-
#
|
|
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
|
|
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
|
-
#
|
|
88
|
-
#
|
|
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
|
|
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
|
|
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
|
|
126
|
+
# Standard mathematical operators used in +NumericMethods+
|
|
118
127
|
MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
|
|
119
128
|
|
|
120
|
-
# Bitwise
|
|
129
|
+
# Bitwise mathematical operators used in +NumericMethods+
|
|
121
130
|
BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>]
|
|
122
131
|
|
|
123
|
-
# Inequality
|
|
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
|
-
:~, :'!~', :'~*', :'!~*', :
|
|
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
|
|
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
|
|
151
|
-
#
|
|
152
|
-
# Raise an
|
|
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
|
-
|
|
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
|
-
#
|
|
194
|
+
# an SQL query.
|
|
177
195
|
class GenericExpression < Expression
|
|
178
196
|
end
|
|
179
197
|
|
|
180
198
|
### Modules ###
|
|
181
199
|
|
|
182
|
-
#
|
|
200
|
+
# Includes an +as+ method that creates an SQL alias.
|
|
183
201
|
module AliasMethods
|
|
184
|
-
# Create an SQL
|
|
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
|
|
192
|
-
# make sense for
|
|
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
|
|
212
|
-
# used in a boolean context in SQL
|
|
213
|
-
# and SQL::
|
|
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
|
-
#
|
|
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
|
|
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
|
|
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
|
|
249
|
-
# and return the result as a StringExpression
|
|
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
|
|
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) #
|
|
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
|
|
349
|
+
# Includes an +identifier+ method that returns <tt>Identifier</tt>s.
|
|
300
350
|
module IdentifierMethods
|
|
301
|
-
# Return self wrapped as an
|
|
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::
|
|
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
|
-
#
|
|
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
|
|
344
|
-
# used in a numeric context in SQL
|
|
345
|
-
# and SQL::
|
|
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
|
-
#
|
|
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
|
|
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
|
|
365
|
-
|
|
366
|
-
|
|
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
|
|
370
|
-
|
|
371
|
-
|
|
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
|
-
#
|
|
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
|
|
379
|
-
|
|
380
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
#
|
|
490
|
+
# This module includes the +sql_subscript+ method, representing SQL array accesses.
|
|
416
491
|
module SubscriptMethods
|
|
417
|
-
# Return
|
|
492
|
+
# Return a <tt>Subscript</tt> with the given arguments, representing an
|
|
493
|
+
# SQL array access.
|
|
418
494
|
#
|
|
419
|
-
# :array.sql_subscript(1) #
|
|
420
|
-
# :array.sql_subscript(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
|
|
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
|
-
#
|
|
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
|
|
461
|
-
# and converts it to a BooleanExpression
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
759
|
-
|
|
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
|
|
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)
|
|
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
|
|
883
|
+
# The column/table referenced
|
|
785
884
|
attr_reader :column
|
|
786
885
|
|
|
787
|
-
# The table
|
|
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).
|
|
812
|
-
#
|
|
813
|
-
#
|
|
814
|
-
#
|
|
815
|
-
#
|
|
816
|
-
#
|
|
817
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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
|
-
#
|
|
886
|
-
#
|
|
887
|
-
#
|
|
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
|
|
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
|
|
894
|
-
# depending on how it is called.
|
|
895
|
-
#
|
|
896
|
-
#
|
|
897
|
-
#
|
|
898
|
-
#
|
|
899
|
-
#
|
|
900
|
-
#
|
|
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
|
-
#
|
|
904
|
-
#
|
|
905
|
-
#
|
|
906
|
-
#
|
|
907
|
-
#
|
|
908
|
-
#
|
|
909
|
-
#
|
|
910
|
-
#
|
|
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
|
|
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
|
|
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
|
|
971
|
-
#
|
|
972
|
-
#
|
|
973
|
-
#
|
|
974
|
-
#
|
|
975
|
-
#
|
|
976
|
-
#
|
|
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
|
|
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
|