github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/compiler/macro_expansion_test.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package compiler 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/vescale/zgraph/parser" 22 "github.com/vescale/zgraph/parser/ast" 23 "github.com/vescale/zgraph/parser/opcode" 24 ) 25 26 func TestMacroExpansion(t *testing.T) { 27 assert := assert.New(t) 28 29 cases := []struct { 30 query string 31 check func(node ast.Node) 32 }{ 33 { 34 query: `PATH has_parent AS () -[:has_father|has_mother]-> (:Person) 35 SELECT ancestor.name 36 FROM MATCH (p1:Person) -/:has_parent+/-> (ancestor) 37 , MATCH (p2:Person) -/:has_parent+/-> (ancestor) 38 WHERE p1.name = 'Mario' 39 AND p2.name = 'Luigi'`, 40 check: func(node ast.Node) { 41 stmt := node.(*ast.SelectStmt) 42 assert.Equal(1, len(stmt.PathPatternMacros)) 43 expr := stmt.From.Matches[0].Paths[0].Connections[0].(*ast.ReachabilityPathExpr) 44 assert.Equal(expr.Macros["has_parent"], stmt.PathPatternMacros[0].Path) 45 }, 46 }, 47 { 48 query: `PATH connects_to AS (:Generator) -[:has_connector]-> (c:Connector) <-[:has_connector]- (:Generator) 49 WHERE c.status = 'OPERATIONAL' 50 SELECT generatorA.location, generatorB.location 51 FROM MATCH (generatorA) -/:connects_to+/-> (generatorB)`, 52 check: func(node ast.Node) { 53 stmt := node.(*ast.SelectStmt) 54 assert.Equal(1, len(stmt.PathPatternMacros)) 55 expr := stmt.From.Matches[0].Paths[0].Connections[0].(*ast.ReachabilityPathExpr) 56 assert.Equal(expr.Macros["connects_to"], stmt.PathPatternMacros[0].Path) 57 assert.NotNil(stmt.Where) 58 }, 59 }, 60 { 61 query: `PATH connects_to AS (:Generator) -[:has_connector]-> (c:Connector) <-[:has_connector]- (:Generator) 62 WHERE c.status = 'OPERATIONAL' 63 PATH has_parent AS () -[:has_father|has_mother]-> (:Person) 64 SELECT generatorA.location, generatorB.location 65 FROM MATCH (generatorA) -/:connects_to|has_parent+/-> (generatorB)`, 66 check: func(node ast.Node) { 67 stmt := node.(*ast.SelectStmt) 68 assert.Equal(2, len(stmt.PathPatternMacros)) 69 expr := stmt.From.Matches[0].Paths[0].Connections[0].(*ast.ReachabilityPathExpr) 70 assert.Equal(expr.Macros["connects_to"], stmt.PathPatternMacros[0].Path) 71 assert.Equal(expr.Macros["has_parent"], stmt.PathPatternMacros[1].Path) 72 assert.NotNil(stmt.Where) 73 }, 74 }, 75 { 76 query: `PATH connects_to AS (:Generator) -[:has_connector]-> (c:Connector) <-[:has_connector]- (:Generator) 77 WHERE c.status = 'OPERATIONAL' 78 PATH has_parent AS () -[f:has_father|has_mother]-> (:Person) 79 WHERE f.age > 30 80 SELECT generatorA.location, generatorB.location 81 FROM MATCH (generatorA) -/:connects_to|has_parent+/-> (generatorB)`, 82 check: func(node ast.Node) { 83 stmt := node.(*ast.SelectStmt) 84 assert.Equal(2, len(stmt.PathPatternMacros)) 85 expr := stmt.From.Matches[0].Paths[0].Connections[0].(*ast.ReachabilityPathExpr) 86 assert.Equal(expr.Macros["connects_to"], stmt.PathPatternMacros[0].Path) 87 assert.Equal(expr.Macros["has_parent"], stmt.PathPatternMacros[1].Path) 88 assert.NotNil(stmt.Where) 89 logicalAnd := stmt.Where.(*ast.BinaryExpr) 90 assert.Equal(opcode.LogicAnd, logicalAnd.Op) 91 }, 92 }, 93 { 94 query: `PATH connects_to AS (:Generator) -[:has_connector]-> (c:Connector) <-[:has_connector]- (:Generator) 95 WHERE c.status = 'OPERATIONAL' 96 PATH has_parent AS () -[f:has_father|has_mother]-> (:Person) 97 WHERE f.age > 30 98 SELECT generatorA.location, generatorB.location 99 FROM MATCH (generatorA) -/:connects_to|has_parent+/-> (generatorB) 100 WHERE a > 10`, 101 check: func(node ast.Node) { 102 stmt := node.(*ast.SelectStmt) 103 assert.Equal(2, len(stmt.PathPatternMacros)) 104 expr := stmt.From.Matches[0].Paths[0].Connections[0].(*ast.ReachabilityPathExpr) 105 assert.Equal(expr.Macros["connects_to"], stmt.PathPatternMacros[0].Path) 106 assert.Equal(expr.Macros["has_parent"], stmt.PathPatternMacros[1].Path) 107 assert.NotNil(stmt.Where) 108 logicalAnd := stmt.Where.(*ast.BinaryExpr) 109 assert.Equal(opcode.LogicAnd, logicalAnd.Op) 110 logicalEq := logicalAnd.L.(*ast.BinaryExpr) 111 assert.Equal(opcode.GT, logicalEq.Op) // a > 10 112 logicalAnd = logicalAnd.R.(*ast.BinaryExpr) 113 assert.Equal(opcode.LogicAnd, logicalAnd.Op) 114 }, 115 }, 116 } 117 118 for _, c := range cases { 119 parser := parser.New() 120 stmt, err := parser.ParseOneStmt(c.query) 121 assert.Nil(err) 122 123 exp := NewMacroExpansion() 124 n, ok := stmt.Accept(exp) 125 assert.True(ok) 126 c.check(n) 127 } 128 }