"...postgres-fd-implementation.git" did not exist on "076c164559a81ccc55651949f39de0ce9015a335"
descriptor.c 10.6 KB
Newer Older
1 2
/* dynamic SQL support routines
 *
Michael Meskes's avatar
Michael Meskes committed
3
 * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/descriptor.c,v 1.21 2002/01/11 14:43:11 meskes Exp $
4
 */
5 6

#include "postgres_fe.h"
Michael Meskes's avatar
Michael Meskes committed
7
#include "pg_type.h"
8

Bruce Momjian's avatar
Bruce Momjian committed
9 10 11
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
Michael Meskes's avatar
Michael Meskes committed
12
#include "extern.h"
Michael Meskes's avatar
Michael Meskes committed
13
#include "sqlca.h"
Bruce Momjian's avatar
Bruce Momjian committed
14
#include "sql3types.h"
Michael Meskes's avatar
Michael Meskes committed
15

16
struct descriptor *all_descriptors = NULL;
17

18
/* old internal convenience function that might go away later */
Michael Meskes's avatar
Michael Meskes committed
19
static PGresult
20 21
		   *
ECPGresultByDescriptor(int line, const char *name)
Michael Meskes's avatar
Michael Meskes committed
22
{
23 24 25 26
	PGresult  **resultpp = ECPGdescriptor_lvalue(line, name);

	if (resultpp)
		return *resultpp;
Michael Meskes's avatar
Michael Meskes committed
27
	return NULL;
28
}
Michael Meskes's avatar
Michael Meskes committed
29 30 31 32

static unsigned int
ECPGDynamicType_DDT(Oid type)
{
33 34
	switch (type)
	{
Michael Meskes's avatar
Michael Meskes committed
35 36 37 38 39 40 41 42 43 44
		case DATEOID:
			return SQL3_DDT_DATE;
		case TIMEOID:
			return SQL3_DDT_TIME;
		case TIMESTAMPOID:
			return SQL3_DDT_TIMESTAMP;
		case TIMESTAMPTZOID:
			return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
		case TIMETZOID:
			return SQL3_DDT_TIME_WITH_TIME_ZONE;
Michael Meskes's avatar
Michael Meskes committed
45 46 47 48
		default:
			return SQL3_DDT_ILLEGAL;
	}
}
Michael Meskes's avatar
Michael Meskes committed
49

Michael Meskes's avatar
Michael Meskes committed
50
bool
51
ECPGget_desc_header(int lineno, char *desc_name, int *count)
Michael Meskes's avatar
Michael Meskes committed
52
{
Michael Meskes's avatar
Michael Meskes committed
53
	PGresult   *ECPGresult;
54

Michael Meskes's avatar
Michael Meskes committed
55 56
	ECPGinit_sqlca();
	ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
Michael Meskes's avatar
Michael Meskes committed
57 58 59 60
	if (!ECPGresult)
		return false;

	*count = PQnfields(ECPGresult);
Michael Meskes's avatar
Michael Meskes committed
61
	sqlca.sqlerrd[2]=1;
Michael Meskes's avatar
Michael Meskes committed
62
	ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
Michael Meskes's avatar
Michael Meskes committed
63
	return true;
64
}
Michael Meskes's avatar
Michael Meskes committed
65 66

