/*
* 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;
}
}
Messung V0.5 in Prozent C=88 H=95 G=91
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland