Tracing PostgreSQL Parser Reductions with Bison Debug Output
Enabling the Bison Trace
Add the following snippet to the C declarations section of src/backend/parser/gram.y:
#ifdef YYDEBUG
#undef YYDEBUG
#endif
#define YYDEBUG 1
int base_yydebug = 1;
int plpgsql_yydebug = 1; /* matches %name-prefix used by pl_gram.y */
#define YYFPRINTF trace_parser
#include <stdio.h>
#include "utils/guc.h"
static void trace_parser(FILE *stream, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
static void trace_parser(FILE *stream, const char *fmt, ...) {
StringInfoData buf;
va_list ap;
int needed;
char path[1024];
FILE *fp;
if (client_min_messages != LOG)
return;
initStringInfo(&buf);
for (;;) {
va_start(ap, fmt);
needed = appendStringInfoVA(&buf, fmt, ap);
va_end(ap);
if (needed == 0)
break;
enlargeStringInfo(&buf, needed);
}
snprintf(path, sizeof(path), "%s/pgbison.trace", getenv("HOME"));
fp = fopen(path, "a");
if (!fp)
elog(ERROR, "cannot open trace file %s", path);
fwrite(buf.data, 1, buf.len, fp);
fclose(fp);
ereport(LOG, (errmsg_internal("'%s'", buf.data)));
pfree(buf.data);
}
Connnect with psql and run:
SET client_min_messages = 'log';
Execute:
SELECT datetime '2024-01-04 20:16:00';
A trace file appears at $HOME/pgbison.trace.
Reading the Trace
Open the file from bottom to top and search backward for by rule.
-
parse_toplevel
Reducing stack by rule 1 (line 1746): $1 = nterm stmtmulti (: ) -> $$ = nterm parse_toplevel (: )Corresponds to:
parse_toplevel: stmtmulti -
smttmulti
Reducing stack by rule 7 (line 1794): $1 = nterm stmtmulti (: ) $2 = token ';' (: ) $3 = nterm stmt (: ) -> $$ = nterm stmtmulti (: )Rule:
stmtmulti: stmtmulti ';' stmt -
stmt
Reducing stack by rule 137 (line 1945): -> $$ = nterm stmt (: )Empty rule.
-
stmtmulti (single statemant)
Reducing stack by rule 8 (line 1806): $1 = nterm stmt (: ) -> $$ = nterm stmtmulti (: )Rule:
stmtmulti: stmt -
stmt (SELECT)
Reducing stack by rule 127 (line 1934): $1 = nterm SelectStmt (: ) -> $$ = nterm stmt (: )Rule:
stmt: SelectStmt -
SelectStmt
Reducing stack by rule 2211 (line 17578): $1 = nterm select_no_parens (: ) -> $$ = nterm SelectStmt (: )Rule:
SelectStmt: select_no_parens -
select_no_parens
Reducing stack by rule 2215 (line 17599): $1 = nterm simple_select (: ) -> $$ = nterm select_no_parens (: )Rule:
select_no_parens: simple_select -
simple_select
Reducing stack by rule 2225 (line 17686): $1 = token SELECT (: ) $2 = nterm hint_string (: ) $3 = nterm opt_all_clause (: ) $4 = nterm opt_target_list (: ) $5 = nterm into_clause (: ) $6 = nterm from_clause (: ) $7 = nterm where_clause (: ) $8 = nterm hierarchical_query_clause (: ) $9 = nterm group_having_clause (: ) $10 = nterm window_clause (: ) -> $$ = nterm simple_select (: ) -
Optional clauses (all empty)
Reducing stack by rule 2780 (line 21511): -> nterm window_clause Reducing stack by rule 2118 (line 16717): -> nterm group_having_clause Reducing stack by rule 2238 (line 17826): -> nterm hierarchical_query_clause Reducing stack by rule 2428 (line 19025): -> nterm where_clause Reducing stack by rule 2341 (line 18401): -> nterm from_clause Reducing stack by rule 2257 (line 17940): -> nterm into_clause -
opt_target_list
Reducing stack by rule 2914 (line 22182): $1 = nterm target_list (: ) -> $$ = nterm opt_target_list (: )target_list
Reducing stack by rule 2916 (line 22187): $1 = nterm target_el (: ) -> $$ = nterm target_list (: ) -
target_el
Reducing stack by rule 2920 (line 22236): $1 = nterm a_expr (: ) -> $$ = nterm target_el (: )a_expr
Reducing stack by rule 2563 (line 19974): $1 = nterm c_expr (: ) -> $$ = nterm a_expr (: )c_expr
Reducing stack by rule 2664 (line 20515): $1 = nterm AexprConst (: ) -> $$ = nterm c_expr (: ) -
AexprConst
Reducing stack by rule 2959 (line 22717): $1 = nterm func_name (: ) $2 = nterm Sconst (: ) -> $$ = nterm AexprConst (: ) -
Sconst
Reducing stack by rule 2969 (line 22797): $1 = token SCONST (: ) -> $$ = nterm Sconst (: )The literal
'2024-01-04 20:16:00'. -
func_name
Reducing stack by rule 2950 (line 22665): $1 = nterm type_function_name (: ) -> $$ = nterm func_name (: )type_function_name
Reducing stack by rule 2989 (line 22968): $1 = nterm unreserved_keyword (: ) -> $$ = nterm type_function_name (: ) -
unreserved_keyword
Reducing stack by rule 3071 (line 23095): $1 = token DATETIME (: ) -> $$ = nterm unreserved_keyword (: ) -
Empty rules
Reducing stack by rule 2275 (line 18021): -> nterm opt_all_clause Reducing stack by rule 2235 (line 17794): -> nterm hint_string
All components of simple_select are now complete.