Skip to content

Commit 8a20c12

Browse files
authored
Allow using REFRESH expression in CREATE MV syntax (#158)
1 parent 6c8af70 commit 8a20c12

14 files changed

+522
-22
lines changed

parser/ast.go

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,13 @@ type CreateMaterializedView struct {
16231623
Name *TableIdentifier
16241624
IfNotExists bool
16251625
OnCluster *ClusterClause
1626+
Refresh *RefreshExpr
1627+
RandomizeFor *IntervalExpr
1628+
DependsOn []*TableIdentifier
1629+
Settings *SettingsClause
1630+
HasAppend bool
16261631
Engine *EngineExpr
1632+
HasEmpty bool
16271633
Destination *DestinationClause
16281634
SubQuery *SubQuery
16291635
Populate bool
@@ -1653,6 +1659,30 @@ func (c *CreateMaterializedView) String() string {
16531659
builder.WriteString(" ")
16541660
builder.WriteString(c.OnCluster.String())
16551661
}
1662+
if c.Refresh != nil {
1663+
builder.WriteString(" ")
1664+
builder.WriteString(c.Refresh.String())
1665+
}
1666+
if c.RandomizeFor != nil {
1667+
builder.WriteString(" RANDOMIZE FOR ")
1668+
builder.WriteString(c.RandomizeFor.String())
1669+
}
1670+
if c.DependsOn != nil {
1671+
builder.WriteString(" DEPENDS ON ")
1672+
for i, dep := range c.DependsOn {
1673+
if i > 0 {
1674+
builder.WriteString(", ")
1675+
}
1676+
builder.WriteString(dep.String())
1677+
}
1678+
}
1679+
if c.Settings != nil {
1680+
builder.WriteString(" ")
1681+
builder.WriteString(c.Settings.String())
1682+
}
1683+
if c.HasAppend {
1684+
builder.WriteString(" APPEND")
1685+
}
16561686
if c.Engine != nil {
16571687
builder.WriteString(c.Engine.String())
16581688
}
@@ -1664,6 +1694,9 @@ func (c *CreateMaterializedView) String() string {
16641694
builder.WriteString(c.Destination.TableSchema.String())
16651695
}
16661696
}
1697+
if c.HasEmpty {
1698+
builder.WriteString(" EMPTY")
1699+
}
16671700
if c.Populate {
16681701
builder.WriteString(" POPULATE ")
16691702
}
@@ -1690,6 +1723,28 @@ func (c *CreateMaterializedView) Accept(visitor ASTVisitor) error {
16901723
return err
16911724
}
16921725
}
1726+
if c.Refresh != nil {
1727+
if err := c.Refresh.Accept(visitor); err != nil {
1728+
return err
1729+
}
1730+
}
1731+
if c.RandomizeFor != nil {
1732+
if err := c.RandomizeFor.Accept(visitor); err != nil {
1733+
return err
1734+
}
1735+
}
1736+
if c.DependsOn != nil {
1737+
for _, dep := range c.DependsOn {
1738+
if err := dep.Accept(visitor); err != nil {
1739+
return err
1740+
}
1741+
}
1742+
}
1743+
if c.Settings != nil {
1744+
if err := c.Settings.Accept(visitor); err != nil {
1745+
return err
1746+
}
1747+
}
16931748
if c.Engine != nil {
16941749
if err := c.Engine.Accept(visitor); err != nil {
16951750
return err
@@ -2744,6 +2799,55 @@ func (t *TTLPolicyRuleAction) Accept(visitor ASTVisitor) error {
27442799
return visitor.VisitTTLPolicyItemAction(t)
27452800
}
27462801

2802+
type RefreshExpr struct {
2803+
RefreshPos Pos
2804+
Frequency string // EVERY|AFTER
2805+
Interval *IntervalExpr
2806+
Offset *IntervalExpr
2807+
}
2808+
2809+
func (r *RefreshExpr) Pos() Pos {
2810+
return r.RefreshPos
2811+
}
2812+
2813+
func (r *RefreshExpr) End() Pos {
2814+
if r.Offset != nil {
2815+
return r.Offset.End()
2816+
}
2817+
return r.Interval.End()
2818+
}
2819+
2820+
func (r *RefreshExpr) String() string {
2821+
var builder strings.Builder
2822+
builder.WriteString("REFRESH ")
2823+
builder.WriteString(r.Frequency)
2824+
if r.Interval != nil {
2825+
builder.WriteString(" ")
2826+
builder.WriteString(r.Interval.String())
2827+
}
2828+
if r.Offset != nil {
2829+
builder.WriteString(" OFFSET ")
2830+
builder.WriteString(r.Offset.String())
2831+
}
2832+
return builder.String()
2833+
}
2834+
2835+
func (r *RefreshExpr) Accept(visitor ASTVisitor) error {
2836+
visitor.enter(r)
2837+
defer visitor.leave(r)
2838+
if r.Interval != nil {
2839+
if err := r.Interval.Accept(visitor); err != nil {
2840+
return err
2841+
}
2842+
}
2843+
if r.Offset != nil {
2844+
if err := r.Offset.Accept(visitor); err != nil {
2845+
return err
2846+
}
2847+
}
2848+
return visitor.VisitRefreshExpr(r)
2849+
}
2850+
27472851
type TTLPolicyRule struct {
27482852
RulePos Pos
27492853
ToVolume *StringLiteral
@@ -4108,13 +4212,18 @@ func (e *EnumType) Type() string {
41084212
}
41094213

41104214
type IntervalExpr struct {
4215+
// INTERVAL keyword position which might be omitted(IntervalPos = 0)
41114216
IntervalPos Pos
4112-
Expr Expr
4113-
Unit *Ident
4217+
4218+
Expr Expr
4219+
Unit *Ident
41144220
}
41154221

41164222
func (i *IntervalExpr) Pos() Pos {
4117-
return i.IntervalPos
4223+
if i.IntervalPos != 0 {
4224+
return i.IntervalPos
4225+
}
4226+
return i.Expr.Pos()
41184227
}
41194228

41204229
func (i *IntervalExpr) End() Pos {
@@ -4123,7 +4232,9 @@ func (i *IntervalExpr) End() Pos {
41234232

41244233
func (i *IntervalExpr) String() string {
41254234
var builder strings.Builder
4126-
builder.WriteString("INTERVAL ")
4235+
if i.IntervalPos != 0 {
4236+
builder.WriteString("INTERVAL ")
4237+
}
41274238
builder.WriteString(i.Expr.String())
41284239
builder.WriteByte(' ')
41294240
builder.WriteString(i.Unit.String())

parser/ast_visitor.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type ASTVisitor interface {
6464
VisitTTLPolicy(expr *TTLPolicy) error
6565
VisitTTLPolicyRule(expr *TTLPolicyRule) error
6666
VisitTTLPolicyItemAction(expr *TTLPolicyRuleAction) error
67+
VisitRefreshExpr(expr *RefreshExpr) error
6768
VisitOrderByExpr(expr *OrderExpr) error
6869
VisitOrderByListExpr(expr *OrderByClause) error
6970
VisitSettingsExpr(expr *SettingExprList) error
@@ -621,6 +622,13 @@ func (v *DefaultASTVisitor) VisitTTLPolicyItemAction(expr *TTLPolicyRuleAction)
621622
return nil
622623
}
623624

625+
func (v *DefaultASTVisitor) VisitRefreshExpr(expr *RefreshExpr) error {
626+
if v.Visit != nil {
627+
return v.Visit(expr)
628+
}
629+
return nil
630+
}
631+
624632
func (v *DefaultASTVisitor) VisitOrderByExpr(expr *OrderExpr) error {
625633
if v.Visit != nil {
626634
return v.Visit(expr)

parser/keyword.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
KeywordAnd = "AND"
1111
KeywordAnti = "ANTI"
1212
KeywordAny = "ANY"
13+
KeywordAppend = "APPEND"
1314
KeywordApply = "APPLY"
1415
KeywordArray = "ARRAY"
1516
KeywordAs = "AS"
@@ -48,6 +49,7 @@ const (
4849
KeywordDefault = "DEFAULT"
4950
KeywordDelay = "DELAY"
5051
KeywordDelete = "DELETE"
52+
KeywordDepends = "DEPENDS"
5153
KeywordDesc = "DESC"
5254
KeywordDescending = "DESCENDING"
5355
KeywordDescribe = "DESCRIBE"
@@ -62,10 +64,12 @@ const (
6264
KeywordDNS = "DNS"
6365
KeywordElse = "ELSE"
6466
KeywordEmbedded = "EMBEDDED"
67+
KeywordEmpty = "EMPTY"
6568
KeywordEnd = "END"
6669
KeywordEngine = "ENGINE"
6770
KeywordEstimate = "ESTIMATE"
6871
KeywordEvents = "EVENTS"
72+
KeywordEvery = "EVERY"
6973
KeywordExcept = "EXCEPT"
7074
KeywordExists = "EXISTS"
7175
KeywordExplain = "EXPLAIN"
@@ -159,6 +163,7 @@ const (
159163
KeywordQuery = "QUERY"
160164
KeywordQueues = "QUEUES"
161165
KeywordQuota = "QUOTA"
166+
KeywordRandomize = "RANDOMIZE"
162167
KeywordRange = "RANGE"
163168
KeywordRecompress = "RECOMPRESS"
164169
KeywordRefresh = "REFRESH"
@@ -241,6 +246,7 @@ var keywords = NewSet(
241246
KeywordAnd,
242247
KeywordAnti,
243248
KeywordAny,
249+
KeywordAppend,
244250
KeywordApply,
245251
KeywordArray,
246252
KeywordAs,
@@ -279,6 +285,7 @@ var keywords = NewSet(
279285
KeywordDefault,
280286
KeywordDelay,
281287
KeywordDelete,
288+
KeywordDepends,
282289
KeywordDesc,
283290
KeywordDescending,
284291
KeywordDescribe,
@@ -295,7 +302,10 @@ var keywords = NewSet(
295302
KeywordEnd,
296303
KeywordEngine,
297304
KeywordEstimate,
305+
KeywordEmbedded,
306+
KeywordEmpty,
298307
KeywordEvents,
308+
KeywordEvery,
299309
KeywordExcept,
300310
KeywordExists,
301311
KeywordExplain,
@@ -389,6 +399,7 @@ var keywords = NewSet(
389399
KeywordQuery,
390400
KeywordQueues,
391401
KeywordQuota,
402+
KeywordRandomize,
392403
KeywordRange,
393404
KeywordRecompress,
394405
KeywordRefresh,

parser/parser_column.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (p *Parser) parseColumnExtractExpr(pos Pos) (*ExtractExpr, error) {
274274
if err != nil {
275275
return nil, err
276276
}
277-
if !intervalType.Contains(strings.ToUpper(ident.Name)) {
277+
if !intervalUnits.Contains(strings.ToUpper(ident.Name)) {
278278
return nil, fmt.Errorf("unknown interval type: <%q>", ident.Name)
279279
}
280280

@@ -352,7 +352,7 @@ func (p *Parser) parseColumnExpr(pos Pos) (Expr, error) { //nolint:funlen
352352
}
353353
switch {
354354
case p.matchKeyword(KeywordInterval):
355-
return p.parseColumnExprInterval(pos)
355+
return p.parseInterval(true)
356356
case p.matchKeyword(KeywordDate), p.matchKeyword(KeywordTimestamp):
357357
nextToken, err := p.lexer.peekToken()
358358
if err != nil {
@@ -517,30 +517,30 @@ func (p *Parser) parseSelectItems() ([]*SelectItem, error) {
517517
return selectItems, nil
518518
}
519519

520-
// Syntax: INTERVAL expr interval
521-
func (p *Parser) parseColumnExprInterval(pos Pos) (Expr, error) {
522-
if err := p.expectKeyword(KeywordInterval); err != nil {
523-
return nil, err
520+
func (p *Parser) parseInterval(requireKeyword bool) (*IntervalExpr, error) {
521+
var intervalPos Pos
522+
if requireKeyword {
523+
intervalPos = p.Pos()
524+
if err := p.expectKeyword(KeywordInterval); err != nil {
525+
return nil, err
526+
}
524527
}
525-
526-
// store the column expr if it needs
527-
columnExpr, err := p.parseExpr(p.Pos())
528+
expr, err := p.parseExpr(p.Pos())
528529
if err != nil {
529530
return nil, err
530531
}
531532

532-
// parse interval
533-
ident, err := p.parseIdent()
533+
unit, err := p.parseIdent()
534534
if err != nil {
535535
return nil, err
536536
}
537-
if !intervalType.Contains(strings.ToUpper(ident.Name)) {
538-
return nil, fmt.Errorf("unknown interval type: <%q>", ident.Name)
537+
if !intervalUnits.Contains(strings.ToUpper(unit.Name)) {
538+
return nil, fmt.Errorf("unknown interval type: <%q>", unit.Name)
539539
}
540540
return &IntervalExpr{
541-
IntervalPos: pos,
542-
Expr: columnExpr,
543-
Unit: ident,
541+
IntervalPos: intervalPos,
542+
Expr: expr,
543+
Unit: unit,
544544
}, nil
545545
}
546546

0 commit comments

Comments
 (0)