PostgreSQL Source Code git master
conditional.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 * A stack of automaton states to handle nested conditionals.
3 *
4 * This file describes a stack of automaton states which
5 * allow a manage nested conditionals.
6 *
7 * It is used by:
8 * - "psql" interpreter for handling \if ... \endif
9 * - "pgbench" interpreter for handling \if ... \endif
10 * - "pgbench" syntax checker to test for proper nesting
11 *
12 * The stack holds the state of enclosing conditionals (are we in
13 * a true branch? in a false branch? have we already encountered
14 * a true branch?) so that the interpreter knows whether to execute
15 * code and whether to evaluate conditions.
16 *
17 * Copyright (c) 2000-2025, PostgreSQL Global Development Group
18 *
19 * src/include/fe_utils/conditional.h
20 *
21 *-------------------------------------------------------------------------
22 */
23#ifndef CONDITIONAL_H
24#define CONDITIONAL_H
25
26/*
27 * Possible states of a single level of \if block.
28 */
29typedef enum ifState
30{
31 IFSTATE_NONE = 0, /* not currently in an \if block */
32 IFSTATE_TRUE, /* currently in an \if or \elif that is true
33 * and all parent branches (if any) are true */
34 IFSTATE_FALSE, /* currently in an \if or \elif that is false
35 * but no true branch has yet been seen, and
36 * all parent branches (if any) are true */
37 IFSTATE_IGNORED, /* currently in an \elif that follows a true
38 * branch, or the whole \if is a child of a
39 * false parent branch */
40 IFSTATE_ELSE_TRUE, /* currently in an \else that is true and all
41 * parent branches (if any) are true */
42 IFSTATE_ELSE_FALSE, /* currently in an \else that is false or
43 * ignored */
45
46/*
47 * The state of nested \ifs is stored in a stack.
48 *
49 * query_len is used to determine what accumulated text to throw away at the
50 * end of an inactive branch. (We could, perhaps, teach the lexer to not add
51 * stuff to the query buffer in the first place when inside an inactive branch;
52 * but that would be very invasive.) We also need to save and restore the
53 * lexer's parenthesis nesting depth when throwing away text. (We don't need
54 * to save and restore any of its other state, such as comment nesting depth,
55 * because a backslash command could never appear inside a comment or SQL
56 * literal.)
57 */
58typedef struct IfStackElem
59{
60 ifState if_state; /* current state, see enum above */
61 int query_len; /* length of query_buf at last branch start */
62 int paren_depth; /* parenthesis depth at last branch start */
63 struct IfStackElem *next; /* next surrounding \if, if any */
65
67{
70
72
73
75
77
79
81
82extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
83
84extern bool conditional_stack_pop(ConditionalStack cstack);
85
87
88extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
89
91
92extern bool conditional_active(ConditionalStack cstack);
93
95
97
98extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
99
101
102#endif /* CONDITIONAL_H */
struct ConditionalStackData ConditionalStackData
void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
Definition: conditional.c:173
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:106
struct IfStackElem IfStackElem
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:53
ifState
Definition: conditional.h:30
@ IFSTATE_FALSE
Definition: conditional.h:34
@ IFSTATE_ELSE_TRUE
Definition: conditional.h:40
@ IFSTATE_IGNORED
Definition: conditional.h:37
@ IFSTATE_TRUE
Definition: conditional.h:32
@ IFSTATE_NONE
Definition: conditional.h:31
@ IFSTATE_ELSE_FALSE
Definition: conditional.h:42
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
int conditional_stack_depth(ConditionalStack cstack)
Definition: conditional.c:84
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:69
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:43
struct ConditionalStackData * ConditionalStack
Definition: conditional.h:71
void conditional_stack_set_query_len(ConditionalStack cstack, int len)
Definition: conditional.c:151
int conditional_stack_get_query_len(ConditionalStack cstack)
Definition: conditional.c:162
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
void conditional_stack_reset(ConditionalStack cstack)
Definition: conditional.c:30
int conditional_stack_get_paren_depth(ConditionalStack cstack)
Definition: conditional.c:184
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:118
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:130
const void size_t len
IfStackElem * head
Definition: conditional.h:68
struct IfStackElem * next
Definition: conditional.h:63
int paren_depth
Definition: conditional.h:62
ifState if_state
Definition: conditional.h:60