@@ -4192,26 +4192,57 @@ func (p *Parser) parseCreateExternalDataSourceStatement() (*ast.CreateExternalDa
41924192
41934193 // Parse WITH clause
41944194 if p .curTok .Type == TokenWith {
4195+ // Default to EXTERNAL_GENERICS if WITH clause exists but no TYPE specified
4196+ stmt .DataSourceType = "EXTERNAL_GENERICS"
41954197 p .nextToken () // consume WITH
41964198 if p .curTok .Type != TokenLParen {
41974199 return nil , fmt .Errorf ("expected ( after WITH, got %s" , p .curTok .Literal )
41984200 }
41994201 p .nextToken () // consume (
42004202
42014203 for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
4202- opt := & ast.ExternalDataSourceOption {
4203- OptionKind : p .curTok .Literal ,
4204- }
4204+ optName := strings .ToUpper (p .curTok .Literal )
42054205 p .nextToken () // consume option name
42064206 if p .curTok .Type == TokenEquals {
4207+ p .nextToken () // consume =
4208+ }
4209+
4210+ switch optName {
4211+ case "TYPE" :
4212+ // TYPE sets DataSourceType
4213+ stmt .DataSourceType = strings .ToUpper (p .curTok .Literal )
42074214 p .nextToken ()
4208- val , err := p .parseScalarExpression ()
4215+ case "LOCATION" :
4216+ // LOCATION sets Location as StringLiteral
4217+ strLit , err := p .parseStringLiteral ()
42094218 if err != nil {
42104219 return nil , err
42114220 }
4212- opt .Value = val
4221+ stmt .Location = strLit
4222+ default :
4223+ // All other options go into ExternalDataSourceOptions
4224+ opt := & ast.ExternalDataSourceLiteralOrIdentifierOption {
4225+ OptionKind : externalDataSourceOptionKindToPascalCase (optName ),
4226+ Value : & ast.IdentifierOrValueExpression {},
4227+ }
4228+
4229+ // Determine if value is identifier or string literal
4230+ if p .curTok .Type == TokenString {
4231+ strLit , err := p .parseStringLiteral ()
4232+ if err != nil {
4233+ return nil , err
4234+ }
4235+ opt .Value .Value = strLit .Value
4236+ opt .Value .ValueExpression = strLit
4237+ } else {
4238+ // It's an identifier
4239+ ident := p .parseIdentifier ()
4240+ opt .Value .Value = ident .Value
4241+ opt .Value .Identifier = ident
4242+ }
4243+ stmt .ExternalDataSourceOptions = append (stmt .ExternalDataSourceOptions , opt )
42134244 }
4214- stmt . Options = append ( stmt . Options , opt )
4245+
42154246 if p .curTok .Type == TokenComma {
42164247 p .nextToken ()
42174248 }
@@ -4227,6 +4258,26 @@ func (p *Parser) parseCreateExternalDataSourceStatement() (*ast.CreateExternalDa
42274258 return stmt , nil
42284259}
42294260
4261+ // externalDataSourceOptionKindToPascalCase converts option names to PascalCase
4262+ func externalDataSourceOptionKindToPascalCase (optName string ) string {
4263+ switch strings .ToUpper (optName ) {
4264+ case "CREDENTIAL" :
4265+ return "Credential"
4266+ case "RESOURCE_MANAGER_LOCATION" :
4267+ return "ResourceManagerLocation"
4268+ case "DATABASE_NAME" :
4269+ return "DatabaseName"
4270+ case "SHARD_MAP_NAME" :
4271+ return "ShardMapName"
4272+ case "CONNECTION_OPTIONS" :
4273+ return "ConnectionOptions"
4274+ case "PUSHDOWN" :
4275+ return "Pushdown"
4276+ default :
4277+ return optName
4278+ }
4279+ }
4280+
42304281func (p * Parser ) parseCreateExternalFileFormatStatement () (* ast.CreateExternalFileFormatStatement , error ) {
42314282 // FILE FORMAT name WITH (options)
42324283 p .nextToken () // consume FILE
0 commit comments