Skip to content

Commit

Permalink
chore+fix: CySQL fixups to cover BED-5331, BED-5332, BED-5411, and BE…
Browse files Browse the repository at this point in the history
…D-5412 (#1145)
  • Loading branch information
zinic authored Feb 12, 2025
1 parent acb0c50 commit 75f9216
Show file tree
Hide file tree
Showing 43 changed files with 3,549 additions and 3,035 deletions.
17 changes: 8 additions & 9 deletions packages/go/cypher/models/pgsql/format/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,8 @@ func formatNode(builder *OutputBuilder, rootExpr pgsql.SyntaxNode) error {
case pgsql.Variadic:
exprStack = append(exprStack, typedNextExpr.Expression, pgsql.FormattingLiteral("variadic "))

case pgsql.CompoundExpression:
for idx := len(typedNextExpr) - 1; idx >= 0; idx-- {
exprStack = append(exprStack, typedNextExpr[idx])

if idx > 0 {
exprStack = append(exprStack, pgsql.FormattingLiteral("."))
}
}
case pgsql.RowColumnReference:
exprStack = append(exprStack, typedNextExpr.Column, pgsql.FormattingLiteral(")."), typedNextExpr.Identifier, pgsql.FormattingLiteral("("))

case pgsql.ExistsExpression:
exprStack = append(exprStack, typedNextExpr.Subquery, pgsql.FormattingLiteral("exists "))
Expand Down Expand Up @@ -520,6 +514,9 @@ func formatNode(builder *OutputBuilder, rootExpr pgsql.SyntaxNode) error {
case pgsql.Subquery:
exprStack = append(exprStack, pgsql.FormattingLiteral(")"), typedNextExpr.Query, pgsql.FormattingLiteral("("))

case pgsql.SyntaxNodeFuture:
exprStack = append(exprStack, typedNextExpr.Unwrap())

default:
return fmt.Errorf("unable to format pgsql node type: %T", nextExpr)
}
Expand Down Expand Up @@ -1097,7 +1094,9 @@ func Statement(statement pgsql.Statement, builder *OutputBuilder) (string, error
return builder.Build(), nil
}

func SyntaxNode(node pgsql.SyntaxNode, builder *OutputBuilder) (string, error) {
func SyntaxNode(node pgsql.SyntaxNode) (string, error) {
builder := NewOutputBuilder()

switch typedNode := node.(type) {
case pgsql.Statement:
return Statement(typedNode, builder)
Expand Down
2 changes: 1 addition & 1 deletion packages/go/cypher/models/pgsql/identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const (
)

var reservedIdentifiers = []Identifier{
EpochIdentifier,
EpochIdentifier, WildcardIdentifier,
}

func IsReservedIdentifier(identifier Identifier) bool {
Expand Down
53 changes: 45 additions & 8 deletions packages/go/cypher/models/pgsql/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package pgsql

import (
"context"
"fmt"
"strings"

"github.com/specterops/bloodhound/dawgs/graph"
Expand Down Expand Up @@ -224,6 +225,43 @@ func (s Literal) NodeType() string {
return "literal"
}

type Future[U any] struct {
SyntaxNode SyntaxNode
Data U
DataType DataType
}

func NewFuture[U any](data U, dataType DataType) *Future[U] {
return &Future[U]{
Data: data,
DataType: dataType,
}
}

func (s Future[U]) Satisfied() bool {
return s.SyntaxNode != nil
}

func (s Future[U]) Unwrap() SyntaxNode {
return s.SyntaxNode
}

func (s Future[U]) TypeHint() DataType {
return s.DataType
}

func (s Future[U]) NodeType() string {
var (
emptyU U
)

return fmt.Sprintf("syntax_node_future[%T]", emptyU)
}

func (s Future[U]) AsExpression() Expression {
return s
}

type Subquery struct {
Query Query
}
Expand Down Expand Up @@ -572,21 +610,20 @@ func (s ArrayIndex) AsExpression() Expression {
return s
}

type CompoundExpression []Expression

func (s CompoundExpression) NodeType() string {
return "compound_expression"
type RowColumnReference struct {
Identifier Expression
Column Identifier
}

func (s CompoundExpression) AsExpression() Expression {
return s
func (s RowColumnReference) NodeType() string {
return "row_member_reference"
}

func (s CompoundExpression) AsSlice() []Expression {
func (s RowColumnReference) AsExpression() Expression {
return s
}

func (s CompoundExpression) AsSelectItem() SelectItem {
func (s RowColumnReference) AsSelectItem() SelectItem {
return s
}

Expand Down
15 changes: 15 additions & 0 deletions packages/go/cypher/models/pgsql/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ type SyntaxNode interface {
NodeType() string
}

// WrappedNode is an interface that allows for an expression to be wrapped to allow for side effects like futures.
type WrappedNode interface {
SyntaxNode
}

// SyntaxNodeFuture is a SyntaxNode that can be satisfied out-of-tree and communicate if it has been satisfied to
// upstream consumers. This is useful when a SyntaxNode is required to be embedded in a built syntax tree but
// can not be formally built itself due to ordering or missing dependency information (in the case of an
// existential subquery).
type SyntaxNodeFuture interface {
SyntaxNode
Unwrap() SyntaxNode
Satisfied() bool
}

// Statement is a syntax node that does not evaluate to a value.
type Statement interface {
SyntaxNode
Expand Down
3 changes: 1 addition & 2 deletions packages/go/cypher/models/pgsql/pgtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const (
JSONB DataType = "jsonb"
Numeric DataType = "numeric"

AnyArray DataType = "any[]"
AnyArray DataType = "anyarray"
NodeCompositeArray DataType = "nodecomposite[]"
EdgeCompositeArray DataType = "edgecomposite[]"
IntArray DataType = "int[]"
Expand All @@ -110,7 +110,6 @@ const (
TimestampWithoutTimeZone DataType = "timestamp without time zone"

Scope DataType = "scope"
InlineProjection DataType = "inline_projection"
ParameterIdentifier DataType = "parameter_identifier"
ExpansionPattern DataType = "expansion_pattern"
ExpansionPath DataType = "expansion_path"
Expand Down
20 changes: 8 additions & 12 deletions packages/go/cypher/models/pgsql/test/translation_cases/delete.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,36 @@
with s0 as (select (n0.id, n0.kind_ids, n0.properties)::nodecomposite as n0
from node n0
where n0.kind_ids operator (pg_catalog.&&) array [1]::int2[]),
s1
as (delete from node n1 using s0 where (s0.n0).id = n1.id returning (n1.id, n1.kind_ids, n1.properties)::nodecomposite as n0)
s1 as (delete from node n1 using s0 where (s0.n0).id = n1.id)
select 1;

-- case: match ()-[r:EdgeKind1]->() delete r
with s0 as (select (n0.id, n0.kind_ids, n0.properties)::nodecomposite as n0,
(e0.id, e0.start_id, e0.end_id, e0.kind_id, e0.properties)::edgecomposite as e0,
with s0 as (select (e0.id, e0.start_id, e0.end_id, e0.kind_id, e0.properties)::edgecomposite as e0,
(n0.id, n0.kind_ids, n0.properties)::nodecomposite as n0,
(n1.id, n1.kind_ids, n1.properties)::nodecomposite as n1
from edge e0
join node n0 on n0.id = e0.start_id
join node n1 on n1.id = e0.end_id
where e0.kind_id = any (array [3]::int2[])),
s1
as (delete from edge e1 using s0 where (s0.e0).id = e1.id returning (e1.id, e1.start_id, e1.end_id, e1.kind_id, e1.properties)::edgecomposite as e0, s0.n0 as n0, s0.n1 as n1)
s1 as (delete from edge e1 using s0 where (s0.e0).id = e1.id)
select 1;

-- case: match ()-[]->()-[r:EdgeKind1]->() delete r
with s0 as (select (n0.id, n0.kind_ids, n0.properties)::nodecomposite as n0,
(e0.id, e0.start_id, e0.end_id, e0.kind_id, e0.properties)::edgecomposite as e0,
with s0 as (select (e0.id, e0.start_id, e0.end_id, e0.kind_id, e0.properties)::edgecomposite as e0,
(n0.id, n0.kind_ids, n0.properties)::nodecomposite as n0,
(n1.id, n1.kind_ids, n1.properties)::nodecomposite as n1
from edge e0
join node n0 on n0.id = e0.start_id
join node n1 on n1.id = e0.end_id),
s1 as (select s0.e0 as e0,
(e1.id, e1.start_id, e1.end_id, e1.kind_id, e1.properties)::edgecomposite as e1,
s0.n0 as n0,
s0.n1 as n1,
(e1.id, e1.start_id, e1.end_id, e1.kind_id, e1.properties)::edgecomposite as e1,
(n2.id, n2.kind_ids, n2.properties)::nodecomposite as n2
from s0,
edge e1
join node n2 on n2.id = e1.end_id
where e1.kind_id = any (array [3]::int2[])
and (s0.n1).id = e1.start_id),
s2
as (delete from edge e2 using s1 where (s1.e1).id = e2.id returning s1.e0 as e0, (e2.id, e2.start_id, e2.end_id, e2.kind_id, e2.properties)::edgecomposite as e1, s1.n0 as n0, s1.n1 as n1, s1.n2 as n2)
s2 as (delete from edge e2 using s1 where (s1.e1).id = e2.id)
select 1;

Loading

0 comments on commit 75f9216

Please sign in to comment.