aboutsummaryrefslogtreecommitdiff
path: root/src/fe_utils
diff options
context:
space:
mode:
authorTeodor Sigaev <teodor@sigaev.ru>2018-03-22 17:42:03 +0300
committerTeodor Sigaev <teodor@sigaev.ru>2018-03-22 17:42:03 +0300
commitf67b113ac62777d18cd20d3c4d05be964301b936 (patch)
treebd65429918d10cf374292620ae726adba50f7617 /src/fe_utils
parentb5db1d93d2a6e2d3186f8798a5d06e07b7536a1d (diff)
downloadpostgresql-f67b113ac62777d18cd20d3c4d05be964301b936.tar.gz
postgresql-f67b113ac62777d18cd20d3c4d05be964301b936.zip
Add \if support to pgbench
Patch adds \if to pgbench as it done for psql. Implementation shares condition stack code with psql, so, this code is moved to fe_utils directory. Author: Fabien COELHO with minor editorization by me Review by: Vik Fearing, Fedor Sigaev Discussion: https://www.postgresql.org/message-id/flat/alpine.DEB.2.20.1711252200190.28523@lancre
Diffstat (limited to 'src/fe_utils')
-rw-r--r--src/fe_utils/Makefile2
-rw-r--r--src/fe_utils/conditional.c176
2 files changed, 177 insertions, 1 deletions
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index 3f4ba8bf7c9..5362cffd573 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -19,7 +19,7 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
-OBJS = mbprint.o print.o psqlscan.o simple_list.o string_utils.o
+OBJS = mbprint.o print.o psqlscan.o simple_list.o string_utils.o conditional.o
all: libpgfeutils.a
diff --git a/src/fe_utils/conditional.c b/src/fe_utils/conditional.c
new file mode 100644
index 00000000000..0af80521ce1
--- /dev/null
+++ b/src/fe_utils/conditional.c
@@ -0,0 +1,176 @@
+/*-------------------------------------------------------------------------
+ * A stack of automaton states to handle nested conditionals.
+ *
+ * Copyright (c) 2000-2018, PostgreSQL Global Development Group
+ *
+ * src/fe_utils/conditional.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include "fe_utils/conditional.h"
+
+/*
+ * create stack
+ */
+ConditionalStack
+conditional_stack_create(void)
+{
+ ConditionalStack cstack = pg_malloc(sizeof(ConditionalStackData));
+
+ cstack->head = NULL;
+ return cstack;
+}
+
+/*
+ * destroy stack
+ */
+void
+conditional_stack_destroy(ConditionalStack cstack)
+{
+ while (conditional_stack_pop(cstack))
+ continue;
+ free(cstack);
+}
+
+/*
+ * Create a new conditional branch.
+ */
+void
+conditional_stack_push(ConditionalStack cstack, ifState new_state)
+{
+ IfStackElem *p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));
+
+ p->if_state = new_state;
+ p->query_len = -1;
+ p->paren_depth = -1;
+ p->next = cstack->head;
+ cstack->head = p;
+}
+
+/*
+ * Destroy the topmost conditional branch.
+ * Returns false if there was no branch to end.
+ */
+bool
+conditional_stack_pop(ConditionalStack cstack)
+{
+ IfStackElem *p = cstack->head;
+
+ if (!p)
+ return false;
+ cstack->head = cstack->head->next;
+ free(p);
+ return true;
+}
+
+/*
+ * Returns current stack depth, for debugging purposes.
+ */
+int
+conditional_stack_depth(ConditionalStack cstack)
+{
+ if (cstack == NULL)
+ return -1;
+ else
+ {
+ IfStackElem *p = cstack->head;
+ int depth = 0;
+ while (p != NULL)
+ {
+ depth++;
+ p = p->next;
+ }
+ return depth;
+ }
+}
+
+/*
+ * Fetch the current state of the top of the stack.
+ */
+ifState
+conditional_stack_peek(ConditionalStack cstack)
+{
+ if (conditional_stack_empty(cstack))
+ return IFSTATE_NONE;
+ return cstack->head->if_state;
+}
+
+/*
+ * Change the state of the topmost branch.
+ * Returns false if there was no branch state to set.
+ */
+bool
+conditional_stack_poke(ConditionalStack cstack, ifState new_state)
+{
+ if (conditional_stack_empty(cstack))
+ return false;
+ cstack->head->if_state = new_state;
+ return true;
+}
+
+/*
+ * True if there are no active \if-blocks.
+ */
+bool
+conditional_stack_empty(ConditionalStack cstack)
+{
+ return cstack->head == NULL;
+}
+
+/*
+ * True if we should execute commands normally; that is, the current
+ * conditional branch is active, or there is no open \if block.
+ */
+bool
+conditional_active(ConditionalStack cstack)
+{
+ ifState s = conditional_stack_peek(cstack);
+
+ return s == IFSTATE_NONE || s == IFSTATE_TRUE || s == IFSTATE_ELSE_TRUE;
+}
+
+/*
+ * Save current query buffer length in topmost stack entry.
+ */
+void
+conditional_stack_set_query_len(ConditionalStack cstack, int len)
+{
+ Assert(!conditional_stack_empty(cstack));
+ cstack->head->query_len = len;
+}
+
+/*
+ * Fetch last-recorded query buffer length from topmost stack entry.
+ * Will return -1 if no stack or it was never saved.
+ */
+int
+conditional_stack_get_query_len(ConditionalStack cstack)
+{
+ if (conditional_stack_empty(cstack))
+ return -1;
+ return cstack->head->query_len;
+}
+
+/*
+ * Save current parenthesis nesting depth in topmost stack entry.
+ */
+void
+conditional_stack_set_paren_depth(ConditionalStack cstack, int depth)
+{
+ Assert(!conditional_stack_empty(cstack));
+ cstack->head->paren_depth = depth;
+}
+
+/*
+ * Fetch last-recorded parenthesis nesting depth from topmost stack entry.
+ * Will return -1 if no stack or it was never saved.
+ */
+int
+conditional_stack_get_paren_depth(ConditionalStack cstack)
+{
+ if (conditional_stack_empty(cstack))
+ return -1;
+ return cstack->head->paren_depth;
+}