593 lines
18 KiB
C
593 lines
18 KiB
C
/*
|
|
* SQLDA support routines
|
|
*
|
|
* The allocated memory area pointed by an sqlda pointer
|
|
* contains both the metadata and the data, so freeing up
|
|
* is a simple free(sqlda) as expected by the ESQL/C examples.
|
|
*/
|
|
|
|
#define POSTGRES_ECPG_INTERNAL
|
|
#include "postgres_fe.h"
|
|
|
|
#include "catalog/pg_type_d.h"
|
|
#include "decimal.h"
|
|
#include "ecpg-pthread-win32.h"
|
|
#include "ecpgerrno.h"
|
|
#include "ecpglib.h"
|
|
#include "ecpglib_extern.h"
|
|
#include "ecpgtype.h"
|
|
#include "sqlca.h"
|
|
#include "sqlda-compat.h"
|
|
#include "sqlda-native.h"
|
|
|
|
/*
|
|
* Compute the next variable's offset with
|
|
* the current variable's size and alignment.
|
|
*
|
|
*
|
|
* Returns:
|
|
* - the current variable's offset in *current
|
|
* - the next variable's offset in *next
|
|
*/
|
|
static void
|
|
ecpg_sqlda_align_add_size(long offset, int alignment, int size, long *current, long *next)
|
|
{
|
|
if (offset % alignment)
|
|
offset += alignment - (offset % alignment);
|
|
if (current)
|
|
*current = offset;
|
|
offset += size;
|
|
if (next)
|
|
*next = offset;
|
|
}
|
|
|
|
static long
|
|
sqlda_compat_empty_size(const PGresult *res)
|
|
{
|
|
long offset;
|
|
int i;
|
|
int sqld = PQnfields(res);
|
|
|
|
/* Initial size to store main structure and field structures */
|
|
offset = sizeof(struct sqlda_compat) + sqld * sizeof(struct sqlvar_compat);
|
|
|
|
/* Add space for field names */
|
|
for (i = 0; i < sqld; i++)
|
|
offset += strlen(PQfname(res, i)) + 1;
|
|
|
|
/* Add padding to the first field value */
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), 0, &offset, NULL);
|
|
|
|
return offset;
|
|
}
|
|
|
|
static long
|
|
sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, long offset)
|
|
{
|
|
int sqld = PQnfields(res);
|
|
int i;
|
|
long next_offset;
|
|
|
|
/* Add space for the field values */
|
|
for (i = 0; i < sqld; i++)
|
|
{
|
|
enum ECPGttype type = sqlda_dynamic_type(PQftype(res, i), compat);
|
|
|
|
switch (type)
|
|
{
|
|
case ECPGt_short:
|
|
case ECPGt_unsigned_short:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_int:
|
|
case ECPGt_unsigned_int:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_long:
|
|
case ECPGt_unsigned_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_long_long:
|
|
case ECPGt_unsigned_long_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_bool:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_float:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_double:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_decimal:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_numeric:
|
|
|
|
/*
|
|
* We align the numeric struct to allow it to store a pointer,
|
|
* while the digits array is aligned to int (which seems like
|
|
* overkill, but let's keep compatibility here).
|
|
*
|
|
* Unfortunately we need to deconstruct the value twice to
|
|
* find out the digits array's size and then later fill it.
|
|
*/
|
|
ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
|
|
if (!PQgetisnull(res, row, i))
|
|
{
|
|
char *val = PQgetvalue(res, row, i);
|
|
numeric *num;
|
|
|
|
num = PGTYPESnumeric_from_asc(val, NULL);
|
|
if (!num)
|
|
break;
|
|
if (num->buf)
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
|
|
PGTYPESnumeric_free(num);
|
|
}
|
|
break;
|
|
case ECPGt_date:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_timestamp:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_interval:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
|
|
break;
|
|
case ECPGt_char:
|
|
case ECPGt_unsigned_char:
|
|
case ECPGt_string:
|
|
default:
|
|
{
|
|
long datalen = strlen(PQgetvalue(res, row, i)) + 1;
|
|
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
|
|
break;
|
|
}
|
|
}
|
|
offset = next_offset;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static long
|
|
sqlda_compat_total_size(const PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
long offset;
|
|
|
|
offset = sqlda_compat_empty_size(res);
|
|
|
|
if (row < 0)
|
|
return offset;
|
|
|
|
offset = sqlda_common_total_size(res, row, compat, offset);
|
|
return offset;
|
|
}
|
|
|
|
static long
|
|
sqlda_native_empty_size(const PGresult *res)
|
|
{
|
|
long offset;
|
|
int sqld = PQnfields(res);
|
|
|
|
/* Initial size to store main structure and field structures */
|
|
offset = sizeof(struct sqlda_struct) + (sqld - 1) * sizeof(struct sqlvar_struct);
|
|
|
|
/* Add padding to the first field value */
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), 0, &offset, NULL);
|
|
|
|
return offset;
|
|
}
|
|
|
|
static long
|
|
sqlda_native_total_size(const PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
long offset;
|
|
|
|
offset = sqlda_native_empty_size(res);
|
|
|
|
if (row < 0)
|
|
return offset;
|
|
|
|
offset = sqlda_common_total_size(res, row, compat, offset);
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
* Build "struct sqlda_compat" (metadata only) from PGresult
|
|
* leaving enough space for the field values in
|
|
* the given row number
|
|
*/
|
|
struct sqlda_compat *
|
|
ecpg_build_compat_sqlda(int line, PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
struct sqlda_compat *sqlda;
|
|
struct sqlvar_compat *sqlvar;
|
|
char *fname;
|
|
long size;
|
|
int sqld;
|
|
int i;
|
|
|
|
size = sqlda_compat_total_size(res, row, compat);
|
|
sqlda = (struct sqlda_compat *) ecpg_alloc(size, line);
|
|
if (!sqlda)
|
|
return NULL;
|
|
|
|
memset(sqlda, 0, size);
|
|
sqlvar = (struct sqlvar_compat *) (sqlda + 1);
|
|
sqld = PQnfields(res);
|
|
fname = (char *) (sqlvar + sqld);
|
|
|
|
sqlda->sqld = sqld;
|
|
ecpg_log("ecpg_build_compat_sqlda on line %d sqld = %d\n", line, sqld);
|
|
sqlda->desc_occ = size; /* cheat here, keep the full allocated size */
|
|
sqlda->sqlvar = sqlvar;
|
|
|
|
for (i = 0; i < sqlda->sqld; i++)
|
|
{
|
|
sqlda->sqlvar[i].sqltype = sqlda_dynamic_type(PQftype(res, i), compat);
|
|
strcpy(fname, PQfname(res, i));
|
|
sqlda->sqlvar[i].sqlname = fname;
|
|
fname += strlen(sqlda->sqlvar[i].sqlname) + 1;
|
|
|
|
/*
|
|
* this is reserved for future use, so we leave it empty for the time
|
|
* being
|
|
*/
|
|
/* sqlda->sqlvar[i].sqlformat = (char *) (long) PQfformat(res, i); */
|
|
sqlda->sqlvar[i].sqlxid = PQftype(res, i);
|
|
sqlda->sqlvar[i].sqltypelen = PQfsize(res, i);
|
|
}
|
|
|
|
return sqlda;
|
|
}
|
|
|
|
/*
|
|
* Sets values from PGresult.
|
|
*/
|
|
static int16 value_is_null = -1;
|
|
static int16 value_is_not_null = 0;
|
|
|
|
void
|
|
ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
struct sqlda_compat *sqlda = (*_sqlda);
|
|
int i;
|
|
long offset,
|
|
next_offset;
|
|
|
|
if (row < 0)
|
|
return;
|
|
|
|
/* Offset for the first field value */
|
|
offset = sqlda_compat_empty_size(res);
|
|
|
|
/*
|
|
* Set sqlvar[i]->sqldata pointers and convert values to correct format
|
|
*/
|
|
for (i = 0; i < sqlda->sqld; i++)
|
|
{
|
|
int isnull;
|
|
int datalen;
|
|
bool set_data = true;
|
|
|
|
switch (sqlda->sqlvar[i].sqltype)
|
|
{
|
|
case ECPGt_short:
|
|
case ECPGt_unsigned_short:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(short);
|
|
break;
|
|
case ECPGt_int:
|
|
case ECPGt_unsigned_int:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(int);
|
|
break;
|
|
case ECPGt_long:
|
|
case ECPGt_unsigned_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(long);
|
|
break;
|
|
case ECPGt_long_long:
|
|
case ECPGt_unsigned_long_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(long long);
|
|
break;
|
|
case ECPGt_bool:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(bool);
|
|
break;
|
|
case ECPGt_float:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(float);
|
|
break;
|
|
case ECPGt_double:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(double);
|
|
break;
|
|
case ECPGt_decimal:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(decimal);
|
|
break;
|
|
case ECPGt_numeric:
|
|
{
|
|
numeric *num;
|
|
char *val;
|
|
|
|
set_data = false;
|
|
|
|
ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(numeric);
|
|
|
|
if (PQgetisnull(res, row, i))
|
|
{
|
|
ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
|
|
break;
|
|
}
|
|
|
|
val = PQgetvalue(res, row, i);
|
|
num = PGTYPESnumeric_from_asc(val, NULL);
|
|
if (!num)
|
|
{
|
|
ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
|
|
break;
|
|
}
|
|
|
|
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
|
|
|
|
if (num->buf)
|
|
{
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
|
|
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
|
|
|
|
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
|
|
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
|
|
}
|
|
|
|
PGTYPESnumeric_free(num);
|
|
|
|
break;
|
|
}
|
|
case ECPGt_date:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(date);
|
|
break;
|
|
case ECPGt_timestamp:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(timestamp);
|
|
break;
|
|
case ECPGt_interval:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(interval);
|
|
break;
|
|
case ECPGt_char:
|
|
case ECPGt_unsigned_char:
|
|
case ECPGt_string:
|
|
default:
|
|
datalen = strlen(PQgetvalue(res, row, i)) + 1;
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = datalen;
|
|
if (datalen > 32768)
|
|
sqlda->sqlvar[i].sqlilongdata = sqlda->sqlvar[i].sqldata;
|
|
break;
|
|
}
|
|
|
|
isnull = PQgetisnull(res, row, i);
|
|
ecpg_log("ecpg_set_compat_sqlda on line %d row %d col %d %s\n", lineno, row, i, isnull ? "IS NULL" : "IS NOT NULL");
|
|
sqlda->sqlvar[i].sqlind = isnull ? &value_is_null : &value_is_not_null;
|
|
sqlda->sqlvar[i].sqlitype = ECPGt_short;
|
|
sqlda->sqlvar[i].sqlilen = sizeof(short);
|
|
if (!isnull)
|
|
{
|
|
if (set_data)
|
|
ecpg_get_data(res, row, i, lineno,
|
|
sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
|
|
sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
|
|
ECPG_ARRAY_NONE, compat, false);
|
|
}
|
|
else
|
|
ECPGset_noind_null(sqlda->sqlvar[i].sqltype, sqlda->sqlvar[i].sqldata);
|
|
|
|
offset = next_offset;
|
|
}
|
|
}
|
|
|
|
struct sqlda_struct *
|
|
ecpg_build_native_sqlda(int line, PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
struct sqlda_struct *sqlda;
|
|
long size;
|
|
int i;
|
|
|
|
size = sqlda_native_total_size(res, row, compat);
|
|
sqlda = (struct sqlda_struct *) ecpg_alloc(size, line);
|
|
if (!sqlda)
|
|
return NULL;
|
|
|
|
memset(sqlda, 0, size);
|
|
|
|
sprintf(sqlda->sqldaid, "SQLDA ");
|
|
sqlda->sqld = sqlda->sqln = PQnfields(res);
|
|
ecpg_log("ecpg_build_native_sqlda on line %d sqld = %d\n", line, sqlda->sqld);
|
|
sqlda->sqldabc = sizeof(struct sqlda_struct) + (sqlda->sqld - 1) * sizeof(struct sqlvar_struct);
|
|
|
|
for (i = 0; i < sqlda->sqld; i++)
|
|
{
|
|
char *fname;
|
|
|
|
sqlda->sqlvar[i].sqltype = sqlda_dynamic_type(PQftype(res, i), compat);
|
|
fname = PQfname(res, i);
|
|
sqlda->sqlvar[i].sqlname.length = strlen(fname);
|
|
strcpy(sqlda->sqlvar[i].sqlname.data, fname);
|
|
}
|
|
|
|
return sqlda;
|
|
}
|
|
|
|
void
|
|
ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult *res, int row, enum COMPAT_MODE compat)
|
|
{
|
|
struct sqlda_struct *sqlda = (*_sqlda);
|
|
int i;
|
|
long offset,
|
|
next_offset;
|
|
|
|
if (row < 0)
|
|
return;
|
|
|
|
/* Offset for the first field value */
|
|
offset = sqlda_native_empty_size(res);
|
|
|
|
/*
|
|
* Set sqlvar[i]->sqldata pointers and convert values to correct format
|
|
*/
|
|
for (i = 0; i < sqlda->sqld; i++)
|
|
{
|
|
int isnull;
|
|
int datalen;
|
|
bool set_data = true;
|
|
|
|
switch (sqlda->sqlvar[i].sqltype)
|
|
{
|
|
case ECPGt_short:
|
|
case ECPGt_unsigned_short:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(short), sizeof(short), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(short);
|
|
break;
|
|
case ECPGt_int:
|
|
case ECPGt_unsigned_int:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(int), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(int);
|
|
break;
|
|
case ECPGt_long:
|
|
case ECPGt_unsigned_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long), sizeof(long), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(long);
|
|
break;
|
|
case ECPGt_long_long:
|
|
case ECPGt_unsigned_long_long:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(long long), sizeof(long long), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(long long);
|
|
break;
|
|
case ECPGt_bool:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(bool), sizeof(bool), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(bool);
|
|
break;
|
|
case ECPGt_float:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(float), sizeof(float), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(float);
|
|
break;
|
|
case ECPGt_double:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(double), sizeof(double), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(double);
|
|
break;
|
|
case ECPGt_decimal:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), sizeof(decimal), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(decimal);
|
|
break;
|
|
case ECPGt_numeric:
|
|
{
|
|
numeric *num;
|
|
char *val;
|
|
|
|
set_data = false;
|
|
|
|
ecpg_sqlda_align_add_size(offset, sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(numeric);
|
|
|
|
if (PQgetisnull(res, row, i))
|
|
{
|
|
ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
|
|
break;
|
|
}
|
|
|
|
val = PQgetvalue(res, row, i);
|
|
num = PGTYPESnumeric_from_asc(val, NULL);
|
|
if (!num)
|
|
{
|
|
ECPGset_noind_null(ECPGt_numeric, sqlda->sqlvar[i].sqldata);
|
|
break;
|
|
}
|
|
|
|
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
|
|
|
|
if (num->buf)
|
|
{
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
|
|
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
|
|
|
|
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
|
|
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
|
|
}
|
|
|
|
PGTYPESnumeric_free(num);
|
|
|
|
break;
|
|
}
|
|
case ECPGt_date:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(date), sizeof(date), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(date);
|
|
break;
|
|
case ECPGt_timestamp:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(timestamp), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(timestamp);
|
|
break;
|
|
case ECPGt_interval:
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int64), sizeof(interval), &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = sizeof(interval);
|
|
break;
|
|
case ECPGt_char:
|
|
case ECPGt_unsigned_char:
|
|
case ECPGt_string:
|
|
default:
|
|
datalen = strlen(PQgetvalue(res, row, i)) + 1;
|
|
ecpg_sqlda_align_add_size(offset, sizeof(int), datalen, &offset, &next_offset);
|
|
sqlda->sqlvar[i].sqldata = (char *) sqlda + offset;
|
|
sqlda->sqlvar[i].sqllen = datalen;
|
|
break;
|
|
}
|
|
|
|
isnull = PQgetisnull(res, row, i);
|
|
ecpg_log("ecpg_set_native_sqlda on line %d row %d col %d %s\n", lineno, row, i, isnull ? "IS NULL" : "IS NOT NULL");
|
|
sqlda->sqlvar[i].sqlind = isnull ? &value_is_null : &value_is_not_null;
|
|
if (!isnull)
|
|
{
|
|
if (set_data)
|
|
ecpg_get_data(res, row, i, lineno,
|
|
sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
|
|
sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
|
|
ECPG_ARRAY_NONE, compat, false);
|
|
}
|
|
|
|
offset = next_offset;
|
|
}
|
|
}
|