diff --git a/ast/ast.go b/ast/ast.go index ad371744..e7d600d9 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -189,6 +189,7 @@ func (SubQueryTableExpr) isTableExpr() {} func (ParenTableExpr) isTableExpr() {} func (Join) isTableExpr() {} func (TVFCallExpr) isTableExpr() {} +func (GraphTableExpr) isTableExpr() {} // JoinCondition represents condition part of JOIN expression. type JoinCondition interface { @@ -4659,6 +4660,55 @@ func (GQLLimit) isGQLPrimitiveQueryStatement() {} func (GQLOffset) isGQLPrimitiveQueryStatement() {} func (BadGQLPrimitiveQueryStatement) isGQLPrimitiveQueryStatement() {} +// GraphTableQuery represents a query body in a GRAPH_TABLE operator. +type GraphTableQuery interface { + Node + isGraphTableQuery() +} + +func (GQLMultiLinearQueryStatement) isGraphTableQuery() {} +func (GraphTableMatch) isGraphTableQuery() {} + +// GraphTableExpr represents GRAPH_TABLE operator in SQL. +// +// GRAPH_TABLE({{.GraphName | sql}} {{.Query | sql}}) {{.As | sqlOpt}} {{.Sample | sqlOpt}} +type GraphTableExpr struct { + // pos = GraphTable + // end = (Sample ?? As).end || Rparen + 1 + + GraphTable token.Pos // position of "GRAPH_TABLE" + Rparen token.Pos // position of ")" + + GraphName *Path + Query GraphTableQuery + As *AsAlias // optional + Sample *TableSample // optional +} + +// GraphTableMatch represents the SQL/PGQ form of a GRAPH_TABLE query. +// +// {{.Match | sql}} {{.Columns | sqlOpt}} +type GraphTableMatch struct { + // pos = Match.pos + // end = (Columns ?? Match).end + + Match *GQLMatch + Columns *GraphTableColumns // optional +} + +// GraphTableColumns is a COLUMNS shape clause in a GRAPH_TABLE query. +// +// COLUMNS({{.Items | sqlJoin ", "}}) +type GraphTableColumns struct { + // pos = Columns + // end = Rparen + 1 + + Columns token.Pos // position of "COLUMNS" + Rparen token.Pos // position of ")" + + Items []SelectItem // len(Items) > 0 +} + // GQLGraphQuery is a top-level GQL query. // // {{.Hint | sqlOpt}} {{.GraphClause | sql}} {{.Query | sql}} diff --git a/ast/pos.go b/ast/pos.go index 64562d6e..172597e4 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -2334,6 +2334,30 @@ func (c *Call) End() token.Pos { return posAdd(c.Rparen, 1) } +func (g *GraphTableExpr) Pos() token.Pos { + return g.GraphTable +} + +func (g *GraphTableExpr) End() token.Pos { + return posChoice(nodeEnd(nodeChoice(wrapNode(g.Sample), wrapNode(g.As))), posAdd(g.Rparen, 1)) +} + +func (g *GraphTableMatch) Pos() token.Pos { + return nodePos(wrapNode(g.Match)) +} + +func (g *GraphTableMatch) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(g.Columns), wrapNode(g.Match))) +} + +func (g *GraphTableColumns) Pos() token.Pos { + return g.Columns +} + +func (g *GraphTableColumns) End() token.Pos { + return posAdd(g.Rparen, 1) +} + func (g *GQLGraphQuery) Pos() token.Pos { return nodePos(nodeChoice(wrapNode(g.Hint), wrapNode(g.GraphClause))) } diff --git a/ast/sql.go b/ast/sql.go index 9045f4a7..a154bea2 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -1540,6 +1540,18 @@ func (c *Call) SQL() string { // // ================================================================================ +func (n *GraphTableExpr) SQL() string { + return "GRAPH_TABLE(" + n.GraphName.SQL() + " " + n.Query.SQL() + ")" + sqlOpt(" ", n.As, "") + sqlOpt(" ", n.Sample, "") +} + +func (m *GraphTableMatch) SQL() string { + return m.Match.SQL() + sqlOpt(" ", m.Columns, "") +} + +func (c *GraphTableColumns) SQL() string { + return "COLUMNS(" + sqlJoin(c.Items, ", ") + ")" +} + func (q *GQLGraphQuery) SQL() string { return sqlOpt("", q.Hint, " ") + q.GraphClause.SQL() + " " + q.Query.SQL() } diff --git a/ast/walk_internal.go b/ast/walk_internal.go index 371b31a9..7b0f7265 100644 --- a/ast/walk_internal.go +++ b/ast/walk_internal.go @@ -1079,6 +1079,19 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem { stack = append(stack, &stackItem{nodes: wrapNodes(n.Args), visitor: v.Field("Args")}) stack = append(stack, &stackItem{node: wrapNode(n.Name), visitor: v.Field("Name")}) + case *GraphTableExpr: + stack = append(stack, &stackItem{node: wrapNode(n.Sample), visitor: v.Field("Sample")}) + stack = append(stack, &stackItem{node: wrapNode(n.As), visitor: v.Field("As")}) + stack = append(stack, &stackItem{node: wrapNode(n.Query), visitor: v.Field("Query")}) + stack = append(stack, &stackItem{node: wrapNode(n.GraphName), visitor: v.Field("GraphName")}) + + case *GraphTableMatch: + stack = append(stack, &stackItem{node: wrapNode(n.Columns), visitor: v.Field("Columns")}) + stack = append(stack, &stackItem{node: wrapNode(n.Match), visitor: v.Field("Match")}) + + case *GraphTableColumns: + stack = append(stack, &stackItem{nodes: wrapNodes(n.Items), visitor: v.Field("Items")}) + case *GQLGraphQuery: stack = append(stack, &stackItem{node: wrapNode(n.Query), visitor: v.Field("Query")}) stack = append(stack, &stackItem{node: wrapNode(n.GraphClause), visitor: v.Field("GraphClause")}) diff --git a/parser.go b/parser.go index 828a6290..6cc331e5 100644 --- a/parser.go +++ b/parser.go @@ -1210,6 +1210,22 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { return p.parseUnnestSuffix(expr, unnest, rparen) } + if p.Token.Kind == "GRAPH_TABLE" { + graphTable := p.expect("GRAPH_TABLE").Pos + p.expect("(") + graphName := p.parsePath() + query := p.parseGraphTableQuery() + rparen := p.expect(")").Pos + as := p.tryParseAsAlias(withOptionalAs) + return p.parseTableExprSuffix(&ast.GraphTableExpr{ + GraphTable: graphTable, + GraphName: graphName, + Query: query, + Rparen: rparen, + As: as, + }) + } + if p.Token.Kind == token.TokenIdent { ids := p.parseIdentOrPath() if p.Token.Kind == "(" { @@ -1221,7 +1237,52 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { return p.parsePathTableExprSuffix(&ast.Path{Idents: ids}) } - panic(p.errorfAtToken(&p.Token, "expected token: (, UNNEST, , but: %s", p.Token.Kind)) + panic(p.errorfAtToken(&p.Token, "expected token: (, UNNEST, GRAPH_TABLE, , but: %s", p.Token.Kind)) +} + +func (p *Parser) parseGraphTableQuery() ast.GraphTableQuery { + // A single MATCH followed by COLUMNS or the GRAPH_TABLE closing parenthesis + // is the SQL/PGQ form. Other MATCH forms are advanced GQL query blocks. + if p.lookaheadGraphTableMatch() { + return p.parseGraphTableMatch() + } + return p.parseGQLMultiLinearQueryStatement() +} + +func (p *Parser) lookaheadGraphTableMatch() bool { + if !p.Token.IsKeywordLike("MATCH") { + return false + } + + lexer := p.cloneLexer() + defer func() { p.Lexer = lexer }() + + p.parseGQLMatch() + return p.Token.IsKeywordLike("COLUMNS") || p.Token.Kind == ")" +} + +func (p *Parser) parseGraphTableMatch() *ast.GraphTableMatch { + match := p.parseGQLMatch() + var columns *ast.GraphTableColumns + if p.Token.IsKeywordLike("COLUMNS") { + columns = p.parseGraphTableColumns() + } + return &ast.GraphTableMatch{ + Match: match, + Columns: columns, + } +} + +func (p *Parser) parseGraphTableColumns() *ast.GraphTableColumns { + columns := p.expectKeywordLike("COLUMNS").Pos + p.expect("(") + items := parseCommaSeparatedList(p, p.parseSelectItem) + rparen := p.expect(")").Pos + return &ast.GraphTableColumns{ + Columns: columns, + Rparen: rparen, + Items: items, + } } func (p *Parser) parseTVFCallExpr(ids []*ast.Ident) *ast.TVFCallExpr { @@ -1395,6 +1456,8 @@ func (p *Parser) parseTableExprSuffix(join ast.TableExpr) ast.TableExpr { j.Sample = sample case *ast.ParenTableExpr: j.Sample = sample + case *ast.GraphTableExpr: + j.Sample = sample default: panic(fmt.Sprintf("BUG: unexpected join: %#v", join)) } diff --git a/testdata/input/query/!bad_graph_table_return_columns.sql b/testdata/input/query/!bad_graph_table_return_columns.sql new file mode 100644 index 00000000..8b583784 --- /dev/null +++ b/testdata/input/query/!bad_graph_table_return_columns.sql @@ -0,0 +1 @@ +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) diff --git a/testdata/input/query/graph_table_alias.sql b/testdata/input/query/graph_table_alias.sql new file mode 100644 index 00000000..5b1e3b28 --- /dev/null +++ b/testdata/input/query/graph_table_alias.sql @@ -0,0 +1 @@ +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) t diff --git a/testdata/input/query/graph_table_as_alias.sql b/testdata/input/query/graph_table_as_alias.sql new file mode 100644 index 00000000..862b33b6 --- /dev/null +++ b/testdata/input/query/graph_table_as_alias.sql @@ -0,0 +1 @@ +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS t TABLESAMPLE BERNOULLI (10 PERCENT) diff --git a/testdata/input/query/graph_table_join.sql b/testdata/input/query/graph_table_join.sql new file mode 100644 index 00000000..81eb3036 --- /dev/null +++ b/testdata/input/query/graph_table_join.sql @@ -0,0 +1,4 @@ +SELECT a.id, g.v +FROM Accounts AS a +JOIN GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS g +ON a.id = g.v diff --git a/testdata/input/query/graph_table_match_columns.sql b/testdata/input/query/graph_table_match_columns.sql new file mode 100644 index 00000000..2d5ee185 --- /dev/null +++ b/testdata/input/query/graph_table_match_columns.sql @@ -0,0 +1 @@ +SELECT name, number FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.name AS name, 1 AS number)) diff --git a/testdata/input/query/graph_table_match_columns_dot_star.sql b/testdata/input/query/graph_table_match_columns_dot_star.sql new file mode 100644 index 00000000..88cd7406 --- /dev/null +++ b/testdata/input/query/graph_table_match_columns_dot_star.sql @@ -0,0 +1 @@ +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.*, 1 AS number)) diff --git a/testdata/input/query/graph_table_match_no_columns.sql b/testdata/input/query/graph_table_match_no_columns.sql new file mode 100644 index 00000000..af6f0777 --- /dev/null +++ b/testdata/input/query/graph_table_match_no_columns.sql @@ -0,0 +1 @@ +SELECT n.id FROM GRAPH_TABLE (FinGraph MATCH (n:Person)) AS g diff --git a/testdata/input/query/graph_table_match_return.sql b/testdata/input/query/graph_table_match_return.sql new file mode 100644 index 00000000..8b41bcd9 --- /dev/null +++ b/testdata/input/query/graph_table_match_return.sql @@ -0,0 +1 @@ +SELECT id FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n.id AS id) diff --git a/testdata/input/query/graph_table_minimal.sql b/testdata/input/query/graph_table_minimal.sql new file mode 100644 index 00000000..6b7f5d22 --- /dev/null +++ b/testdata/input/query/graph_table_minimal.sql @@ -0,0 +1 @@ +SELECT * FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) diff --git a/testdata/input/query/graph_table_next.sql b/testdata/input/query/graph_table_next.sql new file mode 100644 index 00000000..34b56c73 --- /dev/null +++ b/testdata/input/query/graph_table_next.sql @@ -0,0 +1 @@ +SELECT * FROM GRAPH_TABLE (FinGraph LET a = 1 RETURN a AS x NEXT FILTER WHERE x > 0 RETURN x) AS t diff --git a/testdata/input/query/graph_table_qualified_graph.sql b/testdata/input/query/graph_table_qualified_graph.sql new file mode 100644 index 00000000..9b02f29c --- /dev/null +++ b/testdata/input/query/graph_table_qualified_graph.sql @@ -0,0 +1 @@ +SELECT * FROM GRAPH_TABLE (schema.FinGraph FILTER WHERE TRUE RETURN 1 AS v) AS t diff --git a/testdata/input/query/graph_table_tablesample.sql b/testdata/input/query/graph_table_tablesample.sql new file mode 100644 index 00000000..a8977f8a --- /dev/null +++ b/testdata/input/query/graph_table_tablesample.sql @@ -0,0 +1,6 @@ +SELECT * +FROM GRAPH_TABLE( + FinGraph + LET x = 1 + RETURN x AS v +) TABLESAMPLE BERNOULLI (10 PERCENT) diff --git a/testdata/result/query/!bad_graph_table_return_columns.sql.txt b/testdata/result/query/!bad_graph_table_return_columns.sql.txt new file mode 100644 index 00000000..6ec0f07f --- /dev/null +++ b/testdata/result/query/!bad_graph_table_return_columns.sql.txt @@ -0,0 +1,166 @@ +--- !bad_graph_table_return_columns.sql +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) + +--- Error +syntax error: testdata/input/query/!bad_graph_table_return_columns.sql:1:63: expected token: ), but: + 1| SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) + | ^~~~~~~ + + +--- AST +&ast.QueryStatement{ + Query: &ast.BadQueryExpr{ + BadNode: &ast.BadNode{ + NodeEnd: 77, + Tokens: []*token.Token{ + &token.Token{ + Kind: "SELECT", + Raw: "SELECT", + End: 6, + }, + &token.Token{ + Kind: "*", + Space: " ", + Raw: "*", + Pos: 7, + End: 8, + }, + &token.Token{ + Kind: "FROM", + Space: " ", + Raw: "FROM", + Pos: 9, + End: 13, + }, + &token.Token{ + Kind: "GRAPH_TABLE", + Space: " ", + Raw: "GRAPH_TABLE", + Pos: 14, + End: 25, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 26, + End: 27, + }, + &token.Token{ + Kind: "", + Raw: "FinGraph", + AsString: "FinGraph", + Pos: 27, + End: 35, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "MATCH", + AsString: "MATCH", + Pos: 36, + End: 41, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 42, + End: 43, + }, + &token.Token{ + Kind: "", + Raw: "n", + AsString: "n", + Pos: 43, + End: 44, + }, + &token.Token{ + Kind: ":", + Raw: ":", + Pos: 44, + End: 45, + }, + &token.Token{ + Kind: "", + Raw: "Person", + AsString: "Person", + Pos: 45, + End: 51, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 51, + End: 52, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "RETURN", + AsString: "RETURN", + Pos: 53, + End: 59, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "n", + AsString: "n", + Pos: 60, + End: 61, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "COLUMNS", + AsString: "COLUMNS", + Pos: 62, + End: 69, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 70, + End: 71, + }, + &token.Token{ + Kind: "", + Raw: "n", + AsString: "n", + Pos: 71, + End: 72, + }, + &token.Token{ + Kind: ".", + Raw: ".", + Pos: 72, + End: 73, + }, + &token.Token{ + Kind: "", + Raw: "id", + AsString: "id", + Pos: 73, + End: 75, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 75, + End: 76, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 76, + End: 77, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) diff --git a/testdata/result/query/graph_table_alias.sql.txt b/testdata/result/query/graph_table_alias.sql.txt new file mode 100644 index 00000000..084304ab --- /dev/null +++ b/testdata/result/query/graph_table_alias.sql.txt @@ -0,0 +1,100 @@ +--- graph_table_alias.sql +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "t", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 10, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 11, + Source: &ast.GraphTableExpr{ + GraphTable: 16, + Rparen: 61, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 38, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 42, + NameEnd: 43, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 46, + ValueEnd: 47, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 48, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 55, + NameEnd: 56, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: -1, + Alias: &ast.Ident{ + NamePos: 63, + NameEnd: 64, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT t.v FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) t diff --git a/testdata/result/query/graph_table_as_alias.sql.txt b/testdata/result/query/graph_table_as_alias.sql.txt new file mode 100644 index 00000000..3dcd8482 --- /dev/null +++ b/testdata/result/query/graph_table_as_alias.sql.txt @@ -0,0 +1,115 @@ +--- graph_table_as_alias.sql +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS t TABLESAMPLE BERNOULLI (10 PERCENT) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "t", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 10, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 11, + Source: &ast.GraphTableExpr{ + GraphTable: 16, + Rparen: 61, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 38, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 42, + NameEnd: 43, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 46, + ValueEnd: 47, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 48, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 55, + NameEnd: 56, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 63, + Alias: &ast.Ident{ + NamePos: 66, + NameEnd: 67, + Name: "t", + }, + }, + Sample: &ast.TableSample{ + TableSample: 68, + Method: "BERNOULLI", + Size: &ast.TableSampleSize{ + Lparen: 90, + Rparen: 101, + Value: &ast.IntLiteral{ + ValuePos: 91, + ValueEnd: 93, + Base: 10, + Value: "10", + }, + Unit: "PERCENT", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT t.v FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) AS t TABLESAMPLE BERNOULLI (10 PERCENT) diff --git a/testdata/result/query/graph_table_join.sql.txt b/testdata/result/query/graph_table_join.sql.txt new file mode 100644 index 00000000..fe98bc79 --- /dev/null +++ b/testdata/result/query/graph_table_join.sql.txt @@ -0,0 +1,171 @@ +--- graph_table_join.sql +SELECT a.id, g.v +FROM Accounts AS a +JOIN GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS g +ON a.id = g.v + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "a", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 11, + Name: "id", + }, + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 13, + NameEnd: 14, + Name: "g", + }, + &ast.Ident{ + NamePos: 15, + NameEnd: 16, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 17, + Source: &ast.Join{ + Left: &ast.TableName{ + Table: &ast.Ident{ + NamePos: 22, + NameEnd: 30, + Name: "Accounts", + }, + As: &ast.AsAlias{ + As: 31, + Alias: &ast.Ident{ + NamePos: 34, + NameEnd: 35, + Name: "a", + }, + }, + }, + Op: "INNER JOIN", + Right: &ast.GraphTableExpr{ + GraphTable: 41, + Rparen: 86, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 54, + NameEnd: 62, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 63, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 67, + NameEnd: 68, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 71, + ValueEnd: 72, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 73, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 80, + NameEnd: 81, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 82, + Alias: &ast.Ident{ + NamePos: 85, + NameEnd: 86, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 88, + Alias: &ast.Ident{ + NamePos: 91, + NameEnd: 92, + Name: "g", + }, + }, + }, + Cond: &ast.On{ + On: 93, + Expr: &ast.BinaryExpr{ + Op: "=", + Left: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 96, + NameEnd: 97, + Name: "a", + }, + &ast.Ident{ + NamePos: 98, + NameEnd: 100, + Name: "id", + }, + }, + }, + Right: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 103, + NameEnd: 104, + Name: "g", + }, + &ast.Ident{ + NamePos: 105, + NameEnd: 106, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT a.id, g.v FROM Accounts AS a INNER JOIN GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) AS g ON a.id = g.v diff --git a/testdata/result/query/graph_table_match_columns.sql.txt b/testdata/result/query/graph_table_match_columns.sql.txt new file mode 100644 index 00000000..a3cb0d17 --- /dev/null +++ b/testdata/result/query/graph_table_match_columns.sql.txt @@ -0,0 +1,130 @@ +--- graph_table_match_columns.sql +SELECT name, number FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.name AS name, 1 AS number)) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 7, + NameEnd: 11, + Name: "name", + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 13, + NameEnd: 19, + Name: "number", + }, + }, + }, + From: &ast.From{ + From: 20, + Source: &ast.GraphTableExpr{ + GraphTable: 25, + Rparen: 101, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 38, + NameEnd: 46, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 47, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 53, + Rparen: 62, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 54, + NameEnd: 55, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 55, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 56, + NameEnd: 62, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Columns: &ast.GraphTableColumns{ + Columns: 64, + Rparen: 100, + Items: []ast.SelectItem{ + &ast.Alias{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 73, + NameEnd: 74, + Name: "n", + }, + &ast.Ident{ + NamePos: 75, + NameEnd: 79, + Name: "name", + }, + }, + }, + As: &ast.AsAlias{ + As: 80, + Alias: &ast.Ident{ + NamePos: 83, + NameEnd: 87, + Name: "name", + }, + }, + }, + &ast.Alias{ + Expr: &ast.IntLiteral{ + ValuePos: 89, + ValueEnd: 90, + Base: 10, + Value: "1", + }, + As: &ast.AsAlias{ + As: 91, + Alias: &ast.Ident{ + NamePos: 94, + NameEnd: 100, + Name: "number", + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT name, number FROM GRAPH_TABLE(FinGraph MATCH (n:Person) COLUMNS(n.name AS name, 1 AS number)) diff --git a/testdata/result/query/graph_table_match_columns_dot_star.sql.txt b/testdata/result/query/graph_table_match_columns_dot_star.sql.txt new file mode 100644 index 00000000..5f9de522 --- /dev/null +++ b/testdata/result/query/graph_table_match_columns_dot_star.sql.txt @@ -0,0 +1,103 @@ +--- graph_table_match_columns_dot_star.sql +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.*, 1 AS number)) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 79, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 36, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 42, + Rparen: 51, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 43, + NameEnd: 44, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 44, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 45, + NameEnd: 51, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Columns: &ast.GraphTableColumns{ + Columns: 53, + Rparen: 78, + Items: []ast.SelectItem{ + &ast.DotStar{ + Star: 64, + Expr: &ast.Ident{ + NamePos: 62, + NameEnd: 63, + Name: "n", + }, + }, + &ast.Alias{ + Expr: &ast.IntLiteral{ + ValuePos: 67, + ValueEnd: 68, + Base: 10, + Value: "1", + }, + As: &ast.AsAlias{ + As: 69, + Alias: &ast.Ident{ + NamePos: 72, + NameEnd: 78, + Name: "number", + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph MATCH (n:Person) COLUMNS(n.*, 1 AS number)) diff --git a/testdata/result/query/graph_table_match_no_columns.sql.txt b/testdata/result/query/graph_table_match_no_columns.sql.txt new file mode 100644 index 00000000..61fe3bd8 --- /dev/null +++ b/testdata/result/query/graph_table_match_no_columns.sql.txt @@ -0,0 +1,94 @@ +--- graph_table_match_no_columns.sql +SELECT n.id FROM GRAPH_TABLE (FinGraph MATCH (n:Person)) AS g + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "n", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 11, + Name: "id", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 12, + Source: &ast.GraphTableExpr{ + GraphTable: 17, + Rparen: 55, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 30, + NameEnd: 38, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 39, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 45, + Rparen: 54, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 46, + NameEnd: 47, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 47, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 48, + NameEnd: 54, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "g", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT n.id FROM GRAPH_TABLE(FinGraph MATCH (n:Person)) AS g diff --git a/testdata/result/query/graph_table_match_return.sql.txt b/testdata/result/query/graph_table_match_return.sql.txt new file mode 100644 index 00000000..589f9ceb --- /dev/null +++ b/testdata/result/query/graph_table_match_return.sql.txt @@ -0,0 +1,113 @@ +--- graph_table_match_return.sql +SELECT id FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n.id AS id) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 7, + NameEnd: 9, + Name: "id", + }, + }, + }, + From: &ast.From{ + From: 10, + Source: &ast.GraphTableExpr{ + GraphTable: 15, + Rparen: 71, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 28, + NameEnd: 36, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLMatch{ + Optional: -1, + Match: 37, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 43, + Rparen: 52, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 44, + NameEnd: 45, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 45, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 46, + NameEnd: 52, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 54, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 61, + NameEnd: 62, + Name: "n", + }, + &ast.Ident{ + NamePos: 63, + NameEnd: 65, + Name: "id", + }, + }, + }, + Alias: &ast.AsAlias{ + As: 66, + Alias: &ast.Ident{ + NamePos: 69, + NameEnd: 71, + Name: "id", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT id FROM GRAPH_TABLE(FinGraph MATCH (n:Person) RETURN n.id AS id) diff --git a/testdata/result/query/graph_table_minimal.sql.txt b/testdata/result/query/graph_table_minimal.sql.txt new file mode 100644 index 00000000..7c32710c --- /dev/null +++ b/testdata/result/query/graph_table_minimal.sql.txt @@ -0,0 +1,79 @@ +--- graph_table_minimal.sql +SELECT * FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 59, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 36, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 40, + NameEnd: 41, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 44, + ValueEnd: 45, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 46, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 53, + NameEnd: 54, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 55, + Alias: &ast.Ident{ + NamePos: 58, + NameEnd: 59, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) diff --git a/testdata/result/query/graph_table_next.sql.txt b/testdata/result/query/graph_table_next.sql.txt new file mode 100644 index 00000000..780c43f0 --- /dev/null +++ b/testdata/result/query/graph_table_next.sql.txt @@ -0,0 +1,122 @@ +--- graph_table_next.sql +SELECT * FROM GRAPH_TABLE (FinGraph LET a = 1 RETURN a AS x NEXT FILTER WHERE x > 0 RETURN x) AS t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 92, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 36, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 40, + NameEnd: 41, + Name: "a", + }, + Expr: &ast.IntLiteral{ + ValuePos: 44, + ValueEnd: 45, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 46, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 53, + NameEnd: 54, + Name: "a", + }, + Alias: &ast.AsAlias{ + As: 55, + Alias: &ast.Ident{ + NamePos: 58, + NameEnd: 59, + Name: "x", + }, + }, + }, + }, + }, + }, + }, + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLFilter{ + Filter: 65, + Where: 72, + Expr: &ast.BinaryExpr{ + Op: ">", + Left: &ast.Ident{ + NamePos: 78, + NameEnd: 79, + Name: "x", + }, + Right: &ast.IntLiteral{ + ValuePos: 82, + ValueEnd: 83, + Base: 10, + Value: "0", + }, + }, + }, + &ast.GQLReturn{ + Return: 84, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 91, + NameEnd: 92, + Name: "x", + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 94, + Alias: &ast.Ident{ + NamePos: 97, + NameEnd: 98, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET a = 1 RETURN a AS x NEXT FILTER WHERE x > 0 RETURN x) AS t diff --git a/testdata/result/query/graph_table_qualified_graph.sql.txt b/testdata/result/query/graph_table_qualified_graph.sql.txt new file mode 100644 index 00000000..a605ff56 --- /dev/null +++ b/testdata/result/query/graph_table_qualified_graph.sql.txt @@ -0,0 +1,83 @@ +--- graph_table_qualified_graph.sql +SELECT * FROM GRAPH_TABLE (schema.FinGraph FILTER WHERE TRUE RETURN 1 AS v) AS t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 74, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 33, + Name: "schema", + }, + &ast.Ident{ + NamePos: 34, + NameEnd: 42, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLFilter{ + Filter: 43, + Where: 50, + Expr: &ast.BoolLiteral{ + ValuePos: 56, + Value: true, + }, + }, + &ast.GQLReturn{ + Return: 61, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.IntLiteral{ + ValuePos: 68, + ValueEnd: 69, + Base: 10, + Value: "1", + }, + Alias: &ast.AsAlias{ + As: 70, + Alias: &ast.Ident{ + NamePos: 73, + NameEnd: 74, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 76, + Alias: &ast.Ident{ + NamePos: 79, + NameEnd: 80, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(schema.FinGraph FILTER WHERE TRUE RETURN 1 AS v) AS t diff --git a/testdata/result/query/graph_table_tablesample.sql.txt b/testdata/result/query/graph_table_tablesample.sql.txt new file mode 100644 index 00000000..ccdcf3fb --- /dev/null +++ b/testdata/result/query/graph_table_tablesample.sql.txt @@ -0,0 +1,99 @@ +--- graph_table_tablesample.sql +SELECT * +FROM GRAPH_TABLE( + FinGraph + LET x = 1 + RETURN x AS v +) TABLESAMPLE BERNOULLI (10 PERCENT) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 66, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 40, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 44, + NameEnd: 45, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 48, + ValueEnd: 49, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 52, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 59, + NameEnd: 60, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 61, + Alias: &ast.Ident{ + NamePos: 64, + NameEnd: 65, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + Sample: &ast.TableSample{ + TableSample: 68, + Method: "BERNOULLI", + Size: &ast.TableSampleSize{ + Lparen: 90, + Rparen: 101, + Value: &ast.IntLiteral{ + ValuePos: 91, + ValueEnd: 93, + Base: 10, + Value: "10", + }, + Unit: "PERCENT", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) TABLESAMPLE BERNOULLI (10 PERCENT) diff --git a/testdata/result/statement/!bad_graph_table_return_columns.sql.txt b/testdata/result/statement/!bad_graph_table_return_columns.sql.txt new file mode 100644 index 00000000..6ec0f07f --- /dev/null +++ b/testdata/result/statement/!bad_graph_table_return_columns.sql.txt @@ -0,0 +1,166 @@ +--- !bad_graph_table_return_columns.sql +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) + +--- Error +syntax error: testdata/input/query/!bad_graph_table_return_columns.sql:1:63: expected token: ), but: + 1| SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) + | ^~~~~~~ + + +--- AST +&ast.QueryStatement{ + Query: &ast.BadQueryExpr{ + BadNode: &ast.BadNode{ + NodeEnd: 77, + Tokens: []*token.Token{ + &token.Token{ + Kind: "SELECT", + Raw: "SELECT", + End: 6, + }, + &token.Token{ + Kind: "*", + Space: " ", + Raw: "*", + Pos: 7, + End: 8, + }, + &token.Token{ + Kind: "FROM", + Space: " ", + Raw: "FROM", + Pos: 9, + End: 13, + }, + &token.Token{ + Kind: "GRAPH_TABLE", + Space: " ", + Raw: "GRAPH_TABLE", + Pos: 14, + End: 25, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 26, + End: 27, + }, + &token.Token{ + Kind: "", + Raw: "FinGraph", + AsString: "FinGraph", + Pos: 27, + End: 35, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "MATCH", + AsString: "MATCH", + Pos: 36, + End: 41, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 42, + End: 43, + }, + &token.Token{ + Kind: "", + Raw: "n", + AsString: "n", + Pos: 43, + End: 44, + }, + &token.Token{ + Kind: ":", + Raw: ":", + Pos: 44, + End: 45, + }, + &token.Token{ + Kind: "", + Raw: "Person", + AsString: "Person", + Pos: 45, + End: 51, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 51, + End: 52, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "RETURN", + AsString: "RETURN", + Pos: 53, + End: 59, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "n", + AsString: "n", + Pos: 60, + End: 61, + }, + &token.Token{ + Kind: "", + Space: " ", + Raw: "COLUMNS", + AsString: "COLUMNS", + Pos: 62, + End: 69, + }, + &token.Token{ + Kind: "(", + Space: " ", + Raw: "(", + Pos: 70, + End: 71, + }, + &token.Token{ + Kind: "", + Raw: "n", + AsString: "n", + Pos: 71, + End: 72, + }, + &token.Token{ + Kind: ".", + Raw: ".", + Pos: 72, + End: 73, + }, + &token.Token{ + Kind: "", + Raw: "id", + AsString: "id", + Pos: 73, + End: 75, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 75, + End: 76, + }, + &token.Token{ + Kind: ")", + Raw: ")", + Pos: 76, + End: 77, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n COLUMNS (n.id)) diff --git a/testdata/result/statement/graph_table_alias.sql.txt b/testdata/result/statement/graph_table_alias.sql.txt new file mode 100644 index 00000000..084304ab --- /dev/null +++ b/testdata/result/statement/graph_table_alias.sql.txt @@ -0,0 +1,100 @@ +--- graph_table_alias.sql +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "t", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 10, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 11, + Source: &ast.GraphTableExpr{ + GraphTable: 16, + Rparen: 61, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 38, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 42, + NameEnd: 43, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 46, + ValueEnd: 47, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 48, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 55, + NameEnd: 56, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: -1, + Alias: &ast.Ident{ + NamePos: 63, + NameEnd: 64, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT t.v FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) t diff --git a/testdata/result/statement/graph_table_as_alias.sql.txt b/testdata/result/statement/graph_table_as_alias.sql.txt new file mode 100644 index 00000000..3dcd8482 --- /dev/null +++ b/testdata/result/statement/graph_table_as_alias.sql.txt @@ -0,0 +1,115 @@ +--- graph_table_as_alias.sql +SELECT t.v FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS t TABLESAMPLE BERNOULLI (10 PERCENT) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "t", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 10, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 11, + Source: &ast.GraphTableExpr{ + GraphTable: 16, + Rparen: 61, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 38, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 42, + NameEnd: 43, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 46, + ValueEnd: 47, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 48, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 55, + NameEnd: 56, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 63, + Alias: &ast.Ident{ + NamePos: 66, + NameEnd: 67, + Name: "t", + }, + }, + Sample: &ast.TableSample{ + TableSample: 68, + Method: "BERNOULLI", + Size: &ast.TableSampleSize{ + Lparen: 90, + Rparen: 101, + Value: &ast.IntLiteral{ + ValuePos: 91, + ValueEnd: 93, + Base: 10, + Value: "10", + }, + Unit: "PERCENT", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT t.v FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) AS t TABLESAMPLE BERNOULLI (10 PERCENT) diff --git a/testdata/result/statement/graph_table_join.sql.txt b/testdata/result/statement/graph_table_join.sql.txt new file mode 100644 index 00000000..fe98bc79 --- /dev/null +++ b/testdata/result/statement/graph_table_join.sql.txt @@ -0,0 +1,171 @@ +--- graph_table_join.sql +SELECT a.id, g.v +FROM Accounts AS a +JOIN GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) AS g +ON a.id = g.v + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "a", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 11, + Name: "id", + }, + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 13, + NameEnd: 14, + Name: "g", + }, + &ast.Ident{ + NamePos: 15, + NameEnd: 16, + Name: "v", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 17, + Source: &ast.Join{ + Left: &ast.TableName{ + Table: &ast.Ident{ + NamePos: 22, + NameEnd: 30, + Name: "Accounts", + }, + As: &ast.AsAlias{ + As: 31, + Alias: &ast.Ident{ + NamePos: 34, + NameEnd: 35, + Name: "a", + }, + }, + }, + Op: "INNER JOIN", + Right: &ast.GraphTableExpr{ + GraphTable: 41, + Rparen: 86, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 54, + NameEnd: 62, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 63, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 67, + NameEnd: 68, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 71, + ValueEnd: 72, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 73, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 80, + NameEnd: 81, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 82, + Alias: &ast.Ident{ + NamePos: 85, + NameEnd: 86, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 88, + Alias: &ast.Ident{ + NamePos: 91, + NameEnd: 92, + Name: "g", + }, + }, + }, + Cond: &ast.On{ + On: 93, + Expr: &ast.BinaryExpr{ + Op: "=", + Left: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 96, + NameEnd: 97, + Name: "a", + }, + &ast.Ident{ + NamePos: 98, + NameEnd: 100, + Name: "id", + }, + }, + }, + Right: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 103, + NameEnd: 104, + Name: "g", + }, + &ast.Ident{ + NamePos: 105, + NameEnd: 106, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT a.id, g.v FROM Accounts AS a INNER JOIN GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) AS g ON a.id = g.v diff --git a/testdata/result/statement/graph_table_match_columns.sql.txt b/testdata/result/statement/graph_table_match_columns.sql.txt new file mode 100644 index 00000000..a3cb0d17 --- /dev/null +++ b/testdata/result/statement/graph_table_match_columns.sql.txt @@ -0,0 +1,130 @@ +--- graph_table_match_columns.sql +SELECT name, number FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.name AS name, 1 AS number)) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 7, + NameEnd: 11, + Name: "name", + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 13, + NameEnd: 19, + Name: "number", + }, + }, + }, + From: &ast.From{ + From: 20, + Source: &ast.GraphTableExpr{ + GraphTable: 25, + Rparen: 101, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 38, + NameEnd: 46, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 47, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 53, + Rparen: 62, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 54, + NameEnd: 55, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 55, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 56, + NameEnd: 62, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Columns: &ast.GraphTableColumns{ + Columns: 64, + Rparen: 100, + Items: []ast.SelectItem{ + &ast.Alias{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 73, + NameEnd: 74, + Name: "n", + }, + &ast.Ident{ + NamePos: 75, + NameEnd: 79, + Name: "name", + }, + }, + }, + As: &ast.AsAlias{ + As: 80, + Alias: &ast.Ident{ + NamePos: 83, + NameEnd: 87, + Name: "name", + }, + }, + }, + &ast.Alias{ + Expr: &ast.IntLiteral{ + ValuePos: 89, + ValueEnd: 90, + Base: 10, + Value: "1", + }, + As: &ast.AsAlias{ + As: 91, + Alias: &ast.Ident{ + NamePos: 94, + NameEnd: 100, + Name: "number", + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT name, number FROM GRAPH_TABLE(FinGraph MATCH (n:Person) COLUMNS(n.name AS name, 1 AS number)) diff --git a/testdata/result/statement/graph_table_match_columns_dot_star.sql.txt b/testdata/result/statement/graph_table_match_columns_dot_star.sql.txt new file mode 100644 index 00000000..5f9de522 --- /dev/null +++ b/testdata/result/statement/graph_table_match_columns_dot_star.sql.txt @@ -0,0 +1,103 @@ +--- graph_table_match_columns_dot_star.sql +SELECT * FROM GRAPH_TABLE (FinGraph MATCH (n:Person) COLUMNS (n.*, 1 AS number)) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 79, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 36, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 42, + Rparen: 51, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 43, + NameEnd: 44, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 44, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 45, + NameEnd: 51, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Columns: &ast.GraphTableColumns{ + Columns: 53, + Rparen: 78, + Items: []ast.SelectItem{ + &ast.DotStar{ + Star: 64, + Expr: &ast.Ident{ + NamePos: 62, + NameEnd: 63, + Name: "n", + }, + }, + &ast.Alias{ + Expr: &ast.IntLiteral{ + ValuePos: 67, + ValueEnd: 68, + Base: 10, + Value: "1", + }, + As: &ast.AsAlias{ + As: 69, + Alias: &ast.Ident{ + NamePos: 72, + NameEnd: 78, + Name: "number", + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph MATCH (n:Person) COLUMNS(n.*, 1 AS number)) diff --git a/testdata/result/statement/graph_table_match_no_columns.sql.txt b/testdata/result/statement/graph_table_match_no_columns.sql.txt new file mode 100644 index 00000000..61fe3bd8 --- /dev/null +++ b/testdata/result/statement/graph_table_match_no_columns.sql.txt @@ -0,0 +1,94 @@ +--- graph_table_match_no_columns.sql +SELECT n.id FROM GRAPH_TABLE (FinGraph MATCH (n:Person)) AS g + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 7, + NameEnd: 8, + Name: "n", + }, + &ast.Ident{ + NamePos: 9, + NameEnd: 11, + Name: "id", + }, + }, + }, + }, + }, + From: &ast.From{ + From: 12, + Source: &ast.GraphTableExpr{ + GraphTable: 17, + Rparen: 55, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 30, + NameEnd: 38, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GraphTableMatch{ + Match: &ast.GQLMatch{ + Optional: -1, + Match: 39, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 45, + Rparen: 54, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 46, + NameEnd: 47, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 47, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 48, + NameEnd: 54, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 57, + Alias: &ast.Ident{ + NamePos: 60, + NameEnd: 61, + Name: "g", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT n.id FROM GRAPH_TABLE(FinGraph MATCH (n:Person)) AS g diff --git a/testdata/result/statement/graph_table_match_return.sql.txt b/testdata/result/statement/graph_table_match_return.sql.txt new file mode 100644 index 00000000..589f9ceb --- /dev/null +++ b/testdata/result/statement/graph_table_match_return.sql.txt @@ -0,0 +1,113 @@ +--- graph_table_match_return.sql +SELECT id FROM GRAPH_TABLE (FinGraph MATCH (n:Person) RETURN n.id AS id) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 7, + NameEnd: 9, + Name: "id", + }, + }, + }, + From: &ast.From{ + From: 10, + Source: &ast.GraphTableExpr{ + GraphTable: 15, + Rparen: 71, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 28, + NameEnd: 36, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLMatch{ + Optional: -1, + Match: 37, + Pattern: &ast.GQLGraphPattern{ + Paths: []*ast.GQLTopLevelPathPattern{ + &ast.GQLTopLevelPathPattern{ + Path: &ast.GQLPathPattern{ + Terms: []*ast.GQLPathTerm{ + &ast.GQLPathTerm{ + Primary: &ast.GQLNodePattern{ + Lparen: 43, + Rparen: 52, + Pattern: &ast.GQLElementPatternFiller{ + EmptyPos: -1, + Variable: &ast.Ident{ + NamePos: 44, + NameEnd: 45, + Name: "n", + }, + Label: &ast.GQLLabelFilter{ + Is: -1, + Colon: 45, + Expr: &ast.GQLNameLabel{ + Name: &ast.Ident{ + NamePos: 46, + NameEnd: 52, + Name: "Person", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 54, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 61, + NameEnd: 62, + Name: "n", + }, + &ast.Ident{ + NamePos: 63, + NameEnd: 65, + Name: "id", + }, + }, + }, + Alias: &ast.AsAlias{ + As: 66, + Alias: &ast.Ident{ + NamePos: 69, + NameEnd: 71, + Name: "id", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT id FROM GRAPH_TABLE(FinGraph MATCH (n:Person) RETURN n.id AS id) diff --git a/testdata/result/statement/graph_table_minimal.sql.txt b/testdata/result/statement/graph_table_minimal.sql.txt new file mode 100644 index 00000000..7c32710c --- /dev/null +++ b/testdata/result/statement/graph_table_minimal.sql.txt @@ -0,0 +1,79 @@ +--- graph_table_minimal.sql +SELECT * FROM GRAPH_TABLE (FinGraph LET x = 1 RETURN x AS v) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 59, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 36, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 40, + NameEnd: 41, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 44, + ValueEnd: 45, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 46, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 53, + NameEnd: 54, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 55, + Alias: &ast.Ident{ + NamePos: 58, + NameEnd: 59, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) diff --git a/testdata/result/statement/graph_table_next.sql.txt b/testdata/result/statement/graph_table_next.sql.txt new file mode 100644 index 00000000..780c43f0 --- /dev/null +++ b/testdata/result/statement/graph_table_next.sql.txt @@ -0,0 +1,122 @@ +--- graph_table_next.sql +SELECT * FROM GRAPH_TABLE (FinGraph LET a = 1 RETURN a AS x NEXT FILTER WHERE x > 0 RETURN x) AS t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 92, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 35, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 36, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 40, + NameEnd: 41, + Name: "a", + }, + Expr: &ast.IntLiteral{ + ValuePos: 44, + ValueEnd: 45, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 46, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 53, + NameEnd: 54, + Name: "a", + }, + Alias: &ast.AsAlias{ + As: 55, + Alias: &ast.Ident{ + NamePos: 58, + NameEnd: 59, + Name: "x", + }, + }, + }, + }, + }, + }, + }, + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLFilter{ + Filter: 65, + Where: 72, + Expr: &ast.BinaryExpr{ + Op: ">", + Left: &ast.Ident{ + NamePos: 78, + NameEnd: 79, + Name: "x", + }, + Right: &ast.IntLiteral{ + ValuePos: 82, + ValueEnd: 83, + Base: 10, + Value: "0", + }, + }, + }, + &ast.GQLReturn{ + Return: 84, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 91, + NameEnd: 92, + Name: "x", + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 94, + Alias: &ast.Ident{ + NamePos: 97, + NameEnd: 98, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET a = 1 RETURN a AS x NEXT FILTER WHERE x > 0 RETURN x) AS t diff --git a/testdata/result/statement/graph_table_qualified_graph.sql.txt b/testdata/result/statement/graph_table_qualified_graph.sql.txt new file mode 100644 index 00000000..a605ff56 --- /dev/null +++ b/testdata/result/statement/graph_table_qualified_graph.sql.txt @@ -0,0 +1,83 @@ +--- graph_table_qualified_graph.sql +SELECT * FROM GRAPH_TABLE (schema.FinGraph FILTER WHERE TRUE RETURN 1 AS v) AS t + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 74, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 27, + NameEnd: 33, + Name: "schema", + }, + &ast.Ident{ + NamePos: 34, + NameEnd: 42, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLFilter{ + Filter: 43, + Where: 50, + Expr: &ast.BoolLiteral{ + ValuePos: 56, + Value: true, + }, + }, + &ast.GQLReturn{ + Return: 61, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.IntLiteral{ + ValuePos: 68, + ValueEnd: 69, + Base: 10, + Value: "1", + }, + Alias: &ast.AsAlias{ + As: 70, + Alias: &ast.Ident{ + NamePos: 73, + NameEnd: 74, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + As: &ast.AsAlias{ + As: 76, + Alias: &ast.Ident{ + NamePos: 79, + NameEnd: 80, + Name: "t", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(schema.FinGraph FILTER WHERE TRUE RETURN 1 AS v) AS t diff --git a/testdata/result/statement/graph_table_tablesample.sql.txt b/testdata/result/statement/graph_table_tablesample.sql.txt new file mode 100644 index 00000000..ccdcf3fb --- /dev/null +++ b/testdata/result/statement/graph_table_tablesample.sql.txt @@ -0,0 +1,99 @@ +--- graph_table_tablesample.sql +SELECT * +FROM GRAPH_TABLE( + FinGraph + LET x = 1 + RETURN x AS v +) TABLESAMPLE BERNOULLI (10 PERCENT) + +--- AST +&ast.QueryStatement{ + Query: &ast.Select{ + Results: []ast.SelectItem{ + &ast.Star{ + Star: 7, + }, + }, + From: &ast.From{ + From: 9, + Source: &ast.GraphTableExpr{ + GraphTable: 14, + Rparen: 66, + GraphName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 29, + NameEnd: 37, + Name: "FinGraph", + }, + }, + }, + Query: &ast.GQLMultiLinearQueryStatement{ + Statements: []ast.GQLLinearQueryStatement{ + &ast.GQLSimpleLinearQueryStatement{ + Statements: []ast.GQLPrimitiveQueryStatement{ + &ast.GQLLet{ + Let: 40, + Items: []*ast.GQLLetItem{ + &ast.GQLLetItem{ + Ident: &ast.Ident{ + NamePos: 44, + NameEnd: 45, + Name: "x", + }, + Expr: &ast.IntLiteral{ + ValuePos: 48, + ValueEnd: 49, + Base: 10, + Value: "1", + }, + }, + }, + }, + &ast.GQLReturn{ + Return: 52, + Items: []*ast.GQLReturnItem{ + &ast.GQLReturnItem{ + Star: -1, + Expr: &ast.Ident{ + NamePos: 59, + NameEnd: 60, + Name: "x", + }, + Alias: &ast.AsAlias{ + As: 61, + Alias: &ast.Ident{ + NamePos: 64, + NameEnd: 65, + Name: "v", + }, + }, + }, + }, + }, + }, + }, + }, + }, + Sample: &ast.TableSample{ + TableSample: 68, + Method: "BERNOULLI", + Size: &ast.TableSampleSize{ + Lparen: 90, + Rparen: 101, + Value: &ast.IntLiteral{ + ValuePos: 91, + ValueEnd: 93, + Base: 10, + Value: "10", + }, + Unit: "PERCENT", + }, + }, + }, + }, + }, +} + +--- SQL +SELECT * FROM GRAPH_TABLE(FinGraph LET x = 1 RETURN x AS v) TABLESAMPLE BERNOULLI (10 PERCENT)