Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doris/ast/loc.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,22 @@ func NodeLoc(n Node) Loc {
return v.Loc
case *ShowJobTaskStmt:
return v.Loc
case *AddConstraintStmt:
return v.Loc
case *DropConstraintStmt:
return v.Loc
case *ShowConstraintsStmt:
return v.Loc
case *AnalyzeStmt:
return v.Loc
case *ShowAnalyzeStmt:
return v.Loc
case *ShowStatsStmt:
return v.Loc
case *DropStatsStmt:
return v.Loc
case *KillAnalyzeStmt:
return v.Loc
default:
return NoLoc()
}
Expand Down
41 changes: 41 additions & 0 deletions doris/ast/nodetags.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,31 @@ const (

// T_ShowJobTaskStmt is the tag for *ShowJobTaskStmt.
T_ShowJobTaskStmt
// Statistics / Analyze / Constraint management nodes (T8.3).

// T_AddConstraintStmt is the tag for *AddConstraintStmt.
T_AddConstraintStmt

// T_DropConstraintStmt is the tag for *DropConstraintStmt.
T_DropConstraintStmt

// T_ShowConstraintsStmt is the tag for *ShowConstraintsStmt.
T_ShowConstraintsStmt

// T_AnalyzeStmt is the tag for *AnalyzeStmt.
T_AnalyzeStmt

// T_ShowAnalyzeStmt is the tag for *ShowAnalyzeStmt.
T_ShowAnalyzeStmt

// T_ShowStatsStmt is the tag for *ShowStatsStmt.
T_ShowStatsStmt

// T_DropStatsStmt is the tag for *DropStatsStmt.
T_DropStatsStmt

// T_KillAnalyzeStmt is the tag for *KillAnalyzeStmt.
T_KillAnalyzeStmt
)

// String returns a human-readable representation of the tag.
Expand Down Expand Up @@ -887,6 +912,22 @@ func (t NodeTag) String() string {
return "ShowJobStmt"
case T_ShowJobTaskStmt:
return "ShowJobTaskStmt"
case T_AddConstraintStmt:
return "AddConstraintStmt"
case T_DropConstraintStmt:
return "DropConstraintStmt"
case T_ShowConstraintsStmt:
return "ShowConstraintsStmt"
case T_AnalyzeStmt:
return "AnalyzeStmt"
case T_ShowAnalyzeStmt:
return "ShowAnalyzeStmt"
case T_ShowStatsStmt:
return "ShowStatsStmt"
case T_DropStatsStmt:
return "DropStatsStmt"
case T_KillAnalyzeStmt:
return "KillAnalyzeStmt"
default:
return "Unknown"
}
Expand Down
162 changes: 162 additions & 0 deletions doris/ast/stats_nodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package ast

// This file holds AST node types for statistics, analyze, and constraint
// management statements (T8.3).

// ---------------------------------------------------------------------------
// ADD / DROP CONSTRAINT
// ---------------------------------------------------------------------------

// AddConstraintStmt represents:
//
// ALTER TABLE name ADD CONSTRAINT cname PRIMARY KEY (cols)
// ALTER TABLE name ADD CONSTRAINT cname UNIQUE (cols)
// ALTER TABLE name ADD CONSTRAINT cname FOREIGN KEY (cols) REFERENCES ref_table (cols)
type AddConstraintStmt struct {
Table *ObjectName
Name string // constraint name
Type string // "PRIMARY KEY", "UNIQUE", "FOREIGN KEY"
Columns []string
RefTable *ObjectName // for FOREIGN KEY
RefColumns []string // for FOREIGN KEY
Loc Loc
}

// Tag implements Node.
func (n *AddConstraintStmt) Tag() NodeTag { return T_AddConstraintStmt }

var _ Node = (*AddConstraintStmt)(nil)

// DropConstraintStmt represents:
//
// ALTER TABLE name DROP CONSTRAINT cname
type DropConstraintStmt struct {
Table *ObjectName
Name string
Loc Loc
}

// Tag implements Node.
func (n *DropConstraintStmt) Tag() NodeTag { return T_DropConstraintStmt }

var _ Node = (*DropConstraintStmt)(nil)

// ShowConstraintsStmt represents:
//
// SHOW CONSTRAINTS FROM table
type ShowConstraintsStmt struct {
Table *ObjectName
Loc Loc
}