static bool
67
get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
Michael Meskes's avatar
Michael Meskes committed
68 69
{
	switch (vartype)
70
	{
71
		case ECPGt_short:
Michael Meskes's avatar
Michael Meskes committed
72
			*(short *) var = (short) value;
73
			break;
Michael Meskes's avatar
Michael Meskes committed
74
		case ECPGt_int:
Michael Meskes's avatar
Michael Meskes committed
75
			*(int *) var = (int) value;
76 77
			break;
		case ECPGt_long:
Michael Meskes's avatar
Michael Meskes committed
78
			*(long *) var = (long) value;
79 80
			break;
		case ECPGt_unsigned_short:
Michael Meskes's avatar
Michael Meskes committed
81
			*(unsigned short *) var = (unsigned short) value;
82
			break;
Michael Meskes's avatar
Michael Meskes committed
83
		case ECPGt_unsigned_int:
Michael Meskes's avatar
Michael Meskes committed
84
			*(unsigned int *) var = (unsigned int) value;
85 86
			break;
		case ECPGt_unsigned_long:
Michael Meskes's avatar
Michael Meskes committed
87 88
			*(unsigned long *) var = (unsigned long) value;
			break;
89
#ifdef HAVE_LONG_LONG_INT_64
Michael Meskes's avatar
Michael Meskes committed
90 91 92 93 94
		case ECPGt_long_long:
			*(long long int *) var = (long long int) value;
			break;
		case ECPGt_unsigned_long_long:
			*(unsigned long long int *) var = (unsigned long long int) value;
95
			break;
96
#endif   /* HAVE_LONG_LONG_INT_64 */
97
		case ECPGt_float:
Michael Meskes's avatar
Michael Meskes committed
98
			*(float *) var = (float) value;
99 100
			break;
		case ECPGt_double:
Michael Meskes's avatar
Michael Meskes committed
101
			*(double *) var = (double) value;
102 103 104 105
			break;
		default:
			ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, NULL);
			return (false);
Michael Meskes's avatar
Michael Meskes committed
106
	}
107 108

	return (true);
Michael Meskes's avatar
Michael Meskes committed
109 110
}

Michael Meskes's avatar
Michael Meskes committed
111
static bool
112
get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
Michael Meskes's avatar
Michael Meskes committed
113 114
{
	switch (vartype)
115
	{
116 117
		case ECPGt_char:
		case ECPGt_unsigned_char:
118 119 120 121 122 123 124 125
			strncpy((char *) var, value, varcharsize);
			break;
		case ECPGt_varchar:
			{
				struct ECPGgeneric_varchar *variable =
				(struct ECPGgeneric_varchar *) var;

				if (varcharsize == 0)
Michael Meskes's avatar
Michael Meskes committed
126
					strncpy(variable->arr, value, strlen(value));
127 128 129 130 131 132 133 134 135 136 137
				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);
Michael Meskes's avatar
Michael Meskes committed
138
	}
139 140

	return (true);
Michael Meskes's avatar
Michael Meskes committed
141 142
}

Michael Meskes's avatar
Michael Meskes committed
143
bool
144
ECPGget_desc(int lineno, char *desc_name, int index,...)
Michael Meskes's avatar
Michael Meskes committed
145
{
146
	va_list		args;
Michael Meskes's avatar
Michael Meskes committed
147
	PGresult   *ECPGresult;
148
	enum ECPGdtype type;
149 150
	int			ntuples,
				act_tuple;
Michael Meskes's avatar
Michael Meskes committed
151 152
	struct variable data_var;
	
Michael Meskes's avatar
Michael Meskes committed
153
	va_start(args, index);
Michael Meskes's avatar
Michael Meskes committed
154 155
	ECPGinit_sqlca();
	ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
156 157 158
	if (!ECPGresult)
		return (false);

159 160
	ntuples = PQntuples(ECPGresult);
	if (ntuples < 1)
161 162 163 164 165 166 167 168 169 170
	{
		ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
		return (false);
	}

	if (index < 1 || index > PQnfields(ECPGresult))
	{
		ECPGraise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, NULL);
		return (false);
	}
Michael Meskes's avatar
Michael Meskes committed
171 172

	ECPGlog("ECPGget_desc: reading items for tuple %d\n", index);
173 174 175
	--index;

	type = va_arg(args, enum ECPGdtype);
Michael Meskes's avatar
Michael Meskes committed
176 177 178 179 180
	
	memset (&data_var, 0, sizeof data_var);
	data_var.type=ECPGt_EORT;
	data_var.ind_type=ECPGt_NO_INDICATOR;
	
