From 90192268b8df1249f26ea89342a046561ff83c63 Mon Sep 17 00:00:00 2001 From: Wesley Robert Maffly-Kipp Date: Tue, 18 Jun 2024 14:42:05 -0700 Subject: [PATCH 1/5] first draft working solution, no pg support yet --- cmd/api/src/queries/graph.go | 2 ++ packages/go/cypher/backend/cypher/format.go | 7 +++++++ packages/go/cypher/frontend/expression.go | 9 ++++++++- packages/go/cypher/model/copy.go | 3 +++ packages/go/cypher/model/model.go | 16 ++++++++++++++++ packages/go/cypher/model/walk.go | 3 +++ 6 files changed, 39 insertions(+), 1 deletion(-) diff --git a/cmd/api/src/queries/graph.go b/cmd/api/src/queries/graph.go index 159d80ea9..60fc90f07 100644 --- a/cmd/api/src/queries/graph.go +++ b/cmd/api/src/queries/graph.go @@ -466,6 +466,8 @@ func (s *GraphQuery) RawCypherQuery(ctx context.Context, pQuery PreparedQuery, i bhCtxInst = bhCtx.Get(ctx) ) + fmt.Printf("HERE IS THE QUERY: %s", pQuery.query) + txDelegate := func(tx graph.Transaction) error { if pathSet, err := ops.FetchPathSetByQuery(tx, pQuery.query); err != nil { return err diff --git a/packages/go/cypher/backend/cypher/format.go b/packages/go/cypher/backend/cypher/format.go index 077328791..90db254b1 100644 --- a/packages/go/cypher/backend/cypher/format.go +++ b/packages/go/cypher/backend/cypher/format.go @@ -808,6 +808,13 @@ func (s Emitter) WriteExpression(writer io.Writer, expression model.Expression) return s.WriteExpression(writer, typedExpression.Right) + case *model.UnaryArithmeticExpression: + if _, err := io.WriteString(writer, typedExpression.Operator.String()); err != nil { + return err + } + + return s.WriteExpression(writer, typedExpression.Right) + default: return fmt.Errorf("unexpected expression type for string formatting: %T", expression) } diff --git a/packages/go/cypher/frontend/expression.go b/packages/go/cypher/frontend/expression.go index 179d3993a..04485cdd4 100644 --- a/packages/go/cypher/frontend/expression.go +++ b/packages/go/cypher/frontend/expression.go @@ -271,7 +271,14 @@ func (s *ArithmeticExpressionVisitor) EnterOC_UnaryAddOrSubtractExpression(ctx * } func (s *ArithmeticExpressionVisitor) ExitOC_UnaryAddOrSubtractExpression(ctx *parser.OC_UnaryAddOrSubtractExpressionContext) { - s.exitSubArithmeticExpression(ctx) + if operators := newTokenLiteralIterator(ctx); operators.HasTokens() { + s.Expression = &model.ArithmeticExpression{ + Left: &model.UnaryArithmeticExpression{ + Operator: operators.NextOperator(), + Right: s.ctx.Exit().(*ArithmeticExpressionVisitor).Expression, + }, + } + } } func (s *ArithmeticExpressionVisitor) EnterOC_NonArithmeticOperatorExpression(ctx *parser.OC_NonArithmeticOperatorExpressionContext) { diff --git a/packages/go/cypher/model/copy.go b/packages/go/cypher/model/copy.go index fd67f9032..377f56738 100644 --- a/packages/go/cypher/model/copy.go +++ b/packages/go/cypher/model/copy.go @@ -102,6 +102,9 @@ func Copy[T any](value T, extensions ...CopyExtension[T]) T { case *PartialArithmeticExpression: return any(typedValue.copy()).(T) + case *UnaryArithmeticExpression: + return any(typedValue.copy()).(T) + case *PartialComparison: return any(typedValue.copy()).(T) diff --git a/packages/go/cypher/model/model.go b/packages/go/cypher/model/model.go index cf26f58a7..cc92a395e 100644 --- a/packages/go/cypher/model/model.go +++ b/packages/go/cypher/model/model.go @@ -368,6 +368,22 @@ func (s *ArithmeticExpression) AddArithmeticExpressionPart(part *PartialArithmet s.Partials = append(s.Partials, part) } +type UnaryArithmeticExpression struct { + Operator Operator + Right Expression +} + +func NewUnaryArithmeticExpression() *UnaryArithmeticExpression { + return &UnaryArithmeticExpression{} +} + +func (s *UnaryArithmeticExpression) copy() *UnaryArithmeticExpression { + return &UnaryArithmeticExpression{ + Operator: s.Operator, + Right: Copy(s.Right), + } +} + type Match struct { Optional bool Pattern []*PatternPart diff --git a/packages/go/cypher/model/walk.go b/packages/go/cypher/model/walk.go index 9e8d69f92..533a7f7fd 100644 --- a/packages/go/cypher/model/walk.go +++ b/packages/go/cypher/model/walk.go @@ -267,6 +267,9 @@ func cypherModelCollect(nextCursor *WalkCursor, expression Expression) bool { case *PartialArithmeticExpression: CollectExpression(nextCursor, typedExpr.Right) + case *UnaryArithmeticExpression: + CollectExpression(nextCursor, typedExpr.Right) + case *Merge: Collect(nextCursor, typedExpr.PatternPart) CollectSlice(nextCursor, typedExpr.MergeActions) From b26596d421b8bf046ad1b34e09b0ef9f73eb6388 Mon Sep 17 00:00:00 2001 From: Wesley Robert Maffly-Kipp Date: Thu, 20 Jun 2024 07:57:46 -0700 Subject: [PATCH 2/5] small refactor --- packages/go/cypher/frontend/expression.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/go/cypher/frontend/expression.go b/packages/go/cypher/frontend/expression.go index 04485cdd4..c65371400 100644 --- a/packages/go/cypher/frontend/expression.go +++ b/packages/go/cypher/frontend/expression.go @@ -272,12 +272,10 @@ func (s *ArithmeticExpressionVisitor) EnterOC_UnaryAddOrSubtractExpression(ctx * func (s *ArithmeticExpressionVisitor) ExitOC_UnaryAddOrSubtractExpression(ctx *parser.OC_UnaryAddOrSubtractExpressionContext) { if operators := newTokenLiteralIterator(ctx); operators.HasTokens() { - s.Expression = &model.ArithmeticExpression{ - Left: &model.UnaryArithmeticExpression{ - Operator: operators.NextOperator(), - Right: s.ctx.Exit().(*ArithmeticExpressionVisitor).Expression, - }, - } + s.assignExpression(&model.UnaryArithmeticExpression{ + Operator: operators.NextOperator(), + Right: s.ctx.Exit().(*ArithmeticExpressionVisitor).Expression, + }) } } From 2e329dcfde8ee4193f76e9bab6cc47ebd7437f5c Mon Sep 17 00:00:00 2001 From: Wesley Robert Maffly-Kipp Date: Thu, 20 Jun 2024 15:48:19 -0700 Subject: [PATCH 3/5] add test cases, rename model to match antlr convention --- packages/go/cypher/backend/cypher/format.go | 2 +- packages/go/cypher/frontend/expression.go | 2 +- packages/go/cypher/model/copy.go | 2 +- packages/go/cypher/model/model.go | 10 +++++----- packages/go/cypher/model/walk.go | 2 +- .../go/cypher/test/cases/positive_tests.json | 18 +++++++++++++++++- 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/go/cypher/backend/cypher/format.go b/packages/go/cypher/backend/cypher/format.go index 90db254b1..6b084a2f8 100644 --- a/packages/go/cypher/backend/cypher/format.go +++ b/packages/go/cypher/backend/cypher/format.go @@ -808,7 +808,7 @@ func (s Emitter) WriteExpression(writer io.Writer, expression model.Expression) return s.WriteExpression(writer, typedExpression.Right) - case *model.UnaryArithmeticExpression: + case *model.UnaryAddOrSubtractExpression: if _, err := io.WriteString(writer, typedExpression.Operator.String()); err != nil { return err } diff --git a/packages/go/cypher/frontend/expression.go b/packages/go/cypher/frontend/expression.go index c65371400..267e05b5f 100644 --- a/packages/go/cypher/frontend/expression.go +++ b/packages/go/cypher/frontend/expression.go @@ -272,7 +272,7 @@ func (s *ArithmeticExpressionVisitor) EnterOC_UnaryAddOrSubtractExpression(ctx * func (s *ArithmeticExpressionVisitor) ExitOC_UnaryAddOrSubtractExpression(ctx *parser.OC_UnaryAddOrSubtractExpressionContext) { if operators := newTokenLiteralIterator(ctx); operators.HasTokens() { - s.assignExpression(&model.UnaryArithmeticExpression{ + s.assignExpression(&model.UnaryAddOrSubtractExpression{ Operator: operators.NextOperator(), Right: s.ctx.Exit().(*ArithmeticExpressionVisitor).Expression, }) diff --git a/packages/go/cypher/model/copy.go b/packages/go/cypher/model/copy.go index 377f56738..45f6c3811 100644 --- a/packages/go/cypher/model/copy.go +++ b/packages/go/cypher/model/copy.go @@ -102,7 +102,7 @@ func Copy[T any](value T, extensions ...CopyExtension[T]) T { case *PartialArithmeticExpression: return any(typedValue.copy()).(T) - case *UnaryArithmeticExpression: + case *UnaryAddOrSubtractExpression: return any(typedValue.copy()).(T) case *PartialComparison: diff --git a/packages/go/cypher/model/model.go b/packages/go/cypher/model/model.go index cc92a395e..a6bd72070 100644 --- a/packages/go/cypher/model/model.go +++ b/packages/go/cypher/model/model.go @@ -368,17 +368,17 @@ func (s *ArithmeticExpression) AddArithmeticExpressionPart(part *PartialArithmet s.Partials = append(s.Partials, part) } -type UnaryArithmeticExpression struct { +type UnaryAddOrSubtractExpression struct { Operator Operator Right Expression } -func NewUnaryArithmeticExpression() *UnaryArithmeticExpression { - return &UnaryArithmeticExpression{} +func NewUnaryArithmeticExpression() *UnaryAddOrSubtractExpression { + return &UnaryAddOrSubtractExpression{} } -func (s *UnaryArithmeticExpression) copy() *UnaryArithmeticExpression { - return &UnaryArithmeticExpression{ +func (s *UnaryAddOrSubtractExpression) copy() *UnaryAddOrSubtractExpression { + return &UnaryAddOrSubtractExpression{ Operator: s.Operator, Right: Copy(s.Right), } diff --git a/packages/go/cypher/model/walk.go b/packages/go/cypher/model/walk.go index 533a7f7fd..9344b7279 100644 --- a/packages/go/cypher/model/walk.go +++ b/packages/go/cypher/model/walk.go @@ -267,7 +267,7 @@ func cypherModelCollect(nextCursor *WalkCursor, expression Expression) bool { case *PartialArithmeticExpression: CollectExpression(nextCursor, typedExpr.Right) - case *UnaryArithmeticExpression: + case *UnaryAddOrSubtractExpression: CollectExpression(nextCursor, typedExpr.Right) case *Merge: diff --git a/packages/go/cypher/test/cases/positive_tests.json b/packages/go/cypher/test/cases/positive_tests.json index 6098e2b7f..5be620f78 100644 --- a/packages/go/cypher/test/cases/positive_tests.json +++ b/packages/go/cypher/test/cases/positive_tests.json @@ -793,6 +793,22 @@ "complexity": 1 } }, + { + "name": "Support unary operators in property match", + "type": "string_match", + "details": { + "query": "match (n:Product) where n.prop_1 = -1 return n", + "complexity": 2 + } + }, + { + "name": "Support complex arithmetic expressions with unary operators in property match", + "type": "string_match", + "details": { + "query": "match (n:Product) where n.prop_1 = -(1 + 2) * -3 return n", + "complexity": 2 + } + }, { "name": "Find Kerberoastable Users with most privileges", "type": "string_match", @@ -906,4 +922,4 @@ } } ] -} +} \ No newline at end of file From 3800db5403fefe3079512b8ac936302889ae696a Mon Sep 17 00:00:00 2001 From: Wesley Robert Maffly-Kipp Date: Thu, 20 Jun 2024 15:49:34 -0700 Subject: [PATCH 4/5] remove extra logging --- cmd/api/src/queries/graph.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/api/src/queries/graph.go b/cmd/api/src/queries/graph.go index 60fc90f07..159d80ea9 100644 --- a/cmd/api/src/queries/graph.go +++ b/cmd/api/src/queries/graph.go @@ -466,8 +466,6 @@ func (s *GraphQuery) RawCypherQuery(ctx context.Context, pQuery PreparedQuery, i bhCtxInst = bhCtx.Get(ctx) ) - fmt.Printf("HERE IS THE QUERY: %s", pQuery.query) - txDelegate := func(tx graph.Transaction) error { if pathSet, err := ops.FetchPathSetByQuery(tx, pQuery.query); err != nil { return err From b0991184106f7f8077bb1609ceb754e2d22487db Mon Sep 17 00:00:00 2001 From: Wesley Robert Maffly-Kipp Date: Fri, 21 Jun 2024 09:26:12 -0700 Subject: [PATCH 5/5] consistent naming --- packages/go/cypher/model/model.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/go/cypher/model/model.go b/packages/go/cypher/model/model.go index a6bd72070..bcf35a825 100644 --- a/packages/go/cypher/model/model.go +++ b/packages/go/cypher/model/model.go @@ -373,7 +373,7 @@ type UnaryAddOrSubtractExpression struct { Right Expression } -func NewUnaryArithmeticExpression() *UnaryAddOrSubtractExpression { +func NewUnaryAddOrSubtractExpression() *UnaryAddOrSubtractExpression { return &UnaryAddOrSubtractExpression{} }