scoped_search 4.1.12 → 4.1.13
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/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
|