@@ -5677,6 +5677,15 @@ func (p *Parser) parseCreateTableStatement() (*ast.CreateTableStatement, error)
56775677 },
56785678 },
56795679 }
5680+ // Parse optional ASC/DESC
5681+ sortUpper := strings.ToUpper(p.curTok.Literal)
5682+ if sortUpper == "ASC" {
5683+ col.SortOrder = ast.SortOrderAscending
5684+ p.nextToken()
5685+ } else if sortUpper == "DESC" {
5686+ col.SortOrder = ast.SortOrderDescending
5687+ p.nextToken()
5688+ }
56805689 indexType.Columns = append(indexType.Columns, col)
56815690 if p.curTok.Type == TokenComma {
56825691 p.nextToken()
@@ -5746,6 +5755,62 @@ func (p *Parser) parseCreateTableStatement() (*ast.CreateTableStatement, error)
57465755 // Unknown distribution - skip for now
57475756 p.nextToken()
57485757 }
5758+ } else if optionName == "PARTITION" {
5759+ // Parse PARTITION(column RANGE [LEFT|RIGHT] FOR VALUES (v1, v2, ...))
5760+ if p.curTok.Type == TokenLParen {
5761+ p.nextToken() // consume (
5762+ partOpt := &ast.TablePartitionOption{
5763+ OptionKind: "Partition",
5764+ PartitionOptionSpecs: &ast.TablePartitionOptionSpecifications{},
5765+ }
5766+ // Parse partition column
5767+ partOpt.PartitionColumn = p.parseIdentifier()
5768+ // Expect RANGE keyword
5769+ if strings.ToUpper(p.curTok.Literal) == "RANGE" {
5770+ p.nextToken() // consume RANGE
5771+ // Check for LEFT or RIGHT
5772+ rangeDir := strings.ToUpper(p.curTok.Literal)
5773+ if rangeDir == "LEFT" {
5774+ partOpt.PartitionOptionSpecs.Range = "Left"
5775+ p.nextToken()
5776+ } else if rangeDir == "RIGHT" {
5777+ partOpt.PartitionOptionSpecs.Range = "Right"
5778+ p.nextToken()
5779+ } else {
5780+ partOpt.PartitionOptionSpecs.Range = "NotSpecified"
5781+ }
5782+ // Expect FOR keyword
5783+ if strings.ToUpper(p.curTok.Literal) == "FOR" {
5784+ p.nextToken() // consume FOR
5785+ }
5786+ // Expect VALUES keyword
5787+ if strings.ToUpper(p.curTok.Literal) == "VALUES" {
5788+ p.nextToken() // consume VALUES
5789+ }
5790+ // Parse boundary values list
5791+ if p.curTok.Type == TokenLParen {
5792+ p.nextToken() // consume (
5793+ for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
5794+ val, _ := p.parseScalarExpression()
5795+ if val != nil {
5796+ partOpt.PartitionOptionSpecs.BoundaryValues = append(partOpt.PartitionOptionSpecs.BoundaryValues, val)
5797+ }
5798+ if p.curTok.Type == TokenComma {
5799+ p.nextToken()
5800+ } else {
5801+ break
5802+ }
5803+ }
5804+ if p.curTok.Type == TokenRParen {
5805+ p.nextToken() // consume )
5806+ }
5807+ }
5808+ }
5809+ if p.curTok.Type == TokenRParen {
5810+ p.nextToken() // consume )
5811+ }
5812+ stmt.Options = append(stmt.Options, partOpt)
5813+ }
57495814 } else {
57505815 // Skip unknown option value
57515816 if p.curTok.Type == TokenEquals {
@@ -6065,6 +6130,15 @@ func (p *Parser) parseCreateTableOptions(stmt *ast.CreateTableStatement) (*ast.C
60656130 },
60666131 },
60676132 }
6133+ // Parse optional ASC/DESC
6134+ sortUpper := strings.ToUpper(p.curTok.Literal)
6135+ if sortUpper == "ASC" {
6136+ col.SortOrder = ast.SortOrderAscending
6137+ p.nextToken()
6138+ } else if sortUpper == "DESC" {
6139+ col.SortOrder = ast.SortOrderDescending
6140+ p.nextToken()
6141+ }
60686142 indexType.Columns = append(indexType.Columns, col)
60696143 if p.curTok.Type == TokenComma {
60706144 p.nextToken()
@@ -7140,6 +7214,22 @@ func (p *Parser) parseColumnDefinition() (*ast.ColumnDefinition, error) {
71407214 constraint.IndexType = &ast.IndexType{IndexTypeKind: "NonClustered"}
71417215 }
71427216 }
7217+ // Parse optional column list (column ASC, column DESC, ...)
7218+ if p.curTok.Type == TokenLParen {
7219+ p.nextToken() // consume (
7220+ for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
7221+ colWithSort := p.parseColumnWithSortOrder()
7222+ constraint.Columns = append(constraint.Columns, colWithSort)
7223+ if p.curTok.Type == TokenComma {
7224+ p.nextToken()
7225+ } else {
7226+ break
7227+ }
7228+ }
7229+ if p.curTok.Type == TokenRParen {
7230+ p.nextToken() // consume )
7231+ }
7232+ }
71437233 // Parse WITH (index_options)
71447234 if strings.ToUpper(p.curTok.Literal) == "WITH" {
71457235 p.nextToken() // consume WITH
@@ -7151,6 +7241,13 @@ func (p *Parser) parseColumnDefinition() (*ast.ColumnDefinition, error) {
71517241 fg, _ := p.parseFileGroupOrPartitionScheme()
71527242 constraint.OnFileGroupOrPartitionScheme = fg
71537243 }
7244+ // Parse NOT ENFORCED (Azure Synapse) - but only if next token is ENFORCED
7245+ if p.curTok.Type == TokenNot && strings.ToUpper(p.peekTok.Literal) == "ENFORCED" {
7246+ p.nextToken() // consume NOT
7247+ p.nextToken() // consume ENFORCED
7248+ enforced := false
7249+ constraint.IsEnforced = &enforced
7250+ }
71547251 col.Constraints = append(col.Constraints, constraint)
71557252 } else if upperLit == "PRIMARY" {
71567253 p.nextToken() // consume PRIMARY
@@ -7222,6 +7319,13 @@ func (p *Parser) parseColumnDefinition() (*ast.ColumnDefinition, error) {
72227319 fg, _ := p.parseFileGroupOrPartitionScheme()
72237320 constraint.OnFileGroupOrPartitionScheme = fg
72247321 }
7322+ // Parse NOT ENFORCED (Azure Synapse) - but only if next token is ENFORCED
7323+ if p.curTok.Type == TokenNot && strings.ToUpper(p.peekTok.Literal) == "ENFORCED" {
7324+ p.nextToken() // consume NOT
7325+ p.nextToken() // consume ENFORCED
7326+ enforced := false
7327+ constraint.IsEnforced = &enforced
7328+ }
72257329 col.Constraints = append(col.Constraints, constraint)
72267330 } else if p.curTok.Type == TokenDefault {
72277331 p.nextToken() // consume DEFAULT
@@ -7620,6 +7724,15 @@ func (p *Parser) parseColumnDefinition() (*ast.ColumnDefinition, error) {
76207724 }
76217725 }
76227726 }
7727+ // Parse optional WHERE clause for filtered index
7728+ if p.curTok.Type == TokenWhere {
7729+ p.nextToken() // consume WHERE
7730+ filterExpr, err := p.parseBooleanExpression()
7731+ if err != nil {
7732+ return nil, err
7733+ }
7734+ indexDef.FilterPredicate = filterExpr
7735+ }
76237736 col.Index = indexDef
76247737 } else if upperLit == "SPARSE" {
76257738 p.nextToken() // consume SPARSE
@@ -7864,6 +7977,14 @@ func (p *Parser) parsePrimaryKeyConstraint() (*ast.UniqueConstraintDefinition, e
78647977 constraint.OnFileGroupOrPartitionScheme = fg
78657978 }
78667979
7980+ // Parse NOT ENFORCED (Azure Synapse) - but only if next token is ENFORCED
7981+ if p.curTok.Type == TokenNot && strings.ToUpper(p.peekTok.Literal) == "ENFORCED" {
7982+ p.nextToken() // consume NOT
7983+ p.nextToken() // consume ENFORCED
7984+ enforced := false
7985+ constraint.IsEnforced = &enforced
7986+ }
7987+
78677988 return constraint, nil
78687989}
78697990
@@ -7918,6 +8039,14 @@ func (p *Parser) parseUniqueConstraint() (*ast.UniqueConstraintDefinition, error
79188039 constraint.OnFileGroupOrPartitionScheme = fg
79198040 }
79208041
8042+ // Parse NOT ENFORCED (Azure Synapse) - but only if next token is ENFORCED
8043+ if p.curTok.Type == TokenNot && strings.ToUpper(p.peekTok.Literal) == "ENFORCED" {
8044+ p.nextToken() // consume NOT
8045+ p.nextToken() // consume ENFORCED
8046+ enforced := false
8047+ constraint.IsEnforced = &enforced
8048+ }
8049+
79218050 return constraint, nil
79228051}
79238052
@@ -9265,6 +9394,18 @@ func tableOptionToJSON(opt ast.TableOption) jsonNode {
92659394 node["Value"] = tableDistributionPolicyToJSON(o.Value)
92669395 }
92679396 return node
9397+ case *ast.TablePartitionOption:
9398+ node := jsonNode{
9399+ "$type": "TablePartitionOption",
9400+ "OptionKind": o.OptionKind,
9401+ }
9402+ if o.PartitionColumn != nil {
9403+ node["PartitionColumn"] = identifierToJSON(o.PartitionColumn)
9404+ }
9405+ if o.PartitionOptionSpecs != nil {
9406+ node["PartitionOptionSpecs"] = tablePartitionOptionSpecsToJSON(o.PartitionOptionSpecs)
9407+ }
9408+ return node
92689409 case *ast.SystemVersioningTableOption:
92699410 return systemVersioningTableOptionToJSON(o)
92709411 case *ast.MemoryOptimizedTableOption:
@@ -9417,6 +9558,21 @@ func tableDistributionPolicyToJSON(policy ast.TableDistributionPolicy) jsonNode
94179558 }
94189559}
94199560
9561+ func tablePartitionOptionSpecsToJSON(specs *ast.TablePartitionOptionSpecifications) jsonNode {
9562+ node := jsonNode{
9563+ "$type": "TablePartitionOptionSpecifications",
9564+ "Range": specs.Range,
9565+ }
9566+ if len(specs.BoundaryValues) > 0 {
9567+ vals := make([]jsonNode, len(specs.BoundaryValues))
9568+ for i, v := range specs.BoundaryValues {
9569+ vals[i] = scalarExpressionToJSON(v)
9570+ }
9571+ node["BoundaryValues"] = vals
9572+ }
9573+ return node
9574+ }
9575+
94209576func tableIndexTypeToJSON(t ast.TableIndexType) jsonNode {
94219577 switch v := t.(type) {
94229578 case *ast.TableClusteredIndexType:
0 commit comments