command_search 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ab70b519f399ddeeba1a8862085f8017d327b60a2cbfddaa4682363e56d2f38
4
- data.tar.gz: 204fc638f22b3ffddef67f3065c551885c9b116b4fcadffb118f52d4d7ccffb2
3
+ metadata.gz: 647f1b1fa534c1187bd63333ae986e357fb122a777e9f56d9af2d7d6f34ee6c8
4
+ data.tar.gz: d070864c2e1bba273a8fa837b20c7732efcbb5768149046cf2e68ee666e6f0b3
5
5
  SHA512:
6
- metadata.gz: 15beca3aa277baf873b57ff539b46c7dc966e357801ed69ed3818b17d89e021a6ead6bc233e119fd227bfc62615e2e0078e954cd92b9a32b216e3414cf6313e4
7
- data.tar.gz: 34da12042bd8b24d8b83bdceb08454a8ec72517cd3cfca155072cc286d0b54c683bfa16fc65f8f579759ea1a8279576c989fbd7599fdd818e0a0d45b2a7cd646
6
+ metadata.gz: 3b37775511b9cb93c556c9ce766bc76b3df6f15fb8a2671c814fa0809d32c96a5ffff0371cce4f9fb53dd9de0123f477c233611be04280883c811635a0775208
7
+ data.tar.gz: e9a636dd33c9e53211e381a00e6af3cf2aa0901fdd5e6a12079053285465eb8b4775206f48b295146b2a2e08e4e440b3888e8bff0c1bd8270edff520ad00e0b5
@@ -7,6 +7,7 @@ load(__dir__ + '/command_search/optimizer.rb')
7
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
+ load(__dir__ + '/command_search/backends/sqlite.rb')
10
11
 
11
12
  class Boolean; end
12
13
 
@@ -24,6 +25,10 @@ module CommandSearch
24
25
  Normalizer.normalize!(ast, fields, false)
25
26
  return Postgres.build_query(ast)
26
27
  end
28
+ if type == :sqlite
29
+ Normalizer.normalize!(ast, fields, false)
30
+ return Sqlite.build_query(ast)
31
+ end
27
32
  Normalizer.normalize!(ast, fields)
28
33
  return Mongoer.build_query(ast) if type == :mongo
29
34
  ast
@@ -38,6 +43,10 @@ module CommandSearch
38
43
  ast = CommandSearch.build(:postgres, query, options)
39
44
  return source.where(ast)
40
45
  end
46
+ if source.respond_to?(:sqlite3_connection)
47
+ ast = CommandSearch.build(:sqlite, query, options)
48
+ return source.where(ast)
49
+ end
41
50
  ast = CommandSearch.build(:other, query, options)
42
51
  source.select { |x| CommandSearch::Memory.check(x, ast) }
43
52
  end
@@ -4,16 +4,15 @@ module CommandSearch
4
4
 
5
5
  def quote_string(str)
6
6
  # activerecord/lib/active_record/connection_adapters/abstract/quoting.rb:62
7
- str.gsub!('\\', '\&\&')
8
- str.gsub!("'", "''")
9
- Regexp.escape(str)
7
+ str.gsub('\\', '\&\&').gsub("'", "''")
10
8
  end
11
9
 
12
10
  def build_quoted_regex(input)
13
11
  str = quote_string(input)
12
+ str = Regexp.escape(str)
14
13
  if str[/(^\W)|(\W$)/]
15
- head_border = '(^|\s|[^:+\w])'
16
- tail_border = '($|\s|[^:+\w])'
14
+ head_border = '(^|[^:+\w])'
15
+ tail_border = '($|[^:+\w])'
17
16
  return head_border + str + tail_border
18
17
  end
19
18
  '\m' + str + '\y'
@@ -36,14 +35,23 @@ module CommandSearch
36
35
  end
37
36
  if type == Time
38
37
  return '0 = 1' unless val
