rasti-db 2.0.1 → 2.3.2
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.
- checksums.yaml +4 -4
 - data/README.md +11 -3
 - data/lib/rasti/db.rb +11 -1
 - data/lib/rasti/db/collection.rb +10 -1
 - data/lib/rasti/db/computed_attribute.rb +22 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
 - data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
 - data/lib/rasti/db/nql/nodes/array_content.rb +21 -0
 - data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
 - data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
 - data/lib/rasti/db/nql/nodes/comparisons/base.rb +15 -1
 - data/lib/rasti/db/nql/nodes/comparisons/equal.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/include.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/like.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +0 -4
 - data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +0 -4
 - data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
 - data/lib/rasti/db/nql/nodes/constants/array.rb +17 -0
 - data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
 - data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
 - data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
 - data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
 - data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
 - data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
 - data/lib/rasti/db/nql/syntax.rb +262 -44
 - data/lib/rasti/db/nql/syntax.treetop +27 -14
 - data/lib/rasti/db/query.rb +38 -8
 - data/lib/rasti/db/type_converters/postgres.rb +32 -36
 - data/lib/rasti/db/type_converters/postgres_types/array.rb +11 -9
 - data/lib/rasti/db/type_converters/postgres_types/hstore.rb +10 -9
 - data/lib/rasti/db/type_converters/postgres_types/json.rb +17 -14
 - data/lib/rasti/db/type_converters/postgres_types/jsonb.rb +17 -14
 - data/lib/rasti/db/type_converters/sqlite.rb +62 -0
 - data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
 - data/lib/rasti/db/version.rb +1 -1
 - data/rasti-db.gemspec +1 -0
 - data/spec/collection_spec.rb +8 -0
 - data/spec/computed_attribute_spec.rb +32 -0
 - data/spec/minitest_helper.rb +32 -5
 - data/spec/model_spec.rb +1 -1
 - data/spec/nql/computed_attributes_spec.rb +29 -0
 - data/spec/nql/filter_condition_spec.rb +23 -4
 - data/spec/nql/filter_condition_strategies_spec.rb +112 -0
 - data/spec/nql/syntax_parser_spec.rb +36 -5
 - data/spec/query_spec.rb +235 -34
 - data/spec/type_converters/sqlite_spec.rb +66 -0
 - metadata +38 -3
 - data/lib/rasti/db/nql/nodes/field.rb +0 -23
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 335b135a71edd9bbb047407d8a288094a19f58b6c2e481837bf4406c06605350
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 89c5da3b13e1a1f9a82faaa2eb414bc063d72c8588b35c4871deb44d189c3d5b
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b27407dcb968c5dc6056a50160cc06b6e89f7008623f0ea2234294195080ebc153da762a79a32618740c79915ff7a5424368f58ed5ee64ff951cd1c4e6f9dc32
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 77203709a9d842b819aaca51b789a8ac4c27fcd269f617f680530da18ce96607f610c13c4b78b72a91b75a1be4487efcb66e7daaeb7025a89888397799f2b128
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -93,7 +93,7 @@ User     = Rasti::DB::Model[:id, :name, :posts, :comments, :person] 
     | 
|
| 
       93 
93 
     | 
    
         
             
            Post     = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
         
     | 
| 
       94 
94 
     | 
    
         
             
            Comment  = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
         
     | 
| 
       95 
95 
     | 
    
         
             
            Category = Rasti::DB::Model[:id, :name, :posts]
         
     | 
| 
       96 
     | 
    
         
            -
            Person   = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user]
         
     | 
| 
      
 96 
     | 
    
         
            +
            Person   = Rasti::DB::Model[:document_number, :first_name, :last_name, :full_name, :birth_date, :user_id, :user]
         
     | 
| 
       97 
97 
     | 
    
         
             
            Language = Rasti::DB::Model[:id, :name, :people]
         
     | 
| 
       98 
