提交 9f09e836 编写于 作者: M Michael Meskes

- Fixed truncate bug.

        - Added patch by Christof Petig <christof.petig@wtal.de> to
clean up
ecpglib.
上级 8ae8ddbb
...@@ -1101,5 +1101,11 @@ Tue Sep 25 20:10:03 CEST 2001 ...@@ -1101,5 +1101,11 @@ Tue Sep 25 20:10:03 CEST 2001
- Synced preproc.y with gram.y. - Synced preproc.y with gram.y.
- Changed locale handling. - Changed locale handling.
Mon Okt 1 13:49:40 CEST 2001
- Fixed truncate bug.
- Added patch by Christof Petig <christof.petig@wtal.de> to clean up
ecpglib.
- Set ecpg version to 2.9.0. - Set ecpg version to 2.9.0.
- Set library version to 3.3.0. - Set library version to 3.3.0.
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.15 2001/09/19 14:09:32 meskes Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.16 2001/10/01 12:02:28 meskes Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "sqlca.h" #include "sqlca.h"
bool bool
get_data(PGresult *results, int act_tuple, int act_field, int lineno, get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
enum ECPGttype type, enum ECPGttype ind_type, enum ECPGttype type, enum ECPGttype ind_type,
void *var, void *ind, long varcharsize, long offset, void *var, void *ind, long varcharsize, long offset,
bool isarray) bool isarray)
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.25 2001/09/29 20:12:07 tgl Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.26 2001/10/01 12:02:28 meskes Exp $ */
/* /*
* The aim is to get a simpler inteface to the database routines. * The aim is to get a simpler inteface to the database routines.
...@@ -370,40 +370,107 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia ...@@ -370,40 +370,107 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
return isarray; return isarray;
} }
static bool
ECPGexecute(struct statement * stmt)
{
bool status = false;
char *copiedquery;
PGresult *results;
PGnotify *notify;
struct variable *var;
copiedquery = ecpg_strdup(stmt->command, stmt->lineno); bool
ECPGstore_result(const PGresult *results, int act_field,
const struct statement * stmt, struct variable *var)
{ int isarray,
act_tuple,
ntuples = PQntuples(results);
bool status = true;
isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var);
/* if (!isarray)
* Now, if the type is one of the fill in types then we take the {
* argument and enter that in the string at the first %s position.
* Then if there are any more fill in types we fill in at the next and /*
* so on. * if we don't have enough space, we cannot read
*/ * all tuples
var = stmt->inlist; */
while (var) if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
{ {
char *newcopy; ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
stmt->lineno, ntuples, var->arrsize);
ECPGraise(stmt->lineno, ECPG_TOO_MANY_MATCHES, NULL);
return false;
}
}
else
{
/*
* since we read an array, the variable has to be
* an array too
*/
if (var->arrsize == 0)
{
ECPGlog("ECPGexecute line %d: variable is not an array\n");
ECPGraise(stmt->lineno, ECPG_NO_ARRAY, NULL);
return false;
}
}
/*
* allocate memory for NULL pointers
*/
if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
{
int len = 0;
switch (var->type)
{
case ECPGt_char:
case ECPGt_unsigned_char:
var->varcharsize = 0;
/* check strlen for each tuple */
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
{
int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
if (len > var->varcharsize)
var->varcharsize = len;
}
var->offset *= var->varcharsize;
len = var->offset * ntuples;
break;
case ECPGt_varchar:
len = ntuples * (var->varcharsize + sizeof(int));
break;
default:
len = var->offset * ntuples;
break;
}
var->value = (void *) ecpg_alloc(len, stmt->lineno);
*((void **) var->pointer) = var->value;
add_mem(var->value, stmt->lineno);
}
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
{
if (!get_data(results, act_tuple, act_field, stmt->lineno,
var->type, var->ind_type, var->value,
var->ind_value, var->varcharsize, var->offset, isarray))
status = false;
}
return status;
}
static bool
ECPGstore_input(const struct statement * stmt, const struct variable *var,
const char **tobeinserted_p, bool *malloced_p)
{
char *mallocedval = NULL; char *mallocedval = NULL;
char *tobeinserted = NULL; char *newcopy = NULL;
char *p;
char buff[20];
int hostvarl = 0;
/* /*
* Some special treatment is needed for records since we want * Some special treatment is needed for records since we want
* their contents to arrive in a comma-separated list on insert (I * their contents to arrive in a comma-separated list on insert (I
* think). * think).
*/ */
buff[0] = '\0'; *malloced_p=false;
*tobeinserted_p="";
/* check for null value and set input buffer accordingly */ /* check for null value and set input buffer accordingly */
switch (var->ind_type) switch (var->ind_type)
...@@ -411,30 +478,30 @@ ECPGexecute(struct statement * stmt) ...@@ -411,30 +478,30 @@ ECPGexecute(struct statement * stmt)
case ECPGt_short: case ECPGt_short:
case ECPGt_unsigned_short: case ECPGt_unsigned_short:
if (*(short *) var->ind_value < 0) if (*(short *) var->ind_value < 0)
strcpy(buff, "null"); *tobeinserted_p="null";
break; break;
case ECPGt_int: case ECPGt_int:
case ECPGt_unsigned_int: case ECPGt_unsigned_int:
if (*(int *) var->ind_value < 0) if (*(int *) var->ind_value < 0)
strcpy(buff, "null"); *tobeinserted_p="null";
break; break;
case ECPGt_long: case ECPGt_long:
case ECPGt_unsigned_long: case ECPGt_unsigned_long:
if (*(long *) var->ind_value < 0L) if (*(long *) var->ind_value < 0L)
strcpy(buff, "null"); *tobeinserted_p="null";
break; break;
#ifdef HAVE_LONG_LONG_INT_64 #ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long: case ECPGt_long_long:
case ECPGt_unsigned_long_long: case ECPGt_unsigned_long_long:
if (*(long long int *) var->ind_value < (long long) 0) if (*(long long int *) var->ind_value < (long long) 0)
strcpy(buff, "null"); *tobeinserted_p="null";
break; break;
#endif /* HAVE_LONG_LONG_INT_64 */ #endif /* HAVE_LONG_LONG_INT_64 */
default: default:
break; break;
} }
if (*buff == '\0') if (**tobeinserted_p == '\0')
{ {
switch (var->type) switch (var->type)
{ {
...@@ -456,7 +523,8 @@ ECPGexecute(struct statement * stmt) ...@@ -456,7 +523,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%hd", *((short *) var->value)); sprintf(mallocedval, "%hd", *((short *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_int: case ECPGt_int:
...@@ -475,7 +543,8 @@ ECPGexecute(struct statement * stmt) ...@@ -475,7 +543,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%d", *((int *) var->value)); sprintf(mallocedval, "%d", *((int *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_unsigned_short: case ECPGt_unsigned_short:
...@@ -494,7 +563,8 @@ ECPGexecute(struct statement * stmt) ...@@ -494,7 +563,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%hu", *((unsigned short *) var->value)); sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_unsigned_int: case ECPGt_unsigned_int:
...@@ -513,7 +583,8 @@ ECPGexecute(struct statement * stmt) ...@@ -513,7 +583,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%u", *((unsigned int *) var->value)); sprintf(mallocedval, "%u", *((unsigned int *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_long: case ECPGt_long:
...@@ -532,7 +603,8 @@ ECPGexecute(struct statement * stmt) ...@@ -532,7 +603,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%ld", *((long *) var->value)); sprintf(mallocedval, "%ld", *((long *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_unsigned_long: case ECPGt_unsigned_long:
...@@ -551,7 +623,8 @@ ECPGexecute(struct statement * stmt) ...@@ -551,7 +623,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%lu", *((unsigned long *) var->value)); sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
#ifdef HAVE_LONG_LONG_INT_64 #ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long: case ECPGt_long_long:
...@@ -570,7 +643,8 @@ ECPGexecute(struct statement * stmt) ...@@ -570,7 +643,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%lld", *((long long *) var->value)); sprintf(mallocedval, "%lld", *((long long *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_unsigned_long_long: case ECPGt_unsigned_long_long:
...@@ -589,7 +663,8 @@ ECPGexecute(struct statement * stmt) ...@@ -589,7 +663,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%llu", *((unsigned long long *) var->value)); sprintf(mallocedval, "%llu", *((unsigned long long *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
#endif /* HAVE_LONG_LONG_INT_64 */ #endif /* HAVE_LONG_LONG_INT_64 */
case ECPGt_float: case ECPGt_float:
...@@ -608,7 +683,8 @@ ECPGexecute(struct statement * stmt) ...@@ -608,7 +683,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%.14g", *((float *) var->value)); sprintf(mallocedval, "%.14g", *((float *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_double: case ECPGt_double:
...@@ -627,7 +703,8 @@ ECPGexecute(struct statement * stmt) ...@@ -627,7 +703,8 @@ ECPGexecute(struct statement * stmt)
else else
sprintf(mallocedval, "%.14g", *((double *) var->value)); sprintf(mallocedval, "%.14g", *((double *) var->value));
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_bool: case ECPGt_bool:
...@@ -664,7 +741,8 @@ ECPGexecute(struct statement * stmt) ...@@ -664,7 +741,8 @@ ECPGexecute(struct statement * stmt)
ECPGraise(stmt->lineno, ECPG_CONVERT_BOOL, "different size"); ECPGraise(stmt->lineno, ECPG_CONVERT_BOOL, "different size");
} }
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
break; break;
case ECPGt_char: case ECPGt_char:
...@@ -685,7 +763,8 @@ ECPGexecute(struct statement * stmt) ...@@ -685,7 +763,8 @@ ECPGexecute(struct statement * stmt)
free(newcopy); free(newcopy);
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
} }
break; break;
case ECPGt_char_variable: case ECPGt_char_variable:
...@@ -698,7 +777,8 @@ ECPGexecute(struct statement * stmt) ...@@ -698,7 +777,8 @@ ECPGexecute(struct statement * stmt)
strncpy(mallocedval, (char *) var->value, slen); strncpy(mallocedval, (char *) var->value, slen);
mallocedval[slen] = '\0'; mallocedval[slen] = '\0';
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
} }
break; break;
case ECPGt_varchar: case ECPGt_varchar:
...@@ -718,7 +798,8 @@ ECPGexecute(struct statement * stmt) ...@@ -718,7 +798,8 @@ ECPGexecute(struct statement * stmt)
free(newcopy); free(newcopy);
tobeinserted = mallocedval; *tobeinserted_p = mallocedval;
*malloced_p = true;
} }
break; break;
...@@ -729,9 +810,38 @@ ECPGexecute(struct statement * stmt) ...@@ -729,9 +810,38 @@ ECPGexecute(struct statement * stmt)
break; break;
} }
} }
else return true;
tobeinserted = buff; }
static bool
ECPGexecute(struct statement * stmt)
{
bool status = false;
char *copiedquery;
PGresult *results;
PGnotify *notify;
struct variable *var;
copiedquery = ecpg_strdup(stmt->command, stmt->lineno);
/*
* Now, if the type is one of the fill in types then we take the
* argument and enter that in the string at the first %s position.
* Then if there are any more fill in types we fill in at the next and
* so on.
*/
var = stmt->inlist;
while (var)
{
char *newcopy = NULL;
const char *tobeinserted = NULL;
char *p;
bool malloced=FALSE;
int hostvarl = 0;
if (!ECPGstore_input(stmt, var, &tobeinserted, &malloced))
return false;
/* /*
* Now tobeinserted points to an area that is to be inserted at * Now tobeinserted points to an area that is to be inserted at
* the first %s * the first %s
...@@ -770,10 +880,10 @@ ECPGexecute(struct statement * stmt) ...@@ -770,10 +880,10 @@ ECPGexecute(struct statement * stmt)
* oldcopy and let the copiedquery get the var->value from the * oldcopy and let the copiedquery get the var->value from the
* newcopy. * newcopy.
*/ */
if (mallocedval != NULL) if (malloced)
{ {
free(mallocedval); free((char*)tobeinserted);
mallocedval = NULL; tobeinserted = NULL;
} }
free(copiedquery); free(copiedquery);
...@@ -823,9 +933,7 @@ ECPGexecute(struct statement * stmt) ...@@ -823,9 +933,7 @@ ECPGexecute(struct statement * stmt)
{ {
int nfields, int nfields,
ntuples, ntuples,
act_tuple, act_field;
act_field,
isarray;
case PGRES_TUPLES_OK: case PGRES_TUPLES_OK:
nfields = PQnfields(results); nfields = PQnfields(results);
...@@ -861,83 +969,9 @@ ECPGexecute(struct statement * stmt) ...@@ -861,83 +969,9 @@ ECPGexecute(struct statement * stmt)
ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL); ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL);
return (false); return (false);
} }
status = ECPGstore_result(results, act_field, stmt, var);
isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var);
if (!isarray)
{
/*
* 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);
ECPGraise(stmt->lineno, ECPG_TOO_MANY_MATCHES, NULL);
status = false;
break;
}
}
else
{
/*
* since we read an array, the variable has to be
* an array too
*/
if (var->arrsize == 0)
{
ECPGlog("ECPGexecute line %d: variable is not an array\n");
ECPGraise(stmt->lineno, ECPG_NO_ARRAY, NULL);
status = false;
break;
}
}
/*
* allocate memory for NULL pointers
*/
if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
{
int len = 0;
switch (var->type)
{
case ECPGt_char:
case ECPGt_unsigned_char:
var->varcharsize = 0;
/* check strlen for each tuple */
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
{
int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
if (len > var->varcharsize)
var->varcharsize = len;
}
var->offset *= var->varcharsize;
len = var->offset * ntuples;
break;
case ECPGt_varchar:
len = ntuples * (var->varcharsize + sizeof(int));
break;
default:
len = var->offset * ntuples;
break;
}
var->value = (void *) ecpg_alloc(len, stmt->lineno);
*((void **) var->pointer) = var->value;
add_mem(var->value, stmt->lineno);
}
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
{
if (!get_data(results, act_tuple, act_field, stmt->lineno,
var->type, var->ind_type, var->value,
var->ind_value, var->varcharsize, var->offset, isarray))
status = false;
}
var = var->next; var = var->next;
} }
...@@ -1006,26 +1040,23 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) ...@@ -1006,26 +1040,23 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
va_list args; va_list args;
struct statement *stmt; struct statement *stmt;
struct connection *con = get_connection(connection_name); struct connection *con = get_connection(connection_name);
bool status; bool status = true;
char *oldlocale; char *locale;
/* Make sure we do NOT honor the locale for numeric input/output */ /* Make sure we do NOT honor the locale for numeric input/output */
/* since the database wants the standard decimal point */ /* since the database wants the standard decimal point */
oldlocale = strdup(setlocale(LC_NUMERIC, NULL)); locale = setlocale(LC_NUMERIC, "C");
setlocale(LC_NUMERIC, "C");
if (!ecpg_init(con, connection_name, lineno)) if (!ecpg_init(con, connection_name, lineno))
{ {
setlocale(LC_NUMERIC, oldlocale); setlocale(LC_NUMERIC, locale);
free(oldlocale);
return (false); return (false);
} }
va_start(args, query); va_start(args, query);
if (create_statement(lineno, con, &stmt, query, args) == false) if (create_statement(lineno, con, &stmt, query, args) == false)
{ {
setlocale(LC_NUMERIC, oldlocale); setlocale(LC_NUMERIC, locale);
free(oldlocale);
return (false); return (false);
} }
va_end(args); va_end(args);
...@@ -1036,8 +1067,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) ...@@ -1036,8 +1067,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
free_statement(stmt); free_statement(stmt);
ECPGlog("ECPGdo: not connected to %s\n", con->name); ECPGlog("ECPGdo: not connected to %s\n", con->name);
ECPGraise(lineno, ECPG_NOT_CONN, NULL); ECPGraise(lineno, ECPG_NOT_CONN, NULL);
setlocale(LC_NUMERIC, oldlocale); setlocale(LC_NUMERIC, locale);
free(oldlocale);
return false; return false;
} }
...@@ -1045,9 +1075,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) ...@@ -1045,9 +1075,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
free_statement(stmt); free_statement(stmt);
/* and reset locale value so our application is not affected */ /* and reset locale value so our application is not affected */
setlocale(LC_NUMERIC, oldlocale); setlocale(LC_NUMERIC, locale);
free(oldlocale);
return (status); return (status);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* Here are some methods used by the lib. */ /* Here are some methods used by the lib. */
/* Returns a pointer to a string containing a simple type name. */ /* Returns a pointer to a string containing a simple type name. */
void free_auto_mem(void); void free_auto_mem(void);
bool get_data(PGresult *, int, int, int, enum ECPGttype type, bool get_data(const PGresult *, int, int, int, enum ECPGttype type,
enum ECPGttype, void *, void *, long, long, bool); enum ECPGttype, void *, void *, long, long, bool);
struct connection *get_connection(const char *); struct connection *get_connection(const char *);
void init_sqlca(void); void init_sqlca(void);
...@@ -14,6 +14,7 @@ char *ecpg_strdup(const char *, int); ...@@ -14,6 +14,7 @@ char *ecpg_strdup(const char *, int);
const char *ECPGtype_name(enum ECPGttype); const char *ECPGtype_name(enum ECPGttype);
unsigned int ECPGDynamicType(Oid); unsigned int ECPGDynamicType(Oid);
/* A generic varchar type. */ /* A generic varchar type. */
struct ECPGgeneric_varchar struct ECPGgeneric_varchar
{ {
...@@ -63,3 +64,7 @@ struct descriptor ...@@ -63,3 +64,7 @@ struct descriptor
PGresult ** PGresult **
ECPGdescriptor_lvalue(int line, const char *descriptor); ECPGdescriptor_lvalue(int line, const char *descriptor);
bool
ECPGstore_result(const PGresult *results, int act_field,
const struct statement * stmt, struct variable *var);
...@@ -1552,7 +1552,7 @@ drop_type: TABLE { $$ = make_str("table"); } ...@@ -1552,7 +1552,7 @@ drop_type: TABLE { $$ = make_str("table"); }
*****************************************************************************/ *****************************************************************************/
TruncateStmt: TRUNCATE opt_table relation_name TruncateStmt: TRUNCATE opt_table relation_name
{ {
$$ = cat2_str(make_str("drop table"), $3); $$ = cat2_str(make_str("truncate table"), $3);
} }
; ;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册