What happened
Split out of #68, whose primary fix shipped in #80. That PR fixed the INSERT ... DEFAULT VALUES instance and pinned parser parity with a corpus; this is the underlying shape it deliberately left alone.
Both dialect parsers blank all eight structural fields up front and refill them only for Select / SelectClause / Delete / Update / Insert. Any other AST node keeps Exact = true with every structural flag forced false, discarding the values the FallbackParser had already computed.
Verified on main (e91feae):
CREATE VIEW v AS SELECT * FROM t
fallback: [select-star]
pgparser: [] Kind=StmtOther Exact=true SelectStar=false
CREATE TABLE c AS SELECT * FROM t
fallback: [select-star]
pgparser: [] Kind=StmtOther Exact=true SelectStar=false
The contrast that shows it is the reset and not the grammar: CREATE MATERIALIZED VIEW m AS SELECT * FROM t ORDER BY a is rejected by the grammar, degrades to the fallback, and reports select-star and orderby-without-limit correctly. The statements the grammar understands are the ones that lose findings.
Expected behavior
select-star should fire on CREATE VIEW v AS SELECT * FROM t under pgparser, as it does under the default parser. More generally, opting into an exact parser should not blank a structural fact the fallback had already established.
Note this fails safe — it is a false negative — which is why the parity test added in #80 passes over it. That test asserts the grammar never adds a finding the fallback does not produce; it says nothing about findings the grammar drops.
Exact = true is also wrong here on its own terms. Statement.Exact is documented as covering Kind, HasWhere/HasLimit/HasOrderBy/HasFrom, SelectStar, SelectDistinct, OffsetValue and InsertColumnsListed — but on these nodes none of those were derived from the AST, they were just zeroed.
SQL
CREATE VIEW v AS SELECT * FROM t;
CREATE TABLE c AS SELECT * FROM t;
Minimal Go reproduction
a := analyzer.Default().WithParser(pgparser.New())
fmt.Println(analyzer.Default().Analyze("CREATE VIEW v AS SELECT * FROM t")) // [select-star]
fmt.Println(a.Analyze("CREATE VIEW v AS SELECT * FROM t")) // []
Entry surface
Analyzer API (direct)
Parser in use
parsers/pgparser
sqlguard version
e91feae (post-0.4.0)
Go version
go1.27.1 linux/amd64
Database and dialect
No response
Additional context
Direction (from #68): move the field resets inside each case so a node the switch does not handle keeps the fallback's values.
That needs a decision on what Exact should claim once the fallback's heuristics survive into the result — today its doc comment promises those fields came from an AST, and the honest answer for a CREATE VIEW may be Exact = false. That is the design call which kept this out of #80.
mysqlparser has the same shape (mysqlparser.go, the resets above the switch), so fix both.
What happened
Split out of #68, whose primary fix shipped in #80. That PR fixed the
INSERT ... DEFAULT VALUESinstance and pinned parser parity with a corpus; this is the underlying shape it deliberately left alone.Both dialect parsers blank all eight structural fields up front and refill them only for
Select/SelectClause/Delete/Update/Insert. Any other AST node keepsExact = truewith every structural flag forcedfalse, discarding the values the FallbackParser had already computed.Verified on
main(e91feae):The contrast that shows it is the reset and not the grammar:
CREATE MATERIALIZED VIEW m AS SELECT * FROM t ORDER BY ais rejected by the grammar, degrades to the fallback, and reportsselect-starandorderby-without-limitcorrectly. The statements the grammar understands are the ones that lose findings.Expected behavior
select-starshould fire onCREATE VIEW v AS SELECT * FROM tunderpgparser, as it does under the default parser. More generally, opting into an exact parser should not blank a structural fact the fallback had already established.Note this fails safe — it is a false negative — which is why the parity test added in #80 passes over it. That test asserts the grammar never adds a finding the fallback does not produce; it says nothing about findings the grammar drops.
Exact = trueis also wrong here on its own terms.Statement.Exactis documented as coveringKind,HasWhere/HasLimit/HasOrderBy/HasFrom,SelectStar,SelectDistinct,OffsetValueandInsertColumnsListed— but on these nodes none of those were derived from the AST, they were just zeroed.SQL
Minimal Go reproduction
Entry surface
Analyzer API (direct)
Parser in use
parsers/pgparser
sqlguard version
e91feae (post-0.4.0)
Go version
go1.27.1 linux/amd64
Database and dialect
No response
Additional context
Direction (from #68): move the field resets inside each
caseso a node the switch does not handle keeps the fallback's values.That needs a decision on what
Exactshould claim once the fallback's heuristics survive into the result — today its doc comment promises those fields came from an AST, and the honest answer for aCREATE VIEWmay beExact = false. That is the design call which kept this out of #80.mysqlparserhas the same shape (mysqlparser.go, the resets above theswitch), so fix both.