98 
     | 
    
         
             
            ```
         
     | 
| 
       99 
99 
     | 
    
         | 
| 
         @@ -111,10 +111,10 @@ class Posts < Rasti::DB::Collection 
     | 
|
| 
       111 
111 
     | 
    
         
             
              many_to_many :categories
         
     | 
| 
       112 
112 
     | 
    
         
             
              one_to_many :comments
         
     | 
| 
       113 
113 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
              query :created_by do |user_id| 
     | 
| 
      
 114 
     | 
    
         
            +
              query :created_by do |user_id|
         
     | 
| 
       115 
115 
     | 
    
         
             
                where user_id: user_id
         
     | 
| 
       116 
116 
     | 
    
         
             
              end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       118 
118 
     | 
    
         
             
              query :entitled, -> (title) { where title: title }
         
     | 
| 
       119 
119 
     | 
    
         | 
| 
       120 
120 
     | 
    
         
             
              query :commented_by do |user_id|
         
     | 
| 
         @@ -144,6 +144,10 @@ class People < Rasti::DB::Collection 
     | 
|
| 
       144 
144 
     | 
    
         | 
| 
       145 
145 
     | 
    
         
             
              many_to_one :user
         
     | 
| 
       146 
146 
     | 
    
         
             
              many_to_many :languages
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
              computed_attribute :full_name do
         
     | 
| 
      
 149 
     | 
    
         
            +
                Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
       147 
151 
     | 
    
         
             
            end
         
     | 
| 
       148 
152 
     | 
    
         | 
| 
       149 
153 
     | 
    
         
             
            class Languages < Rasti::DB::Collection
         
     | 
| 
         @@ -210,6 +214,10 @@ posts.all_attributes # => [Post, ...] 
     | 
|
| 
       210 
214 
     | 
    
         
             
            posts.graph('user.person').select_graph_attributes(user: [:id], 'user.person': [:last_name, :user_id]) # => [Post, ...]
         
     | 
| 
       211 
215 
     | 
    
         
             
            posts.graph('user.person').exclude_graph_attributes(user: [:name], 'user.person': [:first_name, :last_name]) # => [Post, ...]
         
     | 
| 
       212 
216 
     | 
    
         
             
            posts.graph('user.person').all_graph_attributes('user.person') # => [Post, ...]
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
            posts.each { |post| do_something post } # Iterate posts loading all at first
         
     | 
| 
      
 219 
     | 
    
         
            +
            posts.each(batch_size: 1000) { |post| do_something post } # Iterate posts loading in batches
         
     | 
| 
      
 220 
     | 
    
         
            +
            posts.each_batch(size: 1000) { |posts| do_something posts } # Iterate batches of posts
         
     | 
| 
       213 
221 
     | 
    
         
             
            ```
         
     | 
| 
       214 
222 
     | 
    
         
             
            ### Natural Query Language
         
     | 
| 
       215 
223 
     | 
    
         | 
    
        data/lib/rasti/db.rb
    CHANGED
    
    | 
         @@ -6,20 +6,25 @@ require 'treetop' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            require 'hierarchical_graph'
         
     | 
| 
       7 
7 
     | 
    
         
             
            require 'class_config'
         
     | 
| 
       8 
8 
     | 
    
         
             
            require 'hash_ext'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'inflecto'
         
     | 
| 
       9 
10 
     | 
    
         
             
            require 'multi_require'
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
            module Rasti
         
     | 
| 
       12 
13 
     | 
    
         
             
              module DB
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       14 
15 
     | 
    
         
             
                extend MultiRequire
         
     | 
| 
       15 
16 
     | 
    
         
             
                extend ClassConfig
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
18 
     | 
    
         
             
                require_relative 'db/query'
         
     | 
| 
       18 
19 
     | 
    
         
             
                require_relative_pattern  'db/relations/*'
         
     | 
| 
       19 
20 
     | 
    
         
             
                require_relative_pattern  'db/type_converters/postgres_types/*'
         
     | 
| 
      
 21 
     | 
    
         
            +
                require_relative_pattern  'db/type_converters/sqlite_types/*'
         
     | 
| 
      
 22 
     | 
    
         
            +
                require_relative 'db/nql/nodes/constants/base'
         
     | 
| 
      
 23 
     | 
    
         
            +
                require_relative_pattern  'db/nql/filter_condition_strategies/types/*'
         
     | 
| 
       20 
24 
     | 
    
         
             
                require_relative_pattern  'db/**/*'
         
     | 
| 
       21 
25 
     | 
    
         | 
| 
       22 
26 
     | 
    
         
             
                attr_config :type_converters, []
         
     | 
| 
      
 27 
     | 
    
         
            +
                attr_config :nql_filter_condition_strategy, nil
         
     | 
| 
       23 
28 
     | 
    
         | 
