LCOV - code coverage report
Current view: top level - src/fe_utils - conditional.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 80.3 % 66 53
Test Date: 2026-02-17 17:20:33 Functions: 92.9 % 14 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  * A stack of automaton states to handle nested conditionals.
       3              :  *
       4              :  * Copyright (c) 2000-2026, PostgreSQL Global Development Group
       5              :  *
       6              :  * src/fe_utils/conditional.c
       7              :  *
       8              :  *-------------------------------------------------------------------------
       9              :  */
      10              : #include "postgres_fe.h"
      11              : 
      12              : #include "fe_utils/conditional.h"
      13              : 
      14              : /*
      15              :  * create stack
      16              :  */
      17              : ConditionalStack
      18         9756 : conditional_stack_create(void)
      19              : {
      20         9756 :     ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
      21              : 
      22         9756 :     cstack->head = NULL;
      23         9756 :     return cstack;
      24              : }
      25              : 
      26              : /*
      27              :  * Destroy all the elements from the stack. The stack itself is not freed.
      28              :  */
      29              : void
      30         9615 : conditional_stack_reset(ConditionalStack cstack)
      31           10 : {
      32         9615 :     if (!cstack)
      33            0 :         return;                 /* nothing to do here */
      34              : 
      35         9625 :     while (conditional_stack_pop(cstack))
      36           10 :         continue;
      37              : }
      38              : 
      39              : /*
      40              :  * destroy stack
      41              :  */
      42              : void
      43         9604 : conditional_stack_destroy(ConditionalStack cstack)
      44              : {
      45         9604 :     conditional_stack_reset(cstack);
      46         9604 :     free(cstack);
      47         9604 : }
      48              : 
      49              : /*
      50              :  * Create a new conditional branch.
      51              :  */
      52              : void
      53        28332 : conditional_stack_push(ConditionalStack cstack, ifState new_state)
      54              : {
      55        28332 :     IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
      56              : 
      57        28332 :     p->if_state = new_state;
      58        28332 :     p->query_len = -1;
      59        28332 :     p->paren_depth = -1;
      60        28332 :     p->next = cstack->head;
      61        28332 :     cstack->head = p;
      62        28332 : }
      63              : 
      64              : /*
      65              :  * Destroy the topmost conditional branch.
      66              :  * Returns false if there was no branch to end.
      67              :  */
      68              : bool
      69        37944 : conditional_stack_pop(ConditionalStack cstack)
      70              : {
      71        37944 :     IfStackElem *p = cstack->head;
      72              : 
      73        37944 :     if (!p)
      74         9616 :         return false;
      75        28328 :     cstack->head = cstack->head->next;
      76        28328 :     free(p);
      77        28328 :     return true;
      78              : }
      79              : 
      80              : /*
      81              :  * Returns current stack depth, for debugging purposes.
      82              :  */
      83              : int
      84            0 : conditional_stack_depth(ConditionalStack cstack)
      85              : {
      86            0 :     if (cstack == NULL)
      87            0 :         return -1;
      88              :     else
      89              :     {
      90            0 :         IfStackElem *p = cstack->head;
      91            0 :         int         depth = 0;
      92              : 
      93            0 :         while (p != NULL)
      94              :         {
      95            0 :             depth++;
      96            0 :             p = p->next;
      97              :         }
      98            0 :         return depth;
      99              :     }
     100              : }
     101              : 
     102              : /*
     103              :  * Fetch the current state of the top of the stack.
     104              :  */
     105              : ifState
     106       260769 : conditional_stack_peek(ConditionalStack cstack)
     107              : {
     108       260769 :     if (conditional_stack_empty(cstack))
     109       258144 :         return IFSTATE_NONE;
     110         2625 :     return cstack->head->if_state;
     111              : }
     112              : 
     113              : /*
     114              :  * Change the state of the topmost branch.
     115              :  * Returns false if there was no branch state to set.
     116              :  */
     117              : bool
     118          171 : conditional_stack_poke(ConditionalStack cstack, ifState new_state)
     119              : {
     120          171 :     if (conditional_stack_empty(cstack))
     121            0 :         return false;
     122          171 :     cstack->head->if_state = new_state;
     123          171 :     return true;
     124              : }
     125              : 
     126              : /*
     127              :  * True if there are no active \if-blocks.
     128              :  */
     129              : bool
     130       270512 : conditional_stack_empty(ConditionalStack cstack)
     131              : {
     132       270512 :     return cstack->head == NULL;
     133              : }
     134              : 
     135              : /*
     136              :  * True if we should execute commands normally; that is, the current
     137              :  * conditional branch is active, or there is no open \if block.
     138              :  */
     139              : bool
     140       260054 : conditional_active(ConditionalStack cstack)
     141              : {
     142       260054 :     ifState     s = conditional_stack_peek(cstack);
     143              : 
     144       260054 :     return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
     145              : }
     146              : 
     147              : /*
     148              :  * Save current query buffer length in topmost stack entry.
     149              :  */
     150              : void
     151          140 : conditional_stack_set_query_len(ConditionalStack cstack, int len)
     152              : {
     153              :     Assert(!conditional_stack_empty(cstack));
     154          140 :     cstack->head->query_len = len;
     155          140 : }
     156              : 
     157              : /*
     158              :  * Fetch last-recorded query buffer length from topmost stack entry.
     159              :  * Will return -1 if no stack or it was never saved.
     160              :  */
     161              : int
     162          118 : conditional_stack_get_query_len(ConditionalStack cstack)
     163              : {
     164          118 :     if (conditional_stack_empty(cstack))
     165            0 :         return -1;
     166          118 :     return cstack->head->query_len;
     167              : }
     168              : 
     169              : /*
     170              :  * Save current parenthesis nesting depth in topmost stack entry.
     171              :  */
     172              : void
     173          140 : conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
     174              : {
     175              :     Assert(!conditional_stack_empty(cstack));
     176          140 :     cstack->head->paren_depth = depth;
     177          140 : }
     178              : 
     179              : /*
     180              :  * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
     181              :  * Will return -1 if no stack or it was never saved.
     182              :  */
     183              : int
     184          118 : conditional_stack_get_paren_depth(ConditionalStack cstack)
     185              : {
     186          118 :     if (conditional_stack_empty(cstack))
     187            0 :         return -1;
     188          118 :     return cstack->head->paren_depth;
     189              : }
        

Generated by: LCOV version 2.0-1