Skip to content

Commit 15a628f

Browse files
committed
Add comprehensive data type parsing support
- Add double-quoted identifier support for data types like "xml" - Add multi-word type names: CHAR VARYING -> VarChar, DOUBLE PRECISION -> Float - Add multi-part type names for user-defined types (dbo.mytype, db.schema.type) - Add parameter parsing for user-defined types (mytype(10), mytype(max)) - Add Parameters field marshaling to userDataTypeReferenceToJSON Enables ScalarDataTypeTests90 and Baselines90_ScalarDataTypeTests90 tests.
1 parent 4514c78 commit 15a628f

4 files changed

Lines changed: 84 additions & 6 deletions

File tree

parser/marshal.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5283,6 +5283,13 @@ func userDataTypeReferenceToJSON(dt *ast.UserDataTypeReference) jsonNode {
52835283
node := jsonNode{
52845284
"$type": "UserDataTypeReference",
52855285
}
5286+
if len(dt.Parameters) > 0 {
5287+
params := make([]jsonNode, len(dt.Parameters))
5288+
for i, p := range dt.Parameters {
5289+
params[i] = scalarExpressionToJSON(p)
5290+
}
5291+
node["Parameters"] = params
5292+
}
52865293
if dt.Name != nil {
52875294
node["Name"] = schemaObjectNameToJSON(dt.Name)
52885295
}

parser/parse_statements.go

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,10 +671,13 @@ func (p *Parser) parseDataTypeReference() (ast.DataTypeReference, error) {
671671
var quoteType string
672672
literal := p.curTok.Literal
673673

674-
// Check if this is a bracketed identifier like [int]
674+
// Check if this is a bracketed or quoted identifier
675675
if len(literal) >= 2 && literal[0] == '[' && literal[len(literal)-1] == ']' {
676676
typeName = literal[1 : len(literal)-1]
677677
quoteType = "SquareBracket"
678+
} else if len(literal) >= 2 && literal[0] == '"' && literal[len(literal)-1] == '"' {
679+
typeName = literal[1 : len(literal)-1]
680+
quoteType = "DoubleQuote"
678681
} else {
679682
typeName = literal
680683
quoteType = "NotQuoted"
@@ -726,11 +729,79 @@ func (p *Parser) parseDataTypeReference() (ast.DataTypeReference, error) {
726729
// Check if this is a known SQL data type
727730
sqlOption, isKnownType := getSqlDataTypeOption(typeName)
728731

732+
// Check for multi-word types: CHAR VARYING -> VarChar, DOUBLE PRECISION -> Float
733+
if upper := strings.ToUpper(typeName); upper == "CHAR" || upper == "DOUBLE" {
734+
nextUpper := strings.ToUpper(p.curTok.Literal)
735+
if upper == "CHAR" && nextUpper == "VARYING" {
736+
sqlOption = "VarChar"
737+
isKnownType = true
738+
p.nextToken() // consume VARYING
739+
} else if upper == "DOUBLE" && nextUpper == "PRECISION" {
740+
baseName.BaseIdentifier.Value = "FLOAT" // Use FLOAT for output
741+
sqlOption = "Float"
742+
isKnownType = true
743+
p.nextToken() // consume PRECISION
744+
}
745+
}
746+
729747
if !isKnownType {
730-
// Return UserDataTypeReference for unknown types
731-
return &ast.UserDataTypeReference{
748+
// Check for multi-part type name (e.g., dbo.mytype)
749+
if p.curTok.Type == TokenDot {
750+
p.nextToken() // consume .
751+
// Get the next identifier
752+
nextIdent := p.parseIdentifier()
753+
// Schema.Type structure
754+
baseName.SchemaIdentifier = baseId
755+
baseName.BaseIdentifier = nextIdent
756+
baseName.Count = 2
757+
baseName.Identifiers = []*ast.Identifier{baseId, nextIdent}
758+
759+
// Check for third part: database.schema.type
760+
if p.curTok.Type == TokenDot {
761+
p.nextToken() // consume .
762+
thirdIdent := p.parseIdentifier()
763+
// Database.Schema.Type structure
764+
baseName.DatabaseIdentifier = baseId
765+
baseName.SchemaIdentifier = nextIdent
766+
baseName.BaseIdentifier = thirdIdent
767+
baseName.Count = 3
768+
baseName.Identifiers = []*ast.Identifier{baseId, nextIdent, thirdIdent}
769+
}
770+
}
771+
772+
userRef := &ast.UserDataTypeReference{
732773
Name: baseName,
733-
}, nil
774+
}
775+
776+
// Check for parameters: mytype(10) or mytype(10, 20) or mytype(max)
777+
if p.curTok.Type == TokenLParen {
778+
p.nextToken() // consume (
779+
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
780+
// Special case: MAX keyword
781+
if p.curTok.Type == TokenIdent && strings.ToUpper(p.curTok.Literal) == "MAX" {
782+
userRef.Parameters = append(userRef.Parameters, &ast.MaxLiteral{
783+
LiteralType: "Max",
784+
Value: p.curTok.Literal,
785+
})
786+
p.nextToken()
787+
} else {
788+
expr, err := p.parseScalarExpression()
789+
if err != nil {
790+
return nil, err
791+
}
792+
userRef.Parameters = append(userRef.Parameters, expr)
793+
}
794+
if p.curTok.Type != TokenComma {
795+
break
796+
}
797+
p.nextToken() // consume comma
798+
}
799+
if p.curTok.Type == TokenRParen {
800+
p.nextToken() // consume )
801+
}
802+
}
803+
804+
return userRef, nil
734805
}
735806

736807
dt := &ast.SqlDataTypeReference{
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)