Goal: Add
Locfield to all 139 AST node structs in pg/ast that are currently missing it, and set location tracking in the parser Verification: Parse SQL → navigate to node → verifysql[node.Loc.Start:node.Loc.End]matches expected source text Reference sources: pg/ast/parsenodes.go (struct definitions), pg/parser/*.go (node creation sites), existing Loc patterns (Alias, RangeVar, SelectStmt) Proof:go test ./pg/parser/... ./pg/parsertest/...| same |go test ./pg/...
Status: [ ] pending, [x] passing, [~] partial (needs upstream change)
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/select.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go (shared with all sections) Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- JoinExpr —
SELECT * FROM t1 JOIN t2 ON t1.id = t2.id→ Loc coverst1 JOIN t2 ON t1.id = t2.id - JoinExpr LEFT —
SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id→ Loc covers full join expr - JoinExpr CROSS —
SELECT * FROM t1 CROSS JOIN t2→ Loc covers cross join expr - JoinExpr NATURAL —
SELECT * FROM t1 NATURAL JOIN t2→ Loc covers natural join expr - RangeSubselect —
SELECT * FROM (SELECT 1) AS sub→ Loc covers(SELECT 1) AS sub - RangeSubselect LATERAL —
SELECT * FROM t1, LATERAL (SELECT * FROM t2) AS sub→ Loc covers lateral subselect - RangeFunction —
SELECT * FROM generate_series(1, 10)→ Loc covers function call in FROM - RangeFunction WITH ORDINALITY —
SELECT * FROM generate_series(1, 10) WITH ORDINALITY→ Loc includes WITH ORDINALITY - RangeFunction ROWS FROM —
SELECT * FROM ROWS FROM(generate_series(1,3), generate_series(1,4))→ Loc covers ROWS FROM - CurrentOfExpr —
DELETE FROM t1 WHERE CURRENT OF cursor1→ Loc coversCURRENT OF cursor1 - LockingClause —
SELECT * FROM t1 FOR UPDATE→ Loc coversFOR UPDATE - IntoClause —
SELECT * INTO newtable FROM t1→ Loc coversINTO newtable
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/expr.go, pg/parser/name.go, pg/parser/select.go, pg/parser/copy.go, pg/parser/maintenance.go, pg/parser/create_view.go, pg/parser/update.go, pg/parser/insert.go, pg/parser/create_table.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run LocNote: A_Star is currentlystruct{}(empty). Adding Loc changes its memory layout — verify all creation sites still compile.
- A_Indices single —
SELECT a[1] FROM t→ Loc covers[1] - A_Indices slice —
SELECT a[1:3] FROM t→ Loc covers[1:3] - A_Indirection —
SELECT (row).field FROM t→ Loc covers.fieldindirection - A_Star —
SELECT * FROM t→ Loc covers*(created in expr.go, name.go, select.go, copy.go, maintenance.go, create_view.go) - MergeWhenClause MATCHED —
MERGE INTO t USING s ON t.id=s.id WHEN MATCHED THEN UPDATE SET x=1→ Loc coversWHEN MATCHED THEN UPDATE SET x=1 - MergeWhenClause NOT MATCHED —
MERGE INTO t USING s ON t.id=s.id WHEN NOT MATCHED THEN INSERT VALUES(1)→ Loc covers WHEN NOT MATCHED clause - MultiAssignRef —
INSERT INTO t(a,b) SELECT 1,2with multi-assign → Loc covers ref - TableLikeClause —
CREATE TABLE t2 (LIKE t1 INCLUDING ALL)→ Loc coversLIKE t1 INCLUDING ALL
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/json.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- JsonArgument —
SELECT json_object('key': 'value')→ Loc covers argument - JsonKeyValue —
SELECT JSON_OBJECT('key' VALUE 'val')→ Loc covers key-value pair - JsonObjectAgg —
SELECT JSON_OBJECTAGG(k VALUE v) FROM t→ Loc covers aggregate - JsonArrayAgg —
SELECT JSON_ARRAYAGG(v) FROM t→ Loc covers aggregate - JsonOutput —
SELECT JSON_OBJECT('k': 'v' RETURNING text)→ Loc covers RETURNING clause - JsonValueExpr — JSON value expression in JSON functions → Loc covers value expr
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/define.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- DefineStmt TYPE —
CREATE TYPE mytype AS (a int, b text)→ Loc covers full statement - DefineStmt OPERATOR —
CREATE OPERATOR === (LEFTARG=int, RIGHTARG=int, FUNCTION=int4eq)→ Loc covers full statement - DefineStmt AGGREGATE —
CREATE AGGREGATE myagg(int) (SFUNC=int4pl, STYPE=int)→ Loc covers full statement - CompositeTypeStmt —
CREATE TYPE comptype AS (x int, y int)→ Loc covers full statement - CreateEnumStmt —
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy')→ Loc covers full statement - CreateRangeStmt —
CREATE TYPE floatrange AS RANGE (SUBTYPE = float8)→ Loc covers full statement - CreateOpClassStmt —
CREATE OPERATOR CLASS myclass FOR TYPE int USING btree AS OPERATOR 1 <→ Loc covers full statement - CreateOpFamilyStmt —
CREATE OPERATOR FAMILY myfam USING btree→ Loc covers full statement - CreateOpClassItem — individual item in operator class definition → Loc covers item
- CreateConversionStmt —
CREATE CONVERSION myconv FOR 'UTF8' TO 'LATIN1' FROM utf8_to_iso8859_1→ Loc covers full statement - CreateStatsStmt —
CREATE STATISTICS mystats (dependencies) ON a, b FROM t→ Loc covers full statement - AlterDefaultPrivilegesStmt —
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO public→ Loc covers full statement - AlterOpFamilyStmt —
ALTER OPERATOR FAMILY myfam USING btree ADD OPERATOR 1 <(int,int)→ Loc covers full statement - AlterOperatorStmt —
ALTER OPERATOR ===(int,int) SET (RESTRICT=eqsel)→ Loc covers full statement - AlterStatsStmt —
ALTER STATISTICS mystats SET STATISTICS 100→ Loc covers full statement - StatsElem — individual element in CREATE STATISTICS → Loc covers element
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/extension.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreateExtensionStmt —
CREATE EXTENSION hstore→ Loc covers full statement - CreateAmStmt —
CREATE ACCESS METHOD myam TYPE INDEX HANDLER myhandler→ Loc covers full statement - CreateCastStmt —
CREATE CAST (int AS text) WITH FUNCTION int4_to_text(int)→ Loc covers full statement - CreateTransformStmt —
CREATE TRANSFORM FOR int LANGUAGE plpgsql (FROM SQL WITH FUNCTION ..., TO SQL WITH FUNCTION ...)→ Loc covers full statement - AlterExtensionStmt —
ALTER EXTENSION hstore UPDATE TO '2.0'→ Loc covers full statement - AlterExtensionContentsStmt —
ALTER EXTENSION hstore ADD TABLE mytable→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/fdw.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreateFdwStmt —
CREATE FOREIGN DATA WRAPPER myfdw→ Loc covers full statement - CreateForeignServerStmt —
CREATE SERVER myserver FOREIGN DATA WRAPPER myfdw→ Loc covers full statement - CreateForeignTableStmt —
CREATE FOREIGN TABLE ft (a int) SERVER myserver→ Loc covers full statement - CreatePLangStmt —
CREATE LANGUAGE plmylang→ Loc covers full statement - CreateUserMappingStmt —
CREATE USER MAPPING FOR current_user SERVER myserver→ Loc covers full statement - AlterFdwStmt —
ALTER FOREIGN DATA WRAPPER myfdw OPTIONS (ADD host 'foo')→ Loc covers full statement - AlterForeignServerStmt —
ALTER SERVER myserver OPTIONS (SET host 'bar')→ Loc covers full statement - AlterUserMappingStmt —
ALTER USER MAPPING FOR current_user SERVER myserver OPTIONS (SET password 'x')→ Loc covers full statement - DropUserMappingStmt —
DROP USER MAPPING FOR current_user SERVER myserver→ Loc covers full statement - ImportForeignSchemaStmt —
IMPORT FOREIGN SCHEMA public FROM SERVER myserver INTO local_schema→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/alter_misc.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- AlterCollationStmt —
ALTER COLLATION "C" REFRESH VERSION→ Loc covers full statement - AlterDomainStmt —
ALTER DOMAIN mydom SET NOT NULL→ Loc covers full statement - AlterEnumStmt —
ALTER TYPE mood ADD VALUE 'great'→ Loc covers full statement - AlterEventTrigStmt —
ALTER EVENT TRIGGER mytrig DISABLE→ Loc covers full statement - AlterFunctionStmt —
ALTER FUNCTION myfunc(int) STABLE→ Loc covers full statement - AlterObjectDependsStmt —
ALTER FUNCTION myfunc DEPENDS ON EXTENSION hstore→ Loc covers full statement - AlterObjectSchemaStmt —
ALTER TABLE t SET SCHEMA newschema→ Loc covers full statement - AlterOwnerStmt —
ALTER TABLE t OWNER TO newowner→ Loc covers full statement - AlterTableSpaceOptionsStmt —
ALTER TABLESPACE myts SET (seq_page_cost=2)→ Loc covers full statement - AlterTSConfigurationStmt —
ALTER TEXT SEARCH CONFIGURATION myconfig ADD MAPPING FOR word WITH simple→ Loc covers full statement - AlterTSDictionaryStmt —
ALTER TEXT SEARCH DICTIONARY mydict (STOPWORDS = 'english')→ Loc covers full statement - AlterTypeStmt —
ALTER TYPE comptype ADD ATTRIBUTE c int→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/alter_table.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- AlterTableStmt —
ALTER TABLE t ADD COLUMN x int→ Loc covers full statement - AlterTableCmd — individual ALTER TABLE sub-command → Loc covers the sub-command
- AlterSeqStmt —
ALTER SEQUENCE myseq RESTART WITH 1→ Loc covers full statement - AlterTableMoveAllStmt —
ALTER TABLE ALL IN TABLESPACE ts1 SET TABLESPACE ts2→ Loc covers full statement - PartitionCmd —
ALTER TABLE t ATTACH PARTITION p FOR VALUES FROM (1) TO (10)→ Loc covers partition command - RenameStmt —
ALTER TABLE t RENAME COLUMN old TO new→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/grant.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- GrantStmt —
GRANT SELECT ON t TO myrole→ Loc covers full statement - GrantRoleStmt —
GRANT myrole TO otheruser→ Loc covers full statement - CreateRoleStmt —
CREATE ROLE myrole WITH LOGIN→ Loc covers full statement - AlterRoleStmt —
ALTER ROLE myrole WITH SUPERUSER→ Loc covers full statement - AlterRoleSetStmt —
ALTER ROLE myrole SET search_path TO public→ Loc covers full statement - AlterPolicyStmt —
ALTER POLICY mypol ON t USING (true)→ Loc covers full statement - CreatePolicyStmt —
CREATE POLICY mypol ON t USING (true)→ Loc covers full statement - DropRoleStmt —
DROP ROLE myrole→ Loc covers full statement - AccessPriv — individual privilege in GRANT → Loc covers privilege entry
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/publication.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreatePublicationStmt —
CREATE PUBLICATION mypub FOR ALL TABLES→ Loc covers full statement - AlterPublicationStmt —
ALTER PUBLICATION mypub ADD TABLE t→ Loc covers full statement - CreateSubscriptionStmt —
CREATE SUBSCRIPTION mysub CONNECTION 'conninfo' PUBLICATION mypub→ Loc covers full statement - AlterSubscriptionStmt —
ALTER SUBSCRIPTION mysub SET PUBLICATION mypub→ Loc covers full statement - PublicationTable — individual table in publication → Loc covers table reference
- RuleStmt —
CREATE RULE myrule AS ON INSERT TO t DO INSTEAD NOTHING→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/database.go, pg/parser/schema.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreatedbStmt —
CREATE DATABASE mydb→ Loc covers full statement - AlterDatabaseStmt —
ALTER DATABASE mydb SET TABLESPACE newtbs→ Loc covers full statement - AlterDatabaseSetStmt —
ALTER DATABASE mydb SET timezone TO 'UTC'→ Loc covers full statement - DropdbStmt —
DROP DATABASE mydb→ Loc covers full statement - CreateSchemaStmt —
CREATE SCHEMA myschema→ Loc covers full statement - CreateTableSpaceStmt —
CREATE TABLESPACE mytbs LOCATION '/data'→ Loc covers full statement - CommentStmt —
COMMENT ON TABLE t IS 'my comment'→ Loc covers full statement - SecLabelStmt —
SECURITY LABEL ON TABLE t IS 'classified'→ Loc covers full statement - ObjectWithArgs — object reference with argument types (e.g., in DROP FUNCTION) → Loc covers object+args
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/sequence.go, pg/parser/create_function.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreateSeqStmt —
CREATE SEQUENCE myseq START 1→ Loc covers full statement - CreateDomainStmt —
CREATE DOMAIN posint AS int CHECK (VALUE > 0)→ Loc covers full statement - CreateFunctionStmt —
CREATE FUNCTION myfunc(int) RETURNS int AS $$ SELECT $1 $$ LANGUAGE sql→ Loc covers full statement - FunctionParameter — individual parameter in function definition → Loc covers parameter
- ReturnStmt —
RETURN exprin function body → Loc covers RETURN statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/trigger.go, pg/parser/create_index.go, pg/parser/create_view.go, pg/parser/create_table.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- CreateTrigStmt —
CREATE TRIGGER mytrig BEFORE INSERT ON t EXECUTE FUNCTION myfunc()→ Loc covers full statement - CreateEventTrigStmt —
CREATE EVENT TRIGGER myevt ON ddl_command_start EXECUTE FUNCTION myfunc()→ Loc covers full statement - TriggerTransition —
REFERENCING NEW TABLE AS newtab→ Loc covers transition clause - IndexStmt —
CREATE INDEX myidx ON t (col)→ Loc covers full statement - IndexElem — individual index element → Loc covers element
- ViewStmt —
CREATE VIEW myview AS SELECT * FROM t→ Loc covers full statement - CreateTableAsStmt —
CREATE TABLE t AS SELECT 1→ Loc covers full statement - RefreshMatViewStmt —
REFRESH MATERIALIZED VIEW myview→ Loc covers full statement - CreateStmt —
CREATE TABLE t (a int, b text)→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/utility.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- ExplainStmt —
EXPLAIN SELECT 1→ Loc covers full statement - CallStmt —
CALL myproc()→ Loc covers full statement - DoStmt —
DO $$ BEGIN RAISE NOTICE 'hi'; END $$→ Loc covers full statement - CheckPointStmt —
CHECKPOINT→ Loc covers full statement - DiscardStmt —
DISCARD ALL→ Loc covers full statement - ListenStmt —
LISTEN mychannel→ Loc covers full statement - NotifyStmt —
NOTIFY mychannel, 'payload'→ Loc covers full statement - UnlistenStmt —
UNLISTEN mychannel→ Loc covers full statement - LoadStmt —
LOAD 'mylib'→ Loc covers full statement - ReassignOwnedStmt —
REASSIGN OWNED BY oldrole TO newrole→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/cursor.go, pg/parser/prepare.go, pg/parser/copy.go, pg/parser/lock.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- DeclareCursorStmt —
DECLARE mycur CURSOR FOR SELECT 1→ Loc covers full statement - FetchStmt —
FETCH NEXT FROM mycur→ Loc covers full statement - ClosePortalStmt —
CLOSE mycur→ Loc covers full statement - PrepareStmt —
PREPARE myplan AS SELECT 1→ Loc covers full statement - ExecuteStmt —
EXECUTE myplan→ Loc covers full statement - CopyStmt —
COPY t FROM STDIN→ Loc covers full statement - LockStmt —
LOCK TABLE t IN ACCESS EXCLUSIVE MODE→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, pg/parser/maintenance.go, pg/parser/set.go, pg/parser/drop.go, pg/parsertest/loc_test.go Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- VacuumStmt —
VACUUM t→ Loc covers full statement - VacuumRelation — individual relation in VACUUM → Loc covers relation reference
- ClusterStmt —
CLUSTER t USING myidx→ Loc covers full statement - ReindexStmt —
REINDEX TABLE t→ Loc covers full statement - VariableSetStmt —
SET search_path TO public→ Loc covers full statement - VariableShowStmt —
SHOW search_path→ Loc covers full statement - AlterSystemStmt —
ALTER SYSTEM SET max_connections = 200→ Loc covers full statement - ConstraintsSetStmt —
SET CONSTRAINTS ALL DEFERRED→ Loc covers full statement - DropStmt —
DROP TABLE t→ Loc covers full statement - DropOwnedStmt —
DROP OWNED BY myrole→ Loc covers full statement - DropSubscriptionStmt —
DROP SUBSCRIPTION mysub→ Loc covers full statement - DropTableSpaceStmt —
DROP TABLESPACE mytbs→ Loc covers full statement - TruncateStmt —
TRUNCATE t→ Loc covers full statement
Targets: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go, investigation required Shared: pg/ast/parsenodes.go, pg/ast/loc.go, pg/ast/outfuncs.go Proof:
go test ./pg/parser/... ./pg/parsertest/... -run Loc
- FromExpr — N/A: planner-internal only; not created in parser (only in pg/catalog/query.go)
- SetOperationStmt — N/A: planner-internal only; parser creates SelectStmt, analyze.go transforms to SetOperationStmt
- WindowClause — N/A: planner-internal only; parser creates WindowDef, analyze.go transforms to WindowClauseQ
- SortGroupClause — N/A: planner-internal only; created exclusively in pg/catalog/analyze.go
- JsonReturning — N/A: struct exists but is never instantiated; parser uses JsonOutput instead