// Tag implements Node.
func (n *ShowConstraintsStmt) Tag() NodeTag { return T_ShowConstraintsStmt }

var _ Node = (*ShowConstraintsStmt)(nil)

// ---------------------------------------------------------------------------
// ANALYZE
// ---------------------------------------------------------------------------

// AnalyzeStmt represents:
//
// ANALYZE DATABASE name
// ANALYZE TABLE name [(col1, col2, ...)]
// ANALYZE PROFILE
//
// followed by optional modifiers:
//
// WITH SAMPLE PERCENT n
// WITH SAMPLE ROWS n
// WITH SYNC
// WITH INCREMENTAL
// PROPERTIES(...)
type AnalyzeStmt struct {
TargetType string // "DATABASE", "TABLE", "PROFILE", or ""
Target *ObjectName // nil for PROFILE
Columns []string // ANALYZE TABLE t(col1, col2) — optional column list
Properties []*Property // WITH ... or PROPERTIES(...)
Loc Loc
}

// Tag implements Node.
func (n *AnalyzeStmt) Tag() NodeTag { return T_AnalyzeStmt }

var _ Node = (*AnalyzeStmt)(nil)

// ---------------------------------------------------------------------------
// SHOW ANALYZE / SHOW STATS
// ---------------------------------------------------------------------------

// ShowAnalyzeStmt represents:
//
// SHOW [ALL | QUEUED] ANALYZE [JOB] [job_id | FOR table | LIKE pat]
// SHOW ANALYZE TASK STATUS job_id
type ShowAnalyzeStmt struct {
All bool // SHOW ALL ANALYZE
Queued bool // SHOW QUEUED ANALYZE JOBS
IsTask bool // SHOW ANALYZE TASK STATUS
JobID int64 // numeric job id (0 if absent)
For *ObjectName // FOR table
Like string // LIKE 'pat'
Where Node // WHERE expr
Loc Loc
}

// Tag implements Node.
func (n *ShowAnalyzeStmt) Tag() NodeTag { return T_ShowAnalyzeStmt }

var _ Node = (*ShowAnalyzeStmt)(nil)

// ShowStatsStmt represents:
//
// SHOW [COLUMN | TABLE | INDEX | PARTITION] STATS [target] [args...]
type ShowStatsStmt struct {
Type string // "COLUMN", "TABLE", "INDEX", "PARTITION", or ""
Target *ObjectName // optional table reference
Where Node // optional WHERE clause
Loc Loc
}

// Tag implements Node.
func (n *ShowStatsStmt) Tag() NodeTag { return T_ShowStatsStmt }

var _ Node = (*ShowStatsStmt)(nil)

// ---------------------------------------------------------------------------
// DROP STATS
// ---------------------------------------------------------------------------

// DropStatsStmt represents:
//
// DROP STATS target [(col1, col2)]
// DROP EXPIRED STATS target
// DROP CACHED STATS target
type DropStatsStmt struct {
Variant string // "", "EXPIRED", "CACHED"
Target *ObjectName
Columns []string // optional column list for plain DROP STATS
Loc Loc
}

// Tag implements Node.
func (n *DropStatsStmt) Tag() NodeTag { return T_DropStatsStmt }

var _ Node = (*DropStatsStmt)(nil)

// ---------------------------------------------------------------------------
// KILL ANALYZE
// ---------------------------------------------------------------------------

// KillAnalyzeStmt represents:
//
// KILL ANALYZE job_id
type KillAnalyzeStmt struct {
JobID int64
Loc Loc
}

// Tag implements Node.
func (n *KillAnalyzeStmt) Tag() NodeTag { return T_KillAnalyzeStmt }

