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
32 changes: 32 additions & 0 deletions ast/alter_server_configuration_statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,35 @@ type OnOffOptionValue struct {
}

func (o *OnOffOptionValue) node() {}

// AlterServerConfigurationSetExternalAuthenticationStatement represents ALTER SERVER CONFIGURATION SET EXTERNAL AUTHENTICATION statement
type AlterServerConfigurationSetExternalAuthenticationStatement struct {
Options []*AlterServerConfigurationExternalAuthenticationContainerOption
}

func (a *AlterServerConfigurationSetExternalAuthenticationStatement) node() {}
func (a *AlterServerConfigurationSetExternalAuthenticationStatement) statement() {}

// AlterServerConfigurationExternalAuthenticationContainerOption represents the container option for external authentication
type AlterServerConfigurationExternalAuthenticationContainerOption struct {
OptionKind string // "OnOff"
OptionValue *OnOffOptionValue // ON or OFF
Suboptions []*AlterServerConfigurationExternalAuthenticationOption // suboptions inside parentheses
}

func (a *AlterServerConfigurationExternalAuthenticationContainerOption) node() {}

// AlterServerConfigurationExternalAuthenticationOption represents an external authentication suboption
type AlterServerConfigurationExternalAuthenticationOption struct {
OptionKind string // "UseIdentity", "CredentialName"
OptionValue *LiteralOptionValue // optional, for CredentialName
}

func (a *AlterServerConfigurationExternalAuthenticationOption) node() {}

// LiteralOptionValue represents a literal option value
type LiteralOptionValue struct {
Value ScalarExpression
}

func (l *LiteralOptionValue) node() {}
55 changes: 55 additions & 0 deletions parser/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ func statementToJSON(stmt ast.Statement) jsonNode {
return alterXmlSchemaCollectionStatementToJSON(s)
case *ast.AlterServerConfigurationSetSoftNumaStatement:
return alterServerConfigurationSetSoftNumaStatementToJSON(s)
case *ast.AlterServerConfigurationSetExternalAuthenticationStatement:
return alterServerConfigurationSetExternalAuthenticationStatementToJSON(s)
case *ast.AlterServerConfigurationStatement:
return alterServerConfigurationStatementToJSON(s)
case *ast.AlterLoginAddDropCredentialStatement:
Expand Down Expand Up @@ -3578,6 +3580,59 @@ func onOffOptionValueToJSON(o *ast.OnOffOptionValue) jsonNode {
}
}

func alterServerConfigurationSetExternalAuthenticationStatementToJSON(s *ast.AlterServerConfigurationSetExternalAuthenticationStatement) jsonNode {
node := jsonNode{
"$type": "AlterServerConfigurationSetExternalAuthenticationStatement",
}
if len(s.Options) > 0 {
options := make([]jsonNode, len(s.Options))
for i, o := range s.Options {
options[i] = alterServerConfigurationExternalAuthenticationContainerOptionToJSON(o)
}
node["Options"] = options
}
return node
}

func alterServerConfigurationExternalAuthenticationContainerOptionToJSON(o *ast.AlterServerConfigurationExternalAuthenticationContainerOption) jsonNode {
node := jsonNode{
"$type": "AlterServerConfigurationExternalAuthenticationContainerOption",
}
if len(o.Suboptions) > 0 {
suboptions := make([]jsonNode, len(o.Suboptions))
for i, s := range o.Suboptions {
suboptions[i] = alterServerConfigurationExternalAuthenticationOptionToJSON(s)
}
node["Suboptions"] = suboptions
}
node["OptionKind"] = o.OptionKind
if o.OptionValue != nil {
node["OptionValue"] = onOffOptionValueToJSON(o.OptionValue)
}
return node
}

func alterServerConfigurationExternalAuthenticationOptionToJSON(o *ast.AlterServerConfigurationExternalAuthenticationOption) jsonNode {
node := jsonNode{
"$type": "AlterServerConfigurationExternalAuthenticationOption",
"OptionKind": o.OptionKind,
}
if o.OptionValue != nil {
node["OptionValue"] = literalOptionValueToJSON(o.OptionValue)
}
return node
}

