Skip to content

Commit 6109f2a

Browse files
committed
Add CREATE SPATIAL INDEX statement parsing support
Implement full parsing of CREATE SPATIAL INDEX statements including: - USING clause with GEOMETRY_GRID, GEOGRAPHY_GRID, GEOMETRY_AUTO_GRID, and GEOGRAPHY_AUTO_GRID indexing schemes - WITH clause options: DATA_COMPRESSION, BOUNDING_BOX, GRIDS, CELLS_PER_OBJECT, and standard index options - ON filegroup clause Add AST types for spatial index components: - CreateSpatialIndexStatement - SpatialIndexOption interface and implementations - BoundingBoxParameter and GridParameter types - DataCompressionOption and IgnoreDupKeyIndexOption index options Enable two passing tests: - CreateSpatialIndexStatementTests110 - Baselines110_CreateSpatialIndexStatementTests110
1 parent 090311d commit 6109f2a

File tree

5 files changed

+495
-2
lines changed

5 files changed

+495
-2
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package ast
2+
3+
// CreateSpatialIndexStatement represents a CREATE SPATIAL INDEX statement
4+
type CreateSpatialIndexStatement struct {
5+
Name *Identifier
6+
Object *SchemaObjectName
7+
SpatialColumnName *Identifier
8+
SpatialIndexingScheme string // "None", "GeometryGrid", "GeographyGrid", "GeometryAutoGrid", "GeographyAutoGrid"
9+
OnFileGroup *IdentifierOrValueExpression
10+
SpatialIndexOptions []SpatialIndexOption
11+
}
12+
13+
func (s *CreateSpatialIndexStatement) node() {}
14+
func (s *CreateSpatialIndexStatement) statement() {}
15+
16+
// SpatialIndexOption is an interface for spatial index options
17+
type SpatialIndexOption interface {
18+
Node
19+
spatialIndexOption()
20+
}
21+
22+
// SpatialIndexRegularOption wraps a regular IndexOption for spatial indexes
23+
type SpatialIndexRegularOption struct {
24+
Option IndexOption
25+
}
26+
27+
func (s *SpatialIndexRegularOption) node() {}
28+
func (s *SpatialIndexRegularOption) spatialIndexOption() {}
29+
30+
// BoundingBoxSpatialIndexOption represents a BOUNDING_BOX option
31+
type BoundingBoxSpatialIndexOption struct {
32+
BoundingBoxParameters []*BoundingBoxParameter
33+
}
34+
35+
func (b *BoundingBoxSpatialIndexOption) node() {}
36+
func (b *BoundingBoxSpatialIndexOption) spatialIndexOption() {}
37+
38+
// BoundingBoxParameter represents a bounding box parameter (XMIN, YMIN, XMAX, YMAX)
39+
type BoundingBoxParameter struct {
40+
Parameter string // "None", "XMin", "YMin", "XMax", "YMax"
41+
Value ScalarExpression
42+
}
43+
44+
func (b *BoundingBoxParameter) node() {}
45+
46+
// GridsSpatialIndexOption represents a GRIDS option
47+
type GridsSpatialIndexOption struct {
48+
GridParameters []*GridParameter
49+
}
50+
51+
func (g *GridsSpatialIndexOption) node() {}
52+
func (g *GridsSpatialIndexOption) spatialIndexOption() {}
53+
54+
// GridParameter represents a grid parameter
55+
type GridParameter struct {
56+
Parameter string // "None", "Level1", "Level2", "Level3", "Level4"
57+
Value string // "Low", "Medium", "High"
58+
}
59+
60+
func (g *GridParameter) node() {}
61+
62+
// CellsPerObjectSpatialIndexOption represents a CELLS_PER_OBJECT option
63+
type CellsPerObjectSpatialIndexOption struct {
64+
Value ScalarExpression
65+
}
66+
67+
func (c *CellsPerObjectSpatialIndexOption) node() {}
68+
func (c *CellsPerObjectSpatialIndexOption) spatialIndexOption() {}
69+
70+
// DataCompressionOption represents a DATA_COMPRESSION option for indexes
71+
type DataCompressionOption struct {
72+
CompressionLevel string // "None", "Row", "Page", "ColumnStore", "ColumnStoreArchive"
73+
OptionKind string // "DataCompression"
74+
PartitionRanges []*CompressionPartitionRange
75+
}
76+
77+
func (d *DataCompressionOption) node() {}
78+
func (d *DataCompressionOption) indexOption() {}
79+
80+
// IgnoreDupKeyIndexOption represents the IGNORE_DUP_KEY option
81+
type IgnoreDupKeyIndexOption struct {
82+
OptionState string // "On", "Off"
83+
OptionKind string // "IgnoreDupKey"
84+
}
85+
86+
func (i *IgnoreDupKeyIndexOption) node() {}
87+
func (i *IgnoreDupKeyIndexOption) indexOption() {}

parser/marshal.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ func statementToJSON(stmt ast.Statement) jsonNode {
346346
return createLoginStatementToJSON(s)
347347
case *ast.CreateIndexStatement:
348348
return createIndexStatementToJSON(s)
349+
case *ast.CreateSpatialIndexStatement:
350+
return createSpatialIndexStatementToJSON(s)
349351
case *ast.CreateAsymmetricKeyStatement:
350352
return createAsymmetricKeyStatementToJSON(s)
351353
case *ast.CreateSymmetricKeyStatement:
@@ -5185,6 +5187,108 @@ func createColumnStoreIndexStatementToJSON(s *ast.CreateColumnStoreIndexStatemen
51855187
return node
51865188
}
51875189

5190+
func createSpatialIndexStatementToJSON(s *ast.CreateSpatialIndexStatement) jsonNode {
5191+
node := jsonNode{
5192+
"$type": "CreateSpatialIndexStatement",
5193+
}
5194+
if s.Name != nil {
5195+
node["Name"] = identifierToJSON(s.Name)
5196+
}
5197+
if s.Object != nil {
5198+
node["Object"] = schemaObjectNameToJSON(s.Object)
5199+
}
5200+
if s.SpatialColumnName != nil {
5201+
node["SpatialColumnName"] = identifierToJSON(s.SpatialColumnName)
5202+
}
5203+
if s.SpatialIndexingScheme != "" {
5204+
node["SpatialIndexingScheme"] = s.SpatialIndexingScheme
5205+
}
5206+
if s.OnFileGroup != nil {
5207+
node["OnFileGroup"] = identifierOrValueExpressionToJSON(s.OnFileGroup)
5208+
}
5209+
if len(s.SpatialIndexOptions) > 0 {
5210+
opts := make([]jsonNode, len(s.SpatialIndexOptions))
5211+
for i, opt := range s.SpatialIndexOptions {
5212+
opts[i] = spatialIndexOptionToJSON(opt)
5213+
}
5214+
node["SpatialIndexOptions"] = opts
5215+
}
5216+
return node
5217+
}
5218+
5219+
func spatialIndexOptionToJSON(opt ast.SpatialIndexOption) jsonNode {
5220+
switch o := opt.(type) {
5221+
case *ast.SpatialIndexRegularOption:
5222+
node := jsonNode{
5223+
"$type": "SpatialIndexRegularOption",
5224+
}
5225+
if o.Option != nil {
5226+
node["Option"] = indexOptionToJSON(o.Option)
5227+
}
5228+
return node
5229+
case *ast.BoundingBoxSpatialIndexOption:
5230+
node := jsonNode{
5231+
"$type": "BoundingBoxSpatialIndexOption",
5232+
}
5233+
if len(o.BoundingBoxParameters) > 0 {
5234+
params := make([]jsonNode, len(o.BoundingBoxParameters))
5235+
for i, p := range o.BoundingBoxParameters {
5236+
params[i] = boundingBoxParameterToJSON(p)
5237+
}
5238+
node["BoundingBoxParameters"] = params
5239+
}
5240+
return node
5241+
case *ast.GridsSpatialIndexOption:
5242+
node := jsonNode{
5243+
"$type": "GridsSpatialIndexOption",
5244+
}
5245+
if len(o.GridParameters) > 0 {
5246+
params := make([]jsonNode, len(o.GridParameters))
5247+
for i, p := range o.GridParameters {
5248+
params[i] = gridParameterToJSON(p)
5249+
}
5250+
node["GridParameters"] = params
5251+
}
5252+
return node
5253+
case *ast.CellsPerObjectSpatialIndexOption:
5254+
node := jsonNode{
5255+
"$type": "CellsPerObjectSpatialIndexOption",
5256+
}
5257+
if o.Value != nil {
5258+
node["Value"] = scalarExpressionToJSON(o.Value)
5259+
}
5260+
return node
5261+
default:
5262+
return jsonNode{"$type": "UnknownSpatialIndexOption"}
5263+
}
5264+
}
5265+
5266+
func boundingBoxParameterToJSON(p *ast.BoundingBoxParameter) jsonNode {
5267+
node := jsonNode{
5268+
"$type": "BoundingBoxParameter",
5269+
}
5270+
if p.Parameter != "" {
5271+
node["Parameter"] = p.Parameter
5272+
}
5273+
if p.Value != nil {
5274+
node["Value"] = scalarExpressionToJSON(p.Value)
5275+
}
5276+
return node
5277+
}
5278+
5279+
func gridParameterToJSON(p *ast.GridParameter) jsonNode {
5280+
node := jsonNode{
5281+
"$type": "GridParameter",
5282+
}
5283+
if p.Parameter != "" {
5284+
node["Parameter"] = p.Parameter
5285+
}
5286+
if p.Value != "" {
5287+
node["Value"] = p.Value
5288+
}
5289+
return node
5290+
}
5291+
51885292
func alterFunctionStatementToJSON(s *ast.AlterFunctionStatement) jsonNode {
51895293
node := jsonNode{
51905294
"$type": "AlterFunctionStatement",
@@ -5378,6 +5482,26 @@ func indexOptionToJSON(opt ast.IndexOption) jsonNode {
53785482
"OptionKind": o.OptionKind,
53795483
"Expression": scalarExpressionToJSON(o.Expression),
53805484
}
5485+
case *ast.DataCompressionOption:
5486+
node := jsonNode{
5487+
"$type": "DataCompressionOption",
5488+
"CompressionLevel": o.CompressionLevel,
5489+
"OptionKind": o.OptionKind,
5490+
}
5491+
if len(o.PartitionRanges) > 0 {
5492+
ranges := make([]jsonNode, len(o.PartitionRanges))
5493+
for i, r := range o.PartitionRanges {
5494+
ranges[i] = compressionPartitionRangeToJSON(r)
5495+
}
5496+
node["PartitionRanges"] = ranges
5497+
}
5498+
return node
5499+
case *ast.IgnoreDupKeyIndexOption:
5500+
return jsonNode{
5501+
"$type": "IgnoreDupKeyIndexOption",
5502+
"OptionState": o.OptionState,
5503+
"OptionKind": o.OptionKind,
5504+
}
53815505
default:
53825506
return jsonNode{"$type": "UnknownIndexOption"}
53835507
}

0 commit comments

Comments
 (0)