command_search 0.11.1 → 0.11.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/lib/command_search.rb +9 -0
- data/lib/command_search/backends/mysql.rb +106 -0
- data/lib/command_search/backends/postgres.rb +1 -1
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c9a7f59d4e3aefbd46963b94d52d18d49d63263ab51ceb31a207ee17ca23bf1b
         | 
| 4 | 
            +
              data.tar.gz: 43fe311f65ec44dd89dcb997f0b61daa1347466f63fae1721c0168eb62bfa377
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f9751ac591a874cf99009d28fc691b6543b5fc038dbbb6d7a7b063cf47f134da0e8ee500300877565e5c2b4164f82a446d983c9a6730c2eab35a86a6ae6a92ed
         | 
| 7 | 
            +
              data.tar.gz: 47173f4d0904edcb9ddcbd1f2a24e00f9cd70d528c9234cd1840c861cb4cb7e85681bc6b3362fb73fefff095d16cb6aa277f83027185bc5068ed43c3b5b9b757
         | 
    
        data/lib/command_search.rb
    CHANGED
    
    | @@ -8,6 +8,7 @@ load(__dir__ + '/command_search/backends/memory.rb') | |
| 8 8 | 
             
            load(__dir__ + '/command_search/backends/mongoer.rb')
         | 
| 9 9 | 
             
            load(__dir__ + '/command_search/backends/postgres.rb')
         | 
| 10 10 | 
             
            load(__dir__ + '/command_search/backends/sqlite.rb')
         | 
| 11 | 
            +
            load(__dir__ + '/command_search/backends/mysql.rb')
         | 
| 11 12 |  | 
| 12 13 | 
             
            class Boolean; end
         | 
| 13 14 |  | 
| @@ -29,6 +30,10 @@ module CommandSearch | |
| 29 30 | 
             
                  Normalizer.normalize!(ast, fields, false)
         | 
| 30 31 | 
             
                  return Sqlite.build_query(ast)
         | 
| 31 32 | 
             
                end
         | 
| 33 | 
            +
                if type == :mysql
         | 
| 34 | 
            +
                  Normalizer.normalize!(ast, fields, false)
         | 
| 35 | 
            +
                  return Mysql.build_query(ast)
         | 
| 36 | 
            +
                end
         | 
| 32 37 | 
             
                Normalizer.normalize!(ast, fields)
         | 
| 33 38 | 
             
                return Mongoer.build_query(ast) if type == :mongo
         | 
| 34 39 | 
             
                ast
         | 
| @@ -47,6 +52,10 @@ module CommandSearch | |
| 47 52 | 
             
                  ast = CommandSearch.build(:sqlite, query, options)
         | 
| 48 53 | 
             
                  return source.where(ast)
         | 
| 49 54 | 
             
                end
         | 
| 55 | 
            +
                if source.respond_to?(:mysql2_connection)
         | 
| 56 | 
            +
                  ast = CommandSearch.build(:mysql, query, options)
         | 
| 57 | 
            +
                  return source.where(ast)
         | 
| 58 | 
            +
                end
         | 
| 50 59 | 
             
                ast = CommandSearch.build(:other, query, options)
         | 
| 51 60 | 
             
                source.select { |x| CommandSearch::Memory.check(x, ast) }
         | 
| 52 61 | 
             
              end
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            module CommandSearch
         | 
| 2 | 
            +
              module Mysql
         | 
| 3 | 
            +
                module_function
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def quote_string(str)
         | 
| 6 | 
            +
                  # activerecord/lib/active_record/connection_adapters/abstract/quoting.rb:62
         | 
| 7 | 
            +
                  str.gsub('\\', '\&\&').gsub("'", "''")
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def build_quoted_regex(str)
         | 
| 11 | 
            +
                  str = Regexp.escape(str)
         | 
| 12 | 
            +
                  str = quote_string(str)
         | 
| 13 | 
            +
                  if str[/(^\W)|(\W$)/]
         | 
| 14 | 
            +
                    head_border = '(^|[^:+[[:alnum:]]])'
         | 
| 15 | 
            +
                    tail_border = '($|[^:+[[:alnum:]]])'
         | 
| 16 | 
            +
                    return head_border + str + tail_border
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  '\\\\b' + str + '\\\\b'
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def command_search(node)
         | 
| 22 | 
            +
                  field_node = node[:value].first
         | 
| 23 | 
            +
                  field = field_node[:value]
         | 
| 24 | 
            +
                  search_node = node[:value].last
         | 
| 25 | 
            +
                  val = search_node[:value]
         | 
| 26 | 
            +
                  type = search_node[:type]
         | 
| 27 | 
            +
                  return '0 = 1' if field == '__CommandSearch_dummy_key__'
         | 
| 28 | 
            +
                  if type == Boolean || type == :existence
         | 
| 29 | 
            +
                    if val
         | 
| 30 | 
            +
                      return "(NOT ((#{field} IS NULL) OR (#{field} LIKE '0')))"
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                    return "((#{field} IS NULL) OR (#{field} LIKE '0'))"
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                  if type == Time
         | 