func literalOptionValueToJSON(o *ast.LiteralOptionValue) jsonNode {
node := jsonNode{
"$type": "LiteralOptionValue",
}
if o.Value != nil {
node["Value"] = scalarExpressionToJSON(o.Value)
}
return node
}

func alterServerConfigurationStatementToJSON(s *ast.AlterServerConfigurationStatement) jsonNode {
node := jsonNode{
"$type": "AlterServerConfigurationStatement",
Expand Down
91 changes: 91 additions & 0 deletions parser/parse_ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,8 @@ func (p *Parser) parseAlterServerConfigurationStatement() (ast.Statement, error)
return p.parseAlterServerConfigurationSetSoftNumaStatement()
case "PROCESS":
return p.parseAlterServerConfigurationSetProcessAffinityStatement()
case "EXTERNAL":
return p.parseAlterServerConfigurationSetExternalAuthenticationStatement()
default:
return nil, fmt.Errorf("unexpected token after SET: %s", p.curTok.Literal)
}
Expand Down Expand Up @@ -1828,6 +1830,95 @@ func (p *Parser) parseAlterServerConfigurationSetSoftNumaStatement() (*ast.Alter
return stmt, nil
}

func (p *Parser) parseAlterServerConfigurationSetExternalAuthenticationStatement() (*ast.AlterServerConfigurationSetExternalAuthenticationStatement, error) {
// Consume EXTERNAL
p.nextToken()

// Expect AUTHENTICATION
if strings.ToUpper(p.curTok.Literal) != "AUTHENTICATION" {
return nil, fmt.Errorf("expected AUTHENTICATION after EXTERNAL, got %s", p.curTok.Literal)
}
p.nextToken()

stmt := &ast.AlterServerConfigurationSetExternalAuthenticationStatement{}

// Parse ON or OFF
optionState := strings.ToUpper(p.curTok.Literal)
if optionState != "ON" && optionState != "OFF" {
return nil, fmt.Errorf("expected ON or OFF after AUTHENTICATION, got %s", p.curTok.Literal)
}
p.nextToken()

containerOption := &ast.AlterServerConfigurationExternalAuthenticationContainerOption{
OptionKind: "OnOff",
OptionValue: &ast.OnOffOptionValue{
OptionState: capitalizeFirst(optionState),
},
}

// Check for suboptions in parentheses (only for ON)
if optionState == "ON" && p.curTok.Type == TokenLParen {
p.nextToken() // consume (

// Parse suboptions
for {
suboption := &ast.AlterServerConfigurationExternalAuthenticationOption{}

optionName := strings.ToUpper(p.curTok.Literal)
switch optionName {
case "USE_IDENTITY":
suboption.OptionKind = "UseIdentity"
p.nextToken()
case "CREDENTIAL_NAME":
suboption.OptionKind = "CredentialName"
p.nextToken()

// Expect =
if p.curTok.Type != TokenEquals {
return nil, fmt.Errorf("expected = after CREDENTIAL_NAME, got %s", p.curTok.Literal)
}
p.nextToken()

// Parse string literal
if p.curTok.Type != TokenString {
return nil, fmt.Errorf("expected string literal for CREDENTIAL_NAME value, got %s", p.curTok.Literal)
}
strLit, err := p.parseStringLiteral()
if err != nil {
return nil, err
}
suboption.OptionValue = &ast.LiteralOptionValue{
Value: strLit,
}
default:
return nil, fmt.Errorf("unexpected option in EXTERNAL AUTHENTICATION: %s", p.curTok.Literal)
}

containerOption.Suboptions = append(containerOption.Suboptions, suboption)

// Check for comma or closing paren
if p.curTok.Type == TokenComma {
p.nextToken()
continue
}
if p.curTok.Type == TokenRParen {
p.nextToken()
break
}
return nil, fmt.Errorf("expected , or ) in EXTERNAL AUTHENTICATION options, got %s", p.curTok.Literal)
}
}

stmt.Options = append(stmt.Options, containerOption)

// Skip optional semicolon
if p.curTok.Type == TokenSemicolon {
p.nextToken()
}

return stmt, nil
}

func (p *Parser) parseAlterServerConfigurationSetProcessAffinityStatement() (*ast.AlterServerConfigurationStatement, error) {
// Consume PROCESS
p.nextToken()
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo": true}
{}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"todo": true}
{}
Loading