181 182 183 184 185 186 187 188 189 190 191 192 193
	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);
Michael Meskes's avatar
Michael Meskes committed
194
		offset = va_arg(args, long);
195 196 197 198

		switch (type)
		{
			case (ECPGd_indicator):
Michael Meskes's avatar
Michael Meskes committed
199 200 201 202 203 204 205 206 207 208
				data_var.ind_type=vartype;
				data_var.ind_pointer=var;
				data_var.ind_varcharsize=varcharsize;
				data_var.ind_arrsize=arrsize;
				data_var.ind_offset=offset;
				if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
					data_var.ind_value = *((void **) (data_var.ind_pointer));
				else
					data_var.ind_value = data_var.ind_pointer;
				break;
209

Michael Meskes's avatar
Michael Meskes committed
210 211 212 213 214 215 216 217 218 219
			case ECPGd_data:
				data_var.type=vartype;
				data_var.pointer=var;
				data_var.varcharsize=varcharsize;
				data_var.arrsize=arrsize;
				data_var.offset=offset;
				if (data_var.arrsize == 0 || data_var.varcharsize == 0)
					data_var.value = *((void **) (data_var.pointer));
				else
					data_var.value = data_var.pointer;
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
				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;

Michael Meskes's avatar
Michael Meskes committed
255 256
			case ECPGd_octet:
				if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
257 258 259 260
					return (false);

				ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
				break;
Michael Meskes's avatar
Michael Meskes committed
261 262 263

			case ECPGd_length:
				if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
					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)));
Michael Meskes's avatar
Michael Meskes committed
281
				break;
Michael Meskes's avatar
Michael Meskes committed
282 283 284 285 286 287 288 289 290 291
				
			case ECPGd_cardinality:
				if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
					return (false);

				ECPGlog("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
				break;

			case ECPGd_ret_length:
			case ECPGd_ret_octet:
292 293

				/*
Michael Meskes's avatar
Michael Meskes committed
294
				 * this is like ECPGstore_result
295
				 */
Michael Meskes's avatar
Michael Meskes committed
296
				if (arrsize > 0 && ntuples > arrsize)
297 298 299
				{
					ECPGlog("ECPGget_desc line %d: Incorrect number of matches: %d don't fit into array of %d\n",
							lineno, ntuples, arrsize);
300 301 302
					ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, NULL);
					return false;
				}
Michael Meskes's avatar
Michael Meskes committed
303 304 305 306 307 308 309 310 311
				/* allocate storage if needed */
				if (arrsize == 0 && var != NULL && *(void**)var == NULL)
				{
					void *mem = (void *) ECPGalloc(offset * ntuples, lineno);
					*(void **)var = mem;
					ECPGadd_mem(mem, lineno);
					var = mem;
				}
	
312 313
				for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
				{
Michael Meskes's avatar
Michael Meskes committed
314
					if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
315
						return (false);
Michael Meskes's avatar
Michael Meskes committed
316 317
					var = (char *) var + offset;
					ECPGlog("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
318 319
				}
				break;
320

321 322 323 324
			default:
				snprintf(type_str, sizeof(type_str), "%d", type);
				ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
				return (false);
Michael Meskes's avatar
Michael Meskes committed
325
		}
326 327 328 329

		type = va_arg(args, enum ECPGdtype);
	}

Michael Meskes's avatar
Michael Meskes committed
330
	if (data_var.type!=ECPGt_EORT)