| 35 | 
            +
                    return '0 = 1' unless val
         | 
| 36 | 
            +
                    return "
         | 
| 37 | 
            +
                      (
         | 
| 38 | 
            +
                        (#{field} > '#{val[0] - 1}') AND
         | 
| 39 | 
            +
                        (#{field} <= '#{val[1] - 1}') AND
         | 
| 40 | 
            +
                        (#{field} IS NOT NULL)
         | 
| 41 | 
            +
                      )
         | 
| 42 | 
            +
                    "
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  if type == :quote
         | 
| 45 | 
            +
                    op = 'RLIKE BINARY'
         | 
| 46 | 
            +
                    val = "'#{build_quoted_regex(val)}'"
         | 
| 47 | 
            +
                  elsif type == :str
         | 
| 48 | 
            +
                    op = 'LIKE'
         | 
| 49 | 
            +
                    val = quote_string(val)
         | 
| 50 | 
            +
                    val.gsub!('%', '\%')
         | 
| 51 | 
            +
                    val.gsub!('_', '\_')
         | 
| 52 | 
            +
                    val = "'%#{val}%'"
         | 
| 53 | 
            +
                  elsif type == :number
         | 
| 54 | 
            +
                    op = '='
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                  "((#{field} #{op} #{val}) AND (#{field} IS NOT NULL))"
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def compare_search(node)
         | 
| 60 | 
            +
                  field_node = node[:value].first
         | 
| 61 | 
            +
                  field = field_node[:value]
         | 
| 62 | 
            +
                  search_node = node[:value].last
         | 
| 63 | 
            +
                  val = search_node[:value]
         | 
| 64 | 
            +
                  type = search_node[:type]
         | 
| 65 | 
            +
                  op = node[:nest_op]
         | 
| 66 | 
            +
                  if node[:compare_across_fields]
         | 
| 67 | 
            +
                    "
         | 
| 68 | 
            +
                      (
         | 
| 69 | 
            +
                        (#{field} #{op} #{val}) AND
         | 
| 70 | 
            +
                        (#{field} IS NOT NULL) AND
         | 
| 71 | 
            +
                        (#{val} IS NOT NULL)
         | 
| 72 | 
            +
                      )
         | 
| 73 | 
            +
                    "
         | 
| 74 | 
            +
                  elsif type == Time && val
         | 
| 75 | 
            +
                    "(#{field} #{op} '#{val}') AND (#{field} IS NOT NULL)"
         | 
| 76 | 
            +
                  elsif val.is_a?(Numeric) || val == val.to_i.to_s || val == val.to_f.to_s
         | 
| 77 | 
            +
                    "(#{field} #{op} #{val}) AND (#{field} IS NOT NULL)"
         | 
| 78 | 
            +
                  else
         | 
| 79 | 
            +
                    '0 = 1'
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                def build_query(ast)
         | 
| 84 | 
            +
                  out = []
         | 
| 85 | 
            +
                  ast = [ast] unless ast.is_a?(Array)
         | 
| 86 | 
            +
                  ast.each do |node|
         | 
| 87 | 
            +
                    type = node[:type]
         | 
| 88 | 
            +
                    if type == :colon
         | 
| 89 | 
            +
                      out.push(command_search(node))
         | 
| 90 | 
            +
                    elsif type == :compare
         | 
| 91 | 
            +
                      out.push(compare_search(node))
         | 
| 92 | 
            +
                    elsif type == :and
         | 
| 93 | 
            +
                      out.push(build_query(node[:value]))
         | 
| 94 | 
            +
                    elsif type == :or
         | 
| 95 | 
            +
                      clauses = node[:value].map { |x| build_query(x) }
         | 
| 96 | 
            +
                      clause = clauses.join(' OR ')
         | 
| 97 | 
            +
                      out.push("(#{clause})")
         | 
| 98 | 
            +
                    elsif type == :not
         | 
| 99 | 
            +
                      clause = build_query(node[:value])
         | 
| 100 | 
            +
                      out.push("NOT (#{clause})")
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
                  out.join(' AND ')
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: command_search
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.11. | 
| 4 | 
            +
              version: 0.11.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - zumbalogy
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019-12- | 
| 11 | 
            +
            date: 2019-12-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: chronic
         | 
| @@ -34,6 +34,7 @@ files: | |
| 34 34 | 
             
            - lib/command_search/aliaser.rb
         | 
| 35 35 | 
             
            - lib/command_search/backends/memory.rb
         | 
| 36 36 | 
             
            - lib/command_search/backends/mongoer.rb
         | 
| 37 | 
            +
            - lib/command_search/backends/mysql.rb
         | 
| 37 38 | 
             
            - lib/command_search/backends/postgres.rb
         | 
| 38 39 | 
             
            - lib/command_search/backends/sqlite.rb
         | 
| 39 40 | 
             
            - lib/command_search/lexer.rb
         |