LCOV - code coverage report
Current view: top level - src/backend/replication - repl_gram.y (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 86 115 74.8 %
Date: 2025-02-21 16:15:14 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : %{
       2             : /*-------------------------------------------------------------------------
       3             :  *
       4             :  * repl_gram.y              - Parser for the replication commands
       5             :  *
       6             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/replication/repl_gram.y
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include "access/xlogdefs.h"
      19             : #include "nodes/makefuncs.h"
      20             : #include "nodes/parsenodes.h"
      21             : #include "nodes/replnodes.h"
      22             : #include "replication/walsender.h"
      23             : #include "replication/walsender_private.h"
      24             : 
      25             : #include "repl_gram.h"
      26             : 
      27             : 
      28             : /*
      29             :  * Bison doesn't allocate anything that needs to live across parser calls,
      30             :  * so we can easily have it use palloc instead of malloc.  This prevents
      31             :  * memory leaks if we error out during parsing.
      32             :  */
      33             : #define YYMALLOC palloc
      34             : #define YYFREE   pfree
      35             : 
      36             : %}
      37             : 
      38             : %parse-param {Node **replication_parse_result_p}
      39             : %parse-param {yyscan_t yyscanner}
      40             : %lex-param   {yyscan_t yyscanner}
      41             : %pure-parser
      42             : %expect 0
      43             : %name-prefix="replication_yy"
      44             : 
      45             : %union
      46             : {
      47             :     char       *str;
      48             :     bool        boolval;
      49             :     uint32      uintval;
      50             :     XLogRecPtr  recptr;
      51             :     Node       *node;
      52             :     List       *list;
      53             :     DefElem    *defelt;
      54             : }
      55             : 
      56             : /* Non-keyword tokens */
      57             : %token <str> SCONST IDENT
      58             : %token <uintval> UCONST
      59             : %token <recptr> RECPTR
      60             : 
      61             : /* Keyword tokens. */
      62             : %token K_BASE_BACKUP
      63             : %token K_IDENTIFY_SYSTEM
      64             : %token K_READ_REPLICATION_SLOT
      65             : %token K_SHOW
      66             : %token K_START_REPLICATION
      67             : %token K_CREATE_REPLICATION_SLOT
      68             : %token K_DROP_REPLICATION_SLOT
      69             : %token K_ALTER_REPLICATION_SLOT
      70             : %token K_TIMELINE_HISTORY
      71             : %token K_WAIT
      72             : %token K_TIMELINE
      73             : %token K_PHYSICAL
      74             : %token K_LOGICAL
      75             : %token K_SLOT
      76             : %token K_RESERVE_WAL
      77             : %token K_TEMPORARY
      78             : %token K_TWO_PHASE
      79             : %token K_EXPORT_SNAPSHOT
      80             : %token K_NOEXPORT_SNAPSHOT
      81             : %token K_USE_SNAPSHOT
      82             : %token K_UPLOAD_MANIFEST
      83             : 
      84             : %type <node>  command
      85             : %type <node>  base_backup start_replication start_logical_replication
      86             :                 create_replication_slot drop_replication_slot
      87             :                 alter_replication_slot identify_system read_replication_slot
      88             :                 timeline_history show upload_manifest
      89             : %type <list>  generic_option_list
      90             : %type <defelt>    generic_option
      91             : %type <uintval>   opt_timeline
      92             : %type <list>  plugin_options plugin_opt_list
      93             : %type <defelt>    plugin_opt_elem
      94             : %type <node>  plugin_opt_arg
      95             : %type <str>       opt_slot var_name ident_or_keyword
      96             : %type <boolval>   opt_temporary
      97             : %type <list>  create_slot_options create_slot_legacy_opt_list
      98             : %type <defelt>    create_slot_legacy_opt
      99             : 
     100             : %%
     101             : 
     102             : firstcmd: command opt_semicolon
     103             :                 {
     104        5484 :                     *replication_parse_result_p = $1;
     105             : 
     106             :                     (void) yynerrs; /* suppress compiler warning */
     107             :                 }
     108             :             ;
     109             : 
     110             : opt_semicolon:  ';'
     111             :                 | /* EMPTY */
     112             :                 ;
     113             : 
     114             : command:
     115             :             identify_system
     116             :             | base_backup
     117             :             | start_replication
     118             :             | start_logical_replication
     119             :             | create_replication_slot
     120             :             | drop_replication_slot
     121             :             | alter_replication_slot
     122             :             | read_replication_slot
     123             :             | timeline_history
     124             :             | show
     125             :             | upload_manifest
     126             :             ;
     127             : 
     128             : /*
     129             :  * IDENTIFY_SYSTEM
     130             :  */
     131             : identify_system:
     132             :             K_IDENTIFY_SYSTEM
     133             :                 {
     134        1310 :                     $$ = (Node *) makeNode(IdentifySystemCmd);
     135             :                 }
     136             :             ;
     137             : 
     138             : /*
     139             :  * READ_REPLICATION_SLOT %s
     140             :  */
     141             : read_replication_slot:
     142             :             K_READ_REPLICATION_SLOT var_name
     143             :                 {
     144          12 :                     ReadReplicationSlotCmd *n = makeNode(ReadReplicationSlotCmd);
     145          12 :                     n->slotname = $2;
     146          12 :                     $$ = (Node *) n;
     147             :                 }
     148             :             ;
     149             : 
     150             : /*
     151             :  * SHOW setting
     152             :  */
     153             : show:
     154             :             K_SHOW var_name
     155             :                 {
     156        1100 :                     VariableShowStmt *n = makeNode(VariableShowStmt);
     157        1100 :                     n->name = $2;
     158        1100 :                     $$ = (Node *) n;
     159             :                 }
     160             : 
     161        1112 : var_name:   IDENT   { $$ = $1; }
     162             :             | var_name '.' IDENT
     163           0 :                 { $$ = psprintf("%s.%s", $1, $3); }
     164             :         ;
     165             : 
     166             : /*
     167             :  * BASE_BACKUP [ ( option [ 'value' ] [, ...] ) ]
     168             :  */
     169             : base_backup:
     170             :             K_BASE_BACKUP '(' generic_option_list ')'
     171             :                 {
     172         348 :                     BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
     173         348 :                     cmd->options = $3;
     174         348 :                     $$ = (Node *) cmd;
     175             :                 }
     176             :             | K_BASE_BACKUP
     177             :                 {
     178           2 :                     BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
     179           2 :                     $$ = (Node *) cmd;
     180             :                 }
     181             :             ;
     182             : 
     183             : create_replication_slot:
     184             :             /* CREATE_REPLICATION_SLOT slot [TEMPORARY] PHYSICAL [options] */
     185             :             K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL create_slot_options
     186             :                 {
     187             :                     CreateReplicationSlotCmd *cmd;
     188         270 :                     cmd = makeNode(CreateReplicationSlotCmd);
     189         270 :                     cmd->kind = REPLICATION_KIND_PHYSICAL;
     190         270 :                     cmd->slotname = $2;
     191         270 :                     cmd->temporary = $3;
     192         270 :                     cmd->options = $5;
     193         270 :                     $$ = (Node *) cmd;
     194             :                 }
     195             :             /* CREATE_REPLICATION_SLOT slot [TEMPORARY] LOGICAL plugin [options] */
     196             :             | K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT create_slot_options
     197             :                 {
     198             :                     CreateReplicationSlotCmd *cmd;
     199         630 :                     cmd = makeNode(CreateReplicationSlotCmd);
     200         630 :                     cmd->kind = REPLICATION_KIND_LOGICAL;
     201         630 :                     cmd->slotname = $2;
     202         630 :                     cmd->temporary = $3;
     203         630 :                     cmd->plugin = $5;
     204         630 :                     cmd->options = $6;
     205         630 :                     $$ = (Node *) cmd;
     206             :                 }
     207             :             ;
     208             : 
     209             : create_slot_options:
     210         896 :             '(' generic_option_list ')'         { $$ = $2; }
     211           4 :             | create_slot_legacy_opt_list       { $$ = $1; }
     212             :             ;
     213             : 
     214             : create_slot_legacy_opt_list:
     215             :             create_slot_legacy_opt_list create_slot_legacy_opt
     216           2 :                 { $$ = lappend($1, $2); }
     217             :             | /* EMPTY */
     218           4 :                 { $$ = NIL; }
     219             :             ;
     220             : 
     221             : create_slot_legacy_opt:
     222             :             K_EXPORT_SNAPSHOT
     223             :                 {
     224           0 :                   $$ = makeDefElem("snapshot",
     225           0 :                                    (Node *) makeString("export"), -1);
     226             :                 }
     227             :             | K_NOEXPORT_SNAPSHOT
     228             :                 {
     229           0 :                   $$ = makeDefElem("snapshot",
     230           0 :                                    (Node *) makeString("nothing"), -1);
     231             :                 }
     232             :             | K_USE_SNAPSHOT
     233             :                 {
     234           0 :                   $$ = makeDefElem("snapshot",
     235           0 :                                    (Node *) makeString("use"), -1);
     236             :                 }
     237             :             | K_RESERVE_WAL
     238             :                 {
     239           2 :                   $$ = makeDefElem("reserve_wal",
     240           2 :                                    (Node *) makeBoolean(true), -1);
     241             :                 }
     242             :             | K_TWO_PHASE
     243             :                 {
     244           0 :                   $$ = makeDefElem("two_phase",
     245           0 :                                    (Node *) makeBoolean(true), -1);
     246             :                 }
     247             :             ;
     248             : 
     249             : /* DROP_REPLICATION_SLOT slot */
     250             : drop_replication_slot:
     251             :             K_DROP_REPLICATION_SLOT IDENT
     252             :                 {
     253             :                     DropReplicationSlotCmd *cmd;
     254           6 :                     cmd = makeNode(DropReplicationSlotCmd);
     255           6 :                     cmd->slotname = $2;
     256           6 :                     cmd->wait = false;
     257           6 :                     $$ = (Node *) cmd;
     258             :                 }
     259             :             | K_DROP_REPLICATION_SLOT IDENT K_WAIT
     260             :                 {
     261             :                     DropReplicationSlotCmd *cmd;
     262         506 :                     cmd = makeNode(DropReplicationSlotCmd);
     263         506 :                     cmd->slotname = $2;
     264         506 :                     cmd->wait = true;
     265         506 :                     $$ = (Node *) cmd;
     266             :                 }
     267             :             ;
     268             : 
     269             : /* ALTER_REPLICATION_SLOT slot (options) */
     270             : alter_replication_slot:
     271             :             K_ALTER_REPLICATION_SLOT IDENT '(' generic_option_list ')'
     272             :                 {
     273             :                     AlterReplicationSlotCmd *cmd;
     274          12 :                     cmd = makeNode(AlterReplicationSlotCmd);
     275          12 :                     cmd->slotname = $2;
     276          12 :                     cmd->options = $4;
     277          12 :                     $$ = (Node *) cmd;
     278             :                 }
     279             :             ;
     280             : 
     281             : /*
     282             :  * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %u]
     283             :  */
     284             : start_replication:
     285             :             K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
     286             :                 {
     287             :                     StartReplicationCmd *cmd;
     288             : 
     289         506 :                     cmd = makeNode(StartReplicationCmd);
     290         506 :                     cmd->kind = REPLICATION_KIND_PHYSICAL;
     291         506 :                     cmd->slotname = $2;
     292         506 :                     cmd->startpoint = $4;
     293         506 :                     cmd->timeline = $5;
     294         506 :                     $$ = (Node *) cmd;
     295             :                 }
     296             :             ;
     297             : 
     298             : /* START_REPLICATION SLOT slot LOGICAL %X/%X options */
     299             : start_logical_replication:
     300             :             K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
     301             :                 {
     302             :                     StartReplicationCmd *cmd;
     303         734 :                     cmd = makeNode(StartReplicationCmd);
     304         734 :                     cmd->kind = REPLICATION_KIND_LOGICAL;
     305         734 :                     cmd->slotname = $3;
     306         734 :                     cmd->startpoint = $5;
     307         734 :                     cmd->options = $6;
     308         734 :                     $$ = (Node *) cmd;
     309             :                 }
     310             :             ;
     311             : /*
     312             :  * TIMELINE_HISTORY %u
     313             :  */
     314             : timeline_history:
     315             :             K_TIMELINE_HISTORY UCONST
     316             :                 {
     317             :                     TimeLineHistoryCmd *cmd;
     318             : 
     319          28 :                     if ($2 <= 0)
     320           0 :                         ereport(ERROR,
     321             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     322             :                                  errmsg("invalid timeline %u", $2)));
     323             : 
     324          28 :                     cmd = makeNode(TimeLineHistoryCmd);
     325          28 :                     cmd->timeline = $2;
     326             : 
     327          28 :                     $$ = (Node *) cmd;
     328             :                 }
     329             :             ;
     330             : 
     331             : /* UPLOAD_MANIFEST doesn't currently accept any arguments */
     332             : upload_manifest:
     333             :             K_UPLOAD_MANIFEST
     334             :                 {
     335          20 :                     UploadManifestCmd *cmd = makeNode(UploadManifestCmd);
     336             : 
     337          20 :                     $$ = (Node *) cmd;
     338             :                 }
     339             : 
     340             : opt_physical:
     341             :             K_PHYSICAL
     342             :             | /* EMPTY */
     343             :             ;
     344             : 
     345             : opt_temporary:
     346         260 :             K_TEMPORARY                     { $$ = true; }
     347         640 :             | /* EMPTY */                   { $$ = false; }
     348             :             ;
     349             : 
     350             : opt_slot:
     351             :             K_SLOT IDENT
     352         352 :                 { $$ = $2; }
     353             :             | /* EMPTY */
     354         154 :                 { $$ = NULL; }
     355             :             ;
     356             : 
     357             : opt_timeline:
     358             :             K_TIMELINE UCONST
     359             :                 {
     360         504 :                     if ($2 <= 0)
     361           0 :                         ereport(ERROR,
     362             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     363             :                                  errmsg("invalid timeline %u", $2)));
     364         504 :                     $$ = $2;
     365             :                 }
     366           2 :                 | /* EMPTY */           { $$ = 0; }
     367             :             ;
     368             : 
     369             : 
     370             : plugin_options:
     371         724 :             '(' plugin_opt_list ')'         { $$ = $2; }
     372          10 :             | /* EMPTY */                   { $$ = NIL; }
     373             :         ;
     374             : 
     375             : plugin_opt_list:
     376             :             plugin_opt_elem
     377             :                 {
     378         724 :                     $$ = list_make1($1);
     379             :                 }
     380             :             | plugin_opt_list ',' plugin_opt_elem
     381             :                 {
     382        2122 :                     $$ = lappend($1, $3);
     383             :                 }
     384             :         ;
     385             : 
     386             : plugin_opt_elem:
     387             :             IDENT plugin_opt_arg
     388             :                 {
     389        2846 :                     $$ = makeDefElem($1, $2, -1);
     390             :                 }
     391             :         ;
     392             : 
     393             : plugin_opt_arg:
     394        2846 :             SCONST                          { $$ = (Node *) makeString($1); }
     395           0 :             | /* EMPTY */                   { $$ = NULL; }
     396             :         ;
     397             : 
     398             : generic_option_list:
     399             :             generic_option_list ',' generic_option
     400        1944 :                 { $$ = lappend($1, $3); }
     401             :             | generic_option
     402        1256 :                 { $$ = list_make1($1); }
     403             :             ;
     404             : 
     405             : generic_option:
     406             :             ident_or_keyword
     407             :                 {
     408         746 :                     $$ = makeDefElem($1, NULL, -1);
     409             :                 }
     410             :             | ident_or_keyword IDENT
     411             :                 {
     412           8 :                     $$ = makeDefElem($1, (Node *) makeString($2), -1);
     413             :                 }
     414             :             | ident_or_keyword SCONST
     415             :                 {
     416        2108 :                     $$ = makeDefElem($1, (Node *) makeString($2), -1);
     417             :                 }
     418             :             | ident_or_keyword UCONST
     419             :                 {
     420         338 :                     $$ = makeDefElem($1, (Node *) makeInteger($2), -1);
     421             :                 }
     422             :             ;
     423             : 
     424             : ident_or_keyword:
     425        2596 :             IDENT                           { $$ = $1; }
     426           0 :             | K_BASE_BACKUP                 { $$ = "base_backup"; }
     427           0 :             | K_IDENTIFY_SYSTEM             { $$ = "identify_system"; }
     428           0 :             | K_SHOW                        { $$ = "show"; }
     429           0 :             | K_START_REPLICATION           { $$ = "start_replication"; }
     430           0 :             | K_CREATE_REPLICATION_SLOT { $$ = "create_replication_slot"; }
     431           0 :             | K_DROP_REPLICATION_SLOT       { $$ = "drop_replication_slot"; }
     432           0 :             | K_ALTER_REPLICATION_SLOT      { $$ = "alter_replication_slot"; }
     433           0 :             | K_TIMELINE_HISTORY            { $$ = "timeline_history"; }
     434         332 :             | K_WAIT                        { $$ = "wait"; }
     435           0 :             | K_TIMELINE                    { $$ = "timeline"; }
     436           0 :             | K_PHYSICAL                    { $$ = "physical"; }
     437           0 :             | K_LOGICAL                     { $$ = "logical"; }
     438           0 :             | K_SLOT                        { $$ = "slot"; }
     439         266 :             | K_RESERVE_WAL                 { $$ = "reserve_wal"; }
     440           0 :             | K_TEMPORARY                   { $$ = "temporary"; }
     441           6 :             | K_TWO_PHASE                   { $$ = "two_phase"; }
     442           0 :             | K_EXPORT_SNAPSHOT             { $$ = "export_snapshot"; }
     443           0 :             | K_NOEXPORT_SNAPSHOT           { $$ = "noexport_snapshot"; }
     444           0 :             | K_USE_SNAPSHOT                { $$ = "use_snapshot"; }
     445           0 :             | K_UPLOAD_MANIFEST             { $$ = "upload_manifest"; }
     446             :         ;
     447             : 
     448             : %%

Generated by: LCOV version 1.14