Skip to content

Commit 3cdc4c1

Browse files
authored
Add support of PROJECTION column in CREATE TABLE (#178)
1 parent b84b7e1 commit 3cdc4c1

File tree

7 files changed

+335
-28
lines changed

7 files changed

+335
-28
lines changed

parser/ast.go

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,10 @@ func (p *ProjectionSelectStmt) Accept(visitor ASTVisitor) error {
786786
}
787787

788788
type TableProjection struct {
789-
ProjectionPos Pos
790-
Identifier *NestedIdentifier
791-
Select *ProjectionSelectStmt
789+
IncludeProjectionKeyword bool
790+
ProjectionPos Pos
791+
Identifier *NestedIdentifier
792+
Select *ProjectionSelectStmt
792793
}
793794

794795
func (t *TableProjection) Pos() Pos {
@@ -801,6 +802,9 @@ func (t *TableProjection) End() Pos {
801802

802803
func (t *TableProjection) String() string {
803804
var builder strings.Builder
805+
if t.IncludeProjectionKeyword {
806+
builder.WriteString("PROJECTION ")
807+
}
804808
builder.WriteString(t.Identifier.String())
805809
builder.WriteString(" ")
806810
builder.WriteString(t.Select.String())
@@ -5182,15 +5186,15 @@ func (c *CreateLiveView) Accept(visitor ASTVisitor) error {
51825186
}
51835187

51845188
type CreateDictionary struct {
5185-
CreatePos Pos
5186-
StatementEnd Pos
5187-
OrReplace bool
5188-
Name *TableIdentifier
5189-
IfNotExists bool
5190-
UUID *UUID
5191-
OnCluster *ClusterClause
5192-
Schema *DictionarySchemaClause
5193-
Engine *DictionaryEngineClause
5189+
CreatePos Pos
5190+
StatementEnd Pos
5191+
OrReplace bool
5192+
Name *TableIdentifier
5193+
IfNotExists bool
5194+
UUID *UUID
5195+
OnCluster *ClusterClause
5196+
Schema *DictionarySchemaClause
5197+
Engine *DictionaryEngineClause
51945198
}
51955199

51965200
func (c *CreateDictionary) Type() string {
@@ -5395,13 +5399,13 @@ func (d *DictionaryAttribute) Accept(visitor ASTVisitor) error {
53955399
}
53965400

53975401
type DictionaryEngineClause struct {
5398-
EnginePos Pos
5399-
PrimaryKey *DictionaryPrimaryKeyClause
5400-
Source *DictionarySourceClause
5401-
Lifetime *DictionaryLifetimeClause
5402-
Layout *DictionaryLayoutClause
5403-
Range *DictionaryRangeClause
5404-
Settings *SettingsClause
5402+
EnginePos Pos
5403+
PrimaryKey *DictionaryPrimaryKeyClause
5404+
Source *DictionarySourceClause
5405+
Lifetime *DictionaryLifetimeClause
5406+
Layout *DictionaryLayoutClause
5407+
Range *DictionaryRangeClause
5408+
Settings *SettingsClause
54055409
}
54065410

54075411
func (d *DictionaryEngineClause) Pos() Pos {
@@ -5432,7 +5436,7 @@ func (d *DictionaryEngineClause) End() Pos {
54325436

54335437
func (d *DictionaryEngineClause) String() string {
54345438
var builder strings.Builder
5435-
5439+
54365440
if d.PrimaryKey != nil {
54375441
builder.WriteString(d.PrimaryKey.String())
54385442
}
@@ -5595,7 +5599,7 @@ func (d *DictionarySourceClause) Accept(visitor ASTVisitor) error {
55955599
type DictionaryArgExpr struct {
55965600
ArgPos Pos
55975601
Name *Ident
5598-
Value Expr // can be Ident with optional parentheses or literal
5602+
Value Expr // can be Ident with optional parentheses or literal
55995603
}
56005604

56015605
func (d *DictionaryArgExpr) Pos() Pos {
@@ -5630,7 +5634,7 @@ type DictionaryLifetimeClause struct {
56305634
LifetimePos Pos
56315635
Min *NumberLiteral
56325636
Max *NumberLiteral
5633-
Value *NumberLiteral // for simple LIFETIME(value) form
5637+
Value *NumberLiteral // for simple LIFETIME(value) form
56345638
RParenPos Pos
56355639
}
56365640

parser/parser_alter.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ func (p *Parser) parseProjectionSelect(pos Pos) (*ProjectionSelectStmt, error) {
206206
}, nil
207207
}
208208

209-
func (p *Parser) parseTableProjection(pos Pos) (*TableProjection, error) {
209+
func (p *Parser) parseTableProjection(pos Pos, includeProjectionKeyword bool) (*TableProjection, error) {
210+
if includeProjectionKeyword {
211+
if err := p.expectKeyword(KeywordProjection); err != nil {
212+
return nil, err
213+
}
214+
}
210215
identifier, err := p.ParseNestedIdentifier(pos)
211216
if err != nil {
212217
return nil, err
@@ -216,9 +221,10 @@ func (p *Parser) parseTableProjection(pos Pos) (*TableProjection, error) {
216221
return nil, err
217222
}
218223
return &TableProjection{
219-
ProjectionPos: pos,
220-
Identifier: identifier,
221-
Select: selectExpr,
224+
IncludeProjectionKeyword: includeProjectionKeyword,
225+
ProjectionPos: pos,
226+
Identifier: identifier,
227+
Select: selectExpr,
222228
}, nil
223229
}
224230

@@ -231,7 +237,7 @@ func (p *Parser) parseAlterTableAddProjection(pos Pos) (*AlterTableAddProjection
231237
if err != nil {
232238
return nil, err
233239
}
234-
tableProjection, err := p.parseTableProjection(p.Pos())
240+
tableProjection, err := p.parseTableProjection(p.Pos(), false)
235241
if err != nil {
236242
return nil, err
237243
}

parser/parser_table.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,12 @@ func (p *Parser) parseTableColumns() ([]Expr, error) {
461461
Constraint: ident,
462462
Expr: expr,
463463
})
464+
case p.matchKeyword(KeywordProjection):
465+
projection, err := p.parseTableProjection(p.Pos(), true)
466+
if err != nil {
467+
return nil, err
468+
}
469+
columns = append(columns, projection)
464470
default:
465471
column, err := p.tryParseTableColumnExpr(p.Pos())
466472
if err != nil {
@@ -1977,7 +1983,6 @@ func (p *Parser) parseDictionarySettingsClause(pos Pos) (*SettingsClause, error)
19771983

19781984
settings := &SettingsClause{SettingsPos: pos, ListEnd: pos}
19791985
items := make([]*SettingExprList, 0)
1980-
19811986
// Parse first setting
19821987
expr, err := p.parseSettingsExprList(p.Pos())
19831988
if err != nil {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE TABLE events
2+
(
3+
`event_time` DateTime,
4+
`event_id` UInt64,
5+
`user_id` UInt64,
6+
`huge_string` String,
7+
PROJECTION order_by_user_id
8+
(
9+
SELECT
10+
_part_offset
11+
ORDER BY user_id
12+
)
13+
)
14+
ENGINE = MergeTree()
15+
ORDER BY (event_id);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- Origin SQL:
2+
CREATE TABLE events
3+
(
4+
`event_time` DateTime,
5+
`event_id` UInt64,
6+
`user_id` UInt64,
7+
`huge_string` String,
8+
PROJECTION order_by_user_id
9+
(
10+
SELECT
11+
_part_offset
12+
ORDER BY user_id
13+
)
14+
)
15+
ENGINE = MergeTree()
16+
ORDER BY (event_id);
17+
18+
-- Format SQL:
19+
CREATE TABLE events (`event_time` DateTime, `event_id` UInt64, `user_id` UInt64, `huge_string` String, PROJECTION order_by_user_id (SELECT _part_offset ORDER BY user_id)) ENGINE = MergeTree() ORDER BY (event_id);

parser/testdata/ddl/output/alter_table_add_projection.sql.golden.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"StatementEnd": 140,
1919
"IfNotExists": true,
2020
"TableProjection": {
21+
"IncludeProjectionKeyword": false,
2122
"ProjectionPos": 55,
2223
"Identifier": {
2324
"Ident": {

0 commit comments

Comments
 (0)