mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-06 08:07:11 +00:00
[pubsub/query] quote values using single quotes
This fixes the problem with base-16 encoded values which may start with digits: 015AB.... In such cases, the parser recognizes them as numbers but fails to parse because of the follow-up characters (AB). ``` failed to parse tm.events.type=Tx AND hash=136E18F7E4C348B780CF873A0BF43922E5BAFA63: parse error near digit (line 1 symbol 31 - line 1 symbol 32): "6" ``` So, from now on we should quote any values. This seems to be the way Postgresql has chosen.
This commit is contained in:
+20
-13
@@ -13,30 +13,37 @@ func TestParser(t *testing.T) {
|
||||
query string
|
||||
valid bool
|
||||
}{
|
||||
{"tm.events.type=NewBlock", true},
|
||||
{"tm.events.type = NewBlock", true},
|
||||
{"tm.events.type=TIME", true},
|
||||
{"tm.events.type=DATE", true},
|
||||
{"tm.events.type='NewBlock'", true},
|
||||
{"tm.events.type = 'NewBlock'", true},
|
||||
{"tm.events.name = ''", true},
|
||||
{"tm.events.type='TIME'", true},
|
||||
{"tm.events.type='DATE'", true},
|
||||
{"tm.events.type='='", true},
|
||||
{"tm.events.type='TIME", false},
|
||||
{"tm.events.type=TIME'", false},
|
||||
{"tm.events.type==", false},
|
||||
{"tm.events.type=NewBlock", false},
|
||||
{">==", false},
|
||||
{"tm.events.type NewBlock =", false},
|
||||
{"tm.events.type>NewBlock", false},
|
||||
{"tm.events.type 'NewBlock' =", false},
|
||||
{"tm.events.type>'NewBlock'", false},
|
||||
{"", false},
|
||||
{"=", false},
|
||||
{"=NewBlock", false},
|
||||
{"='NewBlock'", false},
|
||||
{"tm.events.type=", false},
|
||||
|
||||
{"tm.events.typeNewBlock", false},
|
||||
{"tm.events.type'NewBlock'", false},
|
||||
{"'NewBlock'", false},
|
||||
{"NewBlock", false},
|
||||
{"", false},
|
||||
|
||||
{"tm.events.type=NewBlock AND abci.account.name=Igor", true},
|
||||
{"tm.events.type=NewBlock AND", false},
|
||||
{"tm.events.type=NewBlock AN", false},
|
||||
{"tm.events.type=NewBlock AN tm.events.type=NewBlockHeader", false},
|
||||
{"AND tm.events.type=NewBlock ", false},
|
||||
{"tm.events.type='NewBlock' AND abci.account.name='Igor'", true},
|
||||
{"tm.events.type='NewBlock' AND", false},
|
||||
{"tm.events.type='NewBlock' AN", false},
|
||||
{"tm.events.type='NewBlock' AN tm.events.type='NewBlockHeader'", false},
|
||||
{"AND tm.events.type='NewBlock' ", false},
|
||||
|
||||
{"abci.account.name CONTAINS Igor", true},
|
||||
{"abci.account.name CONTAINS 'Igor'", true},
|
||||
|
||||
{"tx.date > DATE 2013-05-03", true},
|
||||
{"tx.date < DATE 2013-05-03", true},
|
||||
|
||||
@@ -94,9 +94,12 @@ func (q *Query) Matches(tags map[string]interface{}) bool {
|
||||
case rulecontains:
|
||||
op = opContains
|
||||
case rulevalue:
|
||||
// strip single quotes from value (i.e. "'NewBlock'" -> "NewBlock")
|
||||
valueWithoutSingleQuotes := buffer[begin+1 : end-1]
|
||||
|
||||
// see if the triplet (tag, operator, operand) matches any tag
|
||||
// "tx.gas", "=", "7", { "tx.gas": 7, "tx.ID": "4AE393495334" }
|
||||
if !match(tag, op, reflect.ValueOf(buffer[begin:end]), tags) {
|
||||
if !match(tag, op, reflect.ValueOf(valueWithoutSingleQuotes), tags) {
|
||||
return false
|
||||
}
|
||||
case rulenumber:
|
||||
|
||||
@@ -13,8 +13,8 @@ condition <- tag ' '* (le ' '* (number / time / date)
|
||||
/ contains ' '* value
|
||||
)
|
||||
|
||||
tag <- < (![ \t\n\r\\()"=><] .)+ >
|
||||
value <- < (![ \t\n\r\\()"=><] .)+ >
|
||||
tag <- < (![ \t\n\r\\()"'=><] .)+ >
|
||||
value <- < '\'' (!["'] .)* '\''>
|
||||
number <- < ('0'
|
||||
/ [1-9] digit* ('.' digit*)?) >
|
||||
digit <- [0-9]
|
||||
|
||||
+358
-474
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ func TestMatches(t *testing.T) {
|
||||
err bool
|
||||
matches bool
|
||||
}{
|
||||
{"tm.events.type=NewBlock", map[string]interface{}{"tm.events.type": "NewBlock"}, false, true},
|
||||
{"tm.events.type='NewBlock'", map[string]interface{}{"tm.events.type": "NewBlock"}, false, true},
|
||||
|
||||
{"tx.gas > 7", map[string]interface{}{"tx.gas": 8}, false, true},
|
||||
{"tx.gas > 7 AND tx.gas < 9", map[string]interface{}{"tx.gas": 8}, false, true},
|
||||
@@ -40,8 +40,8 @@ func TestMatches(t *testing.T) {
|
||||
{"tx.time >= TIME 2013-05-03T14:45:00Z", map[string]interface{}{"tx.time": time.Now()}, false, true},
|
||||
{"tx.time = TIME 2013-05-03T14:45:00Z", map[string]interface{}{"tx.time": txTime}, false, false},
|
||||
|
||||
{"abci.owner.name CONTAINS Igor", map[string]interface{}{"abci.owner.name": "Igor,Ivan"}, false, true},
|
||||
{"abci.owner.name CONTAINS Igor", map[string]interface{}{"abci.owner.name": "Pavel,Ivan"}, false, false},
|
||||
{"abci.owner.name CONTAINS 'Igor'", map[string]interface{}{"abci.owner.name": "Igor,Ivan"}, false, true},
|
||||
{"abci.owner.name CONTAINS 'Igor'", map[string]interface{}{"abci.owner.name": "Pavel,Ivan"}, false, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@@ -60,5 +60,5 @@ func TestMatches(t *testing.T) {
|
||||
|
||||
func TestMustParse(t *testing.T) {
|
||||
assert.Panics(t, func() { query.MustParse("=") })
|
||||
assert.NotPanics(t, func() { query.MustParse("tm.events.type=NewBlock") })
|
||||
assert.NotPanics(t, func() { query.MustParse("tm.events.type='NewBlock'") })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user