[postgresql] trace parsing steps of bison

发布时间 2024-01-04 21:18:23作者: winter-loo

setup

In the section of C declarations within the file src/backend/parser/gram.y, include the following code,

#define YYDEBUG 1
int base_yydebug = 1;
#define YYFPRINTF trace_parser
#include <stdio.h>
#include "utils/guc.h"

void trace_parser(FILE* stderr, const char* fmt, ...) {
  if (client_min_messages != LOG)
  	return;

  StringInfoData buf;
  va_list   ap;
  int     needed;

  initStringInfo(&buf);
  for (;;)
  {
    va_start(ap, fmt);
    needed = appendStringInfoVA(&buf, fmt, ap);
    va_end(ap);
    if (needed == 0)
      break;
    enlargeStringInfo(&buf, needed);
  }

  char trace_file[1024];
  strcpy(trace_file, getenv("HOME"));
  strcat(trace_file, "/pgbison.trace");
  FILE* trace_fd = fopen(trace_file, "a+");
  if (!trace_fd)
    elog(ERROR, "cannot open file %s", trace_file);

  fwrite(buf.data, sizeof(char), buf.len, trace_fd);
  fclose(trace_fd);

  ereport(LOG, (errmsg_internal("'%s'", buf.data)));
  pfree(buf.data);
}

then using psql connect to database, and execute command,

set client_min_messages = 'log';

next, execute the following sql,

select datetime '2024-01-04 20:16:00';

and, the trace file is generated at $HOME/pgbison.trace.

analyze trace file

[!NOTE]

  1. reading the trace file from the end to the beginning.
  2. seach reversely the keyword 'by rule'
  1. parse_toplevel
Reducing stack by rule 1 (line 1746):
   $1 = nterm stmtmulti (: )
-> $$ = nterm parse_toplevel (: )

The above output is a rule at line 1746 of gram.y, which is,
![[Pasted image 20240104202826.png]]
image

  1. stmtmulti
Reducing stack by rule 7 (line 1794):
   $1 = nterm stmtmulti (: )
   $2 = token ';' (: )
   $3 = nterm stmt (: )
-> $$ = nterm stmtmulti (: )

The above output is a rule at line 1794 of gram.y, which is
![[Pasted image 20240104203053.png]]
image

  1. stmt
Reducing stack by rule 137 (line 1945):
-> $$ = nterm stmt (: )

The above output is a rule at line 1945 of gram.y, which is
![[Pasted image 20240104203254.png]]
image

  1. stmtmulti
Reducing stack by rule 8 (line 1806):
   $1 = nterm stmt (: )
-> $$ = nterm stmtmulti (: )

The above output is a rule at line 1806 of gram.y, which is
![[Pasted image 20240104203510.png]]
image

  1. stmt
Reducing stack by rule 127 (line 1934):
   $1 = nterm SelectStmt (: )
-> $$ = nterm stmt (: )

The above output is a rule at line 1934 of gram.y, which is
![[Pasted image 20240104203622.png]]
image

  1. SelectStmt
Reducing stack by rule 2211 (line 17578):
   $1 = nterm select_no_parens (: )
-> $$ = nterm SelectStmt (: )

The above output is a rule at line 17578 of gram.y, which is
![[Pasted image 20240104203939.png]]
image

  1. select_no_parens
Reducing stack by rule 2215 (line 17599):
   $1 = nterm simple_select (: )
-> $$ = nterm select_no_parens (: )

The above output is a rule at line 17599 of gram.y, which is
![[Pasted image 20240104204101.png]]
image

  1. 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 (: )

The above output is a rule at line 17686 of gram.y, which is
![[Pasted image 20240104204227.png]]
image

  1. optional clauses
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 (: )

no more explanations

  1. opt_target_list
Reducing stack by rule 2914 (line 22182):
   $1 = nterm target_list (: )
-> $$ = nterm opt_target_list (: )

Reducing stack by rule 2916 (line 22187):
   $1 = nterm target_el (: )
-> $$ = nterm target_list (: )

![[Pasted image 20240104204752.png]]
image

  1. target_el
Reducing stack by rule 2920 (line 22236):
   $1 = nterm a_expr (: )
-> $$ = nterm target_el (: )

Reducing stack by rule 2563 (line 19974):
   $1 = nterm c_expr (: )
-> $$ = nterm a_expr (: )

Reducing stack by rule 2664 (line 20515):
   $1 = nterm AexprConst (: )
-> $$ = nterm c_expr (: )
  1. AexprConst
Reducing stack by rule 2959 (line 22717):
   $1 = nterm func_name (: )
   $2 = nterm Sconst (: )
-> $$ = nterm AexprConst (: )

We take the prolonged path to reach the core rule, AexprConst.
![[Pasted image 20240104205523.png]]
image

  1. Sconst
Reducing stack by rule 2969 (line 22797):
   $1 = token SCONST (: )
-> $$ = nterm Sconst (: )

The above output is a rule at line 22797 of gram.y, which is
![[Pasted image 20240104205700.png]]
image

The SCONST is our datetime string '2024-01-04 20:16:00'.

  1. func_name
Reducing stack by rule 2950 (line 22665):
   $1 = nterm type_function_name (: )
-> $$ = nterm func_name (: )

Reducing stack by rule 2989 (line 22968):
   $1 = nterm unreserved_keyword (: )
-> $$ = nterm type_function_name (: )

The above output says func_name is an unreserved_keyword.

  1. unreserved_keyword
Reducing stack by rule 3071 (line 23095):
   $1 = token DATETIME (: )
-> $$ = nterm unreserved_keyword (: )

Finally, we get the unreserved_keyword DATETIME.
![[Pasted image 20240104210146.png]]
image

  1. opt_all_clause and hint_string
Reducing stack by rule 2275 (line 18021):
-> $$ = nterm opt_all_clause (: )

Reducing stack by rule 2235 (line 17794):
-> $$ = nterm hint_string (: )

The two rules are empty rules. So far, the simple_select rule is completly parsed.