331
	{
Michael Meskes's avatar
Michael Meskes committed
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
		struct statement stmt;
		memset (&stmt, 0, sizeof stmt);
		stmt.lineno=lineno;
		/* desparate try to guess something sensible */
		stmt.connection=ECPGget_connection(NULL);
		ECPGstore_result(ECPGresult, index, &stmt, &data_var);
	}
	else if (data_var.ind_type!=ECPGt_NO_INDICATOR)
	{
		/*
		 * this is like ECPGstore_result
		 * but since we don't have a data variable at hand, we can't call it
		 */
		if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
		{
			ECPGlog("ECPGget_desc line %d: Incorrect number of matches (indicator): %d don't fit into array of %d\n",
					lineno, ntuples, data_var.ind_arrsize);
			ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, NULL);
			return false;
		}
		/* allocate storage if needed */
		if (data_var.ind_arrsize == 0 && data_var.ind_pointer != NULL && data_var.ind_value == NULL)
		{
			void *mem = (void *) ECPGalloc(data_var.ind_offset * ntuples, lineno);
			*(void **)data_var.ind_pointer = mem;
			ECPGadd_mem(mem, lineno);
			data_var.ind_value = mem;
		}
360 361
		for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
		{
Michael Meskes's avatar
Michael Meskes committed
362
			if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
363
				return (false);
Michael Meskes's avatar
Michael Meskes committed
364 365
			data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
			ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
366
		}
Michael Meskes's avatar
Michael Meskes committed
367
	}
Michael Meskes's avatar
Michael Meskes committed
368
	sqlca.sqlerrd[2]=ntuples;
369
	return (true);
Michael Meskes's avatar
Michael Meskes committed
370
}
Michael Meskes's avatar
Michael Meskes committed
371 372 373 374 375 376

bool
ECPGdeallocate_desc(int line, const char *name)
{
	struct descriptor *i;
	struct descriptor **lastptr = &all_descriptors;
377

Michael Meskes's avatar
Michael Meskes committed
378
	ECPGinit_sqlca();
Michael Meskes's avatar
Michael Meskes committed
379 380 381 382 383
	for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
	{
		if (!strcmp(name, i->name))
		{
			*lastptr = i->next;
384
			ECPGfree(i->name);
Michael Meskes's avatar
Michael Meskes committed
385
			PQclear(i->result);
386
			ECPGfree(i);
Michael Meskes's avatar
Michael Meskes committed
387 388 389 390 391
			return true;
		}
	}
	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
	return false;
392
}
Michael Meskes's avatar
Michael Meskes committed
393 394

bool
395
ECPGallocate_desc(int line, const char *name)
Michael Meskes's avatar
Michael Meskes committed
396
{
Michael Meskes's avatar
Michael Meskes committed
397
	struct descriptor *new;
398

Michael Meskes's avatar
Michael Meskes committed
399 400 401
	ECPGinit_sqlca();
	new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
	if (!new) return false;
Michael Meskes's avatar
Michael Meskes committed
402
	new->next = all_descriptors;
Michael Meskes's avatar
Michael Meskes committed
403
	new->name = ECPGalloc(strlen(name) + 1, line);
Michael Meskes's avatar
Michael Meskes committed
404 405 406 407 408
	if (!new->name) 
	{
		ECPGfree(new);
		return false;
	}
Michael Meskes's avatar
Michael Meskes committed
409
	new->result = PQmakeEmptyPGresult(NULL, 0);
Michael Meskes's avatar
Michael Meskes committed
410 411 412 413 414 415 416
	if (!new->result) 
	{
		ECPGfree(new->name);
		ECPGfree(new);
		ECPGraise(line, ECPG_OUT_OF_MEMORY, NULL);
		return false;
	}
Michael Meskes's avatar
Michael Meskes committed
417 418 419 420
	strcpy(new->name, name);
	all_descriptors = new;
	return true;
}
421

422
PGresult  **
423 424 425 426 427 428
ECPGdescriptor_lvalue(int line, const char *descriptor)
{
	struct descriptor *i;

	for (i = all_descriptors; i != NULL; i = i->next)
	{
429
		if (!strcmp(descriptor, i->name))
430 431 432 433 434 435
			return &i->result;
	}

	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, (char *) descriptor);
	return NULL;
}