1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

This one cleans the cursor problems ecpg had so far. It is now able

to understand cursors with variables.

Michael
This commit is contained in:
Bruce Momjian
1998-08-11 18:33:37 +00:00
parent 79c8d2e3a0
commit c6dd1e63a9
10 changed files with 334 additions and 232 deletions

View File

@@ -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 we don't have enough space, we cannot read all tuples */
if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize))
if (var == NULL)
{
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: 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 ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
{
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);
}