prequel 0.0.1
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/LICENSE +19 -0
 - data/README.md +0 -0
 - data/lib/prequel.rb +38 -0
 - data/lib/prequel/composite_tuple.rb +33 -0
 - data/lib/prequel/core_extensions.rb +62 -0
 - data/lib/prequel/expressions.rb +12 -0
 - data/lib/prequel/expressions/aliased_expression.rb +15 -0
 - data/lib/prequel/expressions/column.rb +35 -0
 - data/lib/prequel/expressions/derived_column.rb +24 -0
 - data/lib/prequel/expressions/equal.rb +22 -0
 - data/lib/prequel/expressions/expression.rb +10 -0
 - data/lib/prequel/expressions/set_function.rb +24 -0
 - data/lib/prequel/field.rb +10 -0
 - data/lib/prequel/record.rb +50 -0
 - data/lib/prequel/relations.rb +11 -0
 - data/lib/prequel/relations/inner_join.rb +39 -0
 - data/lib/prequel/relations/projection.rb +86 -0
 - data/lib/prequel/relations/relation.rb +71 -0
 - data/lib/prequel/relations/selection.rb +31 -0
 - data/lib/prequel/relations/table.rb +56 -0
 - data/lib/prequel/session.rb +12 -0
 - data/lib/prequel/sql.rb +13 -0
 - data/lib/prequel/sql/derived_query_column.rb +23 -0
 - data/lib/prequel/sql/inner_joined_table_ref.rb +23 -0
 - data/lib/prequel/sql/named_table_ref.rb +19 -0
 - data/lib/prequel/sql/query.rb +110 -0
 - data/lib/prequel/sql/query_column.rb +22 -0
 - data/lib/prequel/sql/subquery.rb +25 -0
 - data/lib/prequel/sql/table_ref.rb +26 -0
 - data/lib/prequel/tuple.rb +64 -0
 - data/lib/prequel/version.rb +3 -0
 - metadata +119 -0
 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (C) 2011 by Nathan Sobo
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 4 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 5 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 6 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 7 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 8 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 11 
     | 
    
         
            +
            all copies or substantial portions of the Software.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 14 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 15 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 16 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 17 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 18 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 19 
     | 
    
         
            +
            THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         
            File without changes
         
     | 
    
        data/lib/prequel.rb
    ADDED
    
    | 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/all'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'sequel'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'prequel/version'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 6 
     | 
    
         
            +
              extend ActiveSupport::Autoload
         
     | 
