diff --git a/ast/ast.go b/ast/ast.go index 5708a22a..2bac23cd 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -71,51 +71,53 @@ type Statement interface { // - https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language // - https://cloud.google.com/spanner/docs/reference/standard-sql/dml-syntax -func (BadStatement) isStatement() {} -func (BadDDL) isStatement() {} -func (BadDML) isStatement() {} -func (QueryStatement) isStatement() {} -func (CreateSchema) isStatement() {} -func (DropSchema) isStatement() {} -func (CreateDatabase) isStatement() {} -func (AlterDatabase) isStatement() {} -func (CreatePlacement) isStatement() {} -func (CreateProtoBundle) isStatement() {} -func (AlterProtoBundle) isStatement() {} -func (DropProtoBundle) isStatement() {} -func (CreateTable) isStatement() {} -func (AlterTable) isStatement() {} -func (DropTable) isStatement() {} -func (RenameTable) isStatement() {} -func (CreateIndex) isStatement() {} -func (AlterIndex) isStatement() {} -func (DropIndex) isStatement() {} -func (CreateSearchIndex) isStatement() {} -func (DropSearchIndex) isStatement() {} -func (AlterSearchIndex) isStatement() {} -func (CreateView) isStatement() {} -func (DropView) isStatement() {} -func (CreateChangeStream) isStatement() {} -func (AlterChangeStream) isStatement() {} -func (DropChangeStream) isStatement() {} -func (CreateRole) isStatement() {} -func (DropRole) isStatement() {} -func (Grant) isStatement() {} -func (Revoke) isStatement() {} -func (CreateSequence) isStatement() {} -func (AlterSequence) isStatement() {} -func (DropSequence) isStatement() {} -func (AlterStatistics) isStatement() {} -func (CreateModel) isStatement() {} -func (AlterModel) isStatement() {} -func (DropModel) isStatement() {} -func (Analyze) isStatement() {} -func (CreateVectorIndex) isStatement() {} -func (DropVectorIndex) isStatement() {} -func (Insert) isStatement() {} -func (Delete) isStatement() {} -func (Update) isStatement() {} -func (Call) isStatement() {} +func (BadStatement) isStatement() {} +func (BadDDL) isStatement() {} +func (BadDML) isStatement() {} +func (QueryStatement) isStatement() {} +func (CreateSchema) isStatement() {} +func (DropSchema) isStatement() {} +func (CreateDatabase) isStatement() {} +func (AlterDatabase) isStatement() {} +func (CreatePlacement) isStatement() {} +func (CreateProtoBundle) isStatement() {} +func (AlterProtoBundle) isStatement() {} +func (DropProtoBundle) isStatement() {} +func (CreateTable) isStatement() {} +func (AlterTable) isStatement() {} +func (DropTable) isStatement() {} +func (RenameTable) isStatement() {} +func (CreateIndex) isStatement() {} +func (AlterIndex) isStatement() {} +func (DropIndex) isStatement() {} +func (CreateSearchIndex) isStatement() {} +func (DropSearchIndex) isStatement() {} +func (AlterSearchIndex) isStatement() {} +func (CreateView) isStatement() {} +func (DropView) isStatement() {} +func (CreateChangeStream) isStatement() {} +func (AlterChangeStream) isStatement() {} +func (DropChangeStream) isStatement() {} +func (CreateRole) isStatement() {} +func (DropRole) isStatement() {} +func (Grant) isStatement() {} +func (Revoke) isStatement() {} +func (CreateSequence) isStatement() {} +func (AlterSequence) isStatement() {} +func (DropSequence) isStatement() {} +func (AlterStatistics) isStatement() {} +func (CreateModel) isStatement() {} +func (AlterModel) isStatement() {} +func (DropModel) isStatement() {} +func (Analyze) isStatement() {} +func (CreateVectorIndex) isStatement() {} +func (DropVectorIndex) isStatement() {} +func (CreatePropertyGraph) isStatement() {} +func (DropPropertyGraph) isStatement() {} +func (Insert) isStatement() {} +func (Delete) isStatement() {} +func (Update) isStatement() {} +func (Call) isStatement() {} // QueryExpr represents query expression, which can be body of QueryStatement or subqueries. // Select and FromQuery are leaf QueryExpr and others wrap other QueryExpr. @@ -361,44 +363,46 @@ type DDL interface { // // - https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language -func (BadDDL) isDDL() {} -func (CreateSchema) isDDL() {} -func (DropSchema) isDDL() {} -func (CreateDatabase) isDDL() {} -func (AlterDatabase) isDDL() {} -func (CreatePlacement) isDDL() {} -func (CreateProtoBundle) isDDL() {} -func (AlterProtoBundle) isDDL() {} -func (DropProtoBundle) isDDL() {} -func (CreateTable) isDDL() {} -func (AlterTable) isDDL() {} -func (DropTable) isDDL() {} -func (RenameTable) isDDL() {} -func (CreateIndex) isDDL() {} -func (AlterIndex) isDDL() {} -func (DropIndex) isDDL() {} -func (CreateView) isDDL() {} -func (CreateSearchIndex) isDDL() {} -func (DropSearchIndex) isDDL() {} -func (AlterSearchIndex) isDDL() {} -func (DropView) isDDL() {} -func (CreateChangeStream) isDDL() {} -func (AlterChangeStream) isDDL() {} -func (DropChangeStream) isDDL() {} -func (CreateRole) isDDL() {} -func (DropRole) isDDL() {} -func (Grant) isDDL() {} -func (Revoke) isDDL() {} -func (CreateSequence) isDDL() {} -func (AlterSequence) isDDL() {} -func (DropSequence) isDDL() {} -func (AlterStatistics) isDDL() {} -func (CreateModel) isDDL() {} -func (AlterModel) isDDL() {} -func (DropModel) isDDL() {} -func (Analyze) isDDL() {} -func (CreateVectorIndex) isDDL() {} -func (DropVectorIndex) isDDL() {} +func (BadDDL) isDDL() {} +func (CreateSchema) isDDL() {} +func (DropSchema) isDDL() {} +func (CreateDatabase) isDDL() {} +func (AlterDatabase) isDDL() {} +func (CreatePlacement) isDDL() {} +func (CreateProtoBundle) isDDL() {} +func (AlterProtoBundle) isDDL() {} +func (DropProtoBundle) isDDL() {} +func (CreateTable) isDDL() {} +func (AlterTable) isDDL() {} +func (DropTable) isDDL() {} +func (RenameTable) isDDL() {} +func (CreateIndex) isDDL() {} +func (AlterIndex) isDDL() {} +func (DropIndex) isDDL() {} +func (CreateView) isDDL() {} +func (CreateSearchIndex) isDDL() {} +func (DropSearchIndex) isDDL() {} +func (AlterSearchIndex) isDDL() {} +func (DropView) isDDL() {} +func (CreateChangeStream) isDDL() {} +func (AlterChangeStream) isDDL() {} +func (DropChangeStream) isDDL() {} +func (CreateRole) isDDL() {} +func (DropRole) isDDL() {} +func (Grant) isDDL() {} +func (Revoke) isDDL() {} +func (CreateSequence) isDDL() {} +func (AlterSequence) isDDL() {} +func (DropSequence) isDDL() {} +func (AlterStatistics) isDDL() {} +func (CreateModel) isDDL() {} +func (AlterModel) isDDL() {} +func (DropModel) isDDL() {} +func (Analyze) isDDL() {} +func (CreateVectorIndex) isDDL() {} +func (DropVectorIndex) isDDL() {} +func (CreatePropertyGraph) isDDL() {} +func (DropPropertyGraph) isDDL() {} // Constraint represents table constraint of CONSTARINT clause. type Constraint interface { @@ -3612,6 +3616,313 @@ type AlterSearchIndex struct { IndexAlteration IndexAlteration } +// ================================================================================ +// +// GQL schema statements +// +// ================================================================================ + +// PropertyGraphLabelsOrProperties represents labels with properties or a single properties of node or edge. +type PropertyGraphLabelsOrProperties interface { + Node + isPropertyGraphLabelsOrProperties() +} + +func (PropertyGraphSingleProperties) isPropertyGraphLabelsOrProperties() {} +func (PropertyGraphLabelAndPropertiesList) isPropertyGraphLabelsOrProperties() {} + +// PropertyGraphElementLabel represents a element label definition. +type PropertyGraphElementLabel interface { + Node + isPropertyGraphElementLabel() +} + +func (PropertyGraphElementLabelLabelName) isPropertyGraphElementLabel() {} +func (PropertyGraphElementLabelDefaultLabel) isPropertyGraphElementLabel() {} + +// PropertyGraphElementKeys represents PropertyGraphNodeElementKey or PropertyGraphEdgeElementKeys. +type PropertyGraphElementKeys interface { + Node + isPropertyGraphElementKeys() +} + +func (PropertyGraphNodeElementKey) isPropertyGraphElementKeys() {} +func (PropertyGraphEdgeElementKeys) isPropertyGraphElementKeys() {} + +// PropertyGraphElementProperties represents a definition of properties. +// See https://cloud.google.com/spanner/docs/reference/standard-sql/graph-schema-statements#element_table_property_definition. +type PropertyGraphElementProperties interface { + Node + isPropertyGraphElementProperties() +} + +func (PropertyGraphNoProperties) isPropertyGraphElementProperties() {} +func (PropertyGraphPropertiesAre) isPropertyGraphElementProperties() {} +func (PropertyGraphDerivedPropertyList) isPropertyGraphElementProperties() {} + +// CreatePropertyGraph is CREATE PROPERTY GRAPH statement node. +// +// CREATE {{if .OrReplace}}OR REPLACE{{end}} PROPERTY GRAPH +// {{if .IfNotExists}}IF NOT EXISTS{{end}} +// {{.Name | sql}} +// {{.Content | sql}} +type CreatePropertyGraph struct { + // pos = Create + // end = Content.end + + Create token.Pos // position of "CREATE" keyword + OrReplace bool + IfNotExists bool + Name *Ident + Content *PropertyGraphContent +} + +// PropertyGraphContent represents body of CREATE PROPERTY GRAPH statement. +// +// NODE TABLES {{.NodeTables | sql}} {{.EdgeTables | sqlOpt}} +type PropertyGraphContent struct { + // pos = NodeTables.pos + // end = (EdgeTables ?? NodeTables).end + + NodeTables *PropertyGraphNodeTables + EdgeTables *PropertyGraphEdgeTables //optional +} + +// PropertyGraphNodeTables is NODE TABLES node in CREATE PROPERTY GRAPH statement. +// +// NODE TABLES {{.Tables | sql}} +type PropertyGraphNodeTables struct { + // pos = Node + // end = Tables.end + + Node token.Pos + Tables *PropertyGraphElementList +} + +// PropertyGraphEdgeTables is EDGE TABLES node in CREATE PROPERTY GRAPH statement. +// +// EDGE TABLES {{.Tables | sql}} +type PropertyGraphEdgeTables struct { + // pos = Edge + // end = Tables.end + + Edge token.Pos + Tables *PropertyGraphElementList +} + +// PropertyGraphElementList represents element list in NODE TABLES or EDGE TABLES. +// +// ({{.Elements | sqlJoin ", "}}) +type PropertyGraphElementList struct { + // pos = Lparen + // end = Rparen + 1 + + Lparen, Rparen token.Pos + Elements []*PropertyGraphElement +} + +// PropertyGraphElement represents a single element in NODE TABLES or EDGE TABLES. +// +// {{.Name | sql}} {{if .Alias | isnil | not)}}AS {{.Alias | sql}}{{end}} +// {{.Keys | sqlOpt}} {{.Properties | sqlOpt}} +type PropertyGraphElement struct { + // pos = Name.pos + // end = (Properties ?? Keys ?? Alias ?? Name).end + + Name *Ident + Alias *Ident // optional + Keys PropertyGraphElementKeys // optional + Properties PropertyGraphLabelsOrProperties // optional +} + +// PropertyGraphSingleProperties is wrapper node for PropertyGraphElementProperties in PropertyGraphElement. +// It implements PropertyGraphLabelsOrProperties. +// +// {{.Properties | sql}} +type PropertyGraphSingleProperties struct { + // pos = Properties.pos + // end = Properties.end + + Properties PropertyGraphElementProperties +} + +// PropertyGraphLabelAndPropertiesList represents whitespace-separated list of PropertyGraphLabelAndProperties. +// It implements PropertyGraphLabelsOrProperties. +// +// {{.LabelAndProperties | sqlJoin " "}} +type PropertyGraphLabelAndPropertiesList struct { + // pos = LabelAndProperties[0].pos + // end = LabelAndProperties[$].end + + LabelAndProperties []*PropertyGraphLabelAndProperties // len(LabelAndProperties) > 0 +} + +// PropertyGraphLabelAndProperties represents label and properties definition for a single label. +// +// {{.Label | sql}} {{.Properties | sqlOpt}} +type PropertyGraphLabelAndProperties struct { + // pos = Label.pos + // end = (Properties ?? Label).end + + Label PropertyGraphElementLabel + Properties PropertyGraphElementProperties // optional +} + +// PropertyGraphElementLabelLabelName represents LABEL label_name node. +// +// LABEL {{.Name | sql}} +type PropertyGraphElementLabelLabelName struct { + // pos = Label + // end = Name.end + + Label token.Pos + Name *Ident +} + +// PropertyGraphElementLabelDefaultLabel represents DEFAULT LABEL node. +// +// DEFAULT LABEL +type PropertyGraphElementLabelDefaultLabel struct { + // pos = Default + // end = Label + 5 + + Default token.Pos + Label token.Pos +} + +// PropertyGraphNodeElementKey is a wrapper of PropertyGraphElementKey to implement PropertyGraphElementKeys +// without deeper AST hierarchy. +// +// {{.Key | sql}} +type PropertyGraphNodeElementKey struct { + // pos = Key.pos + // end = Key.end + + Key *PropertyGraphElementKey +} + +// PropertyGraphEdgeElementKeys represents PropertyGraphSourceKey and PropertyGraphDestinationKey with optional PropertyGraphElementKey. +// +// {{.Element | sqlOpt}} {{.Source | sql}} {{.Destination | sql}} +type PropertyGraphEdgeElementKeys struct { + // pos = Element.pos + // end = Destination.end + Element *PropertyGraphElementKey // optional + Source *PropertyGraphSourceKey + Destination *PropertyGraphDestinationKey +} + +// PropertyGraphElementKey represents the key that identifies the node or edge element. +// +// KEY {{.Keys | sql}} +type PropertyGraphElementKey struct { + // pos = Key + // end = Keys.end + + Key token.Pos + Keys *PropertyGraphColumnNameList +} + +// PropertyGraphSourceKey represents the key for the source node of the edge. +// +// SOURCE KEY {{.Keys | sql}} +// REFERENCES {{.ElementReference | sql}} {{.ReferenceColumns | sqlOpt}} +type PropertyGraphSourceKey struct { + // pos = Source + // end = (ReferenceColumns ?? ElementReference).end + + Source token.Pos + Keys *PropertyGraphColumnNameList + ElementReference *Ident + ReferenceColumns *PropertyGraphColumnNameList // optional +} + +// PropertyGraphDestinationKey represents the key for the destination node of the edge. +// +// DESTINATION KEY {{.Keys | sql}} +// REFERENCES {{.ElementReference | sql}} {{.ReferenceColumns | sqlOpt}} +type PropertyGraphDestinationKey struct { + // pos = Destination + // end = (ReferenceColumns ?? ElementReference).end + + Destination token.Pos + Keys *PropertyGraphColumnNameList + ElementReference *Ident + ReferenceColumns *PropertyGraphColumnNameList // optional +} + +// PropertyGraphColumnNameList represents one or more columns to assign to a key. +// +// ({{.ColumnNameList | sqlJoin ", "}}) +type PropertyGraphColumnNameList struct { + // pos = Lparen + // end = Rparen + 1 + + Lparen, Rparen token.Pos + + ColumnNameList []*Ident +} + +// PropertyGraphNoProperties represents the element doesn't have properties. +// +// NO PROPERTIES +type PropertyGraphNoProperties struct { + // pos = No + // end = Properties + 10 + + No, Properties token.Pos // position of "NO" and "PROPERTIES" +} + +// PropertyGraphPropertiesAre defines which columns to include as element properties. +// +// PROPERTIES ARE ALL COLUMNS{{if .ExceptColumns | isnil | not}} EXCEPT {{.ExceptColumns | sql}}{{end}} +type PropertyGraphPropertiesAre struct { + // pos = Properties + // end = ExceptColumns.end || Columns + 7 + + Properties token.Pos // position of "PROPERTIES" + Columns token.Pos // position of "COLUMNS" + + ExceptColumns *PropertyGraphColumnNameList // optional +} + +// PropertyGraphDerivedPropertyList represents a list of PropertyGraphDerivedProperty. +// NOTE: In current syntax reference, "(" and ")" are missing. +// +// PROPERTIES ({{.DerivedProperties | sqlJoin ", "}}) +type PropertyGraphDerivedPropertyList struct { + // pos = Properties + // end = Rparen + + Properties token.Pos // position of "PROPERTIES" + Rparen token.Pos // position of ")" + DerivedProperties []*PropertyGraphDerivedProperty // len(DerivedProperties) > 0 +} + +// PropertyGraphDerivedProperty represents an expression that defines a property and can optionally reference the input table columns. +// +// {{.Expr | sql}} {{if .Alias}}AS {{.Alias | sql}}{{end}} +type PropertyGraphDerivedProperty struct { + // pos = Expr.pos + // end = (Alias ?? Expr).end + + Expr Expr + Alias *Ident // optional +} + +// DropPropertyGraph is DROP PROPERTY GRAPH statement node. +// +// DROP PROPERTY GRAPH {{if .IfExists}}IF EXISTS{{end}} {{.Name | sql}} +type DropPropertyGraph struct { + // pos = Drop + // end = Name.end + + Drop token.Pos + + IfExists bool + Name *Ident +} + // ================================================================================ // // DML diff --git a/ast/pos.go b/ast/pos.go index f9244465..d370cc48 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -1814,6 +1814,182 @@ func (a *AlterSearchIndex) End() token.Pos { return nodeEnd(wrapNode(a.IndexAlteration)) } +func (c *CreatePropertyGraph) Pos() token.Pos { + return c.Create +} + +func (c *CreatePropertyGraph) End() token.Pos { + return nodeEnd(wrapNode(c.Content)) +} + +func (p *PropertyGraphContent) Pos() token.Pos { + return nodePos(wrapNode(p.NodeTables)) +} + +func (p *PropertyGraphContent) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.EdgeTables), wrapNode(p.NodeTables))) +} + +func (p *PropertyGraphNodeTables) Pos() token.Pos { + return p.Node +} + +func (p *PropertyGraphNodeTables) End() token.Pos { + return nodeEnd(wrapNode(p.Tables)) +} + +func (p *PropertyGraphEdgeTables) Pos() token.Pos { + return p.Edge +} + +func (p *PropertyGraphEdgeTables) End() token.Pos { + return nodeEnd(wrapNode(p.Tables)) +} + +func (p *PropertyGraphElementList) Pos() token.Pos { + return p.Lparen +} + +func (p *PropertyGraphElementList) End() token.Pos { + return posAdd(p.Rparen, 1) +} + +func (p *PropertyGraphElement) Pos() token.Pos { + return nodePos(wrapNode(p.Name)) +} + +func (p *PropertyGraphElement) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.Properties), wrapNode(p.Keys), wrapNode(p.Alias), wrapNode(p.Name))) +} + +func (p *PropertyGraphSingleProperties) Pos() token.Pos { + return nodePos(wrapNode(p.Properties)) +} + +func (p *PropertyGraphSingleProperties) End() token.Pos { + return nodeEnd(wrapNode(p.Properties)) +} + +func (p *PropertyGraphLabelAndPropertiesList) Pos() token.Pos { + return nodePos(nodeSliceIndex(p.LabelAndProperties, 0)) +} + +func (p *PropertyGraphLabelAndPropertiesList) End() token.Pos { + return nodeEnd(nodeSliceLast(p.LabelAndProperties)) +} + +func (p *PropertyGraphLabelAndProperties) Pos() token.Pos { + return nodePos(wrapNode(p.Label)) +} + +func (p *PropertyGraphLabelAndProperties) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.Properties), wrapNode(p.Label))) +} + +func (p *PropertyGraphElementLabelLabelName) Pos() token.Pos { + return p.Label +} + +func (p *PropertyGraphElementLabelLabelName) End() token.Pos { + return nodeEnd(wrapNode(p.Name)) +} + +func (p *PropertyGraphElementLabelDefaultLabel) Pos() token.Pos { + return p.Default +} + +func (p *PropertyGraphElementLabelDefaultLabel) End() token.Pos { + return posAdd(p.Label, 5) +} + +func (p *PropertyGraphNodeElementKey) Pos() token.Pos { + return nodePos(wrapNode(p.Key)) +} + +func (p *PropertyGraphNodeElementKey) End() token.Pos { + return nodeEnd(wrapNode(p.Key)) +} + +func (p *PropertyGraphEdgeElementKeys) Pos() token.Pos { + return nodePos(wrapNode(p.Element)) +} + +func (p *PropertyGraphEdgeElementKeys) End() token.Pos { + return nodeEnd(wrapNode(p.Destination)) +} + +func (p *PropertyGraphElementKey) Pos() token.Pos { + return p.Key +} + +func (p *PropertyGraphElementKey) End() token.Pos { + return nodeEnd(wrapNode(p.Keys)) +} + +func (p *PropertyGraphSourceKey) Pos() token.Pos { + return p.Source +} + +func (p *PropertyGraphSourceKey) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.ReferenceColumns), wrapNode(p.ElementReference))) +} + +func (p *PropertyGraphDestinationKey) Pos() token.Pos { + return p.Destination +} + +func (p *PropertyGraphDestinationKey) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.ReferenceColumns), wrapNode(p.ElementReference))) +} + +func (p *PropertyGraphColumnNameList) Pos() token.Pos { + return p.Lparen +} + +func (p *PropertyGraphColumnNameList) End() token.Pos { + return posAdd(p.Rparen, 1) +} + +func (p *PropertyGraphNoProperties) Pos() token.Pos { + return p.No +} + +func (p *PropertyGraphNoProperties) End() token.Pos { + return posAdd(p.Properties, 10) +} + +func (p *PropertyGraphPropertiesAre) Pos() token.Pos { + return p.Properties +} + +func (p *PropertyGraphPropertiesAre) End() token.Pos { + return posChoice(nodeEnd(wrapNode(p.ExceptColumns)), posAdd(p.Columns, 7)) +} + +func (p *PropertyGraphDerivedPropertyList) Pos() token.Pos { + return p.Properties +} + +func (p *PropertyGraphDerivedPropertyList) End() token.Pos { + return p.Rparen +} + +func (p *PropertyGraphDerivedProperty) Pos() token.Pos { + return nodePos(wrapNode(p.Expr)) +} + +func (p *PropertyGraphDerivedProperty) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(p.Alias), wrapNode(p.Expr))) +} + +func (d *DropPropertyGraph) Pos() token.Pos { + return d.Drop +} + +func (d *DropPropertyGraph) End() token.Pos { + return nodeEnd(wrapNode(d.Name)) +} + func (w *WithAction) Pos() token.Pos { return w.With } diff --git a/ast/sql.go b/ast/sql.go index e63880d7..f110b0cf 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -1149,6 +1149,104 @@ func (d *DropModel) SQL() string { return "DROP MODEL " + strOpt(d.IfExists, "IF EXISTS ") + d.Name.SQL() } +// ================================================================================ +// +// GQL schema statements +// +// ================================================================================ + +func (c *CreatePropertyGraph) SQL() string { + return "CREATE " + + strOpt(c.OrReplace, "OR REPLACE ") + + "PROPERTY GRAPH " + + strOpt(c.IfNotExists, "IF NOT EXISTS ") + + c.Name.SQL() + " " + c.Content.SQL() +} + +func (p *PropertyGraphContent) SQL() string { + return p.NodeTables.SQL() + sqlOpt(" ", p.EdgeTables, "") +} + +func (p *PropertyGraphNodeTables) SQL() string { + return "NODE TABLES " + p.Tables.SQL() +} + +func (p *PropertyGraphEdgeTables) SQL() string { + return "EDGE TABLES " + p.Tables.SQL() +} + +func (p *PropertyGraphElementList) SQL() string { + return "(" + sqlJoin(p.Elements, ", ") + ")" +} + +func (p *PropertyGraphElement) SQL() string { + return p.Name.SQL() + + sqlOpt(" AS ", p.Alias, "") + + sqlOpt(" ", p.Keys, "") + + sqlOpt(" ", p.Properties, "") +} + +func (p *PropertyGraphSingleProperties) SQL() string { return p.Properties.SQL() } + +func (p *PropertyGraphLabelAndPropertiesList) SQL() string { + return sqlJoin(p.LabelAndProperties, " ") +} + +func (p *PropertyGraphLabelAndProperties) SQL() string { + return p.Label.SQL() + sqlOpt(" ", p.Properties, "") +} + +func (p *PropertyGraphElementLabelLabelName) SQL() string { return "LABEL " + p.Name.SQL() } + +func (p *PropertyGraphElementLabelDefaultLabel) SQL() string { return "DEFAULT LABEL" } + +func (p *PropertyGraphNodeElementKey) SQL() string { return p.Key.SQL() } + +func (p *PropertyGraphEdgeElementKeys) SQL() string { + return sqlOpt("", p.Element, " ") + + p.Source.SQL() + " " + p.Destination.SQL() +} + +func (p *PropertyGraphElementKey) SQL() string { return "KEY " + p.Keys.SQL() } + +func (p *PropertyGraphSourceKey) SQL() string { + return "SOURCE KEY " + p.Keys.SQL() + + " REFERENCES " + p.ElementReference.SQL() + + sqlOpt(" ", p.ReferenceColumns, "") +} + +func (p *PropertyGraphDestinationKey) SQL() string { + return "DESTINATION KEY " + p.Keys.SQL() + + " REFERENCES " + p.ElementReference.SQL() + + sqlOpt(" ", p.ReferenceColumns, "") +} + +func (p *PropertyGraphColumnNameList) SQL() string { + return "(" + sqlJoin(p.ColumnNameList, ", ") + ")" +} + +func (p *PropertyGraphNoProperties) SQL() string { + return "NO PROPERTIES" +} + +func (p *PropertyGraphPropertiesAre) SQL() string { + return "PROPERTIES ARE ALL COLUMNS" + sqlOpt(" EXCEPT ", p.ExceptColumns, "") +} + +func (p *PropertyGraphDerivedPropertyList) SQL() string { + return "PROPERTIES (" + sqlJoin(p.DerivedProperties, ", ") + ")" +} + +func (p *PropertyGraphDerivedProperty) SQL() string { + return p.Expr.SQL() + sqlOpt(" AS ", p.Alias, "") +} + +func (g *DropPropertyGraph) SQL() string { + return "DROP PROPERTY GRAPH " + + strOpt(g.IfExists, "IF EXISTS ") + + g.Name.SQL() +} + // ================================================================================ // // Types for Schema diff --git a/parser.go b/parser.go index f7596156..821371af 100644 --- a/parser.go +++ b/parser.go @@ -2823,7 +2823,11 @@ func (p *Parser) parseDDL() (ddl ast.DDL) { return p.parseCreateView(pos, true) case p.Token.IsKeywordLike("MODEL"): return p.parseCreateModel(pos, true) + case p.Token.IsKeywordLike("PROPERTY"): + return p.parseCreatePropertyGraph(pos, true) } + case p.Token.IsKeywordLike("PROPERTY"): + return p.parseCreatePropertyGraph(pos, false) } p.panicfAtToken(&p.Token, "expected pseudo keyword: DATABASE, TABLE, INDEX, UNIQUE, NULL_FILTERED, ROLE, CHANGE, OR but: %s", p.Token.AsString) case p.Token.IsKeywordLike("ALTER"): @@ -2874,6 +2878,8 @@ func (p *Parser) parseDDL() (ddl ast.DDL) { return p.parseDropChangeStream(pos) case p.Token.IsKeywordLike("MODEL"): return p.parseDropModel(pos) + case p.Token.IsKeywordLike("PROPERTY"): + return p.parseDropPropertyGraph(pos) } p.panicfAtToken(&p.Token, "expected pseudo keyword: TABLE, INDEX, ROLE, CHANGE, MODEL, but: %s", p.Token.AsString) case p.Token.IsKeywordLike("RENAME"): @@ -4462,6 +4468,307 @@ func (p *Parser) tryParseTablePrivilegeColumns() ([]*ast.Ident, token.Pos) { return columns, rparen } +// begin CREATE PROPERTY GRAPH + +func (p *Parser) parseCreatePropertyGraph(pos token.Pos, orReplace bool) *ast.CreatePropertyGraph { + p.expectKeywordLike("PROPERTY") + p.expectKeywordLike("GRAPH") + + ifNotExists := p.parseIfNotExists() + name := p.parseIdent() + content := p.parsePropertyGraphContent() + + return &ast.CreatePropertyGraph{ + Create: pos, + OrReplace: orReplace, + IfNotExists: ifNotExists, + Name: name, + Content: content, + } +} + +func (p *Parser) parsePropertyGraphContent() *ast.PropertyGraphContent { + node := p.expectKeywordLike("NODE").Pos + p.expectKeywordLike("TABLES") + + nodeTables := &ast.PropertyGraphNodeTables{ + Node: node, + Tables: p.parsePropertyGraphElementList(), + } + + var edgeTables *ast.PropertyGraphEdgeTables + if p.Token.IsKeywordLike("EDGE") { + edge := p.expectKeywordLike("EDGE").Pos + p.expectKeywordLike("TABLES") + tables := p.parsePropertyGraphElementList() + edgeTables = &ast.PropertyGraphEdgeTables{ + Edge: edge, + Tables: tables, + } + } + + return &ast.PropertyGraphContent{ + NodeTables: nodeTables, + EdgeTables: edgeTables, + } +} + +func (p *Parser) parsePropertyGraphElementList() *ast.PropertyGraphElementList { + lparen := p.expect("(").Pos + elements := parseCommaSeparatedList(p, p.parsePropertyGraphElement) + rparen := p.expect(")").Pos + + return &ast.PropertyGraphElementList{ + Lparen: lparen, + Rparen: rparen, + Elements: elements, + } + +} + +func (p *Parser) parsePropertyGraphElement() *ast.PropertyGraphElement { + name := p.parseIdent() + + var alias *ast.Ident + if p.Token.Kind == "AS" { + p.nextToken() + alias = p.parseIdent() + } + + keys := p.tryParsePropertyGraphElementKeys() + properties := p.tryParsePropertyGraphLabelsOrProperties() + + return &ast.PropertyGraphElement{ + Name: name, + Alias: alias, + Keys: keys, + Properties: properties, + } +} + +// parsePropertyGraphLabelAndPropertiesList parses consecutive ast.PropertyGraphLabelAndProperties, +// and returns *ast.PropertyGraphLabelAndPropertiesList. +func (p *Parser) parsePropertyGraphLabelAndPropertiesList() *ast.PropertyGraphLabelAndPropertiesList { + // list can be empty + var list []*ast.PropertyGraphLabelAndProperties + for { + if p.Token.Kind != "DEFAULT" && !p.Token.IsKeywordLike("LABEL") { + break + } + + elemLabel := p.parsePropertyGraphElementLabel() + properties := p.tryParsePropertyGraphElementProperties() + + list = append(list, &ast.PropertyGraphLabelAndProperties{ + Label: elemLabel, + Properties: properties, + }) + } + + return &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: list, + } +} + +func (p *Parser) parsePropertyGraphElementLabel() ast.PropertyGraphElementLabel { + if p.Token.Kind == "DEFAULT" { + def := p.expect("DEFAULT").Pos + label := p.expectKeywordLike("LABEL").Pos + + return &ast.PropertyGraphElementLabelDefaultLabel{ + Default: def, + Label: label, + } + } + + label := p.expectKeywordLike("LABEL").Pos + name := p.parseIdent() + + return &ast.PropertyGraphElementLabelLabelName{ + Label: label, + Name: name, + } +} + +func (p *Parser) tryParsePropertyGraphElementProperties() ast.PropertyGraphElementProperties { + if p.Token.Kind != "NO" && !p.Token.IsKeywordLike("PROPERTIES") { + return nil + } + + return p.parsePropertyGraphElementProperties() +} + +func (p *Parser) parsePropertyGraphElementProperties() ast.PropertyGraphElementProperties { + if p.Token.Kind != "NO" && !p.Token.IsKeywordLike("PROPERTIES") { + p.panicfAtToken(&p.Token, `expect "NO" or "PROPERTIES", but %v`, p.Token.Kind) + } + + if p.Token.Kind == "NO" { + no := p.expect("NO").Pos + properties := p.expectKeywordLike("PROPERTIES").Pos + + return &ast.PropertyGraphNoProperties{ + No: no, + Properties: properties, + } + } + + properties := p.expectKeywordLike("PROPERTIES") + if p.Token.IsKeywordLike("ARE") || p.Token.Kind == "ALL" { + // "ARE" is optional + if p.Token.IsKeywordLike("ARE") { + p.nextToken() + } + + p.expect("ALL") + columns := p.expectKeywordLike("COLUMNS").Pos + + var exceptColumns *ast.PropertyGraphColumnNameList + if p.Token.Kind == "EXCEPT" { + p.nextToken() + exceptColumns = p.parsePropertyGraphColumnNameList() + } + + return &ast.PropertyGraphPropertiesAre{ + Properties: properties.Pos, + Columns: columns, + ExceptColumns: exceptColumns, + } + } + + p.expect("(") + list := parseCommaSeparatedList(p, p.parsePropertyGraphDerivedProperty) + rparen := p.expect(")").Pos + + return &ast.PropertyGraphDerivedPropertyList{ + Rparen: rparen, + Properties: properties.Pos, + DerivedProperties: list, + } +} + +func (p *Parser) parsePropertyGraphDerivedProperty() *ast.PropertyGraphDerivedProperty { + expr := p.parseExpr() + + var name *ast.Ident + if p.Token.Kind == "AS" { + p.nextToken() + name = p.parseIdent() + } + + return &ast.PropertyGraphDerivedProperty{ + Expr: expr, + Alias: name, + } +} + +func (p *Parser) tryParsePropertyGraphLabelsOrProperties() ast.PropertyGraphLabelsOrProperties { + if p.Token.IsKeywordLike("LABEL") || p.Token.Kind == "DEFAULT" { + return p.parsePropertyGraphLabelAndPropertiesList() + } + + if properties := p.tryParsePropertyGraphElementProperties(); properties != nil { + return &ast.PropertyGraphSingleProperties{ + Properties: properties, + } + } + return nil +} + +func (p *Parser) tryParsePropertyGraphElementKeys() ast.PropertyGraphElementKeys { + if !p.Token.IsKeywordLike("KEY") && !p.Token.IsKeywordLike("SOURCE") { + return nil + } + + // element_key + var elementKey *ast.PropertyGraphElementKey + if p.Token.IsKeywordLike("KEY") { + key := p.expectKeywordLike("KEY").Pos + keyColumns := p.parsePropertyGraphColumnNameList() + + elementKey = &ast.PropertyGraphElementKey{ + Key: key, + Keys: keyColumns, + } + + // if SOURCE KEY doesn't follow, it is node_element_key. + if !p.Token.IsKeywordLike("SOURCE") { + return &ast.PropertyGraphNodeElementKey{ + Key: elementKey, + } + } + + } + + // the rest of edge_element_keys + + // source_key + source := p.expectKeywordLike("SOURCE").Pos + p.expectKeywordLike("KEY") + sourceColumns := p.parsePropertyGraphColumnNameList() + p.expectKeywordLike("REFERENCES") + sourceReference := p.parseIdent() + sourceReferenceColumns := p.tryParsePropertyGraphColumnNameList() + + // destination_key + destination := p.expectKeywordLike("DESTINATION").Pos + p.expectKeywordLike("KEY") + destinationColumns := p.parsePropertyGraphColumnNameList() + p.expectKeywordLike("REFERENCES") + destinationReference := p.parseIdent() + destinationReferenceColumns := p.tryParsePropertyGraphColumnNameList() + + return &ast.PropertyGraphEdgeElementKeys{ + Element: elementKey, + Source: &ast.PropertyGraphSourceKey{ + Source: source, + Keys: sourceColumns, + ElementReference: sourceReference, + ReferenceColumns: sourceReferenceColumns, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: destination, + Keys: destinationColumns, + ElementReference: destinationReference, + ReferenceColumns: destinationReferenceColumns, + }, + } +} + +func (p *Parser) parsePropertyGraphColumnNameList() *ast.PropertyGraphColumnNameList { + lparen := p.expect("(").Pos + list := parseCommaSeparatedList(p, p.parseIdent) + rparen := p.expect(")").Pos + + return &ast.PropertyGraphColumnNameList{ + Lparen: lparen, + Rparen: rparen, + ColumnNameList: list, + } +} + +func (p *Parser) tryParsePropertyGraphColumnNameList() *ast.PropertyGraphColumnNameList { + if p.Token.Kind != "(" { + return nil + } + return p.parsePropertyGraphColumnNameList() +} + +// end CREATE PROPERTY GRAPH + +func (p *Parser) parseDropPropertyGraph(pos token.Pos) *ast.DropPropertyGraph { + p.expectKeywordLike("PROPERTY") + p.expectKeywordLike("GRAPH") + ifExists := p.parseIfExists() + name := p.parseIdent() + + return &ast.DropPropertyGraph{ + Drop: pos, + IfExists: ifExists, + Name: name, + } +} + func (p *Parser) parseSchemaType() ast.SchemaType { switch p.Token.Kind { case token.TokenIdent: diff --git a/testdata/input/ddl/create_or_replace_property_graph_fingraph_verbose.sql b/testdata/input/ddl/create_or_replace_property_graph_fingraph_verbose.sql new file mode 100644 index 00000000..2e97e23c --- /dev/null +++ b/testdata/input/ddl/create_or_replace_property_graph_fingraph_verbose.sql @@ -0,0 +1,28 @@ +CREATE OR REPLACE PROPERTY GRAPH FinGraph + NODE TABLES ( + Account AS Account -- element_alias + KEY (id) -- element_key in node_element_key in element_keys + -- label_and_property_list + LABEL DetailedAccount -- LABEL label_name in element_label + PROPERTIES (create_time, is_blocked, nick_name AS name) -- derived_property_list + DEFAULT LABEL -- DEFAULT LABEL in element_label + NO PROPERTIES -- NO PROPERTIES in element_properties + , + Person + -- no element_keys + -- no element_label because of direct element_properties + PROPERTIES ARE ALL COLUMNS EXCEPT (city) -- properties_are + ) + EDGE TABLES ( + PersonOwnAccount AS PersonOwnAccount + KEY (id, account_id) + SOURCE KEY (id) REFERENCES Person -- source_key without column_name_list + DESTINATION KEY (account_id) REFERENCES Account -- destination_key without column_name_list + LABEL Owns + PROPERTIES ALL COLUMNS, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) -- source_key + DESTINATION KEY (to_id) REFERENCES Account (id) -- destination_key + LABEL Transfers -- LABEL label_name in element_label + -- without element_properties + ) \ No newline at end of file diff --git a/testdata/input/ddl/create_property_graph_if_not_exists_fingraph.sql b/testdata/input/ddl/create_property_graph_if_not_exists_fingraph.sql new file mode 100644 index 00000000..632af155 --- /dev/null +++ b/testdata/input/ddl/create_property_graph_if_not_exists_fingraph.sql @@ -0,0 +1,15 @@ +CREATE PROPERTY GRAPH IF NOT EXISTS FinGraph + NODE TABLES ( + Account, + Person + ) + EDGE TABLES ( + PersonOwnAccount + SOURCE KEY (id) REFERENCES Person (id) + DESTINATION KEY (account_id) REFERENCES Account (id) + LABEL Owns, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) + DESTINATION KEY (to_id) REFERENCES Account (id) + LABEL Transfers + ) \ No newline at end of file diff --git a/testdata/input/ddl/drop_property_graph.sql b/testdata/input/ddl/drop_property_graph.sql new file mode 100644 index 00000000..403d3298 --- /dev/null +++ b/testdata/input/ddl/drop_property_graph.sql @@ -0,0 +1 @@ +DROP PROPERTY GRAPH FinGraph diff --git a/testdata/input/ddl/drop_property_graph_if_exists.sql b/testdata/input/ddl/drop_property_graph_if_exists.sql new file mode 100644 index 00000000..ecb5196e --- /dev/null +++ b/testdata/input/ddl/drop_property_graph_if_exists.sql @@ -0,0 +1 @@ +DROP PROPERTY GRAPH IF EXISTS FinGraph diff --git a/testdata/result/ddl/create_or_replace_property_graph_fingraph_verbose.sql.txt b/testdata/result/ddl/create_or_replace_property_graph_fingraph_verbose.sql.txt new file mode 100644 index 00000000..4094102f --- /dev/null +++ b/testdata/result/ddl/create_or_replace_property_graph_fingraph_verbose.sql.txt @@ -0,0 +1,341 @@ +--- create_or_replace_property_graph_fingraph_verbose.sql +CREATE OR REPLACE PROPERTY GRAPH FinGraph + NODE TABLES ( + Account AS Account -- element_alias + KEY (id) -- element_key in node_element_key in element_keys + -- label_and_property_list + LABEL DetailedAccount -- LABEL label_name in element_label + PROPERTIES (create_time, is_blocked, nick_name AS name) -- derived_property_list + DEFAULT LABEL -- DEFAULT LABEL in element_label + NO PROPERTIES -- NO PROPERTIES in element_properties + , + Person + -- no element_keys + -- no element_label because of direct element_properties + PROPERTIES ARE ALL COLUMNS EXCEPT (city) -- properties_are + ) + EDGE TABLES ( + PersonOwnAccount AS PersonOwnAccount + KEY (id, account_id) + SOURCE KEY (id) REFERENCES Person -- source_key without column_name_list + DESTINATION KEY (account_id) REFERENCES Account -- destination_key without column_name_list + LABEL Owns + PROPERTIES ALL COLUMNS, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) -- source_key + DESTINATION KEY (to_id) REFERENCES Account (id) -- destination_key + LABEL Transfers -- LABEL label_name in element_label + -- without element_properties + ) +--- AST +&ast.CreatePropertyGraph{ + OrReplace: true, + Name: &ast.Ident{ + NamePos: 33, + NameEnd: 41, + Name: "FinGraph", + }, + Content: &ast.PropertyGraphContent{ + NodeTables: &ast.PropertyGraphNodeTables{ + Node: 44, + Tables: &ast.PropertyGraphElementList{ + Lparen: 56, + Rparen: 638, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 62, + NameEnd: 69, + Name: "Account", + }, + Alias: &ast.Ident{ + NamePos: 73, + NameEnd: 80, + Name: "Account", + }, + Keys: &ast.PropertyGraphNodeElementKey{ + Key: &ast.PropertyGraphElementKey{ + Key: 104, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 108, + Rparen: 111, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 109, + NameEnd: 111, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 203, + Name: &ast.Ident{ + NamePos: 209, + NameEnd: 224, + Name: "DetailedAccount", + }, + }, + Properties: &ast.PropertyGraphDerivedPropertyList{ + Properties: 270, + Rparen: 324, + DerivedProperties: []*ast.PropertyGraphDerivedProperty{ + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 282, + NameEnd: 293, + Name: "create_time", + }, + }, + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 295, + NameEnd: 305, + Name: "is_blocked", + }, + }, + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 307, + NameEnd: 316, + Name: "nick_name", + }, + Alias: &ast.Ident{ + NamePos: 320, + NameEnd: 324, + Name: "name", + }, + }, + }, + }, + }, + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelDefaultLabel{ + Default: 357, + Label: 365, + }, + Properties: &ast.PropertyGraphNoProperties{ + No: 413, + Properties: 416, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 476, + NameEnd: 482, + Name: "Person", + }, + Properties: &ast.PropertyGraphSingleProperties{ + Properties: &ast.PropertyGraphPropertiesAre{ + Properties: 577, + Columns: 596, + ExceptColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 611, + Rparen: 616, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 612, + NameEnd: 616, + Name: "city", + }, + }, + }, + }, + }, + }, + }, + }, + }, + EdgeTables: &ast.PropertyGraphEdgeTables{ + Edge: 642, + Tables: &ast.PropertyGraphElementList{ + Lparen: 654, + Rparen: 1207, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 660, + NameEnd: 676, + Name: "PersonOwnAccount", + }, + Alias: &ast.Ident{ + NamePos: 680, + NameEnd: 696, + Name: "PersonOwnAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Element: &ast.PropertyGraphElementKey{ + Key: 703, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 707, + Rparen: 722, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 708, + NameEnd: 710, + Name: "id", + }, + &ast.Ident{ + NamePos: 712, + NameEnd: 722, + Name: "account_id", + }, + }, + }, + }, + Source: &ast.PropertyGraphSourceKey{ + Source: 730, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 741, + Rparen: 744, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 742, + NameEnd: 744, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 757, + NameEnd: 763, + Name: "Person", + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 809, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 825, + Rparen: 836, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 826, + NameEnd: 836, + Name: "account_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 849, + NameEnd: 856, + Name: "Account", + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 907, + Name: &ast.Ident{ + NamePos: 913, + NameEnd: 917, + Name: "Owns", + }, + }, + Properties: &ast.PropertyGraphPropertiesAre{ + Properties: 926, + Columns: 941, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 954, + NameEnd: 976, + Name: "AccountTransferAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 983, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 994, + Rparen: 997, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 995, + NameEnd: 997, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 1010, + NameEnd: 1017, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 1018, + Rparen: 1021, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1019, + NameEnd: 1021, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 1043, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 1059, + Rparen: 1065, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1060, + NameEnd: 1065, + Name: "to_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 1078, + NameEnd: 1085, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 1086, + Rparen: 1089, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1087, + NameEnd: 1089, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 1116, + Name: &ast.Ident{ + NamePos: 1122, + NameEnd: 1131, + Name: "Transfers", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +CREATE OR REPLACE PROPERTY GRAPH FinGraph NODE TABLES (Account AS Account KEY (id) LABEL DetailedAccount PROPERTIES (create_time, is_blocked, nick_name AS name) DEFAULT LABEL NO PROPERTIES, Person PROPERTIES ARE ALL COLUMNS EXCEPT (city)) EDGE TABLES (PersonOwnAccount AS PersonOwnAccount KEY (id, account_id) SOURCE KEY (id) REFERENCES Person DESTINATION KEY (account_id) REFERENCES Account LABEL Owns PROPERTIES ARE ALL COLUMNS, AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers) diff --git a/testdata/result/ddl/create_property_graph_if_not_exists_fingraph.sql.txt b/testdata/result/ddl/create_property_graph_if_not_exists_fingraph.sql.txt new file mode 100644 index 00000000..a0869e1f --- /dev/null +++ b/testdata/result/ddl/create_property_graph_if_not_exists_fingraph.sql.txt @@ -0,0 +1,228 @@ +--- create_property_graph_if_not_exists_fingraph.sql +CREATE PROPERTY GRAPH IF NOT EXISTS FinGraph + NODE TABLES ( + Account, + Person + ) + EDGE TABLES ( + PersonOwnAccount + SOURCE KEY (id) REFERENCES Person (id) + DESTINATION KEY (account_id) REFERENCES Account (id) + LABEL Owns, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) + DESTINATION KEY (to_id) REFERENCES Account (id) + LABEL Transfers + ) +--- AST +&ast.CreatePropertyGraph{ + IfNotExists: true, + Name: &ast.Ident{ + NamePos: 36, + NameEnd: 44, + Name: "FinGraph", + }, + Content: &ast.PropertyGraphContent{ + NodeTables: &ast.PropertyGraphNodeTables{ + Node: 47, + Tables: &ast.PropertyGraphElementList{ + Lparen: 59, + Rparen: 87, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 65, + NameEnd: 72, + Name: "Account", + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 78, + NameEnd: 84, + Name: "Person", + }, + }, + }, + }, + }, + EdgeTables: &ast.PropertyGraphEdgeTables{ + Edge: 91, + Tables: &ast.PropertyGraphElementList{ + Lparen: 103, + Rparen: 399, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 109, + NameEnd: 125, + Name: "PersonOwnAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 132, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 143, + Rparen: 146, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 144, + NameEnd: 146, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 159, + NameEnd: 165, + Name: "Person", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 166, + Rparen: 169, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 167, + NameEnd: 169, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 177, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 193, + Rparen: 204, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 194, + NameEnd: 204, + Name: "account_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 217, + NameEnd: 224, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 225, + Rparen: 228, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 226, + NameEnd: 228, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 236, + Name: &ast.Ident{ + NamePos: 242, + NameEnd: 246, + Name: "Owns", + }, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 252, + NameEnd: 274, + Name: "AccountTransferAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 281, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 292, + Rparen: 295, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 293, + NameEnd: 295, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 308, + NameEnd: 315, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 316, + Rparen: 319, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 317, + NameEnd: 319, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 327, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 343, + Rparen: 349, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 344, + NameEnd: 349, + Name: "to_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 362, + NameEnd: 369, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 370, + Rparen: 373, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 371, + NameEnd: 373, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 381, + Name: &ast.Ident{ + NamePos: 387, + NameEnd: 396, + Name: "Transfers", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +CREATE PROPERTY GRAPH IF NOT EXISTS FinGraph NODE TABLES (Account, Person) EDGE TABLES (PersonOwnAccount SOURCE KEY (id) REFERENCES Person (id) DESTINATION KEY (account_id) REFERENCES Account (id) LABEL Owns, AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers) diff --git a/testdata/result/ddl/drop_property_graph.sql.txt b/testdata/result/ddl/drop_property_graph.sql.txt new file mode 100644 index 00000000..1a41bcbc --- /dev/null +++ b/testdata/result/ddl/drop_property_graph.sql.txt @@ -0,0 +1,14 @@ +--- drop_property_graph.sql +DROP PROPERTY GRAPH FinGraph + +--- AST +&ast.DropPropertyGraph{ + Name: &ast.Ident{ + NamePos: 20, + NameEnd: 28, + Name: "FinGraph", + }, +} + +--- SQL +DROP PROPERTY GRAPH FinGraph diff --git a/testdata/result/ddl/drop_property_graph_if_exists.sql.txt b/testdata/result/ddl/drop_property_graph_if_exists.sql.txt new file mode 100644 index 00000000..3f0efc34 --- /dev/null +++ b/testdata/result/ddl/drop_property_graph_if_exists.sql.txt @@ -0,0 +1,15 @@ +--- drop_property_graph_if_exists.sql +DROP PROPERTY GRAPH IF EXISTS FinGraph + +--- AST +&ast.DropPropertyGraph{ + IfExists: true, + Name: &ast.Ident{ + NamePos: 30, + NameEnd: 38, + Name: "FinGraph", + }, +} + +--- SQL +DROP PROPERTY GRAPH IF EXISTS FinGraph diff --git a/testdata/result/statement/create_or_replace_property_graph_fingraph_verbose.sql.txt b/testdata/result/statement/create_or_replace_property_graph_fingraph_verbose.sql.txt new file mode 100644 index 00000000..4094102f --- /dev/null +++ b/testdata/result/statement/create_or_replace_property_graph_fingraph_verbose.sql.txt @@ -0,0 +1,341 @@ +--- create_or_replace_property_graph_fingraph_verbose.sql +CREATE OR REPLACE PROPERTY GRAPH FinGraph + NODE TABLES ( + Account AS Account -- element_alias + KEY (id) -- element_key in node_element_key in element_keys + -- label_and_property_list + LABEL DetailedAccount -- LABEL label_name in element_label + PROPERTIES (create_time, is_blocked, nick_name AS name) -- derived_property_list + DEFAULT LABEL -- DEFAULT LABEL in element_label + NO PROPERTIES -- NO PROPERTIES in element_properties + , + Person + -- no element_keys + -- no element_label because of direct element_properties + PROPERTIES ARE ALL COLUMNS EXCEPT (city) -- properties_are + ) + EDGE TABLES ( + PersonOwnAccount AS PersonOwnAccount + KEY (id, account_id) + SOURCE KEY (id) REFERENCES Person -- source_key without column_name_list + DESTINATION KEY (account_id) REFERENCES Account -- destination_key without column_name_list + LABEL Owns + PROPERTIES ALL COLUMNS, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) -- source_key + DESTINATION KEY (to_id) REFERENCES Account (id) -- destination_key + LABEL Transfers -- LABEL label_name in element_label + -- without element_properties + ) +--- AST +&ast.CreatePropertyGraph{ + OrReplace: true, + Name: &ast.Ident{ + NamePos: 33, + NameEnd: 41, + Name: "FinGraph", + }, + Content: &ast.PropertyGraphContent{ + NodeTables: &ast.PropertyGraphNodeTables{ + Node: 44, + Tables: &ast.PropertyGraphElementList{ + Lparen: 56, + Rparen: 638, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 62, + NameEnd: 69, + Name: "Account", + }, + Alias: &ast.Ident{ + NamePos: 73, + NameEnd: 80, + Name: "Account", + }, + Keys: &ast.PropertyGraphNodeElementKey{ + Key: &ast.PropertyGraphElementKey{ + Key: 104, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 108, + Rparen: 111, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 109, + NameEnd: 111, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 203, + Name: &ast.Ident{ + NamePos: 209, + NameEnd: 224, + Name: "DetailedAccount", + }, + }, + Properties: &ast.PropertyGraphDerivedPropertyList{ + Properties: 270, + Rparen: 324, + DerivedProperties: []*ast.PropertyGraphDerivedProperty{ + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 282, + NameEnd: 293, + Name: "create_time", + }, + }, + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 295, + NameEnd: 305, + Name: "is_blocked", + }, + }, + &ast.PropertyGraphDerivedProperty{ + Expr: &ast.Ident{ + NamePos: 307, + NameEnd: 316, + Name: "nick_name", + }, + Alias: &ast.Ident{ + NamePos: 320, + NameEnd: 324, + Name: "name", + }, + }, + }, + }, + }, + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelDefaultLabel{ + Default: 357, + Label: 365, + }, + Properties: &ast.PropertyGraphNoProperties{ + No: 413, + Properties: 416, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 476, + NameEnd: 482, + Name: "Person", + }, + Properties: &ast.PropertyGraphSingleProperties{ + Properties: &ast.PropertyGraphPropertiesAre{ + Properties: 577, + Columns: 596, + ExceptColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 611, + Rparen: 616, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 612, + NameEnd: 616, + Name: "city", + }, + }, + }, + }, + }, + }, + }, + }, + }, + EdgeTables: &ast.PropertyGraphEdgeTables{ + Edge: 642, + Tables: &ast.PropertyGraphElementList{ + Lparen: 654, + Rparen: 1207, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 660, + NameEnd: 676, + Name: "PersonOwnAccount", + }, + Alias: &ast.Ident{ + NamePos: 680, + NameEnd: 696, + Name: "PersonOwnAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Element: &ast.PropertyGraphElementKey{ + Key: 703, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 707, + Rparen: 722, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 708, + NameEnd: 710, + Name: "id", + }, + &ast.Ident{ + NamePos: 712, + NameEnd: 722, + Name: "account_id", + }, + }, + }, + }, + Source: &ast.PropertyGraphSourceKey{ + Source: 730, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 741, + Rparen: 744, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 742, + NameEnd: 744, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 757, + NameEnd: 763, + Name: "Person", + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 809, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 825, + Rparen: 836, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 826, + NameEnd: 836, + Name: "account_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 849, + NameEnd: 856, + Name: "Account", + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 907, + Name: &ast.Ident{ + NamePos: 913, + NameEnd: 917, + Name: "Owns", + }, + }, + Properties: &ast.PropertyGraphPropertiesAre{ + Properties: 926, + Columns: 941, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 954, + NameEnd: 976, + Name: "AccountTransferAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 983, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 994, + Rparen: 997, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 995, + NameEnd: 997, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 1010, + NameEnd: 1017, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 1018, + Rparen: 1021, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1019, + NameEnd: 1021, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 1043, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 1059, + Rparen: 1065, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1060, + NameEnd: 1065, + Name: "to_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 1078, + NameEnd: 1085, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 1086, + Rparen: 1089, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 1087, + NameEnd: 1089, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 1116, + Name: &ast.Ident{ + NamePos: 1122, + NameEnd: 1131, + Name: "Transfers", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +CREATE OR REPLACE PROPERTY GRAPH FinGraph NODE TABLES (Account AS Account KEY (id) LABEL DetailedAccount PROPERTIES (create_time, is_blocked, nick_name AS name) DEFAULT LABEL NO PROPERTIES, Person PROPERTIES ARE ALL COLUMNS EXCEPT (city)) EDGE TABLES (PersonOwnAccount AS PersonOwnAccount KEY (id, account_id) SOURCE KEY (id) REFERENCES Person DESTINATION KEY (account_id) REFERENCES Account LABEL Owns PROPERTIES ARE ALL COLUMNS, AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers) diff --git a/testdata/result/statement/create_property_graph_if_not_exists_fingraph.sql.txt b/testdata/result/statement/create_property_graph_if_not_exists_fingraph.sql.txt new file mode 100644 index 00000000..a0869e1f --- /dev/null +++ b/testdata/result/statement/create_property_graph_if_not_exists_fingraph.sql.txt @@ -0,0 +1,228 @@ +--- create_property_graph_if_not_exists_fingraph.sql +CREATE PROPERTY GRAPH IF NOT EXISTS FinGraph + NODE TABLES ( + Account, + Person + ) + EDGE TABLES ( + PersonOwnAccount + SOURCE KEY (id) REFERENCES Person (id) + DESTINATION KEY (account_id) REFERENCES Account (id) + LABEL Owns, + AccountTransferAccount + SOURCE KEY (id) REFERENCES Account (id) + DESTINATION KEY (to_id) REFERENCES Account (id) + LABEL Transfers + ) +--- AST +&ast.CreatePropertyGraph{ + IfNotExists: true, + Name: &ast.Ident{ + NamePos: 36, + NameEnd: 44, + Name: "FinGraph", + }, + Content: &ast.PropertyGraphContent{ + NodeTables: &ast.PropertyGraphNodeTables{ + Node: 47, + Tables: &ast.PropertyGraphElementList{ + Lparen: 59, + Rparen: 87, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 65, + NameEnd: 72, + Name: "Account", + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 78, + NameEnd: 84, + Name: "Person", + }, + }, + }, + }, + }, + EdgeTables: &ast.PropertyGraphEdgeTables{ + Edge: 91, + Tables: &ast.PropertyGraphElementList{ + Lparen: 103, + Rparen: 399, + Elements: []*ast.PropertyGraphElement{ + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 109, + NameEnd: 125, + Name: "PersonOwnAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 132, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 143, + Rparen: 146, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 144, + NameEnd: 146, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 159, + NameEnd: 165, + Name: "Person", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 166, + Rparen: 169, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 167, + NameEnd: 169, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 177, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 193, + Rparen: 204, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 194, + NameEnd: 204, + Name: "account_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 217, + NameEnd: 224, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 225, + Rparen: 228, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 226, + NameEnd: 228, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 236, + Name: &ast.Ident{ + NamePos: 242, + NameEnd: 246, + Name: "Owns", + }, + }, + }, + }, + }, + }, + &ast.PropertyGraphElement{ + Name: &ast.Ident{ + NamePos: 252, + NameEnd: 274, + Name: "AccountTransferAccount", + }, + Keys: &ast.PropertyGraphEdgeElementKeys{ + Source: &ast.PropertyGraphSourceKey{ + Source: 281, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 292, + Rparen: 295, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 293, + NameEnd: 295, + Name: "id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 308, + NameEnd: 315, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 316, + Rparen: 319, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 317, + NameEnd: 319, + Name: "id", + }, + }, + }, + }, + Destination: &ast.PropertyGraphDestinationKey{ + Destination: 327, + Keys: &ast.PropertyGraphColumnNameList{ + Lparen: 343, + Rparen: 349, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 344, + NameEnd: 349, + Name: "to_id", + }, + }, + }, + ElementReference: &ast.Ident{ + NamePos: 362, + NameEnd: 369, + Name: "Account", + }, + ReferenceColumns: &ast.PropertyGraphColumnNameList{ + Lparen: 370, + Rparen: 373, + ColumnNameList: []*ast.Ident{ + &ast.Ident{ + NamePos: 371, + NameEnd: 373, + Name: "id", + }, + }, + }, + }, + }, + Properties: &ast.PropertyGraphLabelAndPropertiesList{ + LabelAndProperties: []*ast.PropertyGraphLabelAndProperties{ + &ast.PropertyGraphLabelAndProperties{ + Label: &ast.PropertyGraphElementLabelLabelName{ + Label: 381, + Name: &ast.Ident{ + NamePos: 387, + NameEnd: 396, + Name: "Transfers", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +CREATE PROPERTY GRAPH IF NOT EXISTS FinGraph NODE TABLES (Account, Person) EDGE TABLES (PersonOwnAccount SOURCE KEY (id) REFERENCES Person (id) DESTINATION KEY (account_id) REFERENCES Account (id) LABEL Owns, AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers) diff --git a/testdata/result/statement/drop_property_graph.sql.txt b/testdata/result/statement/drop_property_graph.sql.txt new file mode 100644 index 00000000..1a41bcbc --- /dev/null +++ b/testdata/result/statement/drop_property_graph.sql.txt @@ -0,0 +1,14 @@ +--- drop_property_graph.sql +DROP PROPERTY GRAPH FinGraph + +--- AST +&ast.DropPropertyGraph{ + Name: &ast.Ident{ + NamePos: 20, + NameEnd: 28, + Name: "FinGraph", + }, +} + +--- SQL +DROP PROPERTY GRAPH FinGraph diff --git a/testdata/result/statement/drop_property_graph_if_exists.sql.txt b/testdata/result/statement/drop_property_graph_if_exists.sql.txt new file mode 100644 index 00000000..3f0efc34 --- /dev/null +++ b/testdata/result/statement/drop_property_graph_if_exists.sql.txt @@ -0,0 +1,15 @@ +--- drop_property_graph_if_exists.sql +DROP PROPERTY GRAPH IF EXISTS FinGraph + +--- AST +&ast.DropPropertyGraph{ + IfExists: true, + Name: &ast.Ident{ + NamePos: 30, + NameEnd: 38, + Name: "FinGraph", + }, +} + +--- SQL +DROP PROPERTY GRAPH IF EXISTS FinGraph