Class: Sequel::SQL::ComplexExpression

Inherits:
Expression show all
Includes:
AliasMethods, CastMethods, OrderMethods, PatternMatchMethods, SubscriptMethods
Defined in:
lib/sequel/sql.rb,
lib/sequel/sql.rb,
lib/sequel/sql.rb,
lib/sequel/extensions/eval_inspect.rb

Overview

Represents a SQL expression, with a given operator and one or more attributes (which may also be ComplexExpressions, forming a tree). This class is the backbone of Sequel’s ruby expression DSL.

This is an abstract class that is not that useful by itself. The subclasses BooleanExpression, NumericExpression, and StringExpression define the behavior of the DSL via operators.

Constant Summary collapse

OPERTATOR_INVERSIONS =

A hash of the opposite for each operator symbol, used for inverting objects.

{:AND => :OR, :OR => :AND, :< => :>=, :> => :<=,
:<= => :>, :>= => :<, :'=' => :'!=' , :'!=' => :'=', :LIKE => :'NOT LIKE',
:'NOT LIKE' => :LIKE, :~ => :'!~', :'!~' => :~, :IN => :'NOT IN',
:'NOT IN' => :IN, :IS => :'IS NOT', :'IS NOT' => :IS, :'~*' => :'!~*',
:'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
:'NOT ILIKE'=>:ILIKE}.freeze
MATHEMATICAL_OPERATORS =

Standard mathematical operators used in NumericMethods

[:+, :-, :/, :*, :**].freeze
BITWISE_OPERATORS =

Bitwise mathematical operators used in BitwiseMethods

[:&, :|, :^, :<<, :>>, :%].freeze
EQUALITY_OPERATORS =

Operators that check for equality

[:'=', :'!='].freeze
INEQUALITY_OPERATORS =

Inequality operators used in InequalityMethods

[:<, :>, :<=, :>=].freeze
BOOLEAN_OPERATOR_METHODS =

Hash of ruby operator symbols to SQL operators, used in BooleanMethods

{:& => :AND, :| =>:OR}.freeze
IN_OPERATORS =

Operators that use IN/NOT IN for inclusion/exclusion

[:IN, :'NOT IN'].freeze
IS_OPERATORS =

Operators that use IS, used for special casing to override literal true/false values

[:IS, :'IS NOT'].freeze
REGEXP_OPERATORS =

Operators that do pattern matching via regular expressions

[:~, :'!~', :'~*', :'!~*'].freeze
LIKE_OPERATORS =

Operators that do pattern matching via LIKE

[:LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE'].freeze
TWO_ARITY_OPERATORS =

Operator symbols that take exactly two arguments

(EQUALITY_OPERATORS + INEQUALITY_OPERATORS + IS_OPERATORS + IN_OPERATORS + REGEXP_OPERATORS + LIKE_OPERATORS + [:**]).freeze
N_ARITY_OPERATORS =

Operator symbols that take one or more arguments

([:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS - [:**]).freeze
ASSOCIATIVE_OPERATORS =

Operator symbols that are associative

[:AND, :OR, :'||', :+, :*, :&, :|].freeze
ONE_ARITY_OPERATORS =

Operator symbols that take only a single argument

[:NOT, :NOOP, :'B~'].freeze
CUSTOM_EXPRESSIONS =

Custom expressions that may have different syntax on different databases

[:extract].freeze
CONSTANT_INVERSIONS =

A hash of the opposite for each constant, used for inverting constants.

{Constants::TRUE=>Constants::FALSE, Constants::FALSE=>Constants::TRUE,
Constants::NULL=>Constants::NOTNULL, Constants::NOTNULL=>Constants::NULL}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SubscriptMethods

#sql_subscript

Methods included from PatternMatchMethods

#!~, #=~

Methods included from OrderMethods

#asc, #desc

Methods included from CastMethods

#cast, #cast_numeric, #cast_string

Methods included from AliasMethods

#as

Methods inherited from Expression

#==, attr_reader, #clone, #eql?, #hash, inherited, #inspect

Constructor Details

#initialize(op, *args) ⇒ ComplexExpression

Set the operator symbol and arguments for this object to the ones given. Convert all args that are hashes or arrays of two element arrays to BooleanExpressions, other than the second arg for an IN/NOT IN operator. Raise an Error if the operator doesn’t allow boolean input and a boolean argument is given. Raise an Error if the wrong number of arguments for a given operator is used.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/sequel/sql.rb', line 216

def initialize(op, *args)
  orig_args = args
  args = args.map{|a| Sequel.condition_specifier?(a) ? SQL::BooleanExpression.from_value_pairs(a) : a}
  case op
  when *N_ARITY_OPERATORS
    raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
    args.map!{|a| a.is_a?(self.class) && a.op == :NOOP ? a.args.first : a}
    if ASSOCIATIVE_OPERATORS.include?(op)
      old_args = args
      args = []
      old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
    end
  when *TWO_ARITY_OPERATORS
    raise(Error, "The #{op} operator requires precisely 2 arguments") unless args.length == 2
    # With IN/NOT IN, even if the second argument is an array of two element arrays,
    # don't convert it into a boolean expression, since it's definitely being used
    # as a value list.
    args[1] = orig_args[1] if IN_OPERATORS.include?(op)
  when *ONE_ARITY_OPERATORS
    raise(Error, "The #{op} operator requires a single argument") unless args.length == 1
  when *CUSTOM_EXPRESSIONS
    # nothing
  else
    raise(Error, "Invalid operator #{op}")
  end
  @op = op
  @args = args.freeze
  freeze
end

Instance Attribute Details

#argsObject (readonly)

An array of args for this object



209
210
211
# File 'lib/sequel/sql.rb', line 209

def args
  @args
end

#opObject (readonly)

The operator symbol for this object



206
207
208
# File 'lib/sequel/sql.rb', line 206

def op
  @op
end

Instance Method Details

#sql_booleanObject

Return a BooleanExpression with the same op and args.



1272
1273
1274
# File 'lib/sequel/sql.rb', line 1272

def sql_boolean
  BooleanExpression.new(op, *args)
end

#sql_numberObject

Return a NumericExpression with the same op and args.



1277
1278
1279
# File 'lib/sequel/sql.rb', line 1277

def sql_number
  NumericExpression.new(op, *args)
end

#sql_stringObject

Return a StringExpression with the same op and args.



1282
1283
1284
# File 'lib/sequel/sql.rb', line 1282

def sql_string
  StringExpression.new(op, *args)
end