39
- return "(#{field} >= '#{val[0]}') AND (#{field} < '#{val[1]}') AND (#{field} IS NOT NULL)"
38
+ return "
39
+ (
40
+ (#{field} >= '#{val[0]}') AND
41
+ (#{field} < '#{val[1]}') AND
42
+ (#{field} IS NOT NULL)
43
+ )
44
+ "
40
45
  end
41
46
  if type == :quote
42
47
  op = '~'
43
48
  val = "'#{build_quoted_regex(val)}'"
44
49
  elsif type == :str
45
- op = '~*'
46
- val = "'#{quote_string(val)}'"
50
+ op = '~~*'
51
+ val = quote_string(val)
52
+ val.gsub!('%', '\%')
53
+ val.gsub!('_', '\_')
54
+ val = "'%#{val}%'"
47
55
  elsif type == :number
48
56
  op = '='
49
57
  end
@@ -58,7 +66,13 @@ module CommandSearch
58
66
  type = search_node[:type]
59
67
  op = node[:nest_op]
60
68
  if node[:compare_across_fields]
61
- "(#{field} #{op} #{val}) AND (#{field} IS NOT NULL) AND (#{val} IS NOT NULL)"
69
+ "
70
+ (
71
+ (#{field} #{op} #{val}) AND
72
+ (#{field} IS NOT NULL) AND
73
+ (#{val} IS NOT NULL)
74
+ )
75
+ "
62
76
  elsif type == Time && val
63
77
  "(#{field} #{op} '#{val}') AND (#{field} IS NOT NULL)"
64
78
  elsif val.is_a?(Numeric) || val == val.to_i.to_s || val == val.to_f.to_s
@@ -0,0 +1,111 @@
1
+ module CommandSearch
2
+ module Sqlite
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 command_search(node)
11
+ field_node = node[:value].first
12
+ field = field_node[:value]
13
+ search_node = node[:value].last
14
+ val = search_node[:value]
15
+ type = search_node[:type]
16
+ return '0 = 1' if field == '__CommandSearch_dummy_key__'
17
+ if type == Boolean || type == :existence
18
+ false_val = 'false'
19
+ false_val = 0 if field_node[:field_type] == Numeric
20
+ if val
21
+ return "NOT ((#{field} = #{false_val}) OR (#{field} IS NULL))"
22
+ end
23
+ return "((#{field} = #{false_val}) OR (#{field} IS NULL))"
24
+ end
25
+ if type == Time
26
+ return '0 = 1' unless val
27
+ return "
28
+ (
29
+ (#{field} > '#{val[0] - 1}') AND
30
+ (#{field} <= '#{val[1] - 1}') AND
31
+ (#{field} IS NOT NULL)
32
+ )
33
+ "
34
+ end
35
+ if type == :quote
36
+ val = quote_string(val)
37
+ val.gsub!('[', '[[]')
38
+ val.gsub!('*', '[*]')
39
+ val.gsub!('?', '[?]')
40
+ border = '[ .,()?"\'\']'
41
+ return "
42
+ (
43
+ (#{field} IS NOT NULL) AND
44
+ (
45
+ (#{field} GLOB '#{val}') OR
46
+ (#{field} GLOB '*#{border}#{val}#{border}*') OR
47
+ (#{field} GLOB '*#{border}#{val}') OR
48
+ (#{field} GLOB '#{val}#{border}*')
49
+ )
50
+ )
51
+ "
52
+ elsif type == :str
53
+ op = 'LIKE'
54
+ val = quote_string(val)
55
+ val.gsub!('%', '\%')
56
+ val.gsub!('_', '\_')
57
+ val = "'%#{val}%' ESCAPE '\\'"
58
+ elsif type == :number
59
+ op = '='
60
+ end
61
+ "((#{field} #{op} #{val}) AND (#{field} IS NOT NULL))"
62
+ end
63
+
64
+ def compare_search(node)
65
+ field_node = node[:value].first
66
+ field = field_node[:value]
67
+ search_node = node[:value].last
68
+ val = search_node[:value]
69
+ type = search_node[:type]
70
+ op = node[:nest_op]
71
+ if node[:compare_across_fields]
72
+ "
73
+ (
74
+ (#{field} #{op} #{val}) AND
75
+ (#{field} IS NOT NULL) AND
76
+ (#{val} IS NOT NULL)
77
+ )
78
+ "
79
+ elsif type == Time && val
80
+ "(#{field} #{op} '#{val}') AND (#{field} IS NOT NULL)"
81
+ elsif val.is_a?(Numeric) || val == val.to_i.to_s || val == val.to_f.to_s
82
+ "(#{field} #{op} #{val}) AND (#{field} IS NOT NULL)"
83
+ else
84
+ '0 = 1'
85
+ end
86
+ end
87
+
88
+ def build_query(ast)
89
+ out = []
90
+ ast = [ast] unless ast.is_a?(Array)
91
+ ast.each do |node|
92
+ type = node[:type]
93
+ if type == :colon
94
+ out.push(command_search(node))
95
+ elsif type == :compare
96
+ out.push(compare_search(node))
97
+ elsif type == :and
98
+ out.push(build_query(node[:value]))
99
+ elsif type == :or
100
+ clauses = node[:value].map { |x| build_query(x) }
101
+ clause = clauses.join(' OR ')
102
+ out.push("(#{clause})")
103
+ elsif type == :not
104
+ clause = build_query(node[:value])
105
+ out.push("NOT (#{clause})")
106
+ end
107
+ end
108
+ out.join(' AND ')
109
+ end
110
+ end
111
+ end
@@ -53,8 +53,8 @@ module CommandSearch
53
53
  str = Regexp.escape(raw)
54
54
  return node[:value] = /#{str}/i unless type == :quote
55
55
  return node[:value] = /\b#{str}\b/ unless raw[/(\A\W)|(\W\Z)/]
56
- border_a = '(^|\s|[^:+\w])'
57
- border_b = '($|\s|[^:+\w])'
56
+ border_a = '(^|[^:+\w])'
57
+ border_b = '($|[^:+\w])'
58
58
  node[:value] = Regexp.new(border_a + str + border_b)
59
59
  end
60
60
 
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.0
4
+ version: 0.11.1
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-14 00:00:00.000000000 Z
11
+ date: 2019-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chronic
@@ -35,6 +35,7 @@ files:
35
35
  - lib/command_search/backends/memory.rb
36
36
  - lib/command_search/backends/mongoer.rb
37
37
  - lib/command_search/backends/postgres.rb
38
+ - lib/command_search/backends/sqlite.rb
38
39
  - lib/command_search/lexer.rb
39
40
  - lib/command_search/normalizer.rb
40
41
  - lib/command_search/optimizer.rb