scoped_search 4.1.12 → 4.1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/scoped_search/query_language/parser.rb +29 -7
- data/lib/scoped_search/version.rb +1 -1
- data/spec/unit/parser_spec.rb +21 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbd1e857e3b248d6d585ac7c41679b536949dc945f4c7e067b2b16e86ce325b2
|
4
|
+
data.tar.gz: b4c1dc92102ff1d56b1f23406b16cf0523c6bdc17ab336ee92300993de5fd7f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fe965444b5640251c4ca34c5fc1fca34857f2c8cc96a8f759096165391490ca7deb7f5b3f9d8ed8c9219a5ddfa82716660e2739adb5d7dfdb2d61ca95a968a7
|
7
|
+
data.tar.gz: f9ce7c87b95ceec5f3f5d1cc46f6401ef121870bf58a8cffe1b07cb7de597b8bcd3bcd1069e98ef52007df2209b26998f3f1c05a9719eefe17351d1f6da1eebf
|
@@ -31,7 +31,7 @@ module ScopedSearch::QueryLanguage::Parser
|
|
31
31
|
next_token if !root_node && peek_token == :lparen # skip starting :lparen
|
32
32
|
expressions << parse_logical_expression until peek_token.nil? || peek_token == :rparen
|
33
33
|
next_token if !root_node && peek_token == :rparen # skip final :rparen
|
34
|
-
|
34
|
+
|
35
35
|
return ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(DEFAULT_SEQUENCE_OPERATOR, expressions, root_node)
|
36
36
|
end
|
37
37
|
|
@@ -42,18 +42,23 @@ module ScopedSearch::QueryLanguage::Parser
|
|
42
42
|
when :lparen; parse_expression_sequence
|
43
43
|
when :not; parse_logical_not_expression
|
44
44
|
when :null, :notnull; parse_null_expression
|
45
|
+
when *LOGICAL_INFIX_OPERATORS; parse_logical_infix_expression
|
45
46
|
else; parse_comparison
|
46
47
|
end
|
47
48
|
|
48
49
|
if LOGICAL_INFIX_OPERATORS.include?(peek_token)
|
49
|
-
|
50
|
-
rhs = parse_logical_expression
|
51
|
-
ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(operator, [lhs, rhs])
|
50
|
+
parse_logical_infix_expression([lhs])
|
52
51
|
else
|
53
52
|
lhs
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
56
|
+
def parse_logical_infix_expression(previous = [])
|
57
|
+
operator = next_token
|
58
|
+
rhs = parse_logical_expression
|
59
|
+
ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(operator, previous + [rhs])
|
60
|
+
end
|
61
|
+
|
57
62
|
# Parses a NOT expression
|
58
63
|
def parse_logical_not_expression
|
59
64
|
next_token # = skip NOT operator
|
@@ -80,7 +85,24 @@ module ScopedSearch::QueryLanguage::Parser
|
|
80
85
|
|
81
86
|
# Parses a prefix comparison, i.e. without an explicit field: <operator> <value>
|
82
87
|
def parse_prefix_comparison
|
83
|
-
|
88
|
+
token = next_token
|
89
|
+
case token
|
90
|
+
when :in
|
91
|
+
parse_prefix_in(true)
|
92
|
+
when :notin
|
93
|
+
parse_prefix_in(false)
|
94
|
+
else
|
95
|
+
ScopedSearch::QueryLanguage::AST::OperatorNode.new(token, [parse_value])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_prefix_in(inclusion)
|
100
|
+
cmp, log = inclusion ? [:eq, :or] : [:ne, :and]
|
101
|
+
leaves = parse_multiple_values.map do |x|
|
102
|
+
leaf = ScopedSearch::QueryLanguage::AST::LeafNode.new(x)
|
103
|
+
ScopedSearch::QueryLanguage::AST::OperatorNode.new(cmp, [leaf])
|
104
|
+
end
|
105
|
+
ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(log, leaves)
|
84
106
|
end
|
85
107
|
|
86
108
|
# Parses an infix expression, i.e. <field> <operator> <value>
|
@@ -109,7 +131,7 @@ module ScopedSearch::QueryLanguage::Parser
|
|
109
131
|
value = []
|
110
132
|
value << current_token if String === next_token until peek_token.nil? || peek_token == :rparen
|
111
133
|
next_token if peek_token == :rparen # consume the :rparen
|
112
|
-
value
|
134
|
+
value
|
113
135
|
end
|
114
136
|
|
115
137
|
# This can either be a constant value or a field name.
|
@@ -117,7 +139,7 @@ module ScopedSearch::QueryLanguage::Parser
|
|
117
139
|
if String === peek_token
|
118
140
|
ScopedSearch::QueryLanguage::AST::LeafNode.new(next_token)
|
119
141
|
elsif ([:in, :notin].include? current_token)
|
120
|
-
value = parse_multiple_values()
|
142
|
+
value = parse_multiple_values().join(',')
|
121
143
|
ScopedSearch::QueryLanguage::AST::LeafNode.new(value)
|
122
144
|
else
|
123
145
|
raise ScopedSearch::QueryNotSupported, "Value expected but found #{peek_token.inspect}"
|
data/spec/unit/parser_spec.rb
CHANGED
@@ -102,7 +102,27 @@ describe ScopedSearch::QueryLanguage::Parser do
|
|
102
102
|
'set? a b null? c'.should parse_to([:and, [:notnull, 'a'], 'b', [:null, 'c']])
|
103
103
|
end
|
104
104
|
|
105
|
+
it 'should parse logical operators with a single argument' do
|
106
|
+
'& a'.should parse_to('a')
|
107
|
+
'& & & & a & b & & &'.should parse_to([:and, 'a', 'b'])
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should parse in and not in operators with no lhs' do
|
111
|
+
'^ a'.should parse_to([:eq, 'a'])
|
112
|
+
'^ a b'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
|
113
|
+
'^ a,b'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
|
114
|
+
|
115
|
+
'^ (a b)'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
|
116
|
+
'^ (a,b)'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
|
117
|
+
|
118
|
+
'!^ a'.should parse_to([:ne, 'a'])
|
119
|
+
'!^ a b'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
|
120
|
+
'!^ a,b'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
|
121
|
+
'!^ (a b)'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
|
122
|
+
'!^ (a,b)'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
|
123
|
+
end
|
124
|
+
|
105
125
|
it "should refuse to parse an empty not expression" do
|
106
126
|
lambda { ScopedSearch::QueryLanguage::Compiler.parse('!()|*') }.should raise_error(ScopedSearch::QueryNotSupported)
|
107
|
-
end
|
127
|
+
end
|
108
128
|
end
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amos Benari
|
8
8
|
- Willem van Bergen
|
9
9
|
- Wes Hays
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-12-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -144,7 +144,7 @@ homepage: https://github.com/wvanbergen/scoped_search/wiki
|
|
144
144
|
licenses:
|
145
145
|
- MIT
|
146
146
|
metadata: {}
|
147
|
-
post_install_message:
|
147
|
+
post_install_message:
|
148
148
|
rdoc_options:
|
149
149
|
- "--title"
|
150
150
|
- scoped_search
|
@@ -165,8 +165,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
requirements: []
|
168
|
-
rubygems_version: 3.
|
169
|
-
signing_key:
|
168
|
+
rubygems_version: 3.3.27
|
169
|
+
signing_key:
|
170
170
|
specification_version: 4
|
171
171
|
summary: Easily search you ActiveRecord models with a simple query language using
|
172
172
|
a named scope
|