mirror of
https://github.com/postgres/postgres.git
synced 2025-05-11 05:41:32 +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:
parent
79c8d2e3a0
commit
c6dd1e63a9
@ -270,3 +270,10 @@ Mon Aug 3 17:23:18 CEST 1998
|
|||||||
- Fixed cursor handling
|
- Fixed cursor handling
|
||||||
- Set version to 2.3.5
|
- Set version to 2.3.5
|
||||||
- Set library version to 2.4
|
- 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
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
What happens to a cursor declaration with variables?
|
|
||||||
|
|
||||||
The complete structure definition has to be listed inside the declare
|
The complete structure definition has to be listed inside the declare
|
||||||
section of the structure variable for ecpg to be able to understand it.
|
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
|
The error message for "no data" in an exec sql insert select from statement
|
||||||
has to be 100.
|
has to be 100.
|
||||||
|
@ -13,9 +13,6 @@ bool ECPGdisconnect(int, const char *);
|
|||||||
|
|
||||||
void ECPGlog(const char *format,...);
|
void ECPGlog(const char *format,...);
|
||||||
|
|
||||||
bool ECPGdeclare(int, const char *, char *);
|
|
||||||
bool ECPGopen(int, const char *);
|
|
||||||
|
|
||||||
#ifdef LIBPQ_FE_H
|
#ifdef LIBPQ_FE_H
|
||||||
bool ECPGsetdb(PGconn *);
|
bool ECPGsetdb(PGconn *);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
|
|||||||
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
||||||
|
|
||||||
SO_MAJOR_VERSION=2
|
SO_MAJOR_VERSION=2
|
||||||
SO_MINOR_VERSION=4
|
SO_MINOR_VERSION=5
|
||||||
|
|
||||||
PORTNAME=@PORTNAME@
|
PORTNAME=@PORTNAME@
|
||||||
|
|
||||||
|
@ -33,6 +33,29 @@ static struct connection
|
|||||||
struct connection *next;
|
struct connection *next;
|
||||||
} *all_connections = NULL, *actual_connection = NULL;
|
} *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 int simple_debug = 0;
|
||||||
static FILE *debugstream = NULL;
|
static FILE *debugstream = NULL;
|
||||||
static int committed = true;
|
static int committed = true;
|
||||||
@ -116,27 +139,87 @@ ECPGfinish(struct connection *act)
|
|||||||
ECPGlog("ECPGfinish: called an extra time.\n");
|
ECPGlog("ECPGfinish: called an extra time.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
/* create a list of variables */
|
||||||
ECPGdo(int lineno, char *query,...)
|
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;
|
bool status = false;
|
||||||
char *copiedquery;
|
char *copiedquery;
|
||||||
PGresult *results;
|
PGresult *results;
|
||||||
PGnotify *notify;
|
PGnotify *notify;
|
||||||
enum ECPGttype type;
|
struct variable *var;
|
||||||
void *value = NULL, *ind_value;
|
|
||||||
long varcharsize, ind_varcharsize;
|
|
||||||
long arrsize, ind_arrsize;
|
|
||||||
long offset, ind_offset;
|
|
||||||
enum ECPGttype ind_type;
|
|
||||||
|
|
||||||
memset((char *) &sqlca, 0, sizeof (sqlca));
|
memset((char *) &sqlca, 0, sizeof (sqlca));
|
||||||
va_start(ap, query);
|
|
||||||
|
|
||||||
copiedquery = strdup(query);
|
copiedquery = strdup(stmt->command);
|
||||||
|
|
||||||
type = va_arg(ap, enum ECPGttype);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now, if the type is one of the fill in types then we take the
|
* 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
|
* Then if there are any more fill in types we fill in at the next and
|
||||||
* so on.
|
* so on.
|
||||||
*/
|
*/
|
||||||
while (type != ECPGt_EOIT)
|
var = stmt->inlist;
|
||||||
|
while (var)
|
||||||
{
|
{
|
||||||
char *newcopy;
|
char *newcopy;
|
||||||
char *mallocedval = NULL;
|
char *mallocedval = NULL;
|
||||||
@ -158,34 +242,24 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
* think).
|
* 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';
|
buff[0] = '\0';
|
||||||
|
|
||||||
/* check for null value and set input buffer accordingly */
|
/* check for null value and set input buffer accordingly */
|
||||||
switch (ind_type)
|
switch (var->ind_type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
if (*(short *) ind_value < 0)
|
if (*(short *) var->ind_value < 0)
|
||||||
strcpy(buff, "null");
|
strcpy(buff, "null");
|
||||||
break;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
if (*(int *) ind_value < 0)
|
if (*(int *) var->ind_value < 0)
|
||||||
strcpy(buff, "null");
|
strcpy(buff, "null");
|
||||||
break;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
if (*(long *) ind_value < 0L)
|
if (*(long *) var->ind_value < 0L)
|
||||||
strcpy(buff, "null");
|
strcpy(buff, "null");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -194,42 +268,42 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
if (*buff == '\0')
|
if (*buff == '\0')
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (var->type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
sprintf(buff, "%d", *(int *) value);
|
sprintf(buff, "%d", *(int *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
sprintf(buff, "%d", *(unsigned int *) value);
|
sprintf(buff, "%d", *(unsigned int *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
sprintf(buff, "%ld", *(long *) value);
|
sprintf(buff, "%ld", *(long *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
sprintf(buff, "%ld", *(unsigned long *) value);
|
sprintf(buff, "%ld", *(unsigned long *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_float:
|
case ECPGt_float:
|
||||||
sprintf(buff, "%.14g", *(float *) value);
|
sprintf(buff, "%.14g", *(float *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_double:
|
case ECPGt_double:
|
||||||
sprintf(buff, "%.14g", *(double *) value);
|
sprintf(buff, "%.14g", *(double *) var->value);
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_bool:
|
case ECPGt_bool:
|
||||||
sprintf(buff, "'%c'", (*(char *) value ? 't' : 'f'));
|
sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
|
||||||
tobeinserted = buff;
|
tobeinserted = buff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -237,7 +311,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
case ECPGt_unsigned_char:
|
case ECPGt_unsigned_char:
|
||||||
{
|
{
|
||||||
/* set slen to string length if type is 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;
|
char * tmp;
|
||||||
|
|
||||||
newcopy = (char *) malloc(slen + 1);
|
newcopy = (char *) malloc(slen + 1);
|
||||||
@ -245,11 +319,11 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(newcopy, (char *) value, slen);
|
strncpy(newcopy, (char *) var->value, slen);
|
||||||
newcopy[slen] = '\0';
|
newcopy[slen] = '\0';
|
||||||
|
|
||||||
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
||||||
@ -257,7 +331,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +341,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,28 +356,28 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
case ECPGt_varchar:
|
case ECPGt_varchar:
|
||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *var =
|
struct ECPGgeneric_varchar *variable =
|
||||||
(struct ECPGgeneric_varchar *) value;
|
(struct ECPGgeneric_varchar *) (var->value);
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
newcopy = (char *) malloc(var->len + 1);
|
newcopy = (char *) malloc(variable->len + 1);
|
||||||
if (!newcopy)
|
if (!newcopy)
|
||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(newcopy, var->arr, var->len);
|
strncpy(newcopy, variable->arr, variable->len);
|
||||||
newcopy[var->len] = '\0';
|
newcopy[variable->len] = '\0';
|
||||||
|
|
||||||
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
||||||
if (!mallocedval)
|
if (!mallocedval)
|
||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +387,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +403,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
default:
|
default:
|
||||||
/* Not implemented yet */
|
/* Not implemented yet */
|
||||||
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
|
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
|
||||||
ECPGtype_name(type), lineno);
|
ECPGtype_name(var->type), stmt->lineno);
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -348,7 +422,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGfinish(actual_connection);
|
ECPGfinish(actual_connection);
|
||||||
ECPGlog("out of memory\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +434,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
* We have an argument but we dont have the matched up string
|
* We have an argument but we dont have the matched up string
|
||||||
* in the 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;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -379,7 +453,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Now everything is safely copied to the newcopy. Lets free the
|
* 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)
|
if (mallocedval != NULL)
|
||||||
{
|
{
|
||||||
@ -390,13 +464,13 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
free(copiedquery);
|
free(copiedquery);
|
||||||
copiedquery = newcopy;
|
copiedquery = newcopy;
|
||||||
|
|
||||||
type = va_arg(ap, enum ECPGttype);
|
var = var->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there are unmatched things left. */
|
/* Check if there are unmatched things left. */
|
||||||
if (strstr(copiedquery, ";;") != NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,27 +480,28 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
committed = 0;
|
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);
|
results = PQexec(actual_connection->connection, copiedquery);
|
||||||
free(copiedquery);
|
free(copiedquery);
|
||||||
|
|
||||||
if (results == NULL)
|
if (results == NULL)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
|
||||||
PQerrorMessage(actual_connection->connection));
|
PQerrorMessage(actual_connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
||||||
PQerrorMessage(actual_connection->connection), lineno);
|
PQerrorMessage(actual_connection->connection), stmt->lineno);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sqlca.sqlerrd[2] = 0;
|
sqlca.sqlerrd[2] = 0;
|
||||||
|
var = stmt->outlist;
|
||||||
switch (PQresultStatus(results))
|
switch (PQresultStatus(results))
|
||||||
{
|
{
|
||||||
int nfields, ntuples, act_tuple, act_field;
|
int nfields, ntuples, act_tuple, act_field;
|
||||||
@ -445,9 +520,9 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
if (ntuples < 1)
|
if (ntuples < 1)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
|
ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
|
||||||
lineno, ntuples);
|
stmt->lineno, ntuples);
|
||||||
register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
|
register_error(ECPG_NOT_FOUND, "Data not found line %d.", stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -457,23 +532,19 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
char *pval;
|
char *pval;
|
||||||
char *scan_length;
|
char *scan_length;
|
||||||
|
|
||||||
type = va_arg(ap, enum ECPGttype);
|
if (var == NULL)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n",
|
ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
|
||||||
lineno, ntuples, arrsize);
|
register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
|
||||||
register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", 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;
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -481,31 +552,31 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
pval = PQgetvalue(results, act_tuple, act_field);
|
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. */
|
/* Now the pval is a pointer to the var->value. */
|
||||||
/* We will have to decode the value */
|
/* We will have to decode the var->value */
|
||||||
|
|
||||||
/* check for null value and set indicator accordingly */
|
/* check for null var->value and set indicator accordingly */
|
||||||
switch (ind_type)
|
switch (var->ind_type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_unsigned_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;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
case ECPGt_unsigned_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;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
case ECPGt_unsigned_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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
switch (var->type)
|
||||||
{
|
{
|
||||||
long res;
|
long res;
|
||||||
unsigned long ures;
|
unsigned long ures;
|
||||||
@ -520,7 +591,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
if (*scan_length != '\0') /* Garbage left */
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
{
|
{
|
||||||
register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
|
register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
|
||||||
pval, lineno);
|
pval, stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
res = 0L;
|
res = 0L;
|
||||||
}
|
}
|
||||||
@ -529,16 +600,16 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
res = 0L;
|
res = 0L;
|
||||||
|
|
||||||
/* Again?! Yes */
|
/* Again?! Yes */
|
||||||
switch (type)
|
switch (var->type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
((short *) value)[act_tuple] = (short) res;
|
((short *) var->value)[act_tuple] = (short) res;
|
||||||
break;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
((int *) value)[act_tuple] = (int) res;
|
((int *) var->value)[act_tuple] = (int) res;
|
||||||
break;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
((long *) value)[act_tuple] = res;
|
((long *) var->value)[act_tuple] = res;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Cannot happen */
|
/* Cannot happen */
|
||||||
@ -555,7 +626,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
if (*scan_length != '\0') /* Garbage left */
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
{
|
{
|
||||||
register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
|
register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
|
||||||
pval, lineno);
|
pval, stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
ures = 0L;
|
ures = 0L;
|
||||||
}
|
}
|
||||||
@ -564,16 +635,16 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
ures = 0L;
|
ures = 0L;
|
||||||
|
|
||||||
/* Again?! Yes */
|
/* Again?! Yes */
|
||||||
switch (type)
|
switch (var->type)
|
||||||
{
|
{
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
((unsigned short *) value)[act_tuple] = (unsigned short) ures;
|
((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
|
||||||
break;
|
break;
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
((unsigned int *) value)[act_tuple] = (unsigned int) ures;
|
((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
|
||||||
break;
|
break;
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
((unsigned long *) value)[act_tuple] = ures;
|
((unsigned long *) var->value)[act_tuple] = ures;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Cannot happen */
|
/* Cannot happen */
|
||||||
@ -590,7 +661,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
if (*scan_length != '\0') /* Garbage left */
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
{
|
{
|
||||||
register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
|
register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
|
||||||
pval, lineno);
|
pval, stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
dres = 0.0;
|
dres = 0.0;
|
||||||
}
|
}
|
||||||
@ -599,13 +670,13 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
dres = 0.0;
|
dres = 0.0;
|
||||||
|
|
||||||
/* Again?! Yes */
|
/* Again?! Yes */
|
||||||
switch (type)
|
switch (var->type)
|
||||||
{
|
{
|
||||||
case ECPGt_float:
|
case ECPGt_float:
|
||||||
((float *) value)[act_tuple] = dres;
|
((float *) var->value)[act_tuple] = dres;
|
||||||
break;
|
break;
|
||||||
case ECPGt_double:
|
case ECPGt_double:
|
||||||
((double *) value)[act_tuple] = dres;
|
((double *) var->value)[act_tuple] = dres;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Cannot happen */
|
/* Cannot happen */
|
||||||
@ -618,50 +689,50 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
if (pval[0] == 'f' && pval[1] == '\0')
|
if (pval[0] == 'f' && pval[1] == '\0')
|
||||||
{
|
{
|
||||||
((char *) value)[act_tuple] = false;
|
((char *) var->value)[act_tuple] = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (pval[0] == 't' && pval[1] == '\0')
|
else if (pval[0] == 't' && pval[1] == '\0')
|
||||||
{
|
{
|
||||||
((char *) value)[act_tuple] = true;
|
((char *) var->value)[act_tuple] = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
|
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
|
||||||
(pval ? pval : "NULL"),
|
(pval ? pval : "NULL"),
|
||||||
lineno);
|
stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_char:
|
case ECPGt_char:
|
||||||
case ECPGt_unsigned_char:
|
case ECPGt_unsigned_char:
|
||||||
{
|
{
|
||||||
if (varcharsize == 0)
|
if (var->varcharsize == 0)
|
||||||
{
|
{
|
||||||
/* char* */
|
/* char* */
|
||||||
strncpy(((char **) value)[act_tuple], pval, strlen(pval));
|
strncpy(((char **) var->value)[act_tuple], pval, strlen(pval));
|
||||||
(((char **) value)[act_tuple])[strlen(pval)] = '\0';
|
(((char **) var->value)[act_tuple])[strlen(pval)] = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
|
strncpy((char *) (var->value + var->offset * act_tuple), pval, var->varcharsize);
|
||||||
if (varcharsize < strlen(pval))
|
if (var->varcharsize < strlen(pval))
|
||||||
{
|
{
|
||||||
/* truncation */
|
/* truncation */
|
||||||
switch (ind_type)
|
switch (var->ind_type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
((short *) ind_value)[act_tuple] = varcharsize;
|
((short *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
((int *) ind_value)[act_tuple] = varcharsize;
|
((int *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
((long *) ind_value)[act_tuple] = varcharsize;
|
((long *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -674,62 +745,55 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
case ECPGt_varchar:
|
case ECPGt_varchar:
|
||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *var =
|
struct ECPGgeneric_varchar *variable =
|
||||||
(struct ECPGgeneric_varchar *) (value + offset * act_tuple);
|
(struct ECPGgeneric_varchar *) (var->value + var->offset * act_tuple);
|
||||||
|
|
||||||
if (varcharsize == 0)
|
if (var->varcharsize == 0)
|
||||||
strncpy(var->arr, pval, strlen(pval));
|
strncpy(variable->arr, pval, strlen(pval));
|
||||||
else
|
else
|
||||||
strncpy(var->arr, pval, varcharsize);
|
strncpy(variable->arr, pval, var->varcharsize);
|
||||||
|
|
||||||
var->len = strlen(pval);
|
variable->len = strlen(pval);
|
||||||
if (varcharsize > 0 && var->len > varcharsize)
|
if (var->varcharsize > 0 && variable->len > var->varcharsize)
|
||||||
{
|
{
|
||||||
/* truncation */
|
/* truncation */
|
||||||
switch (ind_type)
|
switch (var->ind_type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
((short *) ind_value)[act_tuple] = varcharsize;
|
((short *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
((int *) ind_value)[act_tuple] = varcharsize;
|
((int *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
((long *) ind_value)[act_tuple] = varcharsize;
|
((long *) var->ind_value)[act_tuple] = var->varcharsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
|
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
|
||||||
|
|
||||||
var->len = varcharsize;
|
variable->len = var->varcharsize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
|
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
|
||||||
ECPGtype_name(type), lineno);
|
ECPGtype_name(var->type), stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var = var->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = va_arg(ap, enum ECPGttype);
|
if (status && var != NULL)
|
||||||
|
|
||||||
if (status && type != ECPGt_EORT)
|
|
||||||
{
|
{
|
||||||
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;
|
status = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,35 +801,34 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
break;
|
break;
|
||||||
case PGRES_EMPTY_QUERY:
|
case PGRES_EMPTY_QUERY:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
|
register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
|
||||||
break;
|
break;
|
||||||
case PGRES_COMMAND_OK:
|
case PGRES_COMMAND_OK:
|
||||||
status = true;
|
status = true;
|
||||||
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
|
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
|
||||||
ECPGlog("TEST: %s\n", PQcmdTuples(results));
|
ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
|
||||||
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
|
|
||||||
break;
|
break;
|
||||||
case PGRES_NONFATAL_ERROR:
|
case PGRES_NONFATAL_ERROR:
|
||||||
case PGRES_FATAL_ERROR:
|
case PGRES_FATAL_ERROR:
|
||||||
case PGRES_BAD_RESPONSE:
|
case PGRES_BAD_RESPONSE:
|
||||||
ECPGlog("ECPGdo line %d: Error: %s",
|
ECPGlog("ECPGexecute line %d: Error: %s",
|
||||||
lineno, PQerrorMessage(actual_connection->connection));
|
stmt->lineno, PQerrorMessage(actual_connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Error: %s line %d.",
|
register_error(ECPG_PGSQL, "Error: %s line %d.",
|
||||||
PQerrorMessage(actual_connection->connection), lineno);
|
PQerrorMessage(actual_connection->connection), stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_OUT:
|
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);
|
PQendcopy(results->conn);
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_IN:
|
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);
|
PQendcopy(results->conn);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
|
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
|
||||||
lineno);
|
stmt->lineno);
|
||||||
register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
|
register_error(ECPG_PGSQL, "Postgres error line %d.", stmt->lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -775,8 +838,8 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
notify = PQnotifies(actual_connection->connection);
|
notify = PQnotifies(actual_connection->connection);
|
||||||
if (notify)
|
if (notify)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||||
lineno, notify->relname, notify->be_pid);
|
stmt->lineno, notify->relname, notify->be_pid);
|
||||||
free(notify);
|
free(notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,6 +847,20 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
return status;
|
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
|
bool
|
||||||
ECPGtrans(int lineno, const char * transaction)
|
ECPGtrans(int lineno, const char * transaction)
|
||||||
@ -940,56 +1017,3 @@ sqlprint(void)
|
|||||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
||||||
printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
|
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);
|
|
||||||
}
|
|
||||||
|
@ -23,6 +23,7 @@ extern char *optarg;
|
|||||||
|
|
||||||
struct _include_path *include_paths;
|
struct _include_path *include_paths;
|
||||||
static int no_auto_trans = 0;
|
static int no_auto_trans = 0;
|
||||||
|
struct cursor *cur = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(char *progname)
|
usage(char *progname)
|
||||||
@ -138,6 +139,24 @@ main(int argc, char *const argv[])
|
|||||||
{
|
{
|
||||||
struct cursor *ptr;
|
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 */
|
/* initialize lex */
|
||||||
lex_init();
|
lex_init();
|
||||||
|
|
||||||
|
@ -16,6 +16,15 @@ struct _include_path { char * path;
|
|||||||
|
|
||||||
extern struct _include_path *include_paths;
|
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. */
|
/* This is a linked list of the variable names and types. */
|
||||||
struct variable
|
struct variable
|
||||||
{
|
{
|
||||||
@ -28,6 +37,15 @@ struct variable
|
|||||||
extern struct ECPGtype ecpg_no_indicator;
|
extern struct ECPGtype ecpg_no_indicator;
|
||||||
extern struct variable 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 */
|
/* functions */
|
||||||
|
|
||||||
extern void lex_init(void);
|
extern void lex_init(void);
|
||||||
|
@ -245,14 +245,9 @@ remove_variables(int brace_level)
|
|||||||
* These are of two kinds: input and output.
|
* These are of two kinds: input and output.
|
||||||
* I will make two lists for them.
|
* I will make two lists for them.
|
||||||
*/
|
*/
|
||||||
struct arguments {
|
|
||||||
struct variable * variable;
|
|
||||||
struct variable * indicator;
|
|
||||||
struct arguments * next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct arguments * argsinsert = NULL;
|
struct arguments * argsinsert = NULL;
|
||||||
static struct arguments * argsresult = NULL;
|
struct arguments * argsresult = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reset_variables(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.
|
deletes the list as we go on.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
dump_variables(struct arguments * list)
|
dump_variables(struct arguments * list, int mode)
|
||||||
{
|
{
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
{
|
{
|
||||||
@ -290,7 +285,7 @@ dump_variables(struct arguments * list)
|
|||||||
end of the list:
|
end of the list:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dump_variables(list->next);
|
dump_variables(list->next, mode);
|
||||||
|
|
||||||
/* Then the current element and its indicator */
|
/* Then the current element and its indicator */
|
||||||
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
|
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);
|
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
|
||||||
|
|
||||||
/* Then release the list element. */
|
/* Then release the list element. */
|
||||||
free(list);
|
if (mode != 0)
|
||||||
|
free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -494,9 +490,9 @@ output_statement(char * stmt, int mode)
|
|||||||
fputs("\", ", yyout);
|
fputs("\", ", yyout);
|
||||||
|
|
||||||
/* dump variables to C file*/
|
/* dump variables to C file*/
|
||||||
dump_variables(argsinsert);
|
dump_variables(argsinsert, 1);
|
||||||
fputs("ECPGt_EOIT, ", yyout);
|
fputs("ECPGt_EOIT, ", yyout);
|
||||||
dump_variables(argsresult);
|
dump_variables(argsresult, 1);
|
||||||
fputs("ECPGt_EORT);", yyout);
|
fputs("ECPGt_EORT);", yyout);
|
||||||
whenever_action(mode);
|
whenever_action(mode);
|
||||||
free(stmt);
|
free(stmt);
|
||||||
@ -737,10 +733,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
|
|||||||
| RenameStmt { output_statement($1, 0); }
|
| RenameStmt { output_statement($1, 0); }
|
||||||
| RevokeStmt { output_statement($1, 0); }
|
| RevokeStmt { output_statement($1, 0); }
|
||||||
| OptimizableStmt {
|
| OptimizableStmt {
|
||||||
if (strncmp($1, "ECPGdeclare" , sizeof("ECPGdeclare")-1) == 0)
|
if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
|
||||||
{
|
{
|
||||||
fputs($1, yyout);
|
fputs($1, yyout);
|
||||||
whenever_action(0);
|
|
||||||
free($1);
|
free($1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -775,7 +770,27 @@ stmt: AddAttrStmt { output_statement($1, 0); }
|
|||||||
whenever_action(0);
|
whenever_action(0);
|
||||||
free($1);
|
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);
|
whenever_action(0);
|
||||||
free($1);
|
free($1);
|
||||||
}
|
}
|
||||||
@ -2359,7 +2374,31 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
|
|||||||
group_clause having_clause
|
group_clause having_clause
|
||||||
union_clause sort_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
|
* open is an open cursor, at the moment this has to be removed
|
||||||
*/
|
*/
|
||||||
ECPGOpen: SQL_OPEN name open_opts {
|
ECPGOpen: SQL_OPEN name open_opts {
|
||||||
$$ = make3_str(make1_str("\""), $2, make1_str("\""));
|
$$ = $2;
|
||||||
};
|
};
|
||||||
|
|
||||||
open_opts: /* empty */ { $$ = make1_str(""); }
|
open_opts: /* empty */ { $$ = make1_str(""); }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
all: test1 test2 perftest
|
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: test1.c
|
||||||
test1.c: test1.pgc
|
test1.c: test1.pgc
|
||||||
|
@ -19,6 +19,10 @@ exec sql begin declare section;
|
|||||||
long ind_married;
|
long ind_married;
|
||||||
char married[9];
|
char married[9];
|
||||||
exec sql end declare section;
|
exec sql end declare section;
|
||||||
|
|
||||||
|
exec sql declare cur cursor for
|
||||||
|
select name, born, age, married from meskes;
|
||||||
|
|
||||||
char msg[128], command[128];
|
char msg[128], command[128];
|
||||||
FILE *dbgs;
|
FILE *dbgs;
|
||||||
|
|
||||||
@ -26,7 +30,7 @@ exec sql end declare section;
|
|||||||
ECPGdebug(1, dbgs);
|
ECPGdebug(1, dbgs);
|
||||||
|
|
||||||
strcpy(msg, "connect");
|
strcpy(msg, "connect");
|
||||||
exec sql connect to tcp:postgresql://localhost:5432/mm;
|
exec sql connect to tcp:postgresql://localhost:5432/mm;
|
||||||
|
|
||||||
strcpy(msg, "create");
|
strcpy(msg, "create");
|
||||||
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
|
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");
|
strcpy(msg, "commit");
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
|
|
||||||
strcpy(msg, "declare");
|
|
||||||
exec sql declare cur cursor for
|
|
||||||
select name, born, age, married from meskes;
|
|
||||||
|
|
||||||
strcpy(msg, "open");
|
strcpy(msg, "open");
|
||||||
exec sql open cur;
|
exec sql open cur;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user