aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/ecpg/ChangeLog7
-rw-r--r--src/interfaces/ecpg/TODO4
-rw-r--r--src/interfaces/ecpg/include/ecpglib.h3
-rw-r--r--src/interfaces/ecpg/lib/Makefile.in2
-rw-r--r--src/interfaces/ecpg/lib/ecpglib.c426
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c19
-rw-r--r--src/interfaces/ecpg/preproc/extern.h18
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y73
-rw-r--r--src/interfaces/ecpg/test/Makefile2
-rw-r--r--src/interfaces/ecpg/test/test2.pgc10
10 files changed, 333 insertions, 231 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index 1907471a731..6ac03ff234f 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -270,3 +270,10 @@ Mon Aug 3 17:23:18 CEST 1998
- Fixed cursor handling
- Set version to 2.3.5
- Set library version to 2.4
+
+Fri Aug 7 12:38:50 CEST 1998
+
+ - Fixed cursor handling once again
+ - Added support for variables in cursor
+ - Set version to 2.3.6
+ - Set library version to 2.5
diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO
index 5811cb767de..908ec619270 100644
--- a/src/interfaces/ecpg/TODO
+++ b/src/interfaces/ecpg/TODO
@@ -1,9 +1,7 @@
-What happens to a cursor declaration with variables?
-
The complete structure definition has to be listed inside the declare
section of the structure variable for ecpg to be able to understand it.
-Variable type bool has to be checked. I never used it so far.
+Variable type bool has to be tested. I never used it so far.
The error message for "no data" in an exec sql insert select from statement
has to be 100.
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index a81ca7e8b9c..83f2e6efb86 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -13,9 +13,6 @@ bool ECPGdisconnect(int, const char *);
void ECPGlog(const char *format,...);
-bool ECPGdeclare(int, const char *, char *);
-bool ECPGopen(int, const char *);
-
#ifdef LIBPQ_FE_H
bool ECPGsetdb(PGconn *);
diff --git a/src/interfaces/ecpg/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in
index 8fd6b772030..e236487d6aa 100644
--- a/src/interfaces/ecpg/lib/Makefile.in
+++ b/src/interfaces/ecpg/lib/Makefile.in
@@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
SO_MAJOR_VERSION=2
-SO_MINOR_VERSION=4
+SO_MINOR_VERSION=5
PORTNAME=@PORTNAME@
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 86021d6ee46..0d3d4fa0e6a 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -33,6 +33,29 @@ static struct connection
struct connection *next;
} *all_connections = NULL, *actual_connection = NULL;
+struct variable
+{
+ enum ECPGttype type;
+ void *value;
+ long varcharsize;
+ long arrsize;
+ long offset;
+ enum ECPGttype ind_type;
+ void *ind_value;
+ long ind_varcharsize;
+ long ind_arrsize;
+ long ind_offset;
+ struct variable *next;
+};
+
+struct statement
+{
+ int lineno;
+ char *command;
+ struct variable *inlist;
+ struct variable *outlist;
+};
+
static int simple_debug = 0;
static FILE *debugstream = NULL;
static int committed = true;
@@ -116,27 +139,87 @@ ECPGfinish(struct connection *act)
ECPGlog("ECPGfinish: called an extra time.\n");
}
-bool
-ECPGdo(int lineno, char *query,...)
+/* create a list of variables */
+static bool
+create_statement(int lineno, struct statement **stmt, char *query, va_list ap)
+{
+ struct variable **list = &((*stmt)->inlist);
+ enum ECPGttype type;
+
+ *stmt = calloc(sizeof(struct statement), 1);
+
+ if (!*stmt)
+ {
+ ECPGfinish(actual_connection);
+ ECPGlog("out of memory\n");
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ return false;
+ }
+
+ (*stmt)->command = query;
+ (*stmt)->lineno = lineno;
+
+ list = &((*stmt)->inlist);
+
+ type = va_arg(ap, enum ECPGttype);
+
+ while (type != ECPGt_EORT)
+ {
+ if (type == ECPGt_EOIT)
+ {
+ list = &((*stmt)->outlist);
+ }
+ else
+ {
+ struct variable *var, *ptr;
+
+ var = malloc(sizeof(struct variable));
+ if (!var)
+ {
+ ECPGfinish(actual_connection);
+ ECPGlog("out of memory\n");
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ return false;
+ }
+
+ var->type = type;
+ var->value = va_arg(ap, void *);
+ var->varcharsize = va_arg(ap, long);
+ var->arrsize = va_arg(ap, long);
+ var->offset = va_arg(ap, long);
+ var->ind_type = va_arg(ap, enum ECPGttype);
+ var->ind_value = va_arg(ap, void *);
+ var->ind_varcharsize = va_arg(ap, long);
+ var->ind_arrsize = va_arg(ap, long);
+ var->ind_offset = va_arg(ap, long);
+ var->next = NULL;
+
+ for (ptr = *list; ptr && ptr->next; ptr=ptr->next);
+
+ if (ptr == NULL)
+ *list = var;
+ else
+ ptr->next = var;
+ }
+
+ type = va_arg(ap, enum ECPGttype);
+ }
+
+ return(true);
+}
+
+static bool
+ECPGexecute(struct statement *stmt)
{
- va_list ap;
bool status = false;
char *copiedquery;
PGresult *results;
PGnotify *notify;
- enum ECPGttype type;
- void *value = NULL, *ind_value;
- long varcharsize, ind_varcharsize;
- long arrsize, ind_arrsize;
- long offset, ind_offset;
- enum ECPGttype ind_type;
+ struct variable *var;
memset((char *) &sqlca, 0, sizeof (sqlca));
- va_start(ap, query);
- copiedquery = strdup(query);
-
- type = va_arg(ap, enum ECPGttype);
+ copiedquery = strdup(stmt->command);
/*
* Now, if the type is one of the fill in types then we take the
@@ -144,7 +227,8 @@ ECPGdo(int lineno, char *query,...)
* Then if there are any more fill in types we fill in at the next and
* so on.
*/
- while (type != ECPGt_EOIT)
+ var = stmt->inlist;
+ while (var)
{
char *newcopy;
char *mallocedval = NULL;
@@ -158,34 +242,24 @@ ECPGdo(int lineno, char *query,...)
* think).
*/
- value = va_arg(ap, void *);
- varcharsize = va_arg(ap, long);
- arrsize = va_arg(ap, long);
- offset = va_arg(ap, long);
- ind_type = va_arg(ap, enum ECPGttype);
- ind_value = va_arg(ap, void *);
- ind_varcharsize = va_arg(ap, long);
- ind_arrsize = va_arg(ap, long);
- ind_offset = va_arg(ap, long);
-
buff[0] = '\0';
/* check for null value and set input buffer accordingly */
- switch (ind_type)
+ switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
- if (*(short *) ind_value < 0)
+ if (*(short *) var->ind_value < 0)
strcpy(buff, "null");
break;
case ECPGt_int:
case ECPGt_unsigned_int:
- if (*(int *) ind_value < 0)
+ if (*(int *) var->ind_value < 0)
strcpy(buff, "null");
break;
case ECPGt_long:
case ECPGt_unsigned_long:
- if (*(long *) ind_value < 0L)
+ if (*(long *) var->ind_value < 0L)
strcpy(buff, "null");
break;
default:
@@ -194,42 +268,42 @@ ECPGdo(int lineno, char *query,...)
if (*buff == '\0')
{
- switch (type)
+ switch (var->type)
{
case ECPGt_short:
case ECPGt_int:
- sprintf(buff, "%d", *(int *) value);
+ sprintf(buff, "%d", *(int *) var->value);
tobeinserted = buff;
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
- sprintf(buff, "%d", *(unsigned int *) value);
+ sprintf(buff, "%d", *(unsigned int *) var->value);
tobeinserted = buff;
break;
case ECPGt_long:
- sprintf(buff, "%ld", *(long *) value);
+ sprintf(buff, "%ld", *(long *) var->value);
tobeinserted = buff;
break;
case ECPGt_unsigned_long:
- sprintf(buff, "%ld", *(unsigned long *) value);
+ sprintf(buff, "%ld", *(unsigned long *) var->value);
tobeinserted = buff;
break;
case ECPGt_float:
- sprintf(buff, "%.14g", *(float *) value);
+ sprintf(buff, "%.14g", *(float *) var->value);
tobeinserted = buff;
break;
case ECPGt_double:
- sprintf(buff, "%.14g", *(double *) value);
+ sprintf(buff, "%.14g", *(double *) var->value);
tobeinserted = buff;
break;
case ECPGt_bool:
- sprintf(buff, "'%c'", (*(char *) value ? 't' : 'f'));
+ sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
tobeinserted = buff;
break;
@@ -237,7 +311,7 @@ ECPGdo(int lineno, char *query,...)
case ECPGt_unsigned_char:
{
/* set slen to string length if type is char * */
- int slen = (varcharsize == 0) ? strlen((char *) value) : varcharsize;
+ int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
char * tmp;
newcopy = (char *) malloc(slen + 1);
@@ -245,11 +319,11 @@ ECPGdo(int lineno, char *query,...)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
- strncpy(newcopy, (char *) value, slen);
+ strncpy(newcopy, (char *) var->value, slen);
newcopy[slen] = '\0';
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
@@ -257,7 +331,7 @@ ECPGdo(int lineno, char *query,...)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
@@ -267,7 +341,7 @@ ECPGdo(int lineno, char *query,...)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
@@ -282,28 +356,28 @@ ECPGdo(int lineno, char *query,...)
case ECPGt_varchar:
{
- struct ECPGgeneric_varchar *var =
- (struct ECPGgeneric_varchar *) value;
+ struct ECPGgeneric_varchar *variable =
+ (struct ECPGgeneric_varchar *) (var->value);
char *tmp;
- newcopy = (char *) malloc(var->len + 1);
+ newcopy = (char *) malloc(variable->len + 1);
if (!newcopy)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
- strncpy(newcopy, var->arr, var->len);
- newcopy[var->len] = '\0';
+ strncpy(newcopy, variable->arr, variable->len);
+ newcopy[variable->len] = '\0';
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
if (!mallocedval)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
@@ -313,7 +387,7 @@ ECPGdo(int lineno, char *query,...)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
@@ -329,7 +403,7 @@ ECPGdo(int lineno, char *query,...)
default:
/* Not implemented yet */
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
- ECPGtype_name(type), lineno);
+ ECPGtype_name(var->type), stmt->lineno);
return false;
break;
}
@@ -348,7 +422,7 @@ ECPGdo(int lineno, char *query,...)
{
ECPGfinish(actual_connection);
ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+ register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
return false;
}
@@ -360,7 +434,7 @@ ECPGdo(int lineno, char *query,...)
* We have an argument but we dont have the matched up string
* in the string
*/
- register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
+ register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
return false;
}
else
@@ -379,7 +453,7 @@ ECPGdo(int lineno, char *query,...)
/*
* Now everything is safely copied to the newcopy. Lets free the
- * oldcopy and let the copiedquery get the value from the newcopy.
+ * oldcopy and let the copiedquery get the var->value from the newcopy.
*/
if (mallocedval != NULL)
{
@@ -390,13 +464,13 @@ ECPGdo(int lineno, char *query,...)
free(copiedquery);
copiedquery = newcopy;
- type = va_arg(ap, enum ECPGttype);
+ var = var->next;
}
/* Check if there are unmatched things left. */
if (strstr(copiedquery, ";;") != NULL)
{
- register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
+ register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
return false;
}
@@ -406,27 +480,28 @@ ECPGdo(int lineno, char *query,...)
{
if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
{
- register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
+ register_error(ECPG_TRANS, "Error starting transaction line %d.", stmt->lineno);
return false;
}
PQclear(results);
committed = 0;
}
- ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
+ ECPGlog("ECPGexecute line %d: QUERY: %s\n", stmt->lineno, copiedquery);
results = PQexec(actual_connection->connection, copiedquery);
free(copiedquery);
if (results == NULL)
{
- ECPGlog("ECPGdo line %d: error: %s", lineno,
+ ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
PQerrorMessage(actual_connection->connection));
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
- PQerrorMessage(actual_connection->connection), lineno);
+ PQerrorMessage(actual_connection->connection), stmt->lineno);
}
else
{
sqlca.sqlerrd[2] = 0;
+ var = stmt->outlist;
switch (PQresultStatus(results))
{
int nfields, ntuples, act_tuple, act_field;
@@ -445,9 +520,9 @@ ECPGdo(int lineno, char *query,...)
if (ntuples < 1)
{
- ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
- lineno, ntuples);
- register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
+ ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
+ stmt->lineno, ntuples);
+ register_error(ECPG_NOT_FOUND, "Data not found line %d.", stmt->lineno);
status = false;
break;
}
@@ -457,23 +532,19 @@ ECPGdo(int lineno, char *query,...)
char *pval;
char *scan_length;
- type = va_arg(ap, enum ECPGttype);
- value = va_arg(ap, void *);
- varcharsize = va_arg(ap, long);
- arrsize = va_arg(ap, long);
- offset = va_arg(ap, long);
- ind_type = va_arg(ap, enum ECPGttype);
- ind_value = va_arg(ap, void *);
- ind_varcharsize = va_arg(ap, long);
- ind_arrsize = va_arg(ap, long);
- ind_offset = va_arg(ap, long);
-
+ if (var == NULL)
+ {
+ ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
+ register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
+ return(false);
+ }
+
/* if we don't have enough space, we cannot read all tuples */
- if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize))
+ if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
{
- ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n",
- lineno, ntuples, arrsize);
- register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", lineno);
+ ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
+ stmt->lineno, ntuples, var->arrsize);
+ register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", stmt->lineno);
status = false;
break;
}
@@ -481,31 +552,31 @@ ECPGdo(int lineno, char *query,...)
{
pval = PQgetvalue(results, act_tuple, act_field);
- ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
+ ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
- /* Now the pval is a pointer to the value. */
- /* We will have to decode the value */
+ /* Now the pval is a pointer to the var->value. */
+ /* We will have to decode the var->value */
- /* check for null value and set indicator accordingly */
- switch (ind_type)
+ /* check for null var->value and set indicator accordingly */
+ switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
- ((short *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_int:
case ECPGt_unsigned_int:
- ((int *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_long:
case ECPGt_unsigned_long:
- ((long *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
default:
break;
}
- switch (type)
+ switch (var->type)
{
long res;
unsigned long ures;
@@ -520,7 +591,7 @@ ECPGdo(int lineno, char *query,...)
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
- pval, lineno);
+ pval, stmt->lineno);
status = false;
res = 0L;
}
@@ -529,16 +600,16 @@ ECPGdo(int lineno, char *query,...)
res = 0L;
/* Again?! Yes */
- switch (type)
+ switch (var->type)
{
case ECPGt_short:
- ((short *) value)[act_tuple] = (short) res;
+ ((short *) var->value)[act_tuple] = (short) res;
break;
case ECPGt_int:
- ((int *) value)[act_tuple] = (int) res;
+ ((int *) var->value)[act_tuple] = (int) res;
break;
case ECPGt_long:
- ((long *) value)[act_tuple] = res;
+ ((long *) var->value)[act_tuple] = res;
break;
default:
/* Cannot happen */
@@ -555,7 +626,7 @@ ECPGdo(int lineno, char *query,...)
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
- pval, lineno);
+ pval, stmt->lineno);
status = false;
ures = 0L;
}
@@ -564,16 +635,16 @@ ECPGdo(int lineno, char *query,...)
ures = 0L;
/* Again?! Yes */
- switch (type)
+ switch (var->type)
{
case ECPGt_unsigned_short:
- ((unsigned short *) value)[act_tuple] = (unsigned short) ures;
+ ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
- ((unsigned int *) value)[act_tuple] = (unsigned int) ures;
+ ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
- ((unsigned long *) value)[act_tuple] = ures;
+ ((unsigned long *) var->value)[act_tuple] = ures;
break;
default:
/* Cannot happen */
@@ -590,7 +661,7 @@ ECPGdo(int lineno, char *query,...)
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
- pval, lineno);
+ pval, stmt->lineno);
status = false;
dres = 0.0;
}
@@ -599,13 +670,13 @@ ECPGdo(int lineno, char *query,...)
dres = 0.0;
/* Again?! Yes */
- switch (type)
+ switch (var->type)
{
case ECPGt_float:
- ((float *) value)[act_tuple] = dres;
+ ((float *) var->value)[act_tuple] = dres;
break;
case ECPGt_double:
- ((double *) value)[act_tuple] = dres;
+ ((double *) var->value)[act_tuple] = dres;
break;
default:
/* Cannot happen */
@@ -618,50 +689,50 @@ ECPGdo(int lineno, char *query,...)
{
if (pval[0] == 'f' && pval[1] == '\0')
{
- ((char *) value)[act_tuple] = false;
+ ((char *) var->value)[act_tuple] = false;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
- ((char *) value)[act_tuple] = true;
+ ((char *) var->value)[act_tuple] = true;
break;
}
}
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
(pval ? pval : "NULL"),
- lineno);
+ stmt->lineno);
status = false;
break;
case ECPGt_char:
case ECPGt_unsigned_char:
{
- if (varcharsize == 0)
+ if (var->varcharsize == 0)
{
/* char* */
- strncpy(((char **) value)[act_tuple], pval, strlen(pval));
- (((char **) value)[act_tuple])[strlen(pval)] = '\0';
+ strncpy(((char **) var->value)[act_tuple], pval, strlen(pval));
+ (((char **) var->value)[act_tuple])[strlen(pval)] = '\0';
}
else
{
- strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
- if (varcharsize < strlen(pval))
+ strncpy((char *) (var->value + var->offset * act_tuple), pval, var->varcharsize);
+ if (var->varcharsize < strlen(pval))
{
/* truncation */
- switch (ind_type)
+ switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
- ((short *) ind_value)[act_tuple] = varcharsize;
+ ((short *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
- ((int *) ind_value)[act_tuple] = varcharsize;
+ ((int *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
- ((long *) ind_value)[act_tuple] = varcharsize;
+ ((long *) var->ind_value)[act_tuple] = var->varcharsize;
break;
default:
break;
@@ -674,62 +745,55 @@ ECPGdo(int lineno, char *query,...)
case ECPGt_varchar:
{
- struct ECPGgeneric_varchar *var =
- (struct ECPGgeneric_varchar *) (value + offset * act_tuple);
+ struct ECPGgeneric_varchar *variable =
+ (struct ECPGgeneric_varchar *) (var->value + var->offset * act_tuple);
- if (varcharsize == 0)
- strncpy(var->arr, pval, strlen(pval));
+ if (var->varcharsize == 0)
+ strncpy(variable->arr, pval, strlen(pval));
else
- strncpy(var->arr, pval, varcharsize);
+ strncpy(variable->arr, pval, var->varcharsize);
- var->len = strlen(pval);
- if (varcharsize > 0 && var->len > varcharsize)
+ variable->len = strlen(pval);
+ if (var->varcharsize > 0 && variable->len > var->varcharsize)
{
/* truncation */
- switch (ind_type)
+ switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
- ((short *) ind_value)[act_tuple] = varcharsize;
+ ((short *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
- ((int *) ind_value)[act_tuple] = varcharsize;
+ ((int *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
- ((long *) ind_value)[act_tuple] = varcharsize;
+ ((long *) var->ind_value)[act_tuple] = var->varcharsize;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
- var->len = varcharsize;
+ variable->len = var->varcharsize;
}
}
break;
- case ECPGt_EORT:
- ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
- register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
- status = false;
- break;
-
default:
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
- ECPGtype_name(type), lineno);
+ ECPGtype_name(var->type), stmt->lineno);
status = false;
break;
}
}
+ var = var->next;
}
- type = va_arg(ap, enum ECPGttype);
-
- if (status && type != ECPGt_EORT)
+ if (status && var != NULL)
{
- register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
+ register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
status = false;
}
@@ -737,35 +801,34 @@ ECPGdo(int lineno, char *query,...)
break;
case PGRES_EMPTY_QUERY:
/* do nothing */
- register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
+ register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
break;
case PGRES_COMMAND_OK:
status = true;
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
- ECPGlog("TEST: %s\n", PQcmdTuples(results));
- ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
+ ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
break;
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
- ECPGlog("ECPGdo line %d: Error: %s",
- lineno, PQerrorMessage(actual_connection->connection));
+ ECPGlog("ECPGexecute line %d: Error: %s",
+ stmt->lineno, PQerrorMessage(actual_connection->connection));
register_error(ECPG_PGSQL, "Error: %s line %d.",
- PQerrorMessage(actual_connection->connection), lineno);
+ PQerrorMessage(actual_connection->connection), stmt->lineno);
status = false;
break;
case PGRES_COPY_OUT:
- ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
+ ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
PQendcopy(results->conn);
break;
case PGRES_COPY_IN:
- ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
+ ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
PQendcopy(results->conn);
break;
default:
- ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
- lineno);
- register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
+ ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
+ stmt->lineno);
+ register_error(ECPG_PGSQL, "Postgres error line %d.", stmt->lineno);
status = false;
break;
}
@@ -775,8 +838,8 @@ ECPGdo(int lineno, char *query,...)
notify = PQnotifies(actual_connection->connection);
if (notify)
{
- ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
- lineno, notify->relname, notify->be_pid);
+ ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
+ stmt->lineno, notify->relname, notify->be_pid);
free(notify);
}
@@ -784,6 +847,20 @@ ECPGdo(int lineno, char *query,...)
return status;
}
+bool
+ECPGdo(int lineno, char *query, ...)
+{
+ va_list args;
+ struct statement *stmt;
+
+ va_start(args, query);
+ if (create_statement(lineno, &stmt, query, args) == false)
+ return(false);
+ va_end(args);
+
+ return(ECPGexecute(stmt));
+}
+
bool
ECPGtrans(int lineno, const char * transaction)
@@ -940,56 +1017,3 @@ sqlprint(void)
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
}
-
-/* keep a list of cursors */
-struct cursor *cur = NULL;
-
-bool ECPGdeclare(int lineno, const char *name, char *command)
-{
- struct cursor *ptr;
-
- for (ptr = cur; ptr != NULL; ptr = ptr->next)
- {
- if (strcmp(name, ptr->name) == 0)
- {
- /* re-definition */
- free(ptr->command);
- ptr->command = command;
- break;
- }
- }
-
- if (ptr == NULL)
- {
- struct cursor *this = (struct cursor *) malloc(sizeof(struct cursor));
-
- if (!this)
- {
- ECPGlog("out of memory\n");
- register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
- return false;
- }
- /* initial definition */
- this->next = cur;
- this->name = name;
- this->command = command;
- cur = this;
- }
-
- return(true);
-}
-
-bool ECPGopen(int lineno, const char *name)
-{
- struct cursor *ptr;
-
- for (ptr = cur; ptr != NULL; ptr=ptr->next)
- {
- if (strcmp(ptr->name, name) == 0)
- return(ECPGdo(lineno, ptr->command, ECPGt_EOIT, ECPGt_EORT));
- }
-
- ECPGlog("trying to open undeclared cursor %s\n", name);
- register_error(ECPG_UNDECLARED_CURSOR, "trying to open undeclared cursor %s in line %d", name, lineno);
- return(false);
-}
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index f12b799850c..1fe777845b7 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -23,6 +23,7 @@ extern char *optarg;
struct _include_path *include_paths;
static int no_auto_trans = 0;
+struct cursor *cur = NULL;
static void
usage(char *progname)
@@ -138,6 +139,24 @@ main(int argc, char *const argv[])
{
struct cursor *ptr;
+ /* remove old cursor definitions if any are still there */
+ for (ptr = cur; ptr != NULL; ptr=ptr->next)
+ {
+ struct arguments *l1, *l2;
+
+ free(ptr->command);
+ free(ptr->name);
+ for (l1 = argsinsert; l1; l1 = l2)
+ {
+ l2 = l1->next;
+ free(l1);
+ }
+ for (l1 = argsresult; l1; l1 = l2)
+ {
+ l2 = l1->next;
+ free(l1);
+ }
+ }
/* initialize lex */
lex_init();
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index d2eec0c0978..43a15394af3 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -16,6 +16,15 @@ struct _include_path { char * path;
extern struct _include_path *include_paths;
+struct cursor { char *name;
+ char *command;
+ struct arguments * argsinsert;
+ struct arguments * argsresult;
+ struct cursor *next;
+ };
+
+extern struct cursor *cur;
+
/* This is a linked list of the variable names and types. */
struct variable
{
@@ -28,6 +37,15 @@ struct variable
extern struct ECPGtype ecpg_no_indicator;
extern struct variable no_indicator;
+struct arguments {
+ struct variable * variable;
+ struct variable * indicator;
+ struct arguments * next;
+};
+
+extern struct arguments * argsinsert;
+extern struct arguments * argsresult;
+
/* functions */
extern void lex_init(void);
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 290440a39f5..4d6960e406b 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -245,14 +245,9 @@ remove_variables(int brace_level)
* These are of two kinds: input and output.
* I will make two lists for them.
*/
-struct arguments {
- struct variable * variable;
- struct variable * indicator;
- struct arguments * next;
-};
-static struct arguments * argsinsert = NULL;
-static struct arguments * argsresult = NULL;
+struct arguments * argsinsert = NULL;
+struct arguments * argsresult = NULL;
static void
reset_variables(void)
@@ -279,7 +274,7 @@ add_variable(struct arguments ** list, struct variable * var, struct variable *
deletes the list as we go on.
*/
static void
-dump_variables(struct arguments * list)
+dump_variables(struct arguments * list, int mode)
{
if (list == NULL)
{
@@ -290,7 +285,7 @@ dump_variables(struct arguments * list)
end of the list:
*/
- dump_variables(list->next);
+ dump_variables(list->next, mode);
/* Then the current element and its indicator */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
@@ -298,7 +293,8 @@ dump_variables(struct arguments * list)
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
/* Then release the list element. */
- free(list);
+ if (mode != 0)
+ free(list);
}
static void
@@ -494,9 +490,9 @@ output_statement(char * stmt, int mode)
fputs("\", ", yyout);
/* dump variables to C file*/
- dump_variables(argsinsert);
+ dump_variables(argsinsert, 1);
fputs("ECPGt_EOIT, ", yyout);
- dump_variables(argsresult);
+ dump_variables(argsresult, 1);
fputs("ECPGt_EORT);", yyout);
whenever_action(mode);
free(stmt);
@@ -737,10 +733,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
| RenameStmt { output_statement($1, 0); }
| RevokeStmt { output_statement($1, 0); }
| OptimizableStmt {
- if (strncmp($1, "ECPGdeclare" , sizeof("ECPGdeclare")-1) == 0)
+ if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
{
fputs($1, yyout);
- whenever_action(0);
free($1);
}
else
@@ -775,7 +770,27 @@ stmt: AddAttrStmt { output_statement($1, 0); }
whenever_action(0);
free($1);
}
- | ECPGOpen { fprintf(yyout, "ECPGopen(__LINE__, %s);", $1);
+ | ECPGOpen {
+ struct cursor *ptr;
+
+ for (ptr = cur; ptr != NULL; ptr=ptr->next)
+ {
+ if (strcmp(ptr->name, $1) == 0)
+ break;
+ }
+
+ if (ptr == NULL)
+ {
+ sprintf(errortext, "trying to open undeclared cursor %s\n", $1);
+ yyerror(errortext);
+ }
+
+ fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
+ /* dump variables to C file*/
+ dump_variables(ptr->argsinsert, 0);
+ fputs("ECPGt_EOIT, ", yyout);
+ dump_variables(ptr->argsresult, 0);
+ fputs("ECPGt_EORT);", yyout);
whenever_action(0);
free($1);
}
@@ -2359,7 +2374,31 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
group_clause having_clause
union_clause sort_clause
{
- $$ = make5_str(make1_str("ECPGdeclare(__LINE__, \""), $2, make1_str("\", \""), cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14), make1_str("\");"));
+ struct cursor *ptr, *this;
+
+ for (ptr = cur; ptr != NULL; ptr = ptr->next)
+ {
+ if (strcmp($2, ptr->name) == 0)
+ {
+ /* re-definition is a bug*/
+ sprintf(errortext, "cursor %s already defined", $2);
+ yyerror(errortext);
+ }
+ }
+
+ this = (struct cursor *) mm_alloc(sizeof(struct cursor));
+
+ /* initial definition */
+ this->next = cur;
+ this->name = $2;
+ this->command = cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14);
+ this->argsinsert = argsinsert;
+ this->argsresult = argsresult;
+ argsinsert = argsresult = NULL;
+
+ cur = this;
+
+ $$ = cat3_str(make1_str("/*"), strdup(this->command), make1_str("*/"));
}
;
@@ -4221,7 +4260,7 @@ execstring: cvariable |
* open is an open cursor, at the moment this has to be removed
*/
ECPGOpen: SQL_OPEN name open_opts {
- $$ = make3_str(make1_str("\""), $2, make1_str("\""));
+ $$ = $2;
};
open_opts: /* empty */ { $$ = make1_str(""); }
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
index 8a7f1f69df4..4e19502fca9 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -1,6 +1,6 @@
all: test1 test2 perftest
-LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
+LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt
test1: test1.c
test1.c: test1.pgc
diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
index 1506dd7bfa9..89d938730b8 100644
--- a/src/interfaces/ecpg/test/test2.pgc
+++ b/src/interfaces/ecpg/test/test2.pgc
@@ -19,6 +19,10 @@ exec sql begin declare section;
long ind_married;
char married[9];
exec sql end declare section;
+
+exec sql declare cur cursor for
+ select name, born, age, married from meskes;
+
char msg[128], command[128];
FILE *dbgs;
@@ -26,7 +30,7 @@ exec sql end declare section;
ECPGdebug(1, dbgs);
strcpy(msg, "connect");
- exec sql connect to tcp:postgresql://localhost:5432/mm;
+ exec sql connect to tcp:postgresql://localhost:5432/mm;
strcpy(msg, "create");
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
@@ -41,10 +45,6 @@ exec sql end declare section;
strcpy(msg, "commit");
exec sql commit;
- strcpy(msg, "declare");
- exec sql declare cur cursor for
- select name, born, age, married from meskes;
-
strcpy(msg, "open");
exec sql open cur;