Skip to content

Commit e63703e

Browse files
authored
Add SHOW CREATE USER, ALTER USER, and authentication data parsing (#97)
1 parent 6615b9c commit e63703e

File tree

9 files changed

+65
-147
lines changed

9 files changed

+65
-147
lines changed

ast/ast.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ type CreateQuery struct {
268268
CreateDatabase bool `json:"create_database,omitempty"`
269269
CreateFunction bool `json:"create_function,omitempty"`
270270
CreateUser bool `json:"create_user,omitempty"`
271+
AlterUser bool `json:"alter_user,omitempty"`
272+
HasAuthenticationData bool `json:"has_authentication_data,omitempty"`
271273
CreateDictionary bool `json:"create_dictionary,omitempty"`
272274
DictionaryAttrs []*DictionaryAttributeDeclaration `json:"dictionary_attrs,omitempty"`
273275
DictionaryDef *DictionaryDefinition `json:"dictionary_def,omitempty"`
@@ -659,6 +661,7 @@ const (
659661
ShowCreateDB ShowType = "CREATE_DATABASE"
660662
ShowCreateDictionary ShowType = "CREATE_DICTIONARY"
661663
ShowCreateView ShowType = "CREATE_VIEW"
664+
ShowCreateUser ShowType = "CREATE_USER"
662665
ShowColumns ShowType = "COLUMNS"
663666
ShowDictionaries ShowType = "DICTIONARIES"
664667
ShowFunctions ShowType = "FUNCTIONS"

internal/explain/statements.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,13 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
8484
}
8585
return
8686
}
87-
if n.CreateUser {
88-
fmt.Fprintf(sb, "%sCreateUserQuery\n", indent)
87+
if n.CreateUser || n.AlterUser {
88+
if n.HasAuthenticationData {
89+
fmt.Fprintf(sb, "%sCreateUserQuery (children 1)\n", indent)
90+
fmt.Fprintf(sb, "%s AuthenticationData\n", indent)
91+
} else {
92+
fmt.Fprintf(sb, "%sCreateUserQuery\n", indent)
93+
}
8994
return
9095
}
9196
if n.CreateDictionary {
@@ -551,6 +556,12 @@ func explainShowQuery(sb *strings.Builder, n *ast.ShowQuery, indent string) {
551556
return
552557
}
553558

559+
// SHOW CREATE USER has special output format
560+
if n.ShowType == ast.ShowCreateUser {
561+
fmt.Fprintf(sb, "%sSHOW CREATE USER query\n", indent)
562+
return
563+
}
564+
554565
// SHOW TABLES FROM database - include database as child
555566
if n.ShowType == ast.ShowTables && n.From != "" {
556567
fmt.Fprintf(sb, "%sShowTables (children 1)\n", indent)

parser/parser.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ func (p *Parser) parseStatement() ast.Statement {
125125
case token.DROP:
126126
return p.parseDrop()
127127
case token.ALTER:
128+
// Check for ALTER USER
129+
if p.peekIs(token.USER) {
130+
return p.parseAlterUser()
131+
}
128132
return p.parseAlter()
129133
case token.TRUNCATE:
130134
return p.parseTruncate()
@@ -1809,10 +1813,44 @@ func (p *Parser) parseCreateUser(create *ast.CreateQuery) {
18091813
// Parse user name
18101814
create.UserName = p.parseIdentifierName()
18111815

1816+
// Look for authentication data (NOT IDENTIFIED or IDENTIFIED)
1817+
// Scan through tokens looking for these keywords
1818+
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
1819+
// Check for NOT IDENTIFIED
1820+
if p.currentIs(token.NOT) {
1821+
p.nextToken()
1822+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "IDENTIFIED" {
1823+
create.HasAuthenticationData = true
1824+
}
1825+
continue
1826+
}
1827+
// Check for IDENTIFIED (without NOT)
1828+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "IDENTIFIED" {
1829+
create.HasAuthenticationData = true
1830+
}
1831+
p.nextToken()
1832+
}
1833+
}
1834+
1835+
func (p *Parser) parseAlterUser() *ast.CreateQuery {
1836+
create := &ast.CreateQuery{
1837+
Position: p.current.Pos,
1838+
CreateUser: true,
1839+
AlterUser: true,
1840+
}
1841+
1842+
p.nextToken() // skip ALTER
1843+
p.nextToken() // skip USER
1844+
1845+
// Parse user name
1846+
create.UserName = p.parseIdentifierName()
1847+
18121848
// Skip the rest of the user definition (complex syntax)
18131849
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
18141850
p.nextToken()
18151851
}
1852+
1853+
return create
18161854
}
18171855

18181856
func (p *Parser) parseCreateGeneric(create *ast.CreateQuery) {
@@ -3309,6 +3347,13 @@ func (p *Parser) parseShow() ast.Statement {
33093347
} else if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "VIEW" {
33103348
show.ShowType = ast.ShowCreateView
33113349
p.nextToken()
3350+
} else if p.currentIs(token.USER) {
3351+
show.ShowType = ast.ShowCreateUser
3352+
p.nextToken()
3353+
// Skip user name and host pattern - they don't affect explain output
3354+
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
3355+
p.nextToken()
3356+
}
33123357
} else {
33133358
show.ShowType = ast.ShowCreate
33143359
// Handle SHOW CREATE TABLE, etc.
Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt10": true,
4-
"stmt11": true,
5-
"stmt12": true,
6-
"stmt13": true,
7-
"stmt14": true,
8-
"stmt15": true,
9-
"stmt16": true,
10-
"stmt17": true,
11-
"stmt18": true,
12-
"stmt19": true,
13-
"stmt20": true,
14-
"stmt21": true,
15-
"stmt22": true,
16-
"stmt23": true,
17-
"stmt24": true,
18-
"stmt25": true,
19-
"stmt26": true,
20-
"stmt27": true,
21-
"stmt28": true,
22-
"stmt29": true,
23-
"stmt3": true,
24-
"stmt32": true,
25-
"stmt33": true,
26-
"stmt34": true,
27-
"stmt35": true,
28-
"stmt36": true,
29-
"stmt4": true,
30-
"stmt5": true,
31-
"stmt6": true,
32-
"stmt7": true,
33-
"stmt8": true,
34-
"stmt9": true
35-
}
36-
}
1+
{}
Lines changed: 1 addition & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,35 @@
11
{
22
"explain_todo": {
3-
"stmt100": true,
4-
"stmt101": true,
5-
"stmt102": true,
6-
"stmt103": true,
7-
"stmt104": true,
8-
"stmt105": true,
9-
"stmt106": true,
10-
"stmt107": true,
11-
"stmt108": true,
12-
"stmt109": true,
13-
"stmt11": true,
14-
"stmt110": true,
15-
"stmt111": true,
16-
"stmt112": true,
17-
"stmt12": true,
18-
"stmt124": true,
19-
"stmt125": true,
20-
"stmt126": true,
21-
"stmt127": true,
22-
"stmt128": true,
23-
"stmt129": true,
24-
"stmt13": true,
25-
"stmt130": true,
26-
"stmt131": true,
27-
"stmt132": true,
28-
"stmt133": true,
29-
"stmt134": true,
30-
"stmt135": true,
31-
"stmt136": true,
32-
"stmt137": true,
33-
"stmt138": true,
34-
"stmt14": true,
353
"stmt141": true,
36-
"stmt148": true,
37-
"stmt149": true,
38-
"stmt150": true,
39-
"stmt151": true,
40-
"stmt152": true,
41-
"stmt153": true,
42-
"stmt155": true,
43-
"stmt156": true,
444
"stmt157": true,
455
"stmt158": true,
466
"stmt159": true,
47-
"stmt16": true,
487
"stmt160": true,
49-
"stmt161": true,
50-
"stmt162": true,
51-
"stmt163": true,
52-
"stmt164": true,
53-
"stmt165": true,
54-
"stmt166": true,
558
"stmt169": true,
56-
"stmt17": true,
57-
"stmt170": true,
589
"stmt171": true,
59-
"stmt172": true,
60-
"stmt177": true,
61-
"stmt18": true,
62-
"stmt182": true,
63-
"stmt186": true,
64-
"stmt189": true,
6510
"stmt196": true,
6611
"stmt197": true,
67-
"stmt198": true,
6812
"stmt200": true,
6913
"stmt201": true,
7014
"stmt205": true,
71-
"stmt206": true,
7215
"stmt207": true,
7316
"stmt208": true,
74-
"stmt21": true,
7517
"stmt219": true,
7618
"stmt22": true,
7719
"stmt221": true,
7820
"stmt23": true,
79-
"stmt234": true,
80-
"stmt235": true,
81-
"stmt236": true,
8221
"stmt239": true,
8322
"stmt24": true,
8423
"stmt25": true,
8524
"stmt26": true,
8625
"stmt27": true,
8726
"stmt28": true,
8827
"stmt29": true,
89-
"stmt30": true,
90-
"stmt31": true,
91-
"stmt32": true,
92-
"stmt33": true,
93-
"stmt34": true,
94-
"stmt35": true,
95-
"stmt36": true,
96-
"stmt37": true,
97-
"stmt38": true,
9828
"stmt39": true,
9929
"stmt40": true,
10030
"stmt41": true,
10131
"stmt42": true,
10232
"stmt43": true,
103-
"stmt44": true,
104-
"stmt45": true,
105-
"stmt46": true,
106-
"stmt47": true,
107-
"stmt48": true,
108-
"stmt6": true,
109-
"stmt67": true,
110-
"stmt68": true,
111-
"stmt69": true,
112-
"stmt70": true,
113-
"stmt71": true,
114-
"stmt72": true,
115-
"stmt73": true,
116-
"stmt74": true,
117-
"stmt75": true,
118-
"stmt76": true,
119-
"stmt77": true,
120-
"stmt78": true,
121-
"stmt79": true,
122-
"stmt80": true,
123-
"stmt81": true,
124-
"stmt82": true,
125-
"stmt83": true,
126-
"stmt84": true,
127-
"stmt85": true,
128-
"stmt86": true,
129-
"stmt87": true,
130-
"stmt88": true,
131-
"stmt89": true,
132-
"stmt9": true,
133-
"stmt90": true,
134-
"stmt99": true
33+
"stmt6": true
13534
}
13635
}
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"explain_todo": {
33
"stmt2": true,
4-
"stmt3": true,
54
"stmt5": true
65
}
76
}

parser/testdata/01999_grant_with_replace/metadata.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"explain_todo": {
33
"stmt26": true,
44
"stmt27": true,
5-
"stmt3": true,
65
"stmt47": true,
76
"stmt48": true,
87
"stmt52": true,

parser/testdata/02867_create_user_ssh/metadata.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"stmt2": true,
44
"stmt3": true,
55
"stmt4": true,
6-
"stmt5": true,
7-
"stmt6": true
6+
"stmt5": true
87
}
98
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
{
22
"explain_todo": {
33
"stmt1": true,
4-
"stmt2": true,
5-
"stmt4": true,
6-
"stmt5": true
4+
"stmt4": true
75
}
86
}

0 commit comments

Comments
 (0)