| 
      
 7 
     | 
    
         
            +
              extend self
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def const_missing(name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                if name == :DB
         
     | 
| 
      
 11 
     | 
    
         
            +
                  const_set(:DB, Sequel::DATABASES.first)
         
     | 
| 
      
 12 
     | 
    
         
            +
                else
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def table(name, &block)
         
     | 
| 
      
 18 
     | 
    
         
            +
                Relations::Table.new(name, &block)
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def session
         
     | 
| 
      
 22 
     | 
    
         
            +
                Thread.current[:prequel_session] ||= Session.new
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def clear_session
         
     | 
| 
      
 26 
     | 
    
         
            +
                Thread.current[:prequel_session] = nil if Thread.current[:prequel_session]
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              require 'prequel/core_extensions'
         
     | 
| 
      
 30 
     | 
    
         
            +
              autoload :CompositeTuple
         
     | 
| 
      
 31 
     | 
    
         
            +
              autoload :Expressions
         
     | 
| 
      
 32 
     | 
    
         
            +
              autoload :Field
         
     | 
| 
      
 33 
     | 
    
         
            +
              autoload :Record
         
     | 
| 
      
 34 
     | 
    
         
            +
              autoload :Relations
         
     | 
| 
      
 35 
     | 
    
         
            +
              autoload :Session
         
     | 
| 
      
 36 
     | 
    
         
            +
              autoload :Sql
         
     | 
| 
      
 37 
     | 
    
         
            +
              autoload :Tuple
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              class CompositeTuple
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :left, :right
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(left, right)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @left, @right = left, right
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def [](name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  get_record(name) || get_field_value(name)
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def get_record(table_name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  left.get_record(table_name) || right.get_record(table_name)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def get_field_value(name)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  if name =~ /(.+)__(.+)/
         
     | 
| 
      
 19 
     | 
    
         
            +
                    table_name = $1.to_sym
         
     | 
| 
      
 20 
     | 
    
         
            +
                    field_name = $2.to_sym
         
     | 
| 
      
 21 
     | 
    
         
            +
                    get_record(table_name).try(:get_field_value, field_name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  else
         
     | 
| 
      
 23 
     | 
    
         
            +
                    left.get_field_value(name) || right.get_field_value(name)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def field_values
         
     | 
| 
      
 28 
     | 
    
         
            +
                  [left.field_values, right.field_values]
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                delegate :inspect, :to => :field_values
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module HashExtensions
         
     | 
| 
      
 3 
     | 
    
         
            +
                def to_predicate
         
     | 
| 
      
 4 
     | 
    
         
            +
                  raise NotImplementedError unless size == 1
         
     | 
| 
      
 5 
     | 
    
         
            +
                  keys.first.eq(values.first)
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                Hash.send(:include, self)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              module SymbolExtensions
         
     | 
| 
      
 12 
     | 
    
         
            +
                def as(alias_name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "#{self}___#{alias_name}".to_sym
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def eq(other)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Expressions::Equal.new(self, other)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def count
         
     | 
| 
      
 21 
     | 
    
         
            +
                  Expressions::SetFunction.new(self, :count)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def resolve_in_relations(relations)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  if self =~ /^(.+)___(.+)$/
         
     | 
| 
      
 26 
     | 
    
         
            +
                    column_name = $1.to_sym
         
     | 
| 
      
 27 
     | 
    
         
            +
                    alias_name = $2.to_sym
         
     | 
| 
      
 28 
     | 
    
         
            +
                    Expressions::AliasedExpression.new(column_name, alias_name).resolve_in_relations(relations)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  else
         
     | 
| 
      
 30 
     | 
    
         
            +
                    relations.each do |relation|
         
     | 
| 
      
 31 
     | 
    
         
            +
                      if column = relation.get_column(self)
         
     | 
| 
      
 32 
     | 
    
         
            +
                        return column
         
     | 
| 
      
 33 
     | 
    
         
            +
                      end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def to_sql
         
     | 
| 
      
 40 
     | 
    
         
            +
                  inspect
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                Symbol.send(:include, self)
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              module PrimitiveExtensions
         
     | 
| 
      
 47 
     | 
    
         
            +
                def resolve_in_relations(relations)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  self
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def resolve_in_query(query)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  query.add_literal(self)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                Numeric.send(:include, self)
         
     | 
| 
      
 56 
     | 
    
         
            +
                String.send(:include, self)
         
     | 
| 
      
 57 
     | 
    
         
            +
                TrueClass.send(:include, self)
         
     | 
| 
      
 58 
     | 
    
         
            +
                FalseClass.send(:include, self)
         
     | 
| 
      
 59 
     | 
    
         
            +
                NilClass.send(:include, self)
         
     | 
| 
      
 60 
     | 
    
         
            +
                Time.send(:include, self)
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expressions
         
     | 
| 
      
 3 
     | 
    
         
            +
                class AliasedExpression
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :expression, :alias_name
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(expression, alias_name)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @expression, @alias_name = expression, alias_name
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def resolve_in_relations(relations)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    AliasedExpression.new(expression.resolve_in_relations(relations), alias_name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expressions
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Column
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :table, :name, :type
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(table, name, type)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @table, @name, @type = table, name, type
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def alias_name
         
     | 
| 
      
 11 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def eq(other)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    Equal.new(self, other)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def qualified_name
         
     | 
| 
      
 19 
     | 
    
         
            +
                    "#{table.name}__#{name}".to_sym
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def expression
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def origin
         
     | 
| 
      
 27 
     | 
    
         
            +
                    self
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def resolve_in_query(query)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    query.singular_table_refs[table].resolve_column(self)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expressions
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DerivedColumn
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :relation, :expression, :alias_name
         
     | 
| 
      
 5 
     | 
    
         
            +
                  delegate :origin, :to => :expression
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(relation, expression, alias_name)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @relation, @expression, @alias_name = relation, expression, alias_name
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 12 
     | 
    
         
            +
                    alias_name || expression.name
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def resolve_in_query(query)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if subquery = query.singular_table_refs[relation]
         
     | 
| 
      
 17 
     | 
    
         
            +
                      subquery.resolve_derived_column(self)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else
         
     | 
| 
      
 19 
     | 
    
         
            +
                      expression.resolve_in_query(query)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expressions
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Equal
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :left, :right
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(left, right)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @left, @right = left, right
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
                  
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def resolve_in_relations(relations)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    Equal.new(left.resolve_in_relations(relations), right.resolve_in_relations(relations))
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def resolve_in_query(query)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    Equal.new(left.resolve_in_query(query), right.resolve_in_query(query))
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 18 
     | 
    
         
            +
                    "#{left.to_sql} = #{right.to_sql}"
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expressions
         
     | 
| 
      
 3 
     | 
    
         
            +
                class SetFunction < Expression
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :expression, :type
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(expression, type)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @expression, @type = expression, type
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def resolve_in_relations(relations)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    SetFunction.new(expression.resolve_in_relations(relations), type)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def resolve_in_query(query)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    SetFunction.new(expression.resolve_in_query(query), type)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 19 
     | 
    
         
            +
                    "#{type}(#{expression.to_sql})"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Record < Tuple
         
     | 
| 
      
 3 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 4 
     | 
    
         
            +
                  delegate :all, :result_set, :[], :to_sql, :get_column, :first, :find, :where, :join, :project, :to => :relation
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def table
         
     | 
| 
      
 7 
     | 
    
         
            +
                    relation
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def to_relation
         
     | 
| 
      
 11 
     | 
    
         
            +
                    relation
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def inherited(klass)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    table_name = klass.name.demodulize.underscore.pluralize.to_sym
         
     | 
| 
      
 16 
     | 
    
         
            +
                    klass.relation = Relations::Table.new(table_name, klass)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def def_field_accessor(name)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    def_field_reader(name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    def_field_writer(name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def def_field_writer(name)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    define_method("#{name}=") do |value|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      set_field_value(name, value)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def column(name, type)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    relation.def_column(name, type)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    def_field_accessor(name)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def new(field_values={})
         
     | 
| 
      
 36 
     | 
    
         
            +
                    Prequel.session[table.name][field_values[:id]] ||= super
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def table
         
     | 
| 
      
 41 
     | 
    
         
            +
                  relation
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                public :set_field_value
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def get_record(table_name)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  self if table_name == table.name
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class InnerJoin < Relation
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :left, :right, :predicate
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(left_operand, right_operand, predicate)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @left, @right = left_operand.to_relation, right_operand.to_relation
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @predicate = resolve(predicate.to_predicate)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def get_table(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    left.get_table(name) || right.get_table(name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def columns
         
     | 
| 
      
 16 
     | 
    
         
            +
                    (left.columns + right.columns).map do |column|
         
     | 
| 
      
 17 
     | 
    
         
            +
                      derive(column)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def visit(query)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    query.table_ref = table_ref(query)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    query.select_list = columns.map do |derived_column|
         
     | 
| 
      
 24 
     | 
    
         
            +
                      query.resolve_derived_column(derived_column, :qualified)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def table_ref(query)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    Sql::InnerJoinedTableRef.new(left.table_ref(query), right.singular_table_ref(query), predicate.resolve_in_query(query))
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def operands
         
     | 
| 
      
 35 
     | 
    
         
            +
                    [left, right]
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Projection < Relation
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :operand
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(operand, *symbols)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @operand = operand
         
     | 
| 
      
 8 
     | 
    
         
            +
                    assign_derived_columns(symbols)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def get_column(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    if name.to_s.include?("__")
         
     | 
| 
      
 13 
     | 
    
         
            +
                      super
         
     | 
| 
      
 14 
     | 
    
         
            +
                    else
         
     | 
| 
      
 15 
     | 
    
         
            +
                      derived_columns_by_name[name]
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def columns
         
     | 
| 
      
 20 
     | 
    
         
            +
                    derived_columns.values
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def visit(query)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    operand.visit(query)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    query.select_list = columns.map do |derived_column|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      query.resolve_derived_column(derived_column)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    if projected_table
         
     | 
| 
      
 30 
     | 
    
         
            +
                      query.tuple_builder = query.singular_table_refs[projected_table]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    else
         
     | 
| 
      
 32 
     | 
    
         
            +
                      query.tuple_builder = self
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def build_tuple(field_values)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    tuple_class.new(field_values)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def tuple_class
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @tuple_class ||= Class.new(Tuple).tap do |tuple_class|
         
     | 
| 
      
 42 
     | 
    
         
            +
                      tuple_class.relation = self
         
     | 
| 
      
 43 
     | 
    
         
            +
                      columns.each do |column|
         
     | 
| 
      
 44 
     | 
    
         
            +
                        tuple_class.def_field_reader(column.name)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 50 
     | 
    
         
            +
                  attr_reader :projected_table
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def assign_derived_columns(expressions)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    if @projected_table = detect_projected_table(expressions)
         
     | 
| 
      
 54 
     | 
    
         
            +
                      projected_table.columns.map do |column|
         
     | 
| 
      
 55 
     | 
    
         
            +
                        derive(resolve(column.qualified_name.as(column.name)))
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    else
         
     | 
| 
      
 58 
     | 
    
         
            +
                      expressions.each do |column_name|
         
     | 
| 
      
 59 
     | 
    
         
            +
                        derive(resolve(column_name))
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def detect_projected_table(args)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    return false unless args.size == 1
         
     | 
| 
      
 66 
     | 
    
         
            +
                    arg = args.first
         
     | 
| 
      
 67 
     | 
    
         
            +
                    if arg.instance_of?(Table)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      table_name = arg.name
         
     | 
| 
      
 69 
     | 
    
         
            +
                    elsif arg.instance_of?(Class) && arg.respond_to?(:table)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      table_name = arg.table.name
         
     | 
| 
      
 71 
     | 
    
         
            +
                    elsif arg.instance_of?(Symbol)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      return false if arg =~ /__/
         
     | 
| 
      
 73 
     | 
    
         
            +
                      table_name = arg
         
     | 
| 
      
 74 
     | 
    
         
            +
                    else
         
     | 
| 
      
 75 
     | 
    
         
            +
                      return false
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    operand.get_table(table_name)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  def operands
         
     | 
| 
      
 82 
     | 
    
         
            +
                    [operand]
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Relation
         
     | 
| 
      
 4 
     | 
    
         
            +
                  delegate :to_sql, :result_set, :all, :first, :to => :query
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def query
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Sql::Query.new(self).build
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def find(id)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    where(:id => id).first
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def where(predicate)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    Selection.new(self, predicate)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def join(right, predicate)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    InnerJoin.new(self, right, predicate)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def project(*symbols)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    Projection.new(self, *symbols)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def table_ref(query)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    singular_table_ref(query)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def singular_table_ref(query)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    query.add_subquery(self)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def to_relation
         
     | 
| 
      
 35 
     | 
    
         
            +
                    self
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def get_column(name)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    resolved = resolve(name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    derive(resolved) if resolved
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def resolve(expression)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    expression.resolve_in_relations(operands)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def derive(resolved_expression)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if resolved_expression.instance_of?(Expressions::AliasedExpression)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      alias_name = resolved_expression.alias_name
         
     | 
| 
      
 52 
     | 
    
         
            +
                      resolved_expression = resolved_expression.expression
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                      derived_columns[resolved_expression] ||=
         
     | 
| 
      
 56 
     | 
    
         
            +
                      Expressions::DerivedColumn.new(self, resolved_expression, alias_name).tap do |derived_column|
         
     | 
| 
      
 57 
     | 
    
         
            +
                        derived_columns[resolved_expression] = derived_column
         
     | 
| 
      
 58 
     | 
    
         
            +
                        derived_columns_by_name[derived_column.name] = derived_column
         
     | 
| 
      
 59 
     | 
    
         
            +
                      end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def derived_columns
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @derived_columns ||= {}
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def derived_columns_by_name
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @derived_columns_by_name ||= {}
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Selection < Relation
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :operand, :predicate
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(operand, predicate)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @operand = operand
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @predicate = resolve(predicate.to_predicate)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  delegate :get_table, :to => :operand
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def columns
         
     | 
| 
      
 14 
     | 
    
         
            +
                    operand.columns.map do |column|
         
     | 
| 
      
 15 
     | 
    
         
            +
                      derive(column)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def visit(query)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    operand.visit(query)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    query.add_condition(predicate.resolve_in_query(query))
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def operands
         
     | 
| 
      
 27 
     | 
    
         
            +
                    [operand]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relations
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Table < Relation
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :name, :columns_by_name, :tuple_class
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(name, tuple_class=nil, &block)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @name, @tuple_class = name, tuple_class
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @columns_by_name = {}
         
     | 
| 
      
 9 
     | 
    
         
            +
                    TableDefinitionContext.new(self).instance_eval(&block) if block
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def def_column(name, type)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    columns_by_name[name] = Expressions::Column.new(self, name, type)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def [](col_name)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    "#{name}__#{col_name}".to_sym
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def get_column(column_name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    if column_name.match(/(.+)__(.+)/)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      qualifier, column_name = $1.to_sym, $2.to_sym
         
     | 
| 
      
 23 
     | 
    
         
            +
                      return nil unless qualifier == name
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    columns_by_name[column_name]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def get_table(table_name)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    self if name == table_name
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def columns
         
     | 
| 
      
 33 
     | 
    
         
            +
                    columns_by_name.values
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def visit(query)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    query.table_ref = table_ref(query)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def singular_table_ref(query)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    query.add_singular_table_ref(self, Sql::TableRef.new(self))
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  class TableDefinitionContext
         
     | 
| 
      
 45 
     | 
    
         
            +
                    attr_reader :table
         
     | 
| 
      
 46 
     | 
    
         
            +
                    def initialize(table)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      @table = table
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    def column(name, type)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      table.def_column(name, type)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/prequel/sql.rb
    ADDED
    
    
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DerivedQueryColumn
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :subquery, :name, :expression
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(subquery, name, expression)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @subquery, @name, @expression = subquery, name, expression
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 11 
     | 
    
         
            +
                    "#{subquery.name}.#{name}"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def to_select_clause_sql
         
     | 
| 
      
 15 
     | 
    
         
            +
                    "#{expression.to_sql} as #{name}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def qualified_name
         
     | 
| 
      
 19 
     | 
    
         
            +
                    "#{subquery.name}__#{name}"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class InnerJoinedTableRef
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :left, :right, :predicate
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(left, right, predicate)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @left, @right, @predicate = left, right, predicate
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 10 
     | 
    
         
            +
                    [left.to_sql,
         
     | 
| 
      
 11 
     | 
    
         
            +
                     'inner join',
         
     | 
| 
      
 12 
     | 
    
         
            +
                     right.to_sql,
         
     | 
| 
      
 13 
     | 
    
         
            +
                     'on',
         
     | 
| 
      
 14 
     | 
    
         
            +
                     predicate.to_sql
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ].join(' ')
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def build_tuple(field_values)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    CompositeTuple.new(left.build_tuple(field_values), right.build_tuple(field_values))
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NamedTableRef
         
     | 
| 
      
 4 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def extract_field_values(field_values)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    {}.tap do |specific_field_values|
         
     | 
| 
      
 8 
     | 
    
         
            +
                      field_values.each do |field_name, value|
         
     | 
| 
      
 9 
     | 
    
         
            +
                        if field_name =~ /(.+?)__(.+)/
         
     | 
| 
      
 10 
     | 
    
         
            +
                          qualifier, field_name = $1.to_sym, $2.to_sym
         
     | 
| 
      
 11 
     | 
    
         
            +
                          next unless qualifier == name
         
     | 
| 
      
 12 
     | 
    
         
            +
                        end
         
     | 
| 
      
 13 
     | 
    
         
            +
                        specific_field_values[field_name] = value
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Query
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :select_list
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :relation, :table_ref, :conditions, :literals, :singular_table_refs, :subquery_count, :query_columns
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_writer :tuple_builder
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(relation)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @relation = relation
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @conditions = []
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @literals = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @singular_table_refs = { relation => self }
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @subquery_count = 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @query_columns = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def all
         
     | 
| 
      
 18 
     | 
    
         
            +
                    result_set.map do |field_values|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      tuple_builder.build_tuple(field_values)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def first
         
     | 
| 
      
 24 
     | 
    
         
            +
                    r = result_set
         
     | 
| 
      
 25 
     | 
    
         
            +
                    r.empty?? nil : tuple_builder.build_tuple(r.first)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def result_set
         
     | 
| 
      
 29 
     | 
    
         
            +
                    DB[*to_sql]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 33 
     | 
    
         
            +
                    [sql_string, literals]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def build
         
     | 
| 
      
 37 
     | 
    
         
            +
                    relation.visit(self)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    self
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def table_ref=(table_ref)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    raise "A table ref has already been assigned" if @table_ref
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @table_ref = table_ref
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  def add_condition(predicate)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    conditions.push(predicate)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  def add_literal(literal)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    "v#{literals.size + 1}".to_sym.tap do |placeholder|
         
     | 
| 
      
 52 
     | 
    
         
            +
                      literals[placeholder] = literal
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def add_singular_table_ref(relation, table_ref)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    singular_table_refs[relation] = table_ref
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def add_subquery(relation)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    @subquery_count += 1
         
     | 
| 
      
 62 
     | 
    
         
            +
                    subquery = Subquery.new(self, relation, "t#{subquery_count}".to_sym)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    add_singular_table_ref(relation, subquery)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    subquery.build
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def resolve_derived_column(column, qualified=false)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    query_columns[column] ||= begin
         
     | 
| 
      
 69 
     | 
    
         
            +
                      resolved_expression = column.expression.resolve_in_query(self)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      resolved_name = qualified ? resolved_expression.qualified_name : column.name
         
     | 
| 
      
 71 
     | 
    
         
            +
                      Sql::DerivedQueryColumn.new(self, resolved_name, resolved_expression)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  def tuple_builder
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @tuple_builder || table_ref
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  def sql_string
         
     | 
| 
      
 82 
     | 
    
         
            +
                    ["select",
         
     | 
| 
      
 83 
     | 
    
         
            +
                      select_clause_sql,
         
     | 
| 
      
 84 
     | 
    
         
            +
                      "from",
         
     | 
| 
      
 85 
     | 
    
         
            +
                      from_clause_sql,
         
     | 
| 
      
 86 
     | 
    
         
            +
                      where_clause_sql,
         
     | 
| 
      
 87 
     | 
    
         
            +
                    ].compact.join(" ")
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  def select_clause_sql
         
     | 
| 
      
 91 
     | 
    
         
            +
                    if select_list
         
     | 
| 
      
 92 
     | 
    
         
            +
                      select_list.map {|column| column.to_select_clause_sql}.join(', ')
         
     | 
| 
      
 93 
     | 
    
         
            +
                    else
         
     | 
| 
      
 94 
     | 
    
         
            +
                      '*'
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                  def from_clause_sql
         
     | 
| 
      
 99 
     | 
    
         
            +
                    table_ref.to_sql
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  def where_clause_sql
         
     | 
| 
      
 103 
     | 
    
         
            +
                    return nil if conditions.empty?
         
     | 
| 
      
 104 
     | 
    
         
            +
                    'where ' + conditions.map do |condition|
         
     | 
| 
      
 105 
     | 
    
         
            +
                      condition.to_sql
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end.join(' and ')
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
              end
         
     | 
| 
      
 110 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class QueryColumn
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :table_ref, :name
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(table_ref, name)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @table_ref, @name = table_ref, name
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 10 
     | 
    
         
            +
                    "#{table_ref.name}.#{name}"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def to_select_clause_sql
         
     | 
| 
      
 14 
     | 
    
         
            +
                    to_sql
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def qualified_name
         
     | 
| 
      
 18 
     | 
    
         
            +
                    "#{table_ref.name}__#{name}"
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Subquery < Query
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include NamedTableRef
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :parent, :relation, :name
         
     | 
| 
      
 7 
     | 
    
         
            +
                  delegate :columns, :to => :relation
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(parent, relation, name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @parent, @name = parent, name
         
     | 
| 
      
 11 
     | 
    
         
            +
                    super(relation)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  delegate :add_literal, :add_singular_table_ref, :add_subquery, :singular_table_refs, :to => :parent
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 17 
     | 
    
         
            +
                    ['(', sql_string, ') as ', name].join
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def build_tuple(field_values)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    tuple_builder.build_tuple(extract_field_values(field_values))
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class TableRef
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include NamedTableRef
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :relation, :query_columns
         
     | 
| 
      
 6 
     | 
    
         
            +
                  delegate :name, :columns, :tuple_class, :to => :relation
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(relation)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @relation = relation
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @query_columns = {}
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def to_sql
         
     | 
| 
      
 14 
     | 
    
         
            +
                    name
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def resolve_column(column)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    query_columns[column] ||= Sql::QueryColumn.new(self, column.name)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def build_tuple(field_values)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    tuple_class.new(extract_field_values(field_values))
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Prequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Tuple
         
     | 
| 
      
 3 
     | 
    
         
            +
                class_attribute :relation
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 6 
     | 
    
         
            +
                  delegate :columns, :to => :relation
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def def_field_reader(name)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    define_method(name) do
         
     | 
| 
      
 10 
     | 
    
         
            +
                      get_field_value(name)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def initialize(values = {})
         
     | 
| 
      
 16 
     | 
    
         
            +
                  initialize_fields
         
     | 
| 
      
 17 
     | 
    
         
            +
                  soft_update_fields(values)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                delegate :columns, :to => :relation
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def soft_update_fields(values)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  values.each do |name, value|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    set_field_value(name, value)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def get_field_value(name)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  fields_by_name[name].try(:value)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def field_values
         
     | 
| 
      
 33 
     | 
    
         
            +
                  fields_by_name.inject({}) do |h, (name, field)|
         
     | 
| 
      
 34 
     | 
    
         
            +
                    h[name] = field.value
         
     | 
| 
      
 35 
     | 
    
         
            +
                    h
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def get_record(name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                delegate :inspect, :to => :field_values
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                protected
         
     | 
| 
      
 46 
     | 
    
         
            +
                attr_reader :fields_by_name
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def initialize_fields
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @fields_by_name = {}
         
     | 
| 
      
 50 
     | 
    
         
            +
                  columns.each do |column|
         
     | 
| 
      
 51 
     | 
    
         
            +
                    fields_by_name[column.name] = Field.new(self, column)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def set_field_value(name, value)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  field = fields_by_name[name]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  unless field
         
     | 
| 
      
 58 
     | 
    
         
            +
                    raise "No field found #{name.inspect}"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  field.value = value
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,119 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: prequel
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 5 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Nathan Sobo
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2011-03-03 00:00:00 -08:00
         
     | 
| 
      
 14 
     | 
    
         
            +
            default_executable: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 16 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 17 
     | 
    
         
            +
              name: activesupport
         
     | 
| 
      
 18 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 19 
     | 
    
         
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 20 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 21 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 22 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 23 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 24 
     | 
    
         
            +
                    version: 3.0.4
         
     | 
| 
      
 25 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 26 
     | 
    
         
            +
              version_requirements: *id001
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: sequel
         
     | 
| 
      
 29 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 30 
     | 
    
         
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 31 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 32 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 33 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 34 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    version: 3.20.0
         
     | 
| 
      
 36 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 37 
     | 
    
         
            +
              version_requirements: *id002
         
     | 
| 
      
 38 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 39 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 40 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 41 
     | 
    
         
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 42 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 43 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 47 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 48 
     | 
    
         
            +
              version_requirements: *id003
         
     | 
| 
      
 49 
     | 
    
         
            +
            description: Prequel is the database library I've always wanted.
         
     | 
| 
      
 50 
     | 
    
         
            +
            email: 
         
     | 
| 
      
 51 
     | 
    
         
            +
            - nathansobo@gmail.com
         
     | 
| 
      
 52 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 59 
     | 
    
         
            +
            - lib/prequel/composite_tuple.rb
         
     | 
| 
      
 60 
     | 
    
         
            +
            - lib/prequel/core_extensions.rb
         
     | 
| 
      
 61 
     | 
    
         
            +
            - lib/prequel/expressions/aliased_expression.rb
         
     | 
| 
      
 62 
     | 
    
         
            +
            - lib/prequel/expressions/column.rb
         
     | 
| 
      
 63 
     | 
    
         
            +
            - lib/prequel/expressions/derived_column.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib/prequel/expressions/equal.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            - lib/prequel/expressions/expression.rb
         
     | 
| 
      
 66 
     | 
    
         
            +
            - lib/prequel/expressions/set_function.rb
         
     | 
| 
      
 67 
     | 
    
         
            +
            - lib/prequel/expressions.rb
         
     | 
| 
      
 68 
     | 
    
         
            +
            - lib/prequel/field.rb
         
     | 
| 
      
 69 
     | 
    
         
            +
            - lib/prequel/record.rb
         
     | 
| 
      
 70 
     | 
    
         
            +
            - lib/prequel/relations/inner_join.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/prequel/relations/projection.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - lib/prequel/relations/relation.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            - lib/prequel/relations/selection.rb
         
     | 
| 
      
 74 
     | 
    
         
            +
            - lib/prequel/relations/table.rb
         
     | 
| 
      
 75 
     | 
    
         
            +
            - lib/prequel/relations.rb
         
     | 
| 
      
 76 
     | 
    
         
            +
            - lib/prequel/session.rb
         
     | 
| 
      
 77 
     | 
    
         
            +
            - lib/prequel/sql/derived_query_column.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
            - lib/prequel/sql/inner_joined_table_ref.rb
         
     | 
| 
      
 79 
     | 
    
         
            +
            - lib/prequel/sql/named_table_ref.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - lib/prequel/sql/query.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - lib/prequel/sql/query_column.rb
         
     | 
| 
      
 82 
     | 
    
         
            +
            - lib/prequel/sql/subquery.rb
         
     | 
| 
      
 83 
     | 
    
         
            +
            - lib/prequel/sql/table_ref.rb
         
     | 
| 
      
 84 
     | 
    
         
            +
            - lib/prequel/sql.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - lib/prequel/tuple.rb
         
     | 
| 
      
 86 
     | 
    
         
            +
            - lib/prequel/version.rb
         
     | 
| 
      
 87 
     | 
    
         
            +
            - lib/prequel.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 89 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 90 
     | 
    
         
            +
            has_rdoc: true
         
     | 
| 
      
 91 
     | 
    
         
            +
            homepage: http://github.com/nathansobo/prequel
         
     | 
| 
      
 92 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 95 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 99 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 100 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 101 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 102 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 103 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 104 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 105 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 106 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 107 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 108 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 109 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 110 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 111 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 114 
     | 
    
         
            +
            rubygems_version: 1.5.2
         
     | 
| 
      
 115 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 116 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 117 
     | 
    
         
            +
            summary: A ground-up relational algebraic ORM.
         
     | 
| 
      
 118 
     | 
    
         
            +
            test_files: []
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     |