Skip to content

Commit 6fd4b78

Browse files
authored
support AGGREGATE statement syntaxes (#152)
1 parent da8f7fa commit 6fd4b78

File tree

7 files changed

+20468
-20031
lines changed

7 files changed

+20468
-20031
lines changed

Diff for: postgres/parser/parser/sql.y

+213-31
Large diffs are not rendered by default.

Diff for: postgres/parser/sem/tree/create_aggregate.go

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// Copyright 2024 Dolthub, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tree
16+
17+
import "strings"
18+
19+
var _ Statement = &CreateAggregate{}
20+
21+
// CreateAggregate represents a CREATE AGGREGATE statement.
22+
type CreateAggregate struct {
23+
Name Name
24+
Replace bool
25+
Args RoutineArgs
26+
SFunc string
27+
SType ResolvableTypeReference
28+
AggOptions CreateAggOptions
29+
OrderByArgs RoutineArgs
30+
BaseType ResolvableTypeReference
31+
}
32+
33+
// Format implements the NodeFormatter interface.
34+
func (node *CreateAggregate) Format(ctx *FmtCtx) {
35+
ctx.WriteString("CREATE ")
36+
if node.Replace {
37+
ctx.WriteString("OR REPLACE ")
38+
}
39+
ctx.WriteString("AGGREGATE ")
40+
ctx.FormatNode(&node.Name)
41+
ctx.WriteString(" ( ")
42+
if node.OrderByArgs != nil {
43+
if node.Args != nil {
44+
ctx.FormatNode(node.Args)
45+
}
46+
ctx.WriteString(" ORDER BY ")
47+
ctx.FormatNode(node.OrderByArgs)
48+
ctx.WriteString(" ) ( ")
49+
} else if node.Args != nil {
50+
ctx.FormatNode(node.Args)
51+
ctx.WriteString(" ) ( ")
52+
} else {
53+
ctx.WriteString("BASETYPE = ")
54+
ctx.WriteString(node.BaseType.SQLString())
55+
ctx.WriteString(" , ")
56+
}
57+
ctx.WriteString("SFUNC = ")
58+
ctx.WriteString(node.SFunc)
59+
ctx.WriteString(" , STYPE = ")
60+
ctx.WriteString(node.BaseType.SQLString())
61+
if node.AggOptions != nil {
62+
ctx.FormatNode(&node.AggOptions)
63+
}
64+
}
65+
66+
type FinalFuncModifyType string
67+
68+
const (
69+
FinalFuncModifyReadOnly FinalFuncModifyType = "READ_ONLY"
70+
FinalFuncModifyShareable FinalFuncModifyType = "SHAREABLE"
71+
FinalFuncModifyReadWrite FinalFuncModifyType = "READ_WRITE"
72+
)
73+
74+
type CreateAggOptions []CreateAggOption
75+
76+
// Format implements the NodeFormatter interface.
77+
func (node *CreateAggOptions) Format(ctx *FmtCtx) {
78+
for _, option := range *node {
79+
ctx.WriteString(" , ")
80+
ctx.FormatNode(&option)
81+
}
82+
}
83+
84+
type CreateAggOption struct {
85+
Option CreateOptionType
86+
// IntVal is used for SSpace and MSSpace
87+
IntVal Expr
88+
// CondVal is used for InitCond and MInitCond
89+
CondVal Expr
90+
// BoolVal is used for FinalFuncExtra and MFinalFuncExtra
91+
BoolVal bool
92+
// StrVal is used for FinalFunc, CombineFunc, SerialFunc,
93+
// DeserialFunc, MSFunc, MInvFunc and MFinalFunc
94+
StrVal string
95+
// FinalFuncModify is used for FinalFuncModify and MFinalFuncModify
96+
FinalFuncModify FinalFuncModifyType
97+
// TypeVal is used for MSType
98+
TypeVal ResolvableTypeReference
99+
Parallel Parallel
100+
SortOp Operator
101+
// Hypothetical does not define any stored value.
102+
}
103+
104+
// Format implements the NodeFormatter interface.
105+
func (node *CreateAggOption) Format(ctx *FmtCtx) {
106+
switch node.Option {
107+
case AggOptTypeSSpace:
108+
ctx.WriteString("SSPACE = ")
109+
ctx.FormatNode(node.IntVal)
110+
case AggOptTypeFinalFunc:
111+
ctx.WriteString("FINALFUNC = ")
112+
ctx.WriteString(node.StrVal)
113+
case AggOptTypeFinalFuncExtra:
114+
if node.BoolVal {
115+
ctx.WriteString("FINALFUNC_EXTRA = TRUE")
116+
} else {
117+
ctx.WriteString("FINALFUNC_EXTRA = FALSE")
118+
}
119+
case AggOptTypeFinalFuncModify:
120+
ctx.WriteString("FINALFUNC_MODIFY")
121+
ctx.WriteString(string(node.FinalFuncModify))
122+
case AggOptTypeCombineFunc:
123+
ctx.WriteString("COMBINEFUNC = ")
124+
ctx.WriteString(node.StrVal)
125+
case AggOptTypeSerialFunc:
126+
ctx.WriteString("SERIALFUNC = ")
127+
ctx.WriteString(node.StrVal)
128+
case AggOptTypeDeserialFunc:
129+
ctx.WriteString("DESERIALFUNC = ")
130+
ctx.WriteString(node.StrVal)
131+
case AggOptTypeInitCond:
132+
ctx.WriteString("INITCOND = ")
133+
ctx.FormatNode(node.CondVal)
134+
case AggOptTypeMSFunc:
135+
ctx.WriteString("MSFUNC = ")
136+
ctx.WriteString(node.StrVal)
137+
case AggOptTypeMInvFunc:
138+
ctx.WriteString("MINVFUNC = ")
139+
ctx.WriteString(node.StrVal)
140+
case AggOptTypeMSType:
141+
ctx.WriteString("MSTYPE = ")
142+
ctx.WriteString(node.TypeVal.SQLString())
143+
case AggOptTypeMSSpace:
144+
ctx.WriteString("MSSPACE = ")
145+
ctx.FormatNode(node.IntVal)
146+
case AggOptTypeMFinalFunc:
147+
ctx.WriteString("MFINALFUNC = ")
148+
ctx.WriteString(node.StrVal)
149+
case AggOptTypeMFinalFuncExtra:
150+
if node.BoolVal {
151+
ctx.WriteString("MFINALFUNC_EXTRA = TRUE")
152+
} else {
153+
ctx.WriteString("MFINALFUNC_EXTRA = FALSE")
154+
}
155+
case AggOptTypeMFinalFuncModify:
156+
ctx.WriteString("MFINALFUNC_MODIFY")
157+
ctx.WriteString(string(node.FinalFuncModify))
158+
case AggOptTypeMInitCond:
159+
ctx.WriteString("MINITCOND = ")
160+
ctx.FormatNode(node.CondVal)
161+
case AggOptTypeSortOp:
162+
ctx.WriteString("SORTOP = ")
163+
switch op := node.SortOp.(type) {
164+
case UnaryOperator:
165+
ctx.WriteString(op.String())
166+
case BinaryOperator:
167+
ctx.WriteString(op.String())
168+
case ComparisonOperator:
169+
ctx.WriteString(op.String())
170+
}
171+
case AggOptTypeParallel:
172+
ctx.WriteString("PARALLEL = ")
173+
ctx.WriteString(strings.ToUpper(string(node.Parallel)))
174+
case AggOptTypeHypothetical:
175+
ctx.WriteString("HYPOTHETICAL")
176+
}
177+
}
178+
179+
type CreateOptionType int
180+
181+
const (
182+
AggOptTypeSSpace CreateOptionType = iota
183+
AggOptTypeFinalFunc
184+
AggOptTypeFinalFuncExtra
185+
AggOptTypeFinalFuncModify
186+
AggOptTypeCombineFunc
187+
AggOptTypeSerialFunc
188+
AggOptTypeDeserialFunc
189+
AggOptTypeInitCond
190+
AggOptTypeMSFunc
191+
AggOptTypeMInvFunc
192+
AggOptTypeMSType
193+
AggOptTypeMSSpace
194+
AggOptTypeMFinalFunc
195+
AggOptTypeMFinalFuncExtra
196+
AggOptTypeMFinalFuncModify
197+
AggOptTypeMInitCond
198+
AggOptTypeSortOp
199+
AggOptTypeParallel
200+
AggOptTypeHypothetical
201+
)

Diff for: postgres/parser/sem/tree/drop.go

+37
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,43 @@ func (d DropBehavior) String() string {
5353
return dropBehaviorName[d]
5454
}
5555

56+
var _ Statement = &DropAggregate{}
57+
58+
// DropAggregate represents a DROP AGGREGATE statement.
59+
type DropAggregate struct {
60+
Aggregates []AggregateToDrop
61+
IfExists bool
62+
DropBehavior DropBehavior
63+
}
64+
65+
type AggregateToDrop struct {
66+
Name Name
67+
AggSig *AggregateSignature
68+
}
69+
70+
// Format implements the NodeFormatter interface.
71+
func (node *DropAggregate) Format(ctx *FmtCtx) {
72+
ctx.WriteString("DROP AGGREGATE ")
73+
if node.IfExists {
74+
ctx.WriteString("IF EXISTS ")
75+
}
76+
for i, agg := range node.Aggregates {
77+
if i != 0 {
78+
ctx.WriteString(" , ")
79+
}
80+
ctx.FormatNode(&agg.Name)
81+
ctx.WriteString(" ( ")
82+
ctx.FormatNode(agg.AggSig)
83+
ctx.WriteString(" ) ")
84+
}
85+
switch node.DropBehavior {
86+
case DropDefault:
87+
default:
88+
ctx.WriteByte(' ')
89+
ctx.WriteString(dropBehaviorName[node.DropBehavior])
90+
}
91+
}
92+
5693
var _ Statement = &DropDatabase{}
5794

5895
// DropDatabase represents a DROP DATABASE statement.

Diff for: postgres/parser/sem/tree/stmt.go

+14
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,12 @@ func (*CopyFrom) StatementType() StatementType { return CopyIn }
482482
// StatementTag returns a short string identifying the type of statement.
483483
func (*CopyFrom) StatementTag() string { return "COPY" }
484484

485+
// StatementType implements the Statement interface.
486+
func (*CreateAggregate) StatementType() StatementType { return DDL }
487+
488+
// StatementTag returns a short string identifying the type of statement.
489+
func (*CreateAggregate) StatementTag() string { return "CREATE AGGREGATE" }
490+
485491
// StatementType implements the Statement interface.
486492
func (*CreateChangefeed) StatementType() StatementType { return Rows }
487493

@@ -634,6 +640,12 @@ func (n *Delete) StatementType() StatementType { return n.Returning.statementTyp
634640
// StatementTag returns a short string identifying the type of statement.
635641
func (*Delete) StatementTag() string { return "DELETE" }
636642

643+
// StatementType implements the Statement interface.
644+
func (*DropAggregate) StatementType() StatementType { return DDL }
645+
646+
// StatementTag returns a short string identifying the type of statement.
647+
func (*DropAggregate) StatementTag() string { return "DROP AGGREGATE" }
648+
637649
// StatementType implements the Statement interface.
638650
func (*DropDatabase) StatementType() StatementType { return DDL }
639651

@@ -1232,6 +1244,7 @@ func (n *CommentOnIndex) String() string { return AsString(n) }
12321244
func (n *CommentOnTable) String() string { return AsString(n) }
12331245
func (n *CommitTransaction) String() string { return AsString(n) }
12341246
func (n *CopyFrom) String() string { return AsString(n) }
1247+
func (n *CreateAggregate) String() string { return AsString(n) }
12351248
func (n *CreateChangefeed) String() string { return AsString(n) }
12361249
func (n *CreateDatabase) String() string { return AsString(n) }
12371250
func (n *CreateDomain) String() string { return AsString(n) }
@@ -1251,6 +1264,7 @@ func (n *CreateStats) String() string { return AsString(n) }
12511264
func (n *CreateView) String() string { return AsString(n) }
12521265
func (n *Deallocate) String() string { return AsString(n) }
12531266
func (n *Delete) String() string { return AsString(n) }
1267+
func (n *DropAggregate) String() string { return AsString(n) }
12541268
func (n *DropDatabase) String() string { return AsString(n) }
12551269
func (n *DropDomain) String() string { return AsString(n) }
12561270
func (n *DropExtension) String() string { return AsString(n) }

Diff for: testing/generation/command_docs/custom_variables.go

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ var GlobalCustomVariables = map[string]utils.StatementGenerator{
5353
"loid": customDefinition(`99999`),
5454
"maxvalue": customDefinition(`1`),
5555
"minvalue": customDefinition(`1`),
56+
"mstate_data_size": customDefinition(`16`),
5657
"neighbor_enum_value": customDefinition(`'1'`),
5758
"new_enum_value": customDefinition(`'1'`),
5859
"numeric_literal": customDefinition(`1`),
@@ -65,10 +66,12 @@ var GlobalCustomVariables = map[string]utils.StatementGenerator{
6566
"select": customDefinition(`SELECT 1`),
6667
"sequence_options": customDefinition(`NO MINVALUE`),
6768
"snapshot_id": customDefinition(`'snapshot_id'`),
69+
"sort_operator": customDefinition(`>`),
6870
"source_encoding": customDefinition(`'UTF8'`),
6971
"source_query": customDefinition(`SELECT 1`),
7072
"sql_body": customDefinition(`BEGIN ATOMIC END | RETURN 1`),
7173
"start": customDefinition(`0`),
74+
"state_data_size": customDefinition(`16`),
7275
"storage_parameter": customDefinition(`fillfactor`),
7376
"strategy_number": customDefinition(`3`),
7477
"string_literal": customDefinition(`'str'`),

0 commit comments

Comments
 (0)