Skip to content

Commit 4fcb35e

Browse files
committed
Add COLLATE clause support for expressions
- Add Collation field to FunctionCall and ColumnReferenceExpression AST types - Parse COLLATE clause after expressions in SELECT elements - Add COLLATE to excluded alias keywords to prevent misinterpretation - Update marshalling for both FunctionCall and ColumnReferenceExpression to include Collation field in JSON output Enables 4 tests: SelectWithCollation, Baselines110/120/130_SelectWithCollation
1 parent 0a9ea05 commit 4fcb35e

8 files changed

Lines changed: 29 additions & 5 deletions

File tree

ast/column_reference_expression.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package ast
44
type ColumnReferenceExpression struct {
55
ColumnType string `json:"ColumnType,omitempty"`
66
MultiPartIdentifier *MultiPartIdentifier `json:"MultiPartIdentifier,omitempty"`
7+
Collation *Identifier `json:"Collation,omitempty"`
78
}
89

910
func (*ColumnReferenceExpression) node() {}

ast/function_call.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type FunctionCall struct {
5050
OverClause *OverClause `json:"OverClause,omitempty"`
5151
IgnoreRespectNulls []*Identifier `json:"IgnoreRespectNulls,omitempty"`
5252
WithArrayWrapper bool `json:"WithArrayWrapper,omitempty"`
53+
Collation *Identifier `json:"Collation,omitempty"`
5354
}
5455

5556
func (*FunctionCall) node() {}

parser/marshal.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,9 @@ func scalarExpressionToJSON(expr ast.ScalarExpression) jsonNode {
13161316
if e.MultiPartIdentifier != nil {
13171317
node["MultiPartIdentifier"] = multiPartIdentifierToJSON(e.MultiPartIdentifier)
13181318
}
1319+
if e.Collation != nil {
1320+
node["Collation"] = identifierToJSON(e.Collation)
1321+
}
13191322
return node
13201323
case *ast.IntegerLiteral:
13211324
node := jsonNode{
@@ -1401,6 +1404,9 @@ func scalarExpressionToJSON(expr ast.ScalarExpression) jsonNode {
14011404
node["IgnoreRespectNulls"] = idents
14021405
}
14031406
node["WithArrayWrapper"] = e.WithArrayWrapper
1407+
if e.Collation != nil {
1408+
node["Collation"] = identifierToJSON(e.Collation)
1409+
}
14041410
return node
14051411
case *ast.UserDefinedTypePropertyAccess:
14061412
node := jsonNode{
@@ -5510,6 +5516,9 @@ func columnReferenceExpressionToJSON(c *ast.ColumnReferenceExpression) jsonNode
55105516
if c.MultiPartIdentifier != nil {
55115517
node["MultiPartIdentifier"] = multiPartIdentifierToJSON(c.MultiPartIdentifier)
55125518
}
5519+
if c.Collation != nil {
5520+
node["Collation"] = identifierToJSON(c.Collation)
5521+
}
55135522
return node
55145523
}
55155524

parser/parse_select.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,19 @@ func (p *Parser) parseSelectElement() (ast.SelectElement, error) {
479479
}
480480
}
481481

482+
// Check for COLLATE clause before creating SelectScalarExpression
483+
if p.curTok.Type == TokenIdent && strings.ToUpper(p.curTok.Literal) == "COLLATE" {
484+
p.nextToken() // consume COLLATE
485+
collation := p.parseIdentifier()
486+
// Attach collation to the expression
487+
switch e := expr.(type) {
488+
case *ast.FunctionCall:
489+
e.Collation = collation
490+
case *ast.ColumnReferenceExpression:
491+
e.Collation = collation
492+
}
493+
}
494+
482495
sse := &ast.SelectScalarExpression{Expression: expr}
483496

484497
// Check for column alias: [alias], AS alias, or just alias
@@ -509,7 +522,7 @@ func (p *Parser) parseSelectElement() (ast.SelectElement, error) {
509522
} else if p.curTok.Type == TokenIdent {
510523
// Check if this is an alias (not a keyword that starts a new clause)
511524
upper := strings.ToUpper(p.curTok.Literal)
512-
if upper != "FROM" && upper != "WHERE" && upper != "GROUP" && upper != "HAVING" && upper != "ORDER" && upper != "OPTION" && upper != "INTO" && upper != "UNION" && upper != "EXCEPT" && upper != "INTERSECT" && upper != "GO" {
525+
if upper != "FROM" && upper != "WHERE" && upper != "GROUP" && upper != "HAVING" && upper != "ORDER" && upper != "OPTION" && upper != "INTO" && upper != "UNION" && upper != "EXCEPT" && upper != "INTERSECT" && upper != "GO" && upper != "COLLATE" {
513526
alias := p.parseIdentifier()
514527
sse.ColumnName = &ast.IdentifierOrValueExpression{
515528
Value: alias.Value,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}

0 commit comments

Comments
 (0)