-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.20 2003/09/20 09:10:09 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.21 2003/11/08 19:46:27 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include "pgtypes_timestamp.h"
#include "pgtypes_interval.h"
+static bool garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
+{
+ /* INFORMIX allows for selecting a numeric into an int, the result is truncated */
+ if (isarray == ECPG_ARRAY_NONE && INFORMIX_MODE(compat) && *scan_length == '.')
+ return false;
+
+ if (isarray == ECPG_ARRAY_ARRAY && *scan_length != ',' && *scan_length != '}')
+ return true;
+
+ if (isarray == ECPG_ARRAY_VECTOR && *scan_length != ' ' && *scan_length != '\0')
+ return true;
+
+ if (isarray == ECPG_ARRAY_NONE && *scan_length != ' ' && *scan_length != '\0')
+ return true;
+
+ return false;
+}
+
bool
ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
enum ECPGttype type, enum ECPGttype ind_type,
char *var, char *ind, long varcharsize, long offset,
- long ind_offset, bool isarray, enum COMPAT_MODE compat, bool force_indicator)
+ long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
{
struct sqlca_t *sqlca = ECPGget_sqlca();
char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
int value_for_indicator = 0;
- ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset);
+ ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld array: %d\n", lineno, pval ? pval : "", offset, isarray);
/* pval is a pointer to the value */
- /* let's check is it really is an array if it should be one */
- if (isarray)
+ /* let's check if it really is an array if it should be one */
+ if (isarray == ECPG_ARRAY_ARRAY)
{
if (*pval != '{')
{
if (pval)
{
res = strtol(pval, &scan_length, 10);
- /* INFORMIX allows for selecting a numeric into an int, the result is truncated */
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (pval)
{
ures = strtoul(pval, &scan_length, 10);
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (pval)
{
*((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (isarray && *scan_length == '"')
scan_length++;
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_FLOAT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (isarray && *scan_length == '"')
scan_length++;
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (isarray && *scan_length == '"')
scan_length++;
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (isarray && *scan_length == '"')
scan_length++;
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
if (isarray && *scan_length == '"')
scan_length++;
- if ((isarray && *scan_length != ',' && *scan_length != '}')
- || (!isarray && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
+ if (garbage_left(isarray, scan_length, compat))
{
ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
return (false);
break;
}
- if (isarray)
+ if (isarray == ECPG_ARRAY_ARRAY)
{
bool string = false;
if (*pval == ',')
++pval;
}
- } while (isarray && *pval != '}');
+ else if (isarray == ECPG_ARRAY_VECTOR)
+ {
+ bool string = false;
+
+ /* set array to next entry */
+ ++act_tuple;
+
+ /* set pval to the next entry */
+ for (; string || (*pval != ' ' && *pval != '\0'); ++pval)
+ if (*pval == '"')
+ string = string ? false : true;
+
+ if (*pval == ' ')
+ ++pval;
+ }
+ } while ((isarray == ECPG_ARRAY_ARRAY && *pval != '}') || (isarray == ECPG_ARRAY_VECTOR && *pval != '\0'));
return (true);
}
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.26 2003/10/26 09:50:47 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.27 2003/11/08 19:46:27 meskes Exp $ */
/*
* The aim is to get a simpler inteface to the database routines.
return (*ptr == '\0') ? NULL : ptr;
}
-/*
- * push a value on the cache
- */
-
-static void
-ECPGtypeinfocache_push(struct ECPGtype_information_cache ** cache, int oid, bool isarray, int lineno)
-{
- struct ECPGtype_information_cache *new_entry
- = (struct ECPGtype_information_cache *) ECPGalloc(sizeof(struct ECPGtype_information_cache), lineno);
-
- new_entry->oid = oid;
- new_entry->isarray = isarray;
- new_entry->next = *cache;
- *cache = new_entry;
-}
-
-static bool
+static enum ARRAY_TYPE
ECPGis_type_an_array(int type, const struct statement * stmt, const struct variable * var)
{
- char *array_query;
- int isarray = 0;
- PGresult *query;
- struct ECPGtype_information_cache *cache_entry;
+ char *array_query;
+ enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
+ PGresult *query;
if ((stmt->connection->cache_head) == NULL)
{
* them as an array. This define reminds you to not 'correct'
* these values.
*/
-#define not_an_array_in_ecpg false
-
- /* populate cache with well known types to speed things up */
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOOLOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), BYTEAOID, not_an_array_in_ecpg, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), CHAROID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT8OID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2OID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2VECTOROID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT4OID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), REGPROCOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TEXTOID, not_an_array_in_ecpg, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIDOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), XIDOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDVECTOROID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), POINTOID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), LSEGOID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), PATHOID, not_an_array_in_ecpg, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOXOID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), POLYGONOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), LINEOID, true, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT4OID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT8OID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), ABSTIMEOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), RELTIMEOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TINTERVALOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), UNKNOWNOID, not_an_array_in_ecpg, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIRCLEOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), CASHOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INETOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDROID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), BPCHAROID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARCHAROID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), DATEOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMEOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), INTERVALOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMETZOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), ZPBITOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARBITOID, false, stmt->lineno);
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), NUMERICOID, false, stmt->lineno);
- }
-
- for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
- {
- if (cache_entry->oid == type)
- return cache_entry->isarray;
+#define not_an_array_in_ecpg ECPG_ARRAY_NONE
+
+ switch (type)
+ {
+ case BOOLOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case BYTEAOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case CHAROID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case NAMEOID: isarray = not_an_array_in_ecpg;
+ break;
+ case INT8OID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case INT2OID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case INT2VECTOROID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case INT4OID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case REGPROCOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TEXTOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case OIDOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TIDOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case XIDOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case CIDOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case OIDVECTOROID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case POINTOID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case LSEGOID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case PATHOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case BOXOID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case POLYGONOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case LINEOID: isarray = ECPG_ARRAY_VECTOR;
+ break;
+ case FLOAT4OID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case FLOAT8OID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case ABSTIMEOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case RELTIMEOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TINTERVALOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case UNKNOWNOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case CIRCLEOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case CASHOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case INETOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case CIDROID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case BPCHAROID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case VARCHAROID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case DATEOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TIMEOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TIMESTAMPOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TIMESTAMPTZOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case INTERVALOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case TIMETZOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case ZPBITOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case VARBITOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ case NUMERICOID: isarray = ECPG_ARRAY_NONE;
+ break;
+ default: break;
+ }
}
- array_query = (char *) ECPGalloc(strlen("select typelem from pg_type where oid=") + 11, stmt->lineno);
- sprintf(array_query, "select typelem from pg_type where oid=%d", type);
- query = PQexec(stmt->connection->connection, array_query);
- ECPGfree(array_query);
- if (PQresultStatus(query) == PGRES_TUPLES_OK)
+ if (isarray == ECPG_ARRAY_NOT_SET)
{
- isarray = atol((char *) PQgetvalue(query, 0, 0));
- if (ECPGDynamicType(type) == SQL3_CHARACTER ||
- ECPGDynamicType(type) == SQL3_CHARACTER_VARYING)
+ array_query = (char *) ECPGalloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
+ sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
+ query = PQexec(stmt->connection->connection, array_query);
+ ECPGfree(array_query);
+ if (PQresultStatus(query) == PGRES_TUPLES_OK)
{
- /*
- * arrays of character strings are not yet implemented
- */
- isarray = false;
+ isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
+ if (ECPGDynamicType(type) == SQL3_CHARACTER ||
+ ECPGDynamicType(type) == SQL3_CHARACTER_VARYING)
+ {
+ /*
+ * arrays of character strings are not yet implemented
+ */
+ isarray = ECPG_ARRAY_NONE;
+ }
}
- ECPGlog("ECPGexecute line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, type, var->type, isarray ? "yes" : "no");
- ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
+ PQclear(query);
}
- PQclear(query);
+ ECPGlog("ECPGexecute line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray);
return isarray;
}
ECPGstore_result(const PGresult *results, int act_field,
const struct statement * stmt, struct variable * var)
{
- int isarray,
- act_tuple,
+ enum ARRAY_TYPE isarray;
+ int act_tuple,
ntuples = PQntuples(results);
bool status = true;
isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var);
- if (!isarray)
+ if (isarray == ECPG_ARRAY_NONE)
{
/*
* if we don't have enough space, we cannot read all tuples
case PGRES_TUPLES_OK:
nfields = PQnfields(results);
sqlca->sqlerrd[2] = ntuples = PQntuples(results);
+ ECPGlog("ECPGexecute line %d: Correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
status = true;
if (ntuples < 1)