#include "postgres_fe.h"#include <stdlib.h>#include <string.h>#include <float.h>#include <math.h>#include "ecpgtype.h"#include "ecpglib.h"#include "ecpgerrno.h"#include "extern.h"#include "sqlca.h"#include "pgtypes_numeric.h"#include "pgtypes_date.h"#include "pgtypes_timestamp.h"#include "pgtypes_interval.h"
Go to the source code of this file.
Defines | |
| #define | POSTGRES_ECPG_INTERNAL |
Functions | |
| static bool | array_delimiter (enum ARRAY_TYPE isarray, char c) |
| static bool | array_boundary (enum ARRAY_TYPE isarray, char c) |
| static bool | garbage_left (enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat) |
| static double | get_float8_infinity (void) |
| static double | get_float8_nan (void) |
| static bool | check_special_value (char *ptr, double *retval, char **endptr) |
| bool | ecpg_get_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, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator) |
| static bool array_boundary | ( | enum ARRAY_TYPE | isarray, | |
| char | c | |||
| ) | [static] |
Definition at line 36 of file data.c.
References ECPG_ARRAY_ARRAY, and ECPG_ARRAY_VECTOR.
Referenced by ecpg_get_data(), and garbage_left().
{
if (isarray == ECPG_ARRAY_ARRAY && c == '}')
return true;
if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
return true;
return false;
}
| static bool array_delimiter | ( | enum ARRAY_TYPE | isarray, | |
| char | c | |||
| ) | [static] |
Definition at line 23 of file data.c.
References ECPG_ARRAY_ARRAY, and ECPG_ARRAY_VECTOR.
Referenced by ecpg_get_data(), and garbage_left().
{
if (isarray == ECPG_ARRAY_ARRAY && c == ',')
return true;
if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
return true;
return false;
}
| static bool check_special_value | ( | char * | ptr, | |
| double * | retval, | |||
| char ** | endptr | |||
| ) | [static] |
Definition at line 98 of file data.c.
References get_float8_infinity(), get_float8_nan(), and pg_strncasecmp().
Referenced by ecpg_get_data().
{
if (pg_strncasecmp(ptr, "NaN", 3) == 0)
{
*retval = get_float8_nan();
*endptr = ptr + 3;
return true;
}
else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
{
*retval = get_float8_infinity();
*endptr = ptr + 8;
return true;
}
else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
{
*retval = -get_float8_infinity();
*endptr = ptr + 9;
return true;
}
return false;
}
| bool ecpg_get_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, | |||
| enum ARRAY_TYPE | isarray, | |||
| enum COMPAT_MODE | compat, | |||
| bool | force_indicator | |||
| ) |
Definition at line 123 of file data.c.
References ECPGgeneric_varchar::arr, array_boundary(), array_delimiter(), check_special_value(), ecpg_alloc(), ECPG_ARRAY_ARRAY, ECPG_CONVERT_BOOL, ECPG_DATA_NOT_ARRAY, ECPG_DATE_FORMAT, ECPG_FLOAT_FORMAT, ECPG_INT_FORMAT, ecpg_internal_regression_mode, ECPG_INTERVAL_FORMAT, ECPG_IS_ARRAY, ecpg_log(), ECPG_MISSING_INDICATOR, ECPG_NOT_FOUND, ECPG_NUMERIC_FORMAT, ECPG_OUT_OF_MEMORY, ecpg_raise(), ECPG_SQLSTATE_DATATYPE_MISMATCH, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_NO_DATA, ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER, ECPG_TIMESTAMP_FORMAT, ecpg_type_name(), ECPG_UINT_FORMAT, ECPG_UNSUPPORTED, ECPGget_sqlca(), ECPGset_noind_null(), ECPGt_bool, ECPGt_char, ECPGt_date, ECPGt_decimal, ECPGt_double, ECPGt_float, ECPGt_int, ECPGt_interval, ECPGt_long, ECPGt_long_long, ECPGt_NO_INDICATOR, ECPGt_numeric, ECPGt_short, ECPGt_string, ECPGt_timestamp, ECPGt_unsigned_char, ECPGt_unsigned_int, ECPGt_unsigned_long, ECPGt_unsigned_long_long, ECPGt_unsigned_short, ECPGt_varchar, free, garbage_left(), INFORMIX_MODE, ECPGgeneric_varchar::len, NULL, PGTYPESdate_from_asc(), PGTYPESinterval_copy(), PGTYPESinterval_from_asc(), PGTYPESnumeric_copy(), PGTYPESnumeric_free(), PGTYPESnumeric_from_asc(), PGTYPESnumeric_new(), PGTYPESnumeric_to_decimal(), PGTYPEStimestamp_from_asc(), PQfformat(), PQgetisnull(), PQgetlength(), PQgetvalue(), sqlca, and sqlca_t::sqlwarn.
Referenced by ecpg_set_compat_sqlda(), ecpg_set_native_sqlda(), and ecpg_store_result().
{
struct sqlca_t *sqlca = ECPGget_sqlca();
char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
int binary = PQfformat(results, act_field);
int size = PQgetlength(results, act_tuple, act_field);
int value_for_indicator = 0;
long log_offset;
/*
* If we are running in a regression test, do not log the offset variable,
* it depends on the machine's alignment.
*/
if (ecpg_internal_regression_mode)
log_offset = -1;
else
log_offset = offset;
ecpg_log("ecpg_get_data on line %d: RESULT: %s offset: %ld; array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, ECPG_IS_ARRAY(isarray) ? "yes" : "no");
/* pval is a pointer to the value */
if (!pval)
{
/*
* This should never happen because we already checked that we found
* at least one tuple, but let's play it safe.
*/
ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
return (false);
}
/* We will have to decode the value */
/*
* check for null value and set indicator accordingly, i.e. -1 if NULL and
* 0 if not
*/
if (PQgetisnull(results, act_tuple, act_field))
value_for_indicator = -1;
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
break;
#ifdef HAVE_LONG_LONG_INT
case ECPGt_long_long:
case ECPGt_unsigned_long_long:
*((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
break;
#endif /* HAVE_LONG_LONG_INT */
case ECPGt_NO_INDICATOR:
if (value_for_indicator == -1)
{
if (force_indicator == false)
{
/*
* Informix has an additional way to specify NULLs note
* that this uses special values to denote NULL
*/
ECPGset_noind_null(type, var + offset * act_tuple);
}
else
{
ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
NULL);
return (false);
}
}
break;
default:
ecpg_raise(lineno, ECPG_UNSUPPORTED,
ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
ecpg_type_name(ind_type));
return (false);
break;
}
if (value_for_indicator == -1)
return (true);
/* let's check if it really is an array if it should be one */
if (isarray == ECPG_ARRAY_ARRAY)
{
if (*pval != '{')
{
ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
return (false);
}
switch (type)
{
case ECPGt_char:
case ECPGt_unsigned_char:
case ECPGt_varchar:
case ECPGt_string:
break;
default:
pval++;
break;
}
}
do
{
if (binary)
{
if (varcharsize == 0 || varcharsize * offset >= size)
memcpy(var + offset * act_tuple, pval, size);
else
{
memcpy(var + offset * act_tuple, pval, varcharsize * offset);
if (varcharsize * offset < size)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*((short *) (ind + ind_offset * act_tuple)) = size;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*((int *) (ind + ind_offset * act_tuple)) = size;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*((long *) (ind + ind_offset * act_tuple)) = size;
break;
#ifdef HAVE_LONG_LONG_INT
case ECPGt_long_long:
case ECPGt_unsigned_long_long:
*((long long int *) (ind + ind_offset * act_tuple)) = size;
break;
#endif /* HAVE_LONG_LONG_INT */
default:
break;
}
sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
}
}
pval += size;
}
else
{
switch (type)
{
long res;
unsigned long ures;
double dres;
char *scan_length;
numeric *nres;
date ddres;
timestamp tres;
interval *ires;
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
res = strtol(pval, &scan_length, 10);
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_INT_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
pval = scan_length;
switch (type)
{
case ECPGt_short:
*((short *) (var + offset * act_tuple)) = (short) res;
break;
case ECPGt_int:
*((int *) (var + offset * act_tuple)) = (int) res;
break;
case ECPGt_long:
*((long *) (var + offset * act_tuple)) = (long) res;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
ures = strtoul(pval, &scan_length, 10);
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_UINT_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
pval = scan_length;
switch (type)
{
case ECPGt_unsigned_short:
*((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
*((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
*((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
break;
default:
/* Cannot happen */
break;
}
break;
#ifdef HAVE_LONG_LONG_INT
#ifdef HAVE_STRTOLL
case ECPGt_long_long:
*((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
pval = scan_length;
break;
#endif /* HAVE_STRTOLL */
#ifdef HAVE_STRTOULL
case ECPGt_unsigned_long_long:
*((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
if ((isarray && *scan_length != ',' && *scan_length != '}')
|| (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */
{
ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
pval = scan_length;
break;
#endif /* HAVE_STRTOULL */
#endif /* HAVE_LONG_LONG_INT */
case ECPGt_float:
case ECPGt_double:
if (isarray && *pval == '"')
pval++;
if (!check_special_value(pval, &dres, &scan_length))
dres = strtod(pval, &scan_length);
if (isarray && *scan_length == '"')
scan_length++;
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
pval = scan_length;
switch (type)
{
case ECPGt_float:
*((float *) (var + offset * act_tuple)) = dres;
break;
case ECPGt_double:
*((double *) (var + offset * act_tuple)) = dres;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_bool:
if (pval[0] == 'f' && pval[1] == '\0')
{
if (offset == sizeof(char))
*((char *) (var + offset * act_tuple)) = false;
else if (offset == sizeof(int))
*((int *) (var + offset * act_tuple)) = false;
else
ecpg_raise(lineno, ECPG_CONVERT_BOOL,
ECPG_SQLSTATE_DATATYPE_MISMATCH,
NULL);
pval++;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
if (offset == sizeof(char))
*((char *) (var + offset * act_tuple)) = true;
else if (offset == sizeof(int))
*((int *) (var + offset * act_tuple)) = true;
else
ecpg_raise(lineno, ECPG_CONVERT_BOOL,
ECPG_SQLSTATE_DATATYPE_MISMATCH,
NULL);
pval++;
break;
}
else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
{
/* NULL is valid */
break;
}
ecpg_raise(lineno, ECPG_CONVERT_BOOL,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
case ECPGt_string:
{
char *str = (char *) (var + offset * act_tuple);
if (varcharsize == 0 || varcharsize > size)
{
strncpy(str, pval, size + 1);
/* do the rtrim() */
if (type == ECPGt_string)
{
char *last = str + size;
while (last > str && (*last == ' ' || *last == '\0'))
{
*last = '\0';
last--;
}
}
}
else
{
strncpy(str, pval, varcharsize);
if (varcharsize < size)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*((short *) (ind + ind_offset * act_tuple)) = size;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*((int *) (ind + ind_offset * act_tuple)) = size;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*((long *) (ind + ind_offset * act_tuple)) = size;
break;
#ifdef HAVE_LONG_LONG_INT
case ECPGt_long_long:
case ECPGt_unsigned_long_long:
*((long long int *) (ind + ind_offset * act_tuple)) = size;
break;
#endif /* HAVE_LONG_LONG_INT */
default:
break;
}
sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
}
}
pval += size;
}
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) (var + offset * act_tuple);
variable->len = size;
if (varcharsize == 0)
strncpy(variable->arr, pval, variable->len);
else
{
strncpy(variable->arr, pval, varcharsize);
if (variable->len > varcharsize)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*((short *) (ind + offset * act_tuple)) = variable->len;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*((int *) (ind + offset * act_tuple)) = variable->len;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*((long *) (ind + offset * act_tuple)) = variable->len;
break;
#ifdef HAVE_LONG_LONG_INT
case ECPGt_long_long:
case ECPGt_unsigned_long_long:
*((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
break;
#endif /* HAVE_LONG_LONG_INT */
default:
break;
}
sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
variable->len = varcharsize;
}
}
pval += size;
}
break;
case ECPGt_decimal:
case ECPGt_numeric:
if (isarray && *pval == '"')
nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
else
nres = PGTYPESnumeric_from_asc(pval, &scan_length);
/* did we get an error? */
if (nres == NULL)
{
ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
lineno, pval ? pval : "", errno);
if (INFORMIX_MODE(compat))
{
/*
* Informix wants its own NULL value here instead
* of an error
*/
nres = PGTYPESnumeric_new();
if (nres)
ECPGset_noind_null(ECPGt_numeric, nres);
else
{
ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
return (false);
}
}
else
{
ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
else
{
if (isarray && *scan_length == '"')
scan_length++;
if (garbage_left(isarray, scan_length, compat))
{
free(nres);
ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
pval = scan_length;
if (type == ECPGt_numeric)
PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
else
PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
PGTYPESnumeric_free(nres);
break;
case ECPGt_interval:
if (isarray && *pval == '"')
ires = PGTYPESinterval_from_asc(pval + 1, &scan_length);
else
ires = PGTYPESinterval_from_asc(pval, &scan_length);
/* did we get an error? */
if (ires == NULL)
{
ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
lineno, pval ? pval : "", errno);
if (INFORMIX_MODE(compat))
{
/*
* Informix wants its own NULL value here instead
* of an error
*/
ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
if (!ires)
return (false);
ECPGset_noind_null(ECPGt_interval, ires);
}
else
{
ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
else
{
if (isarray && *scan_length == '"')
scan_length++;
if (garbage_left(isarray, scan_length, compat))
{
free(ires);
ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
pval = scan_length;
PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
free(ires);
break;
case ECPGt_date:
if (isarray && *pval == '"')
ddres = PGTYPESdate_from_asc(pval + 1, &scan_length);
else
ddres = PGTYPESdate_from_asc(pval, &scan_length);
/* did we get an error? */
if (errno != 0)
{
ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
lineno, pval ? pval : "", errno);
if (INFORMIX_MODE(compat))
{
/*
* Informix wants its own NULL value here instead
* of an error
*/
ECPGset_noind_null(ECPGt_date, &ddres);
}
else
{
ecpg_raise(lineno, ECPG_DATE_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
else
{
if (isarray && *scan_length == '"')
scan_length++;
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_DATE_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
*((date *) (var + offset * act_tuple)) = ddres;
pval = scan_length;
break;
case ECPGt_timestamp:
if (isarray && *pval == '"')
tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length);
else
tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
/* did we get an error? */
if (errno != 0)
{
ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
lineno, pval ? pval : "", errno);
if (INFORMIX_MODE(compat))
{
/*
* Informix wants its own NULL value here instead
* of an error
*/
ECPGset_noind_null(ECPGt_timestamp, &tres);
}
else
{
ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
else
{
if (isarray && *scan_length == '"')
scan_length++;
if (garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
}
*((timestamp *) (var + offset * act_tuple)) = tres;
pval = scan_length;
break;
default:
ecpg_raise(lineno, ECPG_UNSUPPORTED,
ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
ecpg_type_name(type));
return (false);
break;
}
if (ECPG_IS_ARRAY(isarray))
{
bool string = false;
/* set array to next entry */
++act_tuple;
/* set pval to the next entry */
/*
* *pval != '\0' should not be needed, but is used as a safety
* guard
*/
for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
if (*pval == '"')
string = string ? false : true;
if (array_delimiter(isarray, *pval))
++pval;
}
}
} while (*pval != '\0' && !array_boundary(isarray, *pval));
return (true);
}
| static bool garbage_left | ( | enum ARRAY_TYPE | isarray, | |
| char * | scan_length, | |||
| enum COMPAT_MODE | compat | |||
| ) | [static] |
Definition at line 49 of file data.c.
References array_boundary(), array_delimiter(), ECPG_ARRAY_NONE, ECPG_IS_ARRAY, and INFORMIX_MODE.
Referenced by ecpg_get_data().
{
/*
* INFORMIX allows for selecting a numeric into an int, the result is
* truncated
*/
if (isarray == ECPG_ARRAY_NONE)
{
if (INFORMIX_MODE(compat) && *scan_length == '.')
return false;
if (*scan_length != ' ' && *scan_length != '\0')
return true;
}
else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, *scan_length) && !array_boundary(isarray, *scan_length))
return true;
return false;
}
| static double get_float8_infinity | ( | void | ) | [static] |
1.7.1