class FluentQuery::Queries::Processor

Query processor.

Its primary aim is to dive processing methods from query object as is. In fact, defines something as processing session.

Constants

COLUMN_DIRECTIVE

Describes column directive. @var Regexp

COLUMN_DIRECTIVE_SIMPLE

Holds simple column definition.

COLUMN_REPLACEMENT

Indicates column replacement to perform. (Flag.)

FORMATTING_DIRECTIVE

Describes formatting directive. @var Regexp

FORMATTING_DIRECTIVE_SIMPLE

Holds simple column definition. @var Regexp

FORMATTING_REPLACEMENT

Indicates formatting directive replacements to perform. (Flag.)

STRING_DIRECTIVE

Describes string directive. @var Regexp

STRING_REPLACEMENT

Indicates string replacement to perform. (Flag.)

Attributes

driver[R]

Public Class Methods

new(driver) click to toggle source

Constructs processor. @param MP_Fluent_Driver driver Driver upon which processor should work upon.

# File lib/fluent-query/queries/processor.rb, line 111
def initialize(driver)
    @driver = driver
end

Public Instance Methods

compile(string) click to toggle source

Compiles the string.

# File lib/fluent-query/queries/processor.rb, line 386
def compile(string)
    self.compiler.compile(string)
end
compiler() click to toggle source

Returns compiler.

# File lib/fluent-query/queries/processor.rb, line 374
def compiler
    if @_compiler.nil?
        @_compiler = FluentQuery::Compiler::new(self)
    end
    
    @_compiler
end
expander() click to toggle source

Returns final fluent expander query.

# File lib/fluent-query/queries/processor.rb, line 344
def expander
    if @__fluent_expander.nil?
        @__fluent_expander = self.class::FORMATTING_DIRECTIVE            
    end

    @__fluent_expander
end
null() click to toggle source

Returns NULL representation.

# File lib/fluent-query/queries/processor.rb, line 335
def null
    @driver.null
end
process_array(array, glue = ",") click to toggle source

Process array to some reasonable string form.

Joins its elements and separates them by commas. Quotes strings by by-driver-defined string quoting and integers by integer quoting.

# File lib/fluent-query/queries/processor.rb, line 123
def process_array(array, glue = ",")
    result = array.map do |i| 
        self.quote_value(i)
    end
    return result.join(glue + " ")
end
process_directive(directive, argument = nil, replacements = 7) click to toggle source

Processes fluent directive. Replacements is three bytes flag array.

# File lib/fluent-query/queries/processor.rb, line 299
def process_directive(directive, argument = nil, replacements = 7)
    if (replacements & self.class::COLUMN_REPLACEMENT > 0) and (directive[0].ord == 91)           # "[", Column directive
        result = directive.gsub(self.class::COLUMN_DIRECTIVE_SIMPLE) { |value| self.quote_identifier(value[1..-2]) }
    elsif (replacements & self.class::STRING_REPLACEMENT > 0) and (directive[-1].ord == 34)           # "\"", String directive
        result = directive.gsub('"', @driver.quote_string("").last)
    elsif (replacements & self.class::FORMATTING_REPLACEMENT > 0) and (directive[0..1] == "%%")   # Formatting directive
        result = directive.gsub(self.class::FORMATTING_DIRECTIVE_SIMPLE) { |value| self.process_formatting(value[2..-1], argument) }
    else
        result = directive
    end

    return result
end
process_formatted(sequence, mode = :build) click to toggle source

Processed strings with format definitions and data specifications.

Mode can be :compile, :build, :prepare or :finish. Compiling means building the query without expanding the formatting directives. Finishing means building the compiled query. Building means both of them. Preparing is basically the same as compiling, but modifies behaviour of some tokens such as INSERT.

# File lib/fluent-query/queries/processor.rb, line 242
def process_formatted(sequence, mode = :build)
    count = sequence.length
    i = 0
    output = ""
                                
    replacer_settings = self.class::COLUMN_REPLACEMENT | self.class::STRING_REPLACEMENT
    expander_settings = self.class::FORMATTING_REPLACEMENT
    
    while i < count 
        item = sequence[i]
         
        ##
        
        if item.kind_of? String
            item = item.dup
        
            # Calls to each occurence of directive matching to directive
            #  finding expression directive processing. In each call increases
            #  sequence position counter so moves forward.

            if mode.in? [:compile, :build, :prepare]
                item.gsub!(self.replacer) do |directive| 
                    directive.strip!
                    self.process_directive(directive, nil, replacer_settings)
                end
            end
            
            if mode.in? [:finish, :build]
                item.gsub!(self.expander) do |directive| 
                    self.process_directive(directive, sequence[i += 1], expander_settings) 
                end
            end
            
            output << item

        elsif item.kind_of? Symbol
            output << self.quote_identifier(item)
            
        else
            output << item.to_s
            
        end

        output << " "
        i += 1
    end

    return output
    
end
process_formatting(directive, argument) click to toggle source

Processes formatting directive.

# File lib/fluent-query/queries/processor.rb, line 318
def process_formatting(directive, argument)
    proc = self.compiler.compile_formatting(directive)
    
    if proc
        output = proc.call(argument)
    else
        output = ""
    end
    
    return output
end
process_hash(hash, glue = ",", equality = :comparing) click to toggle source

Process hash to some reasonable string form.

Joins its elements to name = value form and separates them by commas. Quotes string value by by-driver-defined string quoting and integers by integer quoting. Quotes name by identifiers quoting.

Handles two modes:

* "assigning" which classicaly keeps for example the '=' operator,
* "comparing" which sets for example 'IS' operator for booleans.
# File lib/fluent-query/queries/processor.rb, line 143
def process_hash(hash, glue = ",", equality = :comparing)
    result = [ ]
    mode = equality
    
    hash.each_pair do |key, value|
        operator = @driver.quote_equality(value, mode)                        
        key = self.quote_identifier(key)
        value = self.quote_value(value)

        result << (key + " " + operator + " " + value)
    end

    return result.join(" " << glue << " ")
end
process_identifiers(identifiers) click to toggle source

Processes identifier list to the string representation. Quotes them and joins them separated by commas.

# File lib/fluent-query/queries/processor.rb, line 226
def process_identifiers(identifiers)
    self.quote_identifiers(identifiers).join(", ")
end
quote_identifier(identifier) click to toggle source

Quotes identifiers by identifier quoting.

# File lib/fluent-query/queries/processor.rb, line 207
def quote_identifier(identifier)
    @driver.quote_identifier(identifier.to_s)
end
quote_identifiers(identifiers) click to toggle source

Quotes identifiers list.

# File lib/fluent-query/queries/processor.rb, line 216
def quote_identifiers(identifiers)
    identifiers.map { |i| self.quote_identifier(i) }
end
quote_subquery(subquery) click to toggle source

Quotes subquery by driver subquery quoting.

# File lib/fluent-query/queries/processor.rb, line 194
def quote_subquery(subquery)
    if subquery.kind_of? FluentQuery::Query
        subquery = subquery.build!
    end
    
    return @driver.quote_subquery(subquery)
end
quote_value(value) click to toggle source

 Quotes string by driver string quoting and integers by integer

quoting. Other values are converted to string too and
leaved unquoted.
# File lib/fluent-query/queries/processor.rb, line 165
def quote_value(value)

    if (value.string?) or (value.symbol?)
        result = @driver.quote_string(value.to_s)
    elsif value.kind_of? Integer
        result = @driver.quote_integer(value)
    elsif value.array?
        result = "(" << self.process_array(value) << ")"    # TODO: question is, if we should do it here, if it's enough general just for processor
    elsif value.kind_of? Float
        result = @driver.quote_float(value)
    elsif (value.kind_of? TrueClass) or (value.kind_of? FalseClass)
        result = @driver.quote_boolean(value)
    elsif (value.kind_of? Date) or (value.kind_of? DateTime)
        result = @driver.quote_date_time(value)
    elsif value.nil?
        result = @driver.null
    else
        result = value.to_s
    end
    
    return result
    
end
replacer() click to toggle source

Returns final fluent formatter query.

# File lib/fluent-query/queries/processor.rb, line 357
def replacer
    if @__fluent_replacer.nil?
        parts = Array[self.class::COLUMN_DIRECTIVE, self.class::STRING_DIRECTIVE]

        result = ""
        result << "(?:(?:" << parts.join(")|(?:") << "))"
        
        @__fluent_replacer = Regexp::new(result)
    end

    @__fluent_replacer
end