Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions mssql/ast/loc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ func NodeLoc(n Node) Loc {
return v.Loc
case *FuncCallExpr:
return v.Loc
case *DatePart:
return v.Loc
case *NextValueForExpr:
return v.Loc
case *ParseExpr:
return v.Loc
case *JsonKeyValueExpr:
return v.Loc
case *CaseExpr:
return v.Loc
case *CaseWhen:
Expand Down
4 changes: 4 additions & 0 deletions mssql/ast/loc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func TestNodeLocExpressions(t *testing.T) {
}{
{"BinaryExpr", &BinaryExpr{Loc: Loc{Start: 1, End: 2}}, Loc{Start: 1, End: 2}},
{"FuncCallExpr", &FuncCallExpr{Loc: Loc{Start: 2, End: 5}}, Loc{Start: 2, End: 5}},
{"DatePart", &DatePart{Loc: Loc{Start: 2, End: 6}}, Loc{Start: 2, End: 6}},
{"NextValueForExpr", &NextValueForExpr{Loc: Loc{Start: 2, End: 7}}, Loc{Start: 2, End: 7}},
{"ParseExpr", &ParseExpr{Loc: Loc{Start: 2, End: 8}}, Loc{Start: 2, End: 8}},
{"JsonKeyValueExpr", &JsonKeyValueExpr{Loc: Loc{Start: 2, End: 9}}, Loc{Start: 2, End: 9}},
{"ColumnRef", &ColumnRef{Loc: Loc{Start: 3, End: 4}}, Loc{Start: 3, End: 4}},
{"LikeExpr", &LikeExpr{Loc: Loc{Start: 4, End: 9}}, Loc{Start: 4, End: 9}},
}
Expand Down
82 changes: 82 additions & 0 deletions mssql/ast/outfuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ func writeNode(sb *strings.Builder, node Node) {
writeUnaryExpr(sb, n)
case *FuncCallExpr:
writeFuncCallExpr(sb, n)
case *DatePart:
writeDatePart(sb, n)
case *NextValueForExpr:
writeNextValueForExpr(sb, n)
case *ParseExpr:
writeParseExpr(sb, n)
case *JsonKeyValueExpr:
writeJsonKeyValueExpr(sb, n)
case *CaseExpr:
writeCaseExpr(sb, n)
case *CaseWhen:
Expand Down Expand Up @@ -1901,6 +1909,22 @@ func writeFuncCallExpr(sb *strings.Builder, n *FuncCallExpr) {
if n.Distinct {
sb.WriteString(" :distinct true")
}
if n.TrimOption != "" {
sb.WriteString(fmt.Sprintf(" :trimOption \"%s\"", escapeString(n.TrimOption)))
}
if n.NullTreatment != "" {
sb.WriteString(fmt.Sprintf(" :nullTreatment \"%s\"", escapeString(n.NullTreatment)))
}
if n.JsonNullClause != "" {
sb.WriteString(fmt.Sprintf(" :jsonNullClause \"%s\"", escapeString(n.JsonNullClause)))
}
if n.ReturnType != nil {
sb.WriteString(" :returnType ")
writeNode(sb, n.ReturnType)
}
if n.WithArrayWrapper {
sb.WriteString(" :withArrayWrapper true")
}
if n.Over != nil {
sb.WriteString(" :over ")
writeNode(sb, n.Over)
Expand Down Expand Up @@ -2129,6 +2153,64 @@ func writeIifExpr(sb *strings.Builder, n *IifExpr) {
sb.WriteString("}")
}

func writeDatePart(sb *strings.Builder, n *DatePart) {
sb.WriteString("{DATEPART")
if n.Name != "" {
sb.WriteString(fmt.Sprintf(" :name \"%s\"", escapeString(n.Name)))
}
sb.WriteString(fmt.Sprintf(" :loc %d %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeNextValueForExpr(sb *strings.Builder, n *NextValueForExpr) {
sb.WriteString("{NEXTVALUEFOR")
if n.Sequence != nil {
sb.WriteString(" :sequence ")
writeNode(sb, n.Sequence)
}
if n.Over != nil {
sb.WriteString(" :over ")
writeNode(sb, n.Over)
}
sb.WriteString(fmt.Sprintf(" :loc %d %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeParseExpr(sb *strings.Builder, n *ParseExpr) {
sb.WriteString("{PARSE")
if n.Try {
sb.WriteString(" :try true")
}
if n.Expr != nil {
sb.WriteString(" :expr ")
writeNode(sb, n.Expr)
}
if n.DataType != nil {
sb.WriteString(" :dataType ")
writeNode(sb, n.DataType)
}
if n.Culture != nil {
sb.WriteString(" :culture ")
writeNode(sb, n.Culture)
}
sb.WriteString(fmt.Sprintf(" :loc %d %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeJsonKeyValueExpr(sb *strings.Builder, n *JsonKeyValueExpr) {
sb.WriteString("{JSONKEYVALUE")
if n.Key != nil {
sb.WriteString(" :key ")
writeNode(sb, n.Key)
}
if n.Value != nil {
sb.WriteString(" :value ")
writeNode(sb, n.Value)
}
sb.WriteString(fmt.Sprintf(" :loc %d %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeColumnRef(sb *strings.Builder, n *ColumnRef) {
sb.WriteString("{COLREF")
if n.Server != "" {
Expand Down
61 changes: 54 additions & 7 deletions mssql/ast/parsenodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -1625,19 +1625,66 @@ const (

// FuncCallExpr represents a function call.
type FuncCallExpr struct {
Name *TableRef // potentially schema-qualified
Args *List
Distinct bool
Star bool // e.g., COUNT(*)
Over *OverClause
Within *List // WITHIN GROUP (ORDER BY ...)
Loc Loc
Name *TableRef // potentially schema-qualified
Args *List
Distinct bool
Star bool // e.g., COUNT(*)
TrimOption string // LEADING, TRAILING, or BOTH for TRIM
NullTreatment string // IGNORE or RESPECT for window null treatment
JsonNullClause string // NULL or ABSENT for JSON constructors
ReturnType *DataType
WithArrayWrapper bool
Over *OverClause
Within *List // WITHIN GROUP (ORDER BY ...)
Loc Loc
}

func (n *FuncCallExpr) nodeTag() {}
func (n *FuncCallExpr) exprNode() {}
func (n *FuncCallExpr) tableExpr() {} // table-valued functions can appear in FROM

// DatePart represents a T-SQL datepart token used by date/time functions such
// as DATEADD, DATEDIFF, DATEPART, DATENAME, DATETRUNC, and DATE_BUCKET.
type DatePart struct {
Name string
Loc Loc
}

func (n *DatePart) nodeTag() {}
func (n *DatePart) exprNode() {}

// NextValueForExpr represents NEXT VALUE FOR sequence_name.
type NextValueForExpr struct {
Sequence *TableRef
Over *OverClause
Loc Loc
}

func (n *NextValueForExpr) nodeTag() {}
func (n *NextValueForExpr) exprNode() {}

// ParseExpr represents PARSE or TRY_PARSE.
type ParseExpr struct {
Try bool
Expr ExprNode
DataType *DataType
Culture ExprNode
Loc Loc
}

func (n *ParseExpr) nodeTag() {}
func (n *ParseExpr) exprNode() {}

// JsonKeyValueExpr represents JSON_OBJECT key:value entries.
type JsonKeyValueExpr struct {
Key ExprNode
Value ExprNode
Loc Loc
}

func (n *JsonKeyValueExpr) nodeTag() {}
func (n *JsonKeyValueExpr) exprNode() {}

// CaseExpr represents a CASE expression.
// Ref: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql
type CaseExpr struct {
Expand Down
19 changes: 19 additions & 0 deletions mssql/ast/walk_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mssql/ast/walk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func allKnownNodes() []Node {
&LikeExpr{}, &IsExpr{}, &ExistsExpr{},
&CastExpr{}, &ConvertExpr{}, &TryCastExpr{}, &TryConvertExpr{},
&CoalesceExpr{}, &NullifExpr{}, &IifExpr{},
&DatePart{}, &NextValueForExpr{}, &ParseExpr{}, &JsonKeyValueExpr{},
&ColumnRef{}, &VariableRef{}, &StarExpr{}, &Literal{},
&SubqueryExpr{}, &SubqueryComparisonExpr{},
&CollateExpr{}, &AtTimeZoneExpr{}, &ParenExpr{},
Expand Down
Loading
Loading