| 
       24 
29 
     | 
    
         
             
                def self.to_db(db, collection_name, attribute_name, value)
         
     | 
| 
       25 
30 
     | 
    
         
             
                  type_converters.inject(value) do |result, type_converter|
         
     | 
| 
         @@ -33,5 +38,10 @@ module Rasti 
     | 
|
| 
       33 
38 
     | 
    
         
             
                  end
         
     | 
| 
       34 
39 
     | 
    
         
             
                end
         
     | 
| 
       35 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
                def self.nql_filter_condition_for(comparison_name, identifier, argument)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  raise 'Undefined Rasti::DB.nql_filter_condition_strategy' unless nql_filter_condition_strategy
         
     | 
| 
      
 43 
     | 
    
         
            +
                  nql_filter_condition_strategy.filter_condition_for comparison_name, identifier, argument
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       36 
46 
     | 
    
         
             
              end
         
     | 
| 
       37 
47 
     | 
    
         
             
            end
         
     | 
    
        data/lib/rasti/db/collection.rb
    CHANGED
    
    | 
         @@ -14,7 +14,7 @@ module Rasti 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                    def collection_attributes
         
     | 
| 
       17 
     | 
    
         
            -
                      @collection_attributes ||= model.attributes - relations.keys
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @collection_attributes ||= model.attributes - relations.keys - computed_attributes.keys
         
     | 
| 
       18 
18 
     | 
    
         
             
                    end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                    def primary_key
         
     | 
| 
         @@ -47,6 +47,10 @@ module Rasti 
     | 
|
| 
       47 
47 
     | 
    
         
             
                      @queries ||= Hash::Indifferent.new
         
     | 
| 
       48 
48 
     | 
    
         
             
                    end
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
      
 50 
     | 
    
         
            +
                    def computed_attributes
         
     | 
| 
      
 51 
     | 
    
         
            +
                      @computed_attributes ||= Hash::Indifferent.new
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       50 
54 
     | 
    
         
             
                    private
         
     | 
| 
       51 
55 
     | 
    
         | 
| 
       52 
56 
     | 
    
         
             
                    def set_collection_name(collection_name)
         
     | 
| 
         @@ -91,6 +95,11 @@ module Rasti 
     | 
|
| 
       91 
95 
     | 
    
         
             
                      end
         
     | 
| 
       92 
96 
     | 
    
         
             
                    end
         
     | 
| 
       93 
97 
     | 
    
         | 
| 
      
 98 
     | 
    
         
            +
                    def computed_attribute(name, &block)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      raise "Computed Attribute #{name} already exists" if computed_attributes.key? name
         
     | 
| 
      
 100 
     | 
    
         
            +
                      computed_attributes[name] = block.call
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
       94 
103 
     | 
    
         
             
                  end
         
     | 
| 
       95 
104 
     | 
    
         | 
| 
       96 
105 
     | 
    
         
             
                  def initialize(environment)
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                class ComputedAttribute
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :identifier
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(identifier, &join)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @identifier = identifier
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @join = join
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def apply_join(dataset)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    join ? join.call(dataset) : dataset
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  attr_reader :join
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class Base
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      def filter_condition_for(comparison_name, identifier, argument)
         
     | 
| 
      
 8 
     | 
    
         
            +
                        type = type_for argument
         
     | 
| 
      
 9 
     | 
    
         
            +
                        raise UnsupportedTypeComparison.new(type, comparison_name) unless type.respond_to?(comparison_name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                        type.public_send comparison_name, identifier, argument.value
         
     | 
| 
      
 11 
     | 
    
         
            +
                      end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class Postgres < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      PG_TYPES = {
         
     | 
| 
      
 8 
     | 
    
         
            +
                        array: Types::PGArray
         
     | 
| 
      
 9 
     | 
    
         
            +
                      }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      private
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      def type_for(argument)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        PG_TYPES.fetch(argument.type, Types::Generic)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class SQLite < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      SQLITE_TYPES = {
         
     | 
| 
      
 8 
     | 
    
         
            +
                        array: Types::SQLiteArray
         
     | 
| 
      
 9 
     | 
    
         
            +
                      }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      private
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      def type_for(argument)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        SQLITE_TYPES.fetch(argument.type, Types::Generic)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    module Types
         
     | 
| 
      
 6 
     | 
    
         
            +
                      class Generic
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                        def self.equal(identifier, value)
         
     | 
| 
      
 9 
     | 
    
         
            +
                          {identifier => value}
         
     | 
| 
      
 10 
     | 
    
         
            +
                        end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                        def self.not_equal(identifier, value)
         
     | 
| 
      
 13 
     | 
    
         
            +
                          Sequel.negate equal(identifier, value)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                        def self.greater_than(identifier, value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                          identifier > value
         
     | 
| 
      
 18 
     | 
    
         
            +
                        end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                        def self.greater_than_or_equal(identifier, value)
         
     | 
| 
      
 21 
     | 
    
         
            +
                          identifier >= value
         
     | 
| 
      
 22 
     | 
    
         
            +
                        end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                        def self.less_than(identifier, value)
         
     | 
| 
      
 25 
     | 
    
         
            +
                          identifier < value
         
     | 
| 
      
 26 
     | 
    
         
            +
                        end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                        def self.less_than_or_equal(identifier, value)
         
     | 
| 
      
 29 
     | 
    
         
            +
                          identifier <= value
         
     | 
| 
      
 30 
     | 
    
         
            +
                        end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                        def self.like(identifier, value)
         
     | 
| 
      
 33 
     | 
    
         
            +
                          Sequel.ilike identifier, value
         
     | 
| 
      
 34 
     | 
    
         
            +
                        end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                        def self.include(identifier, value)
         
     | 
| 
      
 37 
     | 
    
         
            +
                          Sequel.ilike identifier, "%#{value}%"
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                        def self.not_include(identifier, value)
         
     | 
| 
      
 41 
     | 
    
         
            +
                          ~include(identifier, value)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      end
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    module Types
         
     | 
| 
      
 6 
     | 
    
         
            +
                      class PGArray
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                        def self.equal(identifier, values)
         
     | 
| 
      
 9 
     | 
    
         
            +
                          Sequel.&(
         
     | 
| 
      
 10 
     | 
    
         
            +
                            Sequel.pg_array(identifier).contains(Sequel.pg_array(values)),
         
     | 
| 
      
 11 
     | 
    
         
            +
                            Sequel.pg_array(identifier).contained_by(Sequel.pg_array(values))
         
     | 
| 
      
 12 
     | 
    
         
            +
                          )
         
     | 
| 
      
 13 
     | 
    
         
            +
                        end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                        def self.not_equal(identifier, values)
         
     | 
| 
      
 16 
     | 
    
         
            +
                          ~equal(identifier, values)
         
     | 
| 
      
 17 
     | 
    
         
            +
                        end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                        def self.include(identifier, values)
         
     | 
| 
      
 20 
     | 
    
         
            +
                          Sequel.pg_array(identifier).overlaps Sequel.pg_array(values)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                        def self.not_include(identifier, values)
         
     | 
| 
      
 24 
     | 
    
         
            +
                          ~include(identifier, values)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    module Types
         
     | 
| 
      
 6 
     | 
    
         
            +
                      class SQLiteArray
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                        def self.equal(identifier, values)
         
     | 
| 
      
 9 
     | 
    
         
            +
                          array = values.map { |value| "\"#{value}\"" }.join(',')
         
     | 
| 
      
 10 
     | 
    
         
            +
                          {identifier => "[#{array}]"}
         
     | 
| 
      
 11 
     | 
    
         
            +
                        end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                        def self.not_equal(identifier, values)
         
     | 
| 
      
 14 
     | 
    
         
            +
                          Sequel.|(*values.map { |value| ~Sequel.like(identifier, "%\"#{value}\"%") })
         
     | 
| 
      
 15 
     | 
    
         
            +
                        end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                        def self.like(identifier, values)
         
     | 
| 
      
 18 
     | 
    
         
            +
                          Sequel.|(*values.map { |value| Sequel.like(identifier, "%#{value}%") })
         
     | 
| 
      
 19 
     | 
    
         
            +
                        end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                        def self.include(identifier, values)
         
     | 
| 
      
 22 
     | 
    
         
            +
                          Sequel.|(*values.map { |value| Sequel.like(identifier, "%\"#{value}\"%") })
         
     | 
| 
      
 23 
     | 
    
         
            +
                        end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                        def self.not_include(identifier, values)
         
     | 
| 
      
 26 
     | 
    
         
            +
                          Sequel.&(*values.map { |value| ~Sequel.like(identifier, "%\"#{value}\"%") })
         
     | 
| 
      
 27 
     | 
    
         
            +
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module FilterConditionStrategies
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class UnsupportedTypeComparison < StandardError
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      attr_reader :argument_type, :comparison_name
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                      def initialize(argument_type, comparison_name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                        @argument_type = argument_type
         
     | 
| 
      
 11 
     | 
    
         
            +
                        @comparison_name = comparison_name
         
     | 
| 
      
 12 
     | 
    
         
            +
                      end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                      def message
         
     | 
| 
      
 15 
     | 
    
         
            +
                        "Unsupported comparison #{comparison_name} for #{argument_type}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                      end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Nodes
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class ArrayContent < Treetop::Runtime::SyntaxNode
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      def values
         
     | 
| 
      
 8 
     | 
    
         
            +
                        [left.value] + right_value
         
     | 
| 
      
 9 
     | 
    
         
            +
                      end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      private
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      def right_value
         
     | 
| 
      
 14 
     | 
    
         
            +
                        right.is_a?(self.class) ? right.values : [right.value]
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rasti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module DB
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NQL
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Nodes
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class Attribute < Treetop::Runtime::SyntaxNode
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      def identifier(collection_class)
         
     | 
| 
      
 8 
     | 
    
         
            +
                        if computed? collection_class
         
     | 
| 
      
 9 
     | 
    
         
            +
                          collection_class.computed_attributes[column].identifier
         
     | 
| 
      
 10 
     | 
    
         
            +
                        else
         
     | 
| 
      
 11 
     | 
    
         
            +
                          tables.empty? ? Sequel[column] : Sequel[tables.join('__').to_sym][column]
         
     | 
| 
      
 12 
     | 
    
         
            +
                        end
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                      def tables
         
     | 
| 
      
 16 
     | 
    
         
            +
                        _tables.elements.map{ |e| e.table.text_value }
         
     | 
| 
      
 17 
     | 
    
         
            +
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                      def column
         
     | 
| 
      
 20 
     | 
    
         
            +
                        _column.text_value.to_sym
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                      def computed_attributes(collection_class)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        computed?(collection_class) ? [column] : []
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      private
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                      def computed?(collection_class)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        collection_class.computed_attributes.key? column
         
     | 
| 
      
 31 
     | 
    
         
            +
                      end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -8,6 +8,10 @@ module Rasti 
     | 
|
| 
       8 
8 
     | 
    
         
             
                        values.flat_map(&:dependency_tables)
         
     | 
| 
       9 
9 
     | 
    
         
             
                      end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                      def computed_attributes(collection_class)
         
     | 
| 
      
 12 
     | 
    
         
            +
                        left.computed_attributes(collection_class) | right.computed_attributes(collection_class)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       11 
15 
     | 
    
         
             
                      def values
         
     | 
| 
       12 
16 
     | 
    
         
             
                        @values ||= values_for(left) + values_for(right)
         
     | 
| 
       13 
17 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -6,7 +6,21 @@ module Rasti 
     | 
|
| 
       6 
6 
     | 
    
         
             
                      class Base < Treetop::Runtime::SyntaxNode
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                        def dependency_tables
         
     | 
| 
       9 
     | 
    
         
            -
                           
     | 
| 
      
 9 
     | 
    
         
            +
                          attribute.tables.empty? ? [] : [attribute.tables.join('.')]
         
     | 
| 
      
 10 
     | 
    
         
            +
                        end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                        def computed_attributes(collection_class)
         
     | 
| 
      
 13 
     | 
    
         
            +
                          attribute.computed_attributes(collection_class)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                        def filter_condition(collection_class)
         
     | 
| 
      
 17 
     | 
    
         
            +
                          DB.nql_filter_condition_for comparison_name, attribute.identifier(collection_class), argument
         
     | 
| 
      
 18 
     | 
    
         
            +
                        end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                        private
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                        def comparison_name
         
     | 
| 
      
 23 
     | 
    
         
            +
                          Inflecto.underscore(Inflecto.demodulize(self.class)).to_sym
         
     | 
| 
       10 
24 
     | 
    
         
             
                        end
         
     | 
| 
       11 
25 
     | 
    
         | 
| 
       12 
26 
     | 
    
         
             
                      end
         
     |