Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Tracing PostgreSQL Parser Reductions with Bison Debug Output

Tech May 17 2

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.

  1. parse_toplevel

    Reducing stack by rule 1 (line 1746):
       $1 = nterm stmtmulti (: )
    -> $$ = nterm parse_toplevel (: )
    

    Corresponds to:

    parse_toplevel: stmtmulti
    
  2. smttmulti

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

    Rule:

    stmtmulti: stmtmulti ';' stmt
    
  3. stmt

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

    Empty rule.

  4. stmtmulti (single statemant)

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

    Rule:

    stmtmulti: stmt
    
  5. stmt (SELECT)

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

    Rule:

    stmt: SelectStmt
    
  6. SelectStmt

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

    Rule:

    SelectStmt: select_no_parens
    
  7. select_no_parens

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

    Rule:

    select_no_parens: simple_select
    
  8. 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 (: )
    
  9. 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
    
  10. 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 (: )
    
  11. 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 (: )
    
  12. AexprConst

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

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

    The literal '2024-01-04 20:16:00'.

  14. 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 (: )
    
  15. unreserved_keyword

    Reducing stack by rule 3071 (line 23095):
       $1 = token DATETIME (: )
    -> $$ = nterm unreserved_keyword (: )
    
  16. 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.

Related Articles

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.