LCOV - code coverage report
Current view: top level - src/fe_utils - conditional.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 52 65 80.0 %
Date: 2024-11-21 10:14:43 Functions: 13 14 92.9 %
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-2024, 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       18470 : conditional_stack_create(void)
      19             : {
      20       18470 :     ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
      21             : 
      22       18470 :     cstack->head = NULL;
      23       18470 :     return cstack;
      24             : }
      25             : 
      26             : /*
      27             :  * Destroy all the elements from the stack. The stack itself is not freed.
      28             :  */
      29             : void
      30       18210 : conditional_stack_reset(ConditionalStack cstack)
      31             : {
      32       18210 :     if (!cstack)
      33           0 :         return;                 /* nothing to do here */
      34             : 
      35       18222 :     while (conditional_stack_pop(cstack))
      36          12 :         continue;
      37             : }
      38             : 
      39             : /*
      40             :  * destroy stack
      41             :  */
      42             : void
      43       18206 : conditional_stack_destroy(ConditionalStack cstack)
      44             : {
      45       18206 :     conditional_stack_reset(cstack);
      46       18206 :     free(cstack);
      47       18206 : }
      48             : 
      49             : /*
      50             :  * Create a new conditional branch.
      51             :  */
      52             : void
      53       13802 : conditional_stack_push(ConditionalStack cstack, ifState new_state)
      54             : {
      55       13802 :     IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
      56             : 
      57       13802 :     p->if_state = new_state;
      58       13802 :     p->query_len = -1;
      59       13802 :     p->paren_depth = -1;
      60       13802 :     p->next = cstack->head;
      61       13802 :     cstack->head = p;
      62       13802 : }
      63             : 
      64             : /*
      65             :  * Destroy the topmost conditional branch.
      66             :  * Returns false if there was no branch to end.
      67             :  */
      68             : bool
      69       32006 : conditional_stack_pop(ConditionalStack cstack)
      70             : {
      71       32006 :     IfStackElem *p = cstack->head;
      72             : 
      73       32006 :     if (!p)
      74       18212 :         return false;
      75       13794 :     cstack->head = cstack->head->next;
      76       13794 :     free(p);
      77       13794 :     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      383514 : conditional_stack_peek(ConditionalStack cstack)
     107             : {
     108      383514 :     if (conditional_stack_empty(cstack))
     109      379142 :         return IFSTATE_NONE;
     110        4372 :     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         294 : conditional_stack_poke(ConditionalStack cstack, ifState new_state)
     119             : {
     120         294 :     if (conditional_stack_empty(cstack))
     121           0 :         return false;
     122         294 :     cstack->head->if_state = new_state;
     123         294 :     return true;
     124             : }
     125             : 
     126             : /*
     127             :  * True if there are no active \if-blocks.
     128             :  */
     129             : bool
     130      402254 : conditional_stack_empty(ConditionalStack cstack)
     131             : {
     132      402254 :     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      382338 : conditional_active(ConditionalStack cstack)
     141             : {
     142      382338 :     ifState     s = conditional_stack_peek(cstack);
     143             : 
     144      382338 :     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         246 : conditional_stack_set_query_len(ConditionalStack cstack, int len)
     152             : {
     153             :     Assert(!conditional_stack_empty(cstack));
     154         246 :     cstack->head->query_len = len;
     155         246 : }
     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         210 : conditional_stack_get_query_len(ConditionalStack cstack)
     163             : {
     164         210 :     if (conditional_stack_empty(cstack))
     165           0 :         return -1;
     166         210 :     return cstack->head->query_len;
     167             : }
     168             : 
     169             : /*
     170             :  * Save current parenthesis nesting depth in topmost stack entry.
     171             :  */
     172             : void
     173         246 : conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
     174             : {
     175             :     Assert(!conditional_stack_empty(cstack));
     176         246 :     cstack->head->paren_depth = depth;
     177         246 : }
     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         210 : conditional_stack_get_paren_depth(ConditionalStack cstack)
     185             : {
     186         210 :     if (conditional_stack_empty(cstack))
     187           0 :         return -1;
     188         210 :     return cstack->head->paren_depth;
     189             : }

Generated by: LCOV version 1.14