mirror of
https://github.com/postgres/postgres.git
synced 2025-05-31 03:21:24 +03:00
The latter was already the dominant use, and it's preferable because in C the convention is that intXX means XX bits. Therefore, allowing mixed use of int2, int4, int8, int16, int32 is obviously confusing. Remove the typedefs for int2 and int4 for now. They don't seem to be widely used outside of the PostgreSQL source tree, and the few uses can probably be cleaned up by the time this ships.
590 lines
18 KiB
C
590 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 "pg_type.h"
|
|
|
|
#include "ecpg-pthread-win32.h"
|
|
#include "decimal.h"
|
|
#include "ecpgtype.h"
|
|
#include "ecpglib.h"
|
|
#include "ecpgerrno.h"
|
|
#include "extern.h"
|
|
#include "sqlca.h"
|
|
#include "sqlda-native.h"
|
|
#include "sqlda-compat.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:
|
|
|
|
/*
|
|
* Let's align both the numeric struct and the digits array to
|
|
* int Unfortunately we need to do double work here to compute
|
|
* the size of the space needed for the numeric structure.
|
|
*/
|
|
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->ndigits)
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &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->ndigits)
|
|
{
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, &next_offset);
|
|
memcpy((char *) sqlda + offset, num->buf, num->ndigits + 1);
|
|
|
|
((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->ndigits)
|
|
{
|
|
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, &next_offset);
|
|
memcpy((char *) sqlda + offset, num->buf, num->ndigits + 1);
|
|
|
|
((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;
|
|
}
|
|
}
|