var _ Node = (*KillAnalyzeStmt)(nil)
44 changes: 44 additions & 0 deletions doris/ast/walk_children.go
Original file line number Diff line number Diff line change
Expand Up @@ -860,5 +860,49 @@ func walkChildren(v Visitor, node Node) {
if n.For != nil {
Walk(v, n.For)
}

// Statistics / Analyze / Constraint management nodes (T8.3).
case *AddConstraintStmt:
if n.Table != nil {
Walk(v, n.Table)
}
if n.RefTable != nil {
Walk(v, n.RefTable)
}
case *DropConstraintStmt:
if n.Table != nil {
Walk(v, n.Table)
}
case *ShowConstraintsStmt:
if n.Table != nil {
Walk(v, n.Table)
}
case *AnalyzeStmt:
if n.Target != nil {
Walk(v, n.Target)
}
for _, prop := range n.Properties {
Walk(v, prop)
}
case *ShowAnalyzeStmt:
if n.For != nil {
Walk(v, n.For)
}
if n.Where != nil {
Walk(v, n.Where)
}
case *ShowStatsStmt:
if n.Target != nil {
Walk(v, n.Target)
}
if n.Where != nil {
Walk(v, n.Where)
}
case *DropStatsStmt:
if n.Target != nil {
Walk(v, n.Target)
}
case *KillAnalyzeStmt:
// leaf node, no children
}
}
11 changes: 11 additions & 0 deletions doris/parser/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ func (p *Parser) parseAlterTable() (ast.Node, error) {
}
stmt.Name = name

// ALTER TABLE name ADD CONSTRAINT ... — produce AddConstraintStmt directly.
if p.cur.Kind == kwADD && p.peekNext().Kind == kwCONSTRAINT {
p.advance() // consume ADD
return p.parseAddConstraint(startLoc, name)
}

// ALTER TABLE name DROP CONSTRAINT ... — produce DropConstraintStmt directly.
if p.cur.Kind == kwDROP && p.peekNext().Kind == kwCONSTRAINT {
return p.parseDropConstraint(startLoc, name)
}

// Parse comma-separated action list.
// Most actions start with a keyword (ADD, DROP, MODIFY, RENAME, SET, ...).
// Exception: after DROP ROLLUP name, a bare identifier means another rollup
Expand Down
23 changes: 22 additions & 1 deletion doris/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,21 @@ func (p *Parser) parseStmt() (ast.Node, error) {
return p.parseDropUser(dropTok.Loc)
case kwJOB:
return p.parseDropJob(dropTok.Loc)
case kwSTATS:
p.advance() // consume STATS
return p.parseDropStats(dropTok.Loc, "")
case kwEXPIRED:
p.advance() // consume EXPIRED
if _, err := p.expect(kwSTATS); err != nil {
return nil, err
}
return p.parseDropStats(dropTok.Loc, "EXPIRED")
case kwCACHED:
p.advance() // consume CACHED
if _, err := p.expect(kwSTATS); err != nil {
return nil, err
}
return p.parseDropStats(dropTok.Loc, "CACHED")
default:
return p.unsupported("DROP")
}
Expand Down Expand Up @@ -412,6 +427,8 @@ func (p *Parser) parseStmt() (ast.Node, error) {
}
// Return unsupported, but we already consumed SHOW so we need to emit the error at cur.
return p.unsupported("SHOW")
p.advance() // consume SHOW; dispatch inside parseShow
return p.parseShow()
case kwDESCRIBE:
return p.parseDescribe()
case kwDESC:
Expand Down Expand Up @@ -450,6 +467,9 @@ func (p *Parser) parseStmt() (ast.Node, error) {
return p.parseAdminStmt(adminTok.Loc)
case kwKILL:
killTok := p.advance() // consume KILL
if p.cur.Kind == kwANALYZE {
return p.parseKillAnalyze(killTok.Loc)
}
return p.parseKill(killTok.Loc)
case kwLOCK:
lockTok := p.advance() // consume LOCK
Expand Down Expand Up @@ -549,7 +569,8 @@ func (p *Parser) parseStmt() (ast.Node, error) {

// Analyze / Sync / Warm
case kwANALYZE:
return p.unsupported("ANALYZE")
p.advance() // consume ANALYZE
return p.parseAnalyze()
case kwSYNC:
syncTok := p.advance() // consume SYNC
return p.parseSyncStmt(syncTok.Loc)
Expand Down
5 changes: 2 additions & 3 deletions doris/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,9 @@ func TestParseAllDispatchCategories(t *testing.T) {
wantMsg string
}{
{"DROP TABLE t", "DROP"},
// Most statement categories are now implemented; only a few REFRESH
// targets and ANALYZE (until T8.3 merges) remain in the unsupported list.
// Most statement categories are now implemented; only REFRESH (with
// unrecognized target kinds) remains as an example of unsupported dispatch.
{"REFRESH DATABASE db", "REFRESH"},
{"ANALYZE TABLE t", "ANALYZE"},
}
for _, tt := range tests {
_, errs := Parse(tt.input)
Expand Down
Loading
Loading