Implement NOT logical operator

This commit is contained in:
Pijus Kamandulis 2025-02-25 19:33:32 +02:00
parent 851b3ca3a8
commit 1711c8fb5c
6 changed files with 1537 additions and 1445 deletions

View File

@ -42,6 +42,7 @@ type SelectItem struct {
SelectItems []SelectItem SelectItems []SelectItem
Type SelectItemType Type SelectItemType
Value interface{} Value interface{}
Invert bool
IsTopLevel bool IsTopLevel bool
} }

File diff suppressed because it is too large Load Diff

View File

@ -329,7 +329,7 @@ AsClause <- (ws As)? ws !ExcludedKeywords alias:Identifier {
return alias, nil return alias, nil
} }
ExcludedKeywords <- Select / Top / As / From / In / Join / Exists / Where / And / Or / GroupBy / OrderBy / Offset ExcludedKeywords <- Select / Top / As / From / In / Join / Exists / Where / And / Or / Not / GroupBy / OrderBy / Offset
DotFieldAccess <- "." id:Identifier { DotFieldAccess <- "." id:Identifier {
return id, nil return id, nil
@ -358,8 +358,14 @@ AndExpression <- ex1:ComparisonExpression ex2:(ws And ws ex:ComparisonExpression
ComparisonExpression <- "(" ws ex:OrExpression ws ")" { return ex, nil } ComparisonExpression <- "(" ws ex:OrExpression ws ")" { return ex, nil }
/ left:SelectItem ws op:ComparisonOperator ws right:SelectItem { / left:SelectItem ws op:ComparisonOperator ws right:SelectItem {
return parsers.ComparisonExpression{Left:left,Right:right,Operation:op.(string)}, nil return parsers.ComparisonExpression{Left:left,Right:right,Operation:op.(string)}, nil
} / inv:(Not ws)? ex:SelectItem {
if inv != nil {
ex1 := ex.(parsers.SelectItem)
ex1.Invert = true
return ex1, nil
}
return ex, nil
} / ex:BooleanLiteral { return ex, nil } } / ex:BooleanLiteral { return ex, nil }
/ ex:SelectItem { return ex, nil }
OrderByClause <- OrderBy ws ex1:OrderExpression others:(ws "," ws ex:OrderExpression { return ex, nil })* { OrderByClause <- OrderBy ws ex1:OrderExpression others:(ws "," ws ex:OrderExpression { return ex, nil })* {
return makeOrderByClause(ex1, others) return makeOrderByClause(ex1, others)
@ -397,6 +403,8 @@ And <- "AND"i
Or <- "OR"i wss Or <- "OR"i wss
Not <- "NOT"i
GroupBy <- "GROUP"i ws "BY"i GroupBy <- "GROUP"i ws "BY"i
OrderBy <- "ORDER"i ws "BY"i OrderBy <- "ORDER"i ws "BY"i

View File

@ -148,4 +148,21 @@ func Test_Parse_Were(t *testing.T) {
}, },
) )
}) })
t.Run("Should correctly parse NOT conditions", func(t *testing.T) {
testQueryParse(
t,
`select c.id
FROM c
WHERE NOT c.boolean`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{{Path: []string{"c", "id"}, Alias: ""}},
Table: parsers.Table{SelectItem: testutils.SelectItem_Path("c")},
Filters: parsers.SelectItem{
Path: []string{"c", "boolean"},
Invert: true,
},
},
)
})
} }

View File

@ -192,6 +192,10 @@ func (r rowContext) applyFilters(filters interface{}) bool {
case parsers.SelectItem: case parsers.SelectItem:
resolvedValue := r.resolveSelectItem(typedFilters) resolvedValue := r.resolveSelectItem(typedFilters)
if value, ok := resolvedValue.(bool); ok { if value, ok := resolvedValue.(bool); ok {
if typedFilters.Invert {
return !value
}
return value return value
} }
} }

View File

@ -136,4 +136,22 @@ func Test_Execute_Where(t *testing.T) {
}, },
) )
}) })
t.Run("Should execute parse NOT conditions", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{{Path: []string{"c", "id"}, Alias: ""}},
Table: parsers.Table{SelectItem: testutils.SelectItem_Path("c")},
Filters: parsers.SelectItem{
Path: []string{"c", "isCool"},
Invert: true,
},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "12345"},
},
)
})
} }