LCOV - code coverage report
Current view: top level - src/backend/replication - repl_scanner.l (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 80.5 % 123 99
Test Date: 2026-07-03 19:57:34 Functions: 66.7 % 12 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 44.4 % 18 8

             Branch data     Line data    Source code
       1                 :             : %top{
       2                 :             : /*-------------------------------------------------------------------------
       3                 :             :  *
       4                 :             :  * repl_scanner.l
       5                 :             :  *    a lexical scanner for the replication commands
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :             :  *
      10                 :             :  *
      11                 :             :  * IDENTIFICATION
      12                 :             :  *    src/backend/replication/repl_scanner.l
      13                 :             :  *
      14                 :             :  *-------------------------------------------------------------------------
      15                 :             :  */
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include "nodes/parsenodes.h"
      19                 :             : #include "utils/builtins.h"
      20                 :             : #include "parser/scansup.h"
      21                 :             : 
      22                 :             : /*
      23                 :             :  * NB: include repl_gram.h only AFTER including walsender_private.h, because
      24                 :             :  * walsender_private includes headers that define XLogRecPtr.
      25                 :             :  */
      26                 :             : #include "replication/walsender_private.h"
      27                 :             : #include "repl_gram.h"
      28                 :             : }
      29                 :             : 
      30                 :             : %{
      31                 :             : /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
      32                 :             : #undef fprintf
      33                 :             : #define fprintf(file, fmt, msg)  fprintf_to_ereport(fmt, msg)
      34                 :             : 
      35                 :             : static void
      36                 :           0 : fprintf_to_ereport(const char *fmt, const char *msg)
      37                 :             : {
      38         [ #  # ]:           0 :     ereport(ERROR, (errmsg_internal("%s", msg)));
      39                 :             : }
      40                 :             : 
      41                 :             : struct replication_yy_extra_type
      42                 :             : {
      43                 :             :     /* Pushed-back token (we only handle one) */
      44                 :             :     int         repl_pushed_back_token;
      45                 :             : 
      46                 :             :     /* Work area for collecting literals */
      47                 :             :     StringInfoData litbuf;
      48                 :             : };
      49                 :             : 
      50                 :             : static void startlit(yyscan_t yyscanner);
      51                 :             : static char *litbufdup(yyscan_t yyscanner);
      52                 :             : static void addlit(char *ytext, int yleng, yyscan_t yyscanner);
      53                 :             : static void addlitchar(unsigned char ychar, yyscan_t yyscanner);
      54                 :             : 
      55                 :             : /* LCOV_EXCL_START */
      56                 :             : 
      57                 :             : %}
      58                 :             : 
      59                 :             : %option reentrant
      60                 :             : %option bison-bridge
      61                 :             : %option 8bit
      62                 :             : %option never-interactive
      63                 :             : %option nodefault
      64                 :             : %option noinput
      65                 :             : %option nounput
      66                 :             : %option noyywrap
      67                 :             : %option noyyalloc
      68                 :             : %option noyyrealloc
      69                 :             : %option noyyfree
      70                 :             : %option warn
      71                 :             : %option prefix="replication_yy"
      72                 :             : %option extra-type="struct replication_yy_extra_type *"
      73                 :             : 
      74                 :             : /*
      75                 :             :  * Exclusive states:
      76                 :             :  *  <xd> delimited identifiers (double-quoted identifiers)
      77                 :             :  *  <xq> standard single-quoted strings
      78                 :             :  */
      79                 :             : %x xd
      80                 :             : %x xq
      81                 :             : 
      82                 :             : space           [ \t\n\r\f\v]
      83                 :             : 
      84                 :             : quote           '
      85                 :             : quotestop       {quote}
      86                 :             : 
      87                 :             : /* Extended quote
      88                 :             :  * xqdouble implements embedded quote, ''''
      89                 :             :  */
      90                 :             : xqstart         {quote}
      91                 :             : xqdouble        {quote}{quote}
      92                 :             : xqinside        [^']+
      93                 :             : 
      94                 :             : /* Double quote
      95                 :             :  * Allows embedded spaces and other special characters into identifiers.
      96                 :             :  */
      97                 :             : dquote          \"
      98                 :             : xdstart         {dquote}
      99                 :             : xdstop          {dquote}
     100                 :             : xddouble        {dquote}{dquote}
     101                 :             : xdinside        [^"]+
     102                 :             : 
     103                 :             : digit           [0-9]
     104                 :             : hexdigit        [0-9A-Fa-f]
     105                 :             : 
     106                 :             : ident_start     [A-Za-z\200-\377_]
     107                 :             : ident_cont      [A-Za-z\200-\377_0-9\$]
     108                 :             : 
     109                 :             : identifier      {ident_start}{ident_cont}*
     110                 :             : 
     111                 :             : %%
     112                 :             : 
     113                 :             : %{
     114                 :             :     /* This code is inserted at the start of replication_yylex() */
     115                 :             : 
     116                 :             :     /* If we have a pushed-back token, return that. */
     117                 :             :     if (yyextra->repl_pushed_back_token)
     118         [ +  + ]:       29686 :     {
     119                 :             :         int         result = yyextra->repl_pushed_back_token;
     120                 :        3231 : 
     121                 :             :         yyextra->repl_pushed_back_token = 0;
     122                 :        3231 :         return result;
     123                 :        3231 :     }
     124                 :             : %}
     125                 :             : 
     126                 :             : BASE_BACKUP         { return K_BASE_BACKUP; }
     127                 :         197 : IDENTIFY_SYSTEM     { return K_IDENTIFY_SYSTEM; }
     128                 :         800 : READ_REPLICATION_SLOT   { return K_READ_REPLICATION_SLOT; }
     129                 :         800 : SHOW        { return K_SHOW; }
     130                 :           6 : TIMELINE            { return K_TIMELINE; }
     131                 :         626 : START_REPLICATION   { return K_START_REPLICATION; }
     132                 :         301 : CREATE_REPLICATION_SLOT     { return K_CREATE_REPLICATION_SLOT; }
     133                 :         757 : DROP_REPLICATION_SLOT       { return K_DROP_REPLICATION_SLOT; }
     134                 :         517 : ALTER_REPLICATION_SLOT      { return K_ALTER_REPLICATION_SLOT; }
     135                 :         293 : TIMELINE_HISTORY    { return K_TIMELINE_HISTORY; }
     136                 :           7 : PHYSICAL            { return K_PHYSICAL; }
     137                 :          16 : RESERVE_WAL         { return K_RESERVE_WAL; }
     138                 :         153 : LOGICAL             { return K_LOGICAL; }
     139                 :         152 : SLOT                { return K_SLOT; }
     140                 :         819 : TEMPORARY           { return K_TEMPORARY; }
     141                 :         658 : TWO_PHASE           { return K_TWO_PHASE; }
     142                 :         147 : EXPORT_SNAPSHOT     { return K_EXPORT_SNAPSHOT; }
     143                 :           3 : NOEXPORT_SNAPSHOT   { return K_NOEXPORT_SNAPSHOT; }
     144                 :           0 : USE_SNAPSHOT        { return K_USE_SNAPSHOT; }
     145                 :           0 : WAIT                { return K_WAIT; }
     146                 :           0 : UPLOAD_MANIFEST     { return K_UPLOAD_MANIFEST; }
     147                 :         475 : 
     148                 :          12 : {space}+        { /* do nothing */ }
     149                 :       13036 : 
     150                 :       13036 : {digit}+        {
     151                 :         506 :                     yylval->uintval = strtoul(yytext, NULL, 10);
     152                 :         506 :                     return UCONST;
     153                 :         506 :                 }
     154                 :             : 
     155                 :             : {hexdigit}+\/{hexdigit}+        {
     156                 :         757 :                     uint32  hi,
     157                 :             :                             lo;
     158                 :             :                     if (sscanf(yytext, "%X/%08X", &hi, &lo) != 2)
     159         [ -  + ]:         757 :                         replication_yyerror(NULL, yyscanner, "invalid streaming start location");
     160                 :           0 :                     yylval->recptr = ((uint64) hi) << 32 | lo;
     161                 :         757 :                     return RECPTR;
     162                 :         757 :                 }
     163                 :             : 
     164                 :             : {xqstart}       {
     165                 :        2960 :                     BEGIN(xq);
     166                 :        2960 :                     startlit(yyscanner);
     167                 :        2960 :                 }
     168                 :             : 
     169                 :        2960 : <xq>{quotestop}   {
     170                 :        2960 :                     yyless(1);
     171                 :        2960 :                     BEGIN(INITIAL);
     172                 :        2960 :                     yylval->str = litbufdup(yyscanner);
     173                 :        2960 :                     return SCONST;
     174                 :        2960 :                 }
     175                 :             : 
     176                 :             : <xq>{xqdouble}    {
     177                 :           0 :                     addlitchar('\'', yyscanner);
     178                 :           0 :                 }
     179                 :             : 
     180                 :           0 : <xq>{xqinside}  {
     181                 :        2959 :                     addlit(yytext, yyleng, yyscanner);
     182                 :        2959 :                 }
     183                 :             : 
     184                 :        2959 : {xdstart}       {
     185                 :        1534 :                     BEGIN(xd);
     186                 :        1534 :                     startlit(yyscanner);
     187                 :        1534 :                 }
     188                 :             : 
     189                 :        1534 : <xd>{xdstop}  {
     190                 :        1534 :                     int         len;
     191                 :             : 
     192                 :             :                     yyless(1);
     193                 :        1534 :                     BEGIN(INITIAL);
     194                 :        1534 :                     yylval->str = litbufdup(yyscanner);
     195                 :        1534 :                     len = strlen(yylval->str);
     196                 :        1534 :                     truncate_identifier(yylval->str, len, true);
     197                 :        1534 :                     return IDENT;
     198                 :        1534 :                 }
     199                 :             : 
     200                 :             : <xd>{xddouble}    {
     201                 :           0 :                     addlitchar('"', yyscanner);
     202                 :           0 :                 }
     203                 :             : 
     204                 :           0 : <xd>{xdinside}  {
     205                 :        1534 :                     addlit(yytext, yyleng, yyscanner);
     206                 :        1534 :                 }
     207                 :             : 
     208                 :        1534 : {identifier}    {
     209                 :        6761 :                     int         len = strlen(yytext);
     210                 :        6761 : 
     211                 :             :                     yylval->str = downcase_truncate_identifier(yytext, len, true);
     212                 :        6761 :                     return IDENT;
     213                 :        6761 :                 }
     214                 :             : 
     215                 :             : .               {
     216                 :        4767 :                     /* Any char not recognized above is returned as itself */
     217                 :             :                     return yytext[0];
     218                 :        4767 :                 }
     219                 :             : 
     220                 :             : <xq,xd><<EOF>>    { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
     221                 :           0 : 
     222                 :             : 
     223                 :        3231 : <<EOF>>         {
     224                 :             :                     yyterminate();
     225                 :        3231 :                 }
     226                 :             : 
     227                 :             : %%
     228                 :           0 : 
     229                 :             : /* LCOV_EXCL_STOP */
     230                 :             : 
     231                 :             : /* see scan.l */
     232                 :             : #undef yyextra
     233                 :             : #define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
     234                 :             : 
     235                 :             : static void
     236                 :             : startlit(yyscan_t yyscanner)
     237                 :        4494 : {
     238                 :             :     initStringInfo(&yyextra->litbuf);
     239                 :        4494 : }
     240                 :        4494 : 
     241                 :             : static char *
     242                 :             : litbufdup(yyscan_t yyscanner)
     243                 :        4494 : {
     244                 :             :     return yyextra->litbuf.data;
     245                 :        4494 : }
     246                 :             : 
     247                 :             : static void
     248                 :             : addlit(char *ytext, int yleng, yyscan_t yyscanner)
     249                 :        4493 : {
     250                 :             :     appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng);
     251                 :        4493 : }
     252                 :        4493 : 
     253                 :             : static void
     254                 :             : addlitchar(unsigned char ychar, yyscan_t yyscanner)
     255                 :           0 : {
     256                 :             :     appendStringInfoChar(&yyextra->litbuf, ychar);
     257                 :           0 : }
     258                 :           0 : 
     259                 :             : /*
     260                 :             :   * (The first argument is enforced by Bison to match the first argument of
     261                 :             :   * yyparse(), but it is not used here.)
     262                 :             :   */
     263                 :             : void
     264                 :             : replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
     265                 :           0 : {
     266                 :             :     ereport(ERROR,
     267         [ #  # ]:           0 :             (errcode(ERRCODE_SYNTAX_ERROR),
     268                 :             :              errmsg_internal("%s", message)));
     269                 :             : }
     270                 :             : 
     271                 :             : void
     272                 :             : replication_scanner_init(const char *str, yyscan_t *yyscannerp)
     273                 :        5808 : {
     274                 :             :     yyscan_t    yyscanner;
     275                 :             :     struct replication_yy_extra_type *yyext = palloc0_object(struct replication_yy_extra_type);
     276                 :        5808 : 
     277                 :             :     if (yylex_init(yyscannerp) != 0)
     278         [ -  + ]:        5808 :         elog(ERROR, "yylex_init() failed: %m");
     279         [ #  # ]:           0 : 
     280                 :             :     yyscanner = *yyscannerp;
     281                 :        5808 : 
     282                 :             :     yyset_extra(yyext, yyscanner);
     283                 :        5808 : 
     284                 :             :     yy_scan_string(str, yyscanner);
     285                 :        5808 : }
     286                 :        5808 : 
     287                 :             : void
     288                 :             : replication_scanner_finish(yyscan_t yyscanner)
     289                 :        5808 : {
     290                 :             :     pfree(yyextra);
     291                 :        5808 :     yylex_destroy(yyscanner);
     292                 :        5808 : }
     293                 :        5808 : 
     294                 :             : /*
     295                 :             :  * Check to see if the first token of a command is a WalSender keyword.
     296                 :             :  *
     297                 :             :  * To keep repl_scanner.l minimal, we don't ask it to know every construct
     298                 :             :  * that the core lexer knows.  Therefore, we daren't lex more than the
     299                 :             :  * first token of a general SQL command.  That will usually look like an
     300                 :             :  * IDENT token here, although some other cases are possible.
     301                 :             :  */
     302                 :             : bool
     303                 :             : replication_scanner_is_replication_command(yyscan_t yyscanner)
     304                 :        5808 : {
     305                 :             :     YYSTYPE     dummy;
     306                 :             :     int         first_token = replication_yylex(&dummy, yyscanner);
     307                 :        5808 : 
     308                 :             :     switch (first_token)
     309         [ +  + ]:        5808 :     {
     310                 :             :         case K_IDENTIFY_SYSTEM:
     311                 :        3231 :         case K_BASE_BACKUP:
     312                 :             :         case K_START_REPLICATION:
     313                 :             :         case K_CREATE_REPLICATION_SLOT:
     314                 :             :         case K_DROP_REPLICATION_SLOT:
     315                 :             :         case K_ALTER_REPLICATION_SLOT:
     316                 :             :         case K_READ_REPLICATION_SLOT:
     317                 :             :         case K_TIMELINE_HISTORY:
     318                 :             :         case K_UPLOAD_MANIFEST:
     319                 :             :         case K_SHOW:
     320                 :             :             /* Yes; push back the first token so we can parse later. */
     321                 :             :             yyextra->repl_pushed_back_token = first_token;
     322                 :        3231 :             return true;
     323                 :        3231 :         default:
     324                 :        2577 :             /* Nope; we don't bother to push back the token. */
     325                 :             :             return false;
     326                 :        2577 :     }
     327                 :             : }
     328                 :             : 
     329                 :             : /*
     330                 :             :  * Interface functions to make flex use palloc() instead of malloc().
     331                 :             :  * It'd be better to make these static, but flex insists otherwise.
     332                 :             :  */
     333                 :             : 
     334                 :             : void *
     335                 :             : yyalloc(yy_size_t size, yyscan_t yyscanner)
     336                 :       23232 : {
     337                 :             :     return palloc(size);
     338                 :       23232 : }
     339                 :             : 
     340                 :             : void *
     341                 :             : yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
     342                 :           0 : {
     343                 :             :     if (ptr)
     344         [ #  # ]:           0 :         return repalloc(ptr, size);
     345                 :           0 :     else
     346                 :             :         return palloc(size);
     347                 :           0 : }
     348                 :             : 
     349                 :             : void
     350                 :             : yyfree(void *ptr, yyscan_t yyscanner)
     351                 :       29040 : {
     352                 :             :     if (ptr)
     353         [ +  + ]:       29040 :         pfree(ptr);
     354                 :       23232 : }
     355                 :       29040 : /* END: function "replication_yyfree" */
        

Generated by: LCOV version 2.0-1