Skip to content

Commit fd144c6

Browse files
committed
ast: snake_case field names in JSON output
Give every node field an explicit json tag with the snake_case form of its name: StmtLocation prints as stmt_location, FromClause as from_clause. The keys now read as JSON rather than as Go leaking through, and they match the names libpg_query uses for the same fields in its own JSON output, so anyone coming from pg_query's tree finds the fields where they expect them. The tags also stop the output from being coupled to the Go field names: a field rename is now a compile-time-visible decision about the JSON, not a silent output change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9LCt1mwdY3mE14x3Zz5Vw
1 parent 4f101f1 commit fd144c6

260 files changed

Lines changed: 1397 additions & 1396 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/howto/parse.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,19 @@ The output is a JSON array with one object per statement:
4949
"cmd": ":one",
5050
"ast": {
5151
"tag": "RawStmt",
52-
"Stmt": {
52+
"stmt": {
5353
"...": "..."
5454
},
55-
"StmtLocation": 0,
56-
"StmtLen": 42
55+
"stmt_location": 0,
56+
"stmt_len": 42
5757
}
5858
}
5959
]
6060
```
6161

6262
Statements without a `-- name:` annotation (for example schema DDL) omit the
63-
`name` and `cmd` fields.
63+
`name` and `cmd` fields. Field names are `snake_case` versions of the AST node
64+
field names.
6465

6566
## Node types
6667

@@ -69,18 +70,18 @@ fields of their own, so without it a star, a null literal and an untranslated
6970
clause would all print as `{}`.
7071

7172
```json
72-
"Val": {
73+
"val": {
7374
"tag": "ColumnRef",
74-
"Name": "",
75-
"Fields": {
75+
"name": "",
76+
"fields": {
7677
"tag": "List",
77-
"Items": [
78+
"items": [
7879
{
7980
"tag": "A_Star"
8081
}
8182
]
8283
},
83-
"Location": 93
84+
"location": 93
8485
}
8586
```
8687

@@ -94,17 +95,17 @@ A field the statement does not use is left out rather than printed as `null`.
9495
An `A_Const` carrying an integer reports only what it has:
9596

9697
```json
97-
"Val": {
98+
"val": {
9899
"tag": "A_Const",
99-
"Val": {
100+
"val": {
100101
"tag": "Integer",
101-
"Ival": 1
102+
"ival": 1
102103
},
103-
"Location": 30
104+
"location": 30
104105
}
105106
```
106107

107108
Only absent fields — and empty lists, which engines construct differently for
108109
the same SQL — are omitted. A zero keeps its place, because zero is a value the
109-
parser can find: `StmtLocation` is 0 for the first statement in a file, and
110-
`LIMIT 0` parses to an `Ival` of 0.
110+
parser can find: `stmt_location` is 0 for the first statement in a file, and
111+
`LIMIT 0` parses to an `ival` of 0.

internal/endtoend/testdata/analyze_ast/postgresql/stdout.txt

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,112 +25,112 @@
2525
],
2626
"ast": {
2727
"tag": "RawStmt",
28-
"Stmt": {
28+
"stmt": {
2929
"tag": "SelectStmt",
30-
"DistinctClause": {
30+
"distinct_clause": {
3131
"tag": "List"
3232
},
33-
"TargetList": {
33+
"target_list": {
3434
"tag": "List",
35-
"Items": [
35+
"items": [
3636
{
3737
"tag": "ResTarget",
38-
"Indirection": {
38+
"indirection": {
3939
"tag": "List"
4040
},
41-
"Val": {
41+
"val": {
4242
"tag": "ColumnRef",
43-
"Name": "",
44-
"Fields": {
43+
"name": "",
44+
"fields": {
4545
"tag": "List",
46-
"Items": [
46+
"items": [
4747
{
4848
"tag": "String",
49-
"Str": "name"
49+
"str": "name"
5050
}
5151
]
5252
},
53-
"Location": 35
53+
"location": 35
5454
},
55-
"Location": 35
55+
"location": 35
5656
}
5757
]
5858
},
59-
"FromClause": {
59+
"from_clause": {
6060
"tag": "List",
61-
"Items": [
61+
"items": [
6262
{
6363
"tag": "RangeVar",
64-
"Relname": "authors",
65-
"Inh": true,
66-
"Relpersistence": 112,
67-
"Location": 45
64+
"relname": "authors",
65+
"inh": true,
66+
"relpersistence": 112,
67+
"location": 45
6868
}
6969
]
7070
},
71-
"WhereClause": {
71+
"where_clause": {
7272
"tag": "A_Expr",
73-
"Kind": 1,
74-
"Name": {
73+
"kind": 1,
74+
"name": {
7575
"tag": "List",
76-
"Items": [
76+
"items": [
7777
{
7878
"tag": "String",
79-
"Str": "="
79+
"str": "="
8080
}
8181
]
8282
},
83-
"Lexpr": {
83+
"lexpr": {
8484
"tag": "ColumnRef",
85-
"Name": "",
86-
"Fields": {
85+
"name": "",
86+
"fields": {
8787
"tag": "List",
88-
"Items": [
88+
"items": [
8989
{
9090
"tag": "String",
91-
"Str": "id"
91+
"str": "id"
9292
}
9393
]
9494
},
95-
"Location": 59
95+
"location": 59
9696
},
97-
"Rexpr": {
97+
"rexpr": {
9898
"tag": "ParamRef",
99-
"Number": 1,
100-
"Location": 64,
101-
"Dollar": true
99+
"number": 1,
100+
"location": 64,
101+
"dollar": true
102102
},
103-
"Location": 62
103+
"location": 62
104104
},
105-
"GroupClause": {
105+
"group_clause": {
106106
"tag": "List"
107107
},
108-
"HavingClause": {
108+
"having_clause": {
109109
"tag": "TODO"
110110
},
111-
"WindowClause": {
111+
"window_clause": {
112112
"tag": "List"
113113
},
114-
"ValuesLists": {
114+
"values_lists": {
115115
"tag": "List"
116116
},
117-
"SortClause": {
117+
"sort_clause": {
118118
"tag": "List"
119119
},
120-
"LimitOffset": {
120+
"limit_offset": {
121121
"tag": "TODO"
122122
},
123-
"LimitCount": {
123+
"limit_count": {
124124
"tag": "TODO"
125125
},
126-
"LockingClause": {
126+
"locking_clause": {
127127
"tag": "List"
128128
},
129-
"Op": 0,
130-
"All": false
129+
"op": 0,
130+
"all": false
131131
},
132-
"StmtLocation": 0,
133-
"StmtLen": 66
132+
"stmt_location": 0,
133+
"stmt_len": 66
134134
}
135135
}
136136
]

internal/endtoend/testdata/parse_basic/clickhouse/stdout.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
"cmd": ":one",
55
"ast": {
66
"tag": "RawStmt",
7-
"Stmt": {
7+
"stmt": {
88
"tag": "SelectStmt",
9-
"TargetList": {
9+
"target_list": {
1010
"tag": "List",
11-
"Items": [
11+
"items": [
1212
{
1313
"tag": "ResTarget",
14-
"Val": {
14+
"val": {
1515
"tag": "A_Const",
16-
"Val": {
16+
"val": {
1717
"tag": "Integer",
18-
"Ival": 1
18+
"ival": 1
1919
},
20-
"Location": 31
20+
"location": 31
2121
},
22-
"Location": 31
22+
"location": 31
2323
}
2424
]
2525
},
26-
"Op": 0,
27-
"All": false
26+
"op": 0,
27+
"all": false
2828
},
29-
"StmtLocation": 0,
30-
"StmtLen": 32
29+
"stmt_location": 0,
30+
"stmt_len": 32
3131
}
3232
}
3333
]

internal/endtoend/testdata/parse_basic/duckdb/stdout.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
"cmd": ":one",
55
"ast": {
66
"tag": "RawStmt",
7-
"Stmt": {
7+
"stmt": {
88
"tag": "SelectStmt",
9-
"TargetList": {
9+
"target_list": {
1010
"tag": "List",
11-
"Items": [
11+
"items": [
1212
{
1313
"tag": "ResTarget",
14-
"Val": {
14+
"val": {
1515
"tag": "A_Const",
16-
"Val": {
16+
"val": {
1717
"tag": "Integer",
18-
"Ival": 1
18+
"ival": 1
1919
},
20-
"Location": 30
20+
"location": 30
2121
},
22-
"Location": 30
22+
"location": 30
2323
}
2424
]
2525
},
26-
"Op": 0,
27-
"All": false
26+
"op": 0,
27+
"all": false
2828
},
29-
"StmtLocation": 0,
30-
"StmtLen": 33
29+
"stmt_location": 0,
30+
"stmt_len": 33
3131
}
3232
}
3333
]

internal/endtoend/testdata/parse_basic/googlesql/stdout.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
"cmd": ":one",
55
"ast": {
66
"tag": "RawStmt",
7-
"Stmt": {
7+
"stmt": {
88
"tag": "SelectStmt",
9-
"TargetList": {
9+
"target_list": {
1010
"tag": "List",
11-
"Items": [
11+
"items": [
1212
{
1313
"tag": "ResTarget",
14-
"Val": {
14+
"val": {
1515
"tag": "A_Const",
16-
"Val": {
16+
"val": {
1717
"tag": "Integer",
18-
"Ival": 1
18+
"ival": 1
1919
},
20-
"Location": 30
20+
"location": 30
2121
},
22-
"Location": 30
22+
"location": 30
2323
}
2424
]
2525
},
26-
"Op": 0,
27-
"All": false
26+
"op": 0,
27+
"all": false
2828
},
29-
"StmtLocation": 0,
30-
"StmtLen": 31
29+
"stmt_location": 0,
30+
"stmt_len": 31
3131
}
3232
}
3333
]

0 commit comments

Comments
 (0)