aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ecpg.sgml8
-rw-r--r--doc/src/sgml/ref/ecpg-ref.sgml6
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c79
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l127
-rw-r--r--src/interfaces/ecpg/preproc/type.h22
-rw-r--r--src/interfaces/ecpg/test/expected/sql-define.c65
-rw-r--r--src/interfaces/ecpg/test/expected/sql-define.stderr24
-rw-r--r--src/interfaces/ecpg/test/expected/sql-define.stdout3
-rw-r--r--src/interfaces/ecpg/test/meson.build3
-rw-r--r--src/interfaces/ecpg/test/sql/Makefile3
-rw-r--r--src/interfaces/ecpg/test/sql/define.pgc25
-rw-r--r--src/interfaces/ecpg/test/sql/define_prelim.pgc6
-rw-r--r--src/interfaces/ecpg/test/sql/meson.build1
13 files changed, 291 insertions, 81 deletions
diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml
index bb4bccd5a94..b72dab50ec4 100644
--- a/doc/src/sgml/ecpg.sgml
+++ b/doc/src/sgml/ecpg.sgml
@@ -5790,6 +5790,14 @@ EXEC SQL UPDATE Tbl SET col = MYNUMBER;
embedded SQL query because in this case the embedded SQL precompiler is not
able to see this declaration.
</para>
+
+ <para>
+ If multiple input files are named on the <command>ecpg</command>
+ preprocessor's command line, the effects of <literal>EXEC SQL
+ DEFINE</literal> and <literal>EXEC SQL UNDEF</literal> do not carry
+ across files: each file starts with only the symbols defined
+ by <option>-D</option> switches on the command line.
+ </para>
</sect2>
<sect2 id="ecpg-ifdef">
diff --git a/doc/src/sgml/ref/ecpg-ref.sgml b/doc/src/sgml/ref/ecpg-ref.sgml
index f3b6034f42a..43f2d8bdaa7 100644
--- a/doc/src/sgml/ref/ecpg-ref.sgml
+++ b/doc/src/sgml/ref/ecpg-ref.sgml
@@ -93,10 +93,12 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
- <term><option>-D <replaceable>symbol</replaceable></option></term>
+ <term><option>-D <replaceable>symbol</replaceable>[=<replaceable>value</replaceable>]</option></term>
<listitem>
<para>
- Define a C preprocessor symbol.
+ Define a preprocessor symbol, equivalently to the <command>EXEC SQL
+ DEFINE</command> directive. If no <replaceable>value</replaceable> is
+ specified, the symbol is defined with the value <literal>1</literal>.
</para>
</listitem>
</varlistentry>
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index 16cfc49e5e3..5ff25f3e7bc 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -82,35 +82,46 @@ add_include_path(char *path)
}
}
+/*
+ * Process a command line -D switch
+ */
static void
add_preprocessor_define(char *define)
{
- struct _defines *pd = defines;
- char *ptr,
- *define_copy = mm_strdup(define);
+ /* copy the argument to avoid relying on argv storage */
+ char *define_copy = mm_strdup(define);
+ char *ptr;
+ struct _defines *newdef;
- defines = mm_alloc(sizeof(struct _defines));
+ newdef = mm_alloc(sizeof(struct _defines));
/* look for = sign */
ptr = strchr(define_copy, '=');
if (ptr != NULL)
{
+ /* symbol has a value */
char *tmp;
- /* symbol has a value */
- for (tmp = ptr - 1; *tmp == ' '; tmp--);
+ /* strip any spaces between name and '=' */
+ for (tmp = ptr - 1; tmp >= define_copy && *tmp == ' '; tmp--);
tmp[1] = '\0';
- defines->olddef = define_copy;
- defines->newdef = ptr + 1;
+
+ /*
+ * Note we don't bother to separately malloc cmdvalue; it will never
+ * be freed so that's not necessary.
+ */
+ newdef->cmdvalue = ptr + 1;
}
else
{
- defines->olddef = define_copy;
- defines->newdef = mm_strdup("1");
+ /* define it as "1"; again no need to malloc it */
+ newdef->cmdvalue = "1";
}
- defines->pertinent = true;
- defines->used = NULL;
- defines->next = pd;
+ newdef->name = define_copy;
+ newdef->value = mm_strdup(newdef->cmdvalue);
+ newdef->used = NULL;
+ newdef->next = defines;
+ defines = newdef;
}
#define ECPG_GETOPT_LONG_REGRESSION 1
@@ -348,6 +359,8 @@ main(int argc, char *const argv[])
{
struct cursor *ptr;
struct _defines *defptr;
+ struct _defines *prevdefptr;
+ struct _defines *nextdefptr;
struct typedefs *typeptr;
struct declared_list *list;
@@ -385,28 +398,28 @@ main(int argc, char *const argv[])
free(this);
}
- /* remove non-pertinent old defines as well */
- while (defines && !defines->pertinent)
+ /* restore defines to their command-line state */
+ prevdefptr = NULL;
+ for (defptr = defines; defptr != NULL; defptr = nextdefptr)
{
- defptr = defines;
- defines = defines->next;
-
- free(defptr->newdef);
- free(defptr->olddef);
- free(defptr);
- }
-
- for (defptr = defines; defptr != NULL; defptr = defptr->next)
- {
- struct _defines *this = defptr->next;
-
- if (this && !this->pertinent)
+ nextdefptr = defptr->next;
+ if (defptr->cmdvalue != NULL)
{
- defptr->next = this->next;
-
- free(this->newdef);
- free(this->olddef);
- free(this);
+ /* keep it, resetting the value */
+ free(defptr->value);
+ defptr->value = mm_strdup(defptr->cmdvalue);
+ prevdefptr = defptr;
+ }
+ else
+ {
+ /* remove it */
+ if (prevdefptr != NULL)
+ prevdefptr->next = nextdefptr;
+ else
+ defines = nextdefptr;
+ free(defptr->name);
+ free(defptr->value);
+ free(defptr);
}
}
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index dcd567e8c3a..bed86cc6804 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -69,7 +69,14 @@ char *token_start;
static int state_before_str_start;
static int state_before_str_stop;
-struct _yy_buffer
+/*
+ * State for handling include files and macro expansion. We use a new
+ * flex input buffer for each level of include or macro, and create a
+ * struct _yy_buffer to remember the previous level. There is not a struct
+ * for the currently active input source; that state is kept in the global
+ * variables YY_CURRENT_BUFFER, yylineno, and input_filename.
+ */
+static struct _yy_buffer
{
YY_BUFFER_STATE buffer;
long lineno;
@@ -77,8 +84,6 @@ struct _yy_buffer
struct _yy_buffer *next;
} *yy_buffer = NULL;
-static char *old;
-
/*
* Vars for handling ifdef/elif/endif constructs. preproc_tos is the current
* nesting depth of such constructs, and stacked_if_value[preproc_tos] is the
@@ -444,6 +449,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
%{
/* code to execute during start of each call of yylex() */
+ char *newdefsymbol = NULL;
+
token_start = NULL;
%}
@@ -1010,6 +1017,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
}
{identifier} {
+ /* First check to see if it's a define symbol to expand */
if (!isdefine())
{
int kwvalue;
@@ -1198,17 +1206,23 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yytext[i+1] = '\0';
- for (ptr = defines; ptr != NULL; ptr2 = ptr, ptr = ptr->next)
+ /* Find and unset any matching define; should be only 1 */
+ for (ptr = defines; ptr; ptr2 = ptr, ptr = ptr->next)
{
- if (strcmp(yytext, ptr->olddef) == 0)
+ if (strcmp(yytext, ptr->name) == 0)
{
- if (ptr2 == NULL)
- defines = ptr->next;
- else
- ptr2->next = ptr->next;
- free(ptr->newdef);
- free(ptr->olddef);
- free(ptr);
+ free(ptr->value);
+ ptr->value = NULL;
+ /* We cannot forget it if there's a cmdvalue */
+ if (ptr->cmdvalue == NULL)
+ {
+ if (ptr2 == NULL)
+ defines = ptr->next;
+ else
+ ptr2->next = ptr->next;
+ free(ptr->name);
+ free(ptr);
+ }
break;
}
}
@@ -1413,11 +1427,17 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
;
yytext[i+1] = '\0';
- for (defptr = defines;
- defptr != NULL &&
- strcmp(yytext, defptr->olddef) != 0;
- defptr = defptr->next)
- /* skip */ ;
+ /* Does a definition exist? */
+ for (defptr = defines; defptr; defptr = defptr->next)
+ {
+ if (strcmp(yytext, defptr->name) == 0)
+ {
+ /* Found it, but is it currently undefined? */
+ if (defptr->value == NULL)
+ defptr = NULL; /* pretend it's not found */
+ break;
+ }
+ }
this_active = (defptr ? ifcond : !ifcond);
stacked_if_value[preproc_tos].active =
@@ -1438,7 +1458,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yyterminate();
}
<def_ident>{identifier} {
- old = mm_strdup(yytext);
+ newdefsymbol = mm_strdup(yytext);
BEGIN(def);
startlit();
}
@@ -1447,26 +1467,31 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yyterminate();
}
<def>{space}*";" {
- struct _defines *ptr, *this;
+ struct _defines *ptr;
+ /* Does it already exist? */
for (ptr = defines; ptr != NULL; ptr = ptr->next)
{
- if (strcmp(old, ptr->olddef) == 0)
- {
- free(ptr->newdef);
- ptr->newdef = mm_strdup(literalbuf);
- }
+ if (strcmp(newdefsymbol, ptr->name) == 0)
+ {
+ free(ptr->value);
+ ptr->value = mm_strdup(literalbuf);
+ /* Don't leak newdefsymbol */
+ free(newdefsymbol);
+ break;
+ }
}
if (ptr == NULL)
{
- this = (struct _defines *) mm_alloc(sizeof(struct _defines));
-
- /* initial definition */
- this->olddef = old;
- this->newdef = mm_strdup(literalbuf);
- this->next = defines;
- this->used = NULL;
- defines = this;
+ /* Not present, make a new entry */
+ ptr = (struct _defines *) mm_alloc(sizeof(struct _defines));
+
+ ptr->name = newdefsymbol;
+ ptr->value = mm_strdup(literalbuf);
+ ptr->cmdvalue = NULL;
+ ptr->used = NULL;
+ ptr->next = defines;
+ defines = ptr;
}
BEGIN(C);
@@ -1483,6 +1508,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
<<EOF>> {
if (yy_buffer == NULL)
{
+ /* No more input */
if (preproc_tos > 0)
{
preproc_tos = 0;
@@ -1492,16 +1518,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
}
else
{
+ /* Revert to previous input source */
struct _yy_buffer *yb = yy_buffer;
int i;
struct _defines *ptr;
+ /* Check to see if we are exiting a macro value */
for (ptr = defines; ptr; ptr = ptr->next)
+ {
if (ptr->used == yy_buffer)
{
ptr->used = NULL;
- break;
+ break; /* there can't be multiple matches */
}
+ }
if (yyin != NULL)
fclose(yyin);
@@ -1726,15 +1756,24 @@ ecpg_isspace(char ch)
return false;
}
-static bool isdefine(void)
+/*
+ * If yytext matches a define symbol, begin scanning the symbol's value
+ * and return true
+ */
+static bool
+isdefine(void)
{
struct _defines *ptr;
/* is it a define? */
for (ptr = defines; ptr; ptr = ptr->next)
{
- if (strcmp(yytext, ptr->olddef) == 0 && ptr->used == NULL)
+ /* notice we do not match anything being actively expanded */
+ if (strcmp(yytext, ptr->name) == 0 &&
+ ptr->value != NULL &&
+ ptr->used == NULL)
{
+ /* Save state associated with the current buffer */
struct _yy_buffer *yb;
yb = mm_alloc(sizeof(struct _yy_buffer));
@@ -1743,10 +1782,17 @@ static bool isdefine(void)
yb->lineno = yylineno;
yb->filename = mm_strdup(input_filename);
yb->next = yy_buffer;
+ yy_buffer = yb;
- ptr->used = yy_buffer = yb;
+ /* Mark symbol as being actively expanded */
+ ptr->used = yb;
- yy_scan_string(ptr->newdef);
+ /*
+ * We use yy_scan_string which will copy the value, so there's
+ * no need to worry about a possible undef happening while we
+ * are still scanning it.
+ */
+ yy_scan_string(ptr->value);
return true;
}
}
@@ -1754,7 +1800,12 @@ static bool isdefine(void)
return false;
}
-static bool isinformixdefine(void)
+/*
+ * Handle replacement of INFORMIX built-in defines. This works just
+ * like isdefine() except for the source of the string to scan.
+ */
+static bool
+isinformixdefine(void)
{
const char *new = NULL;
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 5935cd74730..ce2124361fd 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -163,13 +163,25 @@ struct typedefs
struct typedefs *next;
};
+/*
+ * Info about a defined symbol (macro), coming from a -D command line switch
+ * or a define command in the program. These are stored in a simple list.
+ * Because ecpg supports compiling multiple files per run, we have to remember
+ * the command-line definitions and be able to revert to those; this motivates
+ * storing cmdvalue separately from value.
+ * name and value are separately-malloc'd strings; cmdvalue typically isn't.
+ * used is NULL unless we are currently expanding the macro, in which case
+ * it points to the buffer before the one scanning the macro; we reset it
+ * to NULL upon returning to that buffer. This is used to prevent recursive
+ * expansion of the macro.
+ */
struct _defines
{
- char *olddef;
- char *newdef;
- int pertinent;
- void *used;
- struct _defines *next;
+ char *name; /* symbol's name */
+ char *value; /* current value, or NULL if undefined */
+ const char *cmdvalue; /* value set on command line, or NULL */
+ void *used; /* buffer pointer, or NULL */
+ struct _defines *next; /* list link */
};
/* This is a linked list of the variable names and types. */
diff --git a/src/interfaces/ecpg/test/expected/sql-define.c b/src/interfaces/ecpg/test/expected/sql-define.c
index 29583ecd741..e97caec5b05 100644
--- a/src/interfaces/ecpg/test/expected/sql-define.c
+++ b/src/interfaces/ecpg/test/expected/sql-define.c
@@ -6,6 +6,21 @@
/* End of automatic include section */
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+#line 1 "define_prelim.pgc"
+/*
+ * Test that the effects of these commands don't carry over to the next
+ * file named on the ecpg command line.
+ */
+
+
+/* Processed by ecpg (regression mode) */
+/* These include files are added by the preprocessor */
+#include <ecpglib.h>
+#include <ecpgerrno.h>
+#include <sqlca.h>
+/* End of automatic include section */
+#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
#line 1 "define.pgc"
#line 1 "sqlca.h"
@@ -195,11 +210,57 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
+ /* test handling of a macro defined on the command line */
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select 123", ECPGt_EOIT,
+ ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 57 "define.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 57 "define.pgc"
+
+ printf("original CMDLINESYM: %d\n", i);
+
+
+
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select 42", ECPGt_EOIT,
+ ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 62 "define.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 62 "define.pgc"
+
+ printf("redefined CMDLINESYM: %d\n", i);
+
+
+
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select 43", ECPGt_EOIT,
+ ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 67 "define.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 67 "define.pgc"
+
+ printf("redefined CMDLINESYM: %d\n", i);
+
+
+
+
+
+
+
+ /* this macro should not have carried over from define_prelim.pgc */
+
+
+
+
{ ECPGdisconnect(__LINE__, "CURRENT");
-#line 56 "define.pgc"
+#line 81 "define.pgc"
if (sqlca.sqlcode < 0) sqlprint ( );}
-#line 56 "define.pgc"
+#line 81 "define.pgc"
return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/sql-define.stderr b/src/interfaces/ecpg/test/expected/sql-define.stderr
index 20601b63cf9..c4da9927e8c 100644
--- a/src/interfaces/ecpg/test/expected/sql-define.stderr
+++ b/src/interfaces/ecpg/test/expected/sql-define.stderr
@@ -48,5 +48,29 @@
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 53: OK: SET
[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 57: query: select 123; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 57: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 57: correctly got 1 tuples with 1 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 57: RESULT: 123 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 62: query: select 42; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 62: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 62: correctly got 1 tuples with 1 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 62: RESULT: 42 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 67: query: select 43; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 67: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 67: correctly got 1 tuples with 1 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 67: RESULT: 43 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
[NO_PID]: sqlca: code: 0, state: 00000
diff --git a/src/interfaces/ecpg/test/expected/sql-define.stdout b/src/interfaces/ecpg/test/expected/sql-define.stdout
index 864cd850bf3..eaddc7f8c32 100644
--- a/src/interfaces/ecpg/test/expected/sql-define.stdout
+++ b/src/interfaces/ecpg/test/expected/sql-define.stdout
@@ -1 +1,4 @@
i: 1, s: 29-abcdef
+original CMDLINESYM: 123
+redefined CMDLINESYM: 42
+redefined CMDLINESYM: 43
diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build
index 04c6819a799..8fc352b0145 100644
--- a/src/interfaces/ecpg/test/meson.build
+++ b/src/interfaces/ecpg/test/meson.build
@@ -45,9 +45,10 @@ ecpg_preproc_test_command_start = [
'--regression',
'-I@CURRENT_SOURCE_DIR@',
'-I@SOURCE_ROOT@' + '/src/interfaces/ecpg/include/',
+ '-o', '@OUTPUT@',
]
ecpg_preproc_test_command_end = [
- '-o', '@OUTPUT@', '@INPUT@'
+ '@INPUT@'
]
ecpg_test_dependencies = []
diff --git a/src/interfaces/ecpg/test/sql/Makefile b/src/interfaces/ecpg/test/sql/Makefile
index d8213b25cea..6032762ad70 100644
--- a/src/interfaces/ecpg/test/sql/Makefile
+++ b/src/interfaces/ecpg/test/sql/Makefile
@@ -33,5 +33,8 @@ TESTS = array array.c \
all: $(TESTS)
+define.c: define.pgc define_prelim.pgc $(ECPG_TEST_DEPENDENCIES)
+ $(ECPG) -DCMDLINESYM=123 -o $@ $(srcdir)/define_prelim.pgc $<
+
oldexec.c: oldexec.pgc $(ECPG_TEST_DEPENDENCIES)
$(ECPG) -r questionmarks -o $@ $<
diff --git a/src/interfaces/ecpg/test/sql/define.pgc b/src/interfaces/ecpg/test/sql/define.pgc
index ed58a4bde0c..83f328df468 100644
--- a/src/interfaces/ecpg/test/sql/define.pgc
+++ b/src/interfaces/ecpg/test/sql/define.pgc
@@ -53,6 +53,31 @@ int main(void)
exec sql SET TIMEZONE TO TZVAR;
exec sql endif;
+ /* test handling of a macro defined on the command line */
+ exec sql select CMDLINESYM INTO :i;
+ printf("original CMDLINESYM: %d\n", i);
+
+ exec sql define CMDLINESYM 42;
+
+ exec sql select CMDLINESYM INTO :i;
+ printf("redefined CMDLINESYM: %d\n", i);
+
+ exec sql define CMDLINESYM 43;
+
+ exec sql select CMDLINESYM INTO :i;
+ printf("redefined CMDLINESYM: %d\n", i);
+
+ exec sql undef CMDLINESYM;
+
+ exec sql ifdef CMDLINESYM;
+ exec sql insert into test values (NUMBER, 'no string');
+ exec sql endif;
+
+ /* this macro should not have carried over from define_prelim.pgc */
+ exec sql ifdef NONCMDLINESYM;
+ exec sql insert into test values (NUMBER, 'no string');
+ exec sql endif;
+
exec sql disconnect;
return 0;
}
diff --git a/src/interfaces/ecpg/test/sql/define_prelim.pgc b/src/interfaces/ecpg/test/sql/define_prelim.pgc
new file mode 100644
index 00000000000..7a984f74c84
--- /dev/null
+++ b/src/interfaces/ecpg/test/sql/define_prelim.pgc
@@ -0,0 +1,6 @@
+/*
+ * Test that the effects of these commands don't carry over to the next
+ * file named on the ecpg command line.
+ */
+exec sql define CMDLINESYM 999;
+exec sql define NONCMDLINESYM 1234;
diff --git a/src/interfaces/ecpg/test/sql/meson.build b/src/interfaces/ecpg/test/sql/meson.build
index f4c9418abb8..e2a5ca24154 100644
--- a/src/interfaces/ecpg/test/sql/meson.build
+++ b/src/interfaces/ecpg/test/sql/meson.build
@@ -30,6 +30,7 @@ pgc_files = [
]
pgc_extra_flags = {
+ 'define': ['-DCMDLINESYM=123', files('define_prelim.pgc')],
'oldexec': ['-r', 'questionmarks'],
}