postgresql/src/interfaces/ecpg/lib/descriptor.c

308 lines
6.9 KiB
C

#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
#include "extern.h"
#include "sql3types.h"
struct descriptor
{
char *name;
PGresult *result;
struct descriptor *next;
} *all_descriptors = NULL;
static PGresult
*
ECPGresultByDescriptor(int line, const char *name)
{
struct descriptor *i;
for (i = all_descriptors; i != NULL; i = i->next)
{
if (!strcmp(name, i->name))
return i->result;
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return NULL;
}
static unsigned int
ECPGDynamicType_DDT(Oid type)
{
switch (type)
{
case 1082:return SQL3_DDT_DATE; /* date */
case 1083:
return SQL3_DDT_TIME; /* time */
case 1184:
return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* datetime */
case 1296:
return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* timestamp */
default:
return SQL3_DDT_ILLEGAL;
}
}
bool
ECPGget_desc_header(int lineno, char *desc_name, int *count)
{
PGresult *ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
if (!ECPGresult)
return false;
*count = PQnfields(ECPGresult);
ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
return true;
}
static bool
get_int_item(int lineno, void *var, enum ECPGdtype vartype, int value)
{
switch (vartype)
{
case ECPGt_short:
*(short *) var = value;
break;
case ECPGt_int:
*(int *) var = value;
break;
case ECPGt_long:
*(long *) var = value;
break;
case ECPGt_unsigned_short:
*(unsigned short *) var = value;
break;
case ECPGt_unsigned_int:
*(unsigned int *) var = value;
break;
case ECPGt_unsigned_long:
*(unsigned long *) var = value;
break;
case ECPGt_float:
*(float *) var = value;
break;
case ECPGt_double:
*(double *) var = value;
break;
default:
ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, NULL);
return (false);
}
return (true);
}
static bool
get_char_item(int lineno, void *var, enum ECPGdtype vartype, char *value, int varcharsize)
{
switch (vartype)
{
case ECPGt_char:
case ECPGt_unsigned_char:
strncpy((char *) var, value, varcharsize);
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) var;
if (varcharsize == 0)
strncpy(variable->arr, value, strlen(value));
else
strncpy(variable->arr, value, varcharsize);
variable->len = strlen(value);
if (varcharsize > 0 && variable->len > varcharsize)
variable->len = varcharsize;
}
break;
default:
ECPGraise(lineno, ECPG_VAR_NOT_CHAR, NULL);
return (false);
}
return (true);
}
bool
ECPGget_desc(int lineno, char *desc_name, int index,...)
{
va_list args;
PGresult *ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
enum ECPGdtype type;
bool DataButNoIndicator = false;
va_start(args, index);
if (!ECPGresult)
return (false);
if (PQntuples(ECPGresult) < 1)
{
ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
return (false);
}
if (index < 1 || index > PQnfields(ECPGresult))
{
ECPGraise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, NULL);
return (false);
}
ECPGlog("ECPGget_desc: reading items for tuple %d\n", index);
--index;
type = va_arg(args, enum ECPGdtype);
while (type != ECPGd_EODT)
{
char type_str[20];
long varcharsize;
long offset;
long arrsize;
enum ECPGttype vartype;
void *var;
vartype = va_arg(args, enum ECPGttype);
var = va_arg(args, void *);
varcharsize = va_arg(args, long);
arrsize = va_arg(args, long);
offset = va_arg(args, long);
switch (type)
{
case (ECPGd_indicator):
if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
return (false);
ECPGlog("ECPGget_desc: INDICATOR = %d\n", -PQgetisnull(ECPGresult, 0, index));
break;
case ECPGd_name:
if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
return (false);
ECPGlog("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
break;
case ECPGd_nullable:
if (!get_int_item(lineno, var, vartype, 1))
return (false);
break;
case ECPGd_key_member:
if (!get_int_item(lineno, var, vartype, 0))
return (false);
break;
case ECPGd_scale:
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
return (false);
ECPGlog("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
break;
case ECPGd_precision:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
return (false);
ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
break;
case ECPGd_ret_length:
case ECPGd_ret_octet:
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
return (false);
ECPGlog("ECPGget_desc: RETURNED = %d\n", PQgetlength(ECPGresult, 0, index));
break;
case ECPGd_octet:
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
return (false);
ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
break;
case ECPGd_length:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
return (false);
ECPGlog("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
break;
case ECPGd_type:
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
return (false);
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType(PQftype(ECPGresult, index)));
break;
case ECPGd_di_code:
if (!get_int_item(lineno, var, vartype, ECPGDynamicType_DDT(PQftype(ECPGresult, index))))
return (false);
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType_DDT(PQftype(ECPGresult, index)));
break;
case ECPGd_data:
if (!get_data(ECPGresult, 0, index, lineno, vartype, ECPGt_NO_INDICATOR, var, NULL, varcharsize, offset, false))
return (false);
break;
default:
snprintf(type_str, sizeof(type_str), "%d", type);
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
return (false);
}
type = va_arg(args, enum ECPGdtype);
}
if (DataButNoIndicator && PQgetisnull(ECPGresult, 0, index))
{
ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
return (false);
}
return (true);
}
bool
ECPGdeallocate_desc(int line, const char *name)
{
struct descriptor *i;
struct descriptor **lastptr = &all_descriptors;
for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
{
if (!strcmp(name, i->name))
{
*lastptr = i->next;
free(i->name);
PQclear(i->result);
free(i);
return true;
}
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return false;
}
bool
ECPGallocate_desc(int line, const char *name)
{
struct descriptor *new = (struct descriptor *) malloc(sizeof(struct descriptor));
new->next = all_descriptors;
new->name = malloc(strlen(name) + 1);
new->result = PQmakeEmptyPGresult(NULL, 0);
strcpy(new->name, name);
all_descriptors = new;
return true;
}