1 /*-------
2  * Module:			descriptor.c
3  *
4  * Description:		This module contains functions related to creating
5  *					and manipulating a statement.
6  *
7  * Classes:			DescriptorClass (Functions prefix: "DC_")
8  *
9  *
10  * Comments:		See "readme.txt" for copyright and license information.
11  *-------
12  */
13 
14 #include "environ.h"
15 #include "connection.h"
16 #include "descriptor.h"
17 #include "statement.h"
18 #include "qresult.h"
19 #include "misc.h"
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <ctype.h>
24 
25 #include "pgapifunc.h"
26 
27 
TI_Constructor(TABLE_INFO * self,const ConnectionClass * conn)28 void	TI_Constructor(TABLE_INFO *self, const ConnectionClass *conn)
29 {
30 	memset(self, 0, sizeof(TABLE_INFO));
31 	TI_set_updatable(self);
32 }
TI_Destructor(TABLE_INFO ** ti,int count)33 void	TI_Destructor(TABLE_INFO **ti, int count)
34 {
35 	int	i;
36 
37 MYLOG(DETAIL_LOG_LEVEL, "entering count=%d\n", count);
38 	if (ti)
39 	{
40 		for (i = 0; i < count; i++)
41 		{
42 			if (ti[i])
43 			{
44 				COL_INFO *coli = ti[i]->col_info;
45 				if (coli)
46 				{
47 MYLOG(0, "!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
48 					coli->refcnt--;
49 					if (coli->refcnt <= 0 && 0 == coli->acc_time) /* acc_time == 0 means the table is dropped */
50 						free_col_info_contents(coli);
51 				}
52 				NULL_THE_NAME(ti[i]->schema_name);
53 				NULL_THE_NAME(ti[i]->table_name);
54 				NULL_THE_NAME(ti[i]->table_alias);
55 				NULL_THE_NAME(ti[i]->bestitem);
56 				NULL_THE_NAME(ti[i]->bestqual);
57 				TI_Destroy_IH(ti[i]);
58 				free(ti[i]);
59 				ti[i] = NULL;
60 			}
61 		}
62 	}
63 }
FI_Constructor(FIELD_INFO * self,BOOL reuse)64 void	FI_Constructor(FIELD_INFO *self, BOOL reuse)
65 {
66 MYLOG(DETAIL_LOG_LEVEL, "entering reuse=%d\n", reuse);
67 	if (reuse)
68 		FI_Destructor(&self, 1, FALSE);
69 	memset(self, 0, sizeof(FIELD_INFO));
70 	self->nullable = TRUE;
71 	self->columnkey = -1;
72 	self->typmod = -1;
73 }
FI_Destructor(FIELD_INFO ** fi,int count,BOOL freeFI)74 void	FI_Destructor(FIELD_INFO **fi, int count, BOOL freeFI)
75 {
76 	int	i;
77 
78 MYLOG(DETAIL_LOG_LEVEL, "entering count=%d\n", count);
79 	if (fi)
80 	{
81 		for (i = 0; i < count; i++)
82 		{
83 			if (fi[i])
84 			{
85 				NULL_THE_NAME(fi[i]->column_name);
86 				NULL_THE_NAME(fi[i]->column_alias);
87 				NULL_THE_NAME(fi[i]->schema_name);
88 				NULL_THE_NAME(fi[i]->before_dot);
89 				if (freeFI)
90 				{
91 					free(fi[i]);
92 					fi[i] = NULL;
93 				}
94 			}
95 		}
96 		if (freeFI)
97 			free(fi);
98 	}
99 }
100 
101 static	const pgNAME invNAME = {NULL};
102 
103 #define	INIT_IH	32
TI_Create_IH(TABLE_INFO * ti)104 void	TI_Create_IH(TABLE_INFO *ti)
105 {
106 	int	alloc = INIT_IH;
107 	InheritanceClass	*ih;
108 
109 	ih = (InheritanceClass *) malloc(sizeof(InheritanceClass) + (alloc - 1) * sizeof(ih->inf[0]));
110 	memset(ih, 0, sizeof(InheritanceClass));
111 	ih->allocated = alloc;
112 	ti->ih = ih;
113 }
114 
TI_Destroy_IH(TABLE_INFO * ti)115 void	TI_Destroy_IH(TABLE_INFO *ti)
116 {
117 	InheritanceClass	*ih;
118 	int			i;
119 
120 	if (NULL == (ih = ti->ih))
121 		return;
122 	for (i = 0; i < ih->count; i++)
123 	{
124 		NULL_THE_NAME(ih->inf[i].fullTable);
125 	}
126 	free(ih);
127 	ti->ih = NULL;
128 }
129 
TI_From_IH(TABLE_INFO * ti,OID tableoid)130 const pgNAME	TI_From_IH(TABLE_INFO *ti, OID tableoid)
131 {
132 	InheritanceClass	*ih;
133 	int			i;
134 
135 	if (NULL == (ih = ti->ih))
136 		return invNAME;
137 	if (tableoid == ih->cur_tableoid)
138 		return ih->cur_fullTable;
139 	for (i = 0; i < ih->count; i++)
140 	{
141 		if (ih->inf[i].tableoid == tableoid)
142 		{
143 			ih->cur_tableoid = tableoid;
144 			ih->cur_fullTable = ih->inf[i].fullTable;
145 			return ih->cur_fullTable;
146 		}
147 	}
148 	return invNAME;
149 }
150 
TI_Ins_IH(TABLE_INFO * ti,OID tableoid,const char * fullName)151 const pgNAME	TI_Ins_IH(TABLE_INFO *ti, OID tableoid, const char *fullName)
152 {
153 	InheritanceClass	*ih;
154 	int			count;
155 
156 	if (NULL == (ih = ti->ih))
157 	{
158 		TI_Create_IH(ti);
159 		if (ih = ti->ih, NULL == ih)
160 			return invNAME;
161 	}
162 	if ((count = ih->count) >= ih->allocated)
163 	{
164 		int	alloc = ih->allocated * 2;
165 		InheritanceClass	*nih;
166 
167 		if (nih = (InheritanceClass *) realloc(ih, sizeof(InheritanceClass) + (alloc - 1) * sizeof(ih->inf[0])), NULL == nih)
168 		{
169 			TI_Destroy_IH(ti);
170 			return invNAME;
171 		}
172 		ti->ih = ih = nih;
173 		ih->allocated = alloc;
174 	}
175 	ih->inf[count].tableoid = tableoid;
176 	INIT_NAME(ih->inf[count].fullTable);
177 	STR_TO_NAME(ih->inf[count].fullTable, fullName);
178 	ih->cur_tableoid = tableoid;
179 	ih->cur_fullTable = ih->inf[count].fullTable;
180 	ih->count++;
181 
182 	return ih->inf[count].fullTable;
183 }
184 
DC_Constructor(DescriptorClass * self,BOOL embedded,StatementClass * stmt)185 void	DC_Constructor(DescriptorClass *self, BOOL embedded, StatementClass *stmt)
186 {
187 	memset(self, 0, sizeof(DescriptorClass));
188 	self->deschd.embedded = embedded;
189 }
190 
ARDFields_free(ARDFields * self)191 static void ARDFields_free(ARDFields * self)
192 {
193 MYLOG(DETAIL_LOG_LEVEL, "entering %p bookmark=%p\n", self, self->bookmark);
194 	if (self->bookmark)
195 	{
196 		free(self->bookmark);
197 		self->bookmark = NULL;
198 	}
199 	/*
200 	 * the memory pointed to by the bindings is not deallocated by the
201 	 * driver but by the application that uses that driver, so we don't
202 	 * have to care
203 	 */
204 	ARD_unbind_cols(self, TRUE);
205 }
206 
APDFields_free(APDFields * self)207 static void APDFields_free(APDFields * self)
208 {
209 	if (self->bookmark)
210 	{
211 		free(self->bookmark);
212 		self->bookmark = NULL;
213 	}
214 	/* param bindings */
215 	APD_free_params(self, STMT_FREE_PARAMS_ALL);
216 }
217 
IRDFields_free(IRDFields * self)218 static void IRDFields_free(IRDFields * self)
219 {
220 	/* Free the parsed field information */
221 	if (self->fi)
222 	{
223 		FI_Destructor(self->fi, self->allocated, TRUE);
224 		self->fi = NULL;
225 	}
226 	self->allocated = 0;
227 	self->nfields = 0;
228 }
229 
IPDFields_free(IPDFields * self)230 static void IPDFields_free(IPDFields * self)
231 {
232 	/* param bindings */
233 	IPD_free_params(self, STMT_FREE_PARAMS_ALL);
234 }
235 
DC_Destructor(DescriptorClass * self)236 void	DC_Destructor(DescriptorClass *self)
237 {
238 	DescriptorHeader *deschd = &(self->deschd);
239 	if (deschd->__error_message)
240 	{
241 		free(deschd->__error_message);
242 		deschd->__error_message = NULL;
243 	}
244 	if (deschd->pgerror)
245 	{
246 		ER_Destructor(deschd->pgerror);
247 		deschd->pgerror = NULL;
248 	}
249 	if (deschd->type_defined)
250 	{
251 		switch (deschd->desc_type)
252 		{
253 			case SQL_ATTR_APP_ROW_DESC:
254 				ARDFields_free(&(self->ardf));
255 				break;
256 			case SQL_ATTR_APP_PARAM_DESC:
257 				APDFields_free(&(self->apdf));
258 				break;
259 			case SQL_ATTR_IMP_ROW_DESC:
260 				IRDFields_free(&(self->irdf));
261 				break;
262 			case SQL_ATTR_IMP_PARAM_DESC:
263 				IPDFields_free(&(self->ipdf));
264 				break;
265 		}
266 	}
267 }
268 
InitializeEmbeddedDescriptor(DescriptorClass * self,StatementClass * stmt,UInt4 desc_type)269 void InitializeEmbeddedDescriptor(DescriptorClass *self, StatementClass *stmt,
270 		 UInt4 desc_type)
271 {
272 	DescriptorHeader *deschd = &(self->deschd);
273 	DC_Constructor(self, TRUE, stmt);
274 	DC_get_conn(self) = SC_get_conn(stmt);
275 	deschd->type_defined = TRUE;
276 	deschd->desc_type = desc_type;
277 	switch (desc_type)
278 	{
279 		case SQL_ATTR_APP_ROW_DESC:
280 			memset(&(self->ardf), 0, sizeof(ARDFields));
281 			InitializeARDFields(&(self->ardf));
282 			stmt->ard = self;
283 			break;
284 		case SQL_ATTR_APP_PARAM_DESC:
285 			memset(&(self->apdf), 0, sizeof(APDFields));
286 			InitializeAPDFields(&(self->apdf));
287 			stmt->apd = self;
288 			break;
289 		case SQL_ATTR_IMP_ROW_DESC:
290 			memset(&(self->irdf), 0, sizeof(IRDFields));
291 			stmt->ird = self;
292 			stmt->ird->irdf.stmt = stmt;
293 			break;
294 		case SQL_ATTR_IMP_PARAM_DESC:
295 			memset(&(self->ipdf), 0, sizeof(IPDFields));
296 			stmt->ipd = self;
297 			break;
298 	}
299 }
300 
301 /*
302  * ARDFields initialize
303  */
304 void
InitializeARDFields(ARDFields * opt)305 InitializeARDFields(ARDFields *opt)
306 {
307 	memset(opt, 0, sizeof(ARDFields));
308 	opt->size_of_rowset = 1;
309 	opt->bind_size = 0;		/* default is to bind by column */
310 	opt->size_of_rowset_odbc2 = 1;
311 }
312 /*
313  * APDFields initialize
314  */
315 void
InitializeAPDFields(APDFields * opt)316 InitializeAPDFields(APDFields *opt)
317 {
318 	memset(opt, 0, sizeof(APDFields));
319 	opt->paramset_size = 1;
320 	opt->param_bind_type = 0;	/* default is to bind by column */
321 	opt->paramset_size_dummy = 1;	/* dummy setting */
322 }
323 
ARD_AllocBookmark(ARDFields * ardopts)324 BindInfoClass	*ARD_AllocBookmark(ARDFields *ardopts)
325 {
326 	if (!ardopts->bookmark)
327 	{
328 		ardopts->bookmark = (BindInfoClass *) malloc(sizeof(BindInfoClass));
329 		memset(ardopts->bookmark, 0, sizeof(BindInfoClass));
330 	}
331 	return ardopts->bookmark;
332 }
333 
334 #define	DESC_INCREMENT	10
CC_add_descriptor(ConnectionClass * self,DescriptorClass * desc)335 char CC_add_descriptor(ConnectionClass *self, DescriptorClass *desc)
336 {
337 	int	i;
338 	int	new_num_descs;
339 	DescriptorClass **descs;
340 
341 	MYLOG(0, "entering self=%p, desc=%p\n", self, desc);
342 
343 	for (i = 0; i < self->num_descs; i++)
344 	{
345 		if (!self->descs[i])
346 		{
347 			DC_get_conn(desc) = self;
348 			self->descs[i] = desc;
349 			return TRUE;
350 		}
351 	}
352         /* no more room -- allocate more memory */
353 	new_num_descs = DESC_INCREMENT + self->num_descs;
354 	descs = (DescriptorClass **) realloc(self->descs, sizeof(DescriptorClass *) * new_num_descs);
355 	if (!descs)
356 		return FALSE;
357 	self->descs = descs;
358 
359 	memset(&self->descs[self->num_descs], 0, sizeof(DescriptorClass *) *
360 				DESC_INCREMENT);
361         DC_get_conn(desc) = self;
362 	self->descs[self->num_descs] = desc;
363 	self->num_descs = new_num_descs;
364 
365 	return TRUE;
366 }
367 
368 /*
369  *	This API allocates a Application descriptor.
370  */
371 RETCODE SQL_API
PGAPI_AllocDesc(HDBC ConnectionHandle,SQLHDESC * DescriptorHandle)372 PGAPI_AllocDesc(HDBC ConnectionHandle,
373 				SQLHDESC *DescriptorHandle)
374 {
375 	CSTR func = "PGAPI_AllocDesc";
376 	ConnectionClass	*conn = (ConnectionClass *) ConnectionHandle;
377 	RETCODE	ret = SQL_SUCCESS;
378 	DescriptorClass	*desc;
379 
380 	MYLOG(0, "entering...\n");
381 
382 	desc = (DescriptorClass *) malloc(sizeof(DescriptorClass));
383 	if (desc)
384 	{
385 		memset(desc, 0, sizeof(DescriptorClass));
386 		DC_get_conn(desc) = conn;
387 		if (CC_add_descriptor(conn, desc))
388 			*DescriptorHandle = desc;
389 		else
390 		{
391 			free(desc);
392 			CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of descriptors exceeded", func);
393 			ret = SQL_ERROR;
394 		}
395 	}
396 	else
397 	{
398 		CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory ti allocate a further descriptor", func);
399 		ret = SQL_ERROR;
400 	}
401 	return ret;
402 }
403 
404 RETCODE SQL_API
PGAPI_FreeDesc(SQLHDESC DescriptorHandle)405 PGAPI_FreeDesc(SQLHDESC DescriptorHandle)
406 {
407 	DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
408 	RETCODE	ret = SQL_SUCCESS;
409 
410 	MYLOG(0, "entering...\n");
411 	DC_Destructor(desc);
412 	if (!desc->deschd.embedded)
413 	{
414 		int	i;
415 		ConnectionClass	*conn = DC_get_conn(desc);
416 
417 		for (i = 0; i < conn->num_descs; i++)
418 		{
419 			if (conn->descs[i] == desc)
420 			{
421 				conn->descs[i] = NULL;
422 				break;
423 			}
424 		}
425 		free(desc);
426 	}
427 	return ret;
428 }
429 
BindInfoClass_copy(const BindInfoClass * src,BindInfoClass * target)430 static void BindInfoClass_copy(const BindInfoClass *src, BindInfoClass *target)
431 {
432 	memcpy(target, src, sizeof(BindInfoClass));
433 }
ARDFields_copy(const ARDFields * src,ARDFields * target)434 static void ARDFields_copy(const ARDFields *src, ARDFields *target)
435 {
436 	memcpy(target, src, sizeof(ARDFields));
437 	target->bookmark = NULL;
438 	if (src->bookmark)
439 	{
440 		BindInfoClass *bookmark = ARD_AllocBookmark(target);
441 		if (bookmark)
442 			BindInfoClass_copy(src->bookmark, bookmark);
443 	}
444 	if (src->allocated <= 0)
445 	{
446 		target->allocated = 0;
447 		target->bindings = NULL;
448 	}
449 	else
450 	{
451 		int	i;
452 
453 		target->bindings = malloc(target->allocated * sizeof(BindInfoClass));
454 		if (!target->bindings)
455 			target->allocated = 0;
456 		for (i = 0; i < target->allocated; i++)
457 			BindInfoClass_copy(&src->bindings[i], &target->bindings[i]);
458 	}
459 }
460 
ParameterInfoClass_copy(const ParameterInfoClass * src,ParameterInfoClass * target)461 static void ParameterInfoClass_copy(const ParameterInfoClass *src, ParameterInfoClass *target)
462 {
463 	memcpy(target, src, sizeof(ParameterInfoClass));
464 }
APDFields_copy(const APDFields * src,APDFields * target)465 static void APDFields_copy(const APDFields *src, APDFields *target)
466 {
467 	memcpy(target, src, sizeof(APDFields));
468 	if (src->bookmark)
469 	{
470 		target->bookmark = malloc(sizeof(ParameterInfoClass));
471 		if (target->bookmark)
472 			ParameterInfoClass_copy(src->bookmark, target->bookmark);
473 	}
474 	if (src->allocated <= 0)
475 	{
476 		target->allocated = 0;
477 		target->parameters = NULL;
478 	}
479 	else
480 	{
481 		int	i;
482 
483 		target->parameters = malloc(target->allocated * sizeof(ParameterInfoClass));
484 		if (!target->parameters)
485 			target->allocated = 0;
486 		for (i = 0; i < target->allocated; i++)
487 			ParameterInfoClass_copy(&src->parameters[i], &target->parameters[i]);
488 	}
489 }
490 
ParameterImplClass_copy(const ParameterImplClass * src,ParameterImplClass * target)491 static void ParameterImplClass_copy(const ParameterImplClass *src, ParameterImplClass *target)
492 {
493 	memcpy(target, src, sizeof(ParameterImplClass));
494 }
IPDFields_copy(const IPDFields * src,IPDFields * target)495 static void IPDFields_copy(const IPDFields *src, IPDFields *target)
496 {
497 	memcpy(target, src, sizeof(IPDFields));
498 	if (src->allocated <= 0)
499 	{
500 		target->allocated = 0;
501 		target->parameters = NULL;
502 	}
503 	else
504 	{
505 		int	i;
506 
507 		target->parameters = (ParameterImplClass *) malloc(target->allocated * sizeof(ParameterImplClass));
508 		if (!target->parameters)
509 			target->allocated = 0;
510 		for (i = 0; i < target->allocated; i++)
511 			ParameterImplClass_copy(&src->parameters[i], &target->parameters[i]);
512 	}
513 }
514 
515 RETCODE	SQL_API
PGAPI_CopyDesc(SQLHDESC SourceDescHandle,SQLHDESC TargetDescHandle)516 PGAPI_CopyDesc(SQLHDESC SourceDescHandle,
517 			   SQLHDESC TargetDescHandle)
518 {
519 	RETCODE ret = SQL_ERROR;
520 	DescriptorClass	*src, *target;
521 	DescriptorHeader	*srchd, *targethd;
522 	ARDFields	*ard_src, *ard_tgt;
523 	APDFields	*apd_src, *apd_tgt;
524 	IPDFields	*ipd_src, *ipd_tgt;
525 
526 	MYLOG(0, "entering...\n");
527 	src = (DescriptorClass *) SourceDescHandle;
528 	target = (DescriptorClass *) TargetDescHandle;
529 	srchd = &(src->deschd);
530 	targethd = &(target->deschd);
531 	if (!srchd->type_defined)
532 	{
533 		MYLOG(0, "source type undefined\n");
534 		DC_set_error(target, DESC_EXEC_ERROR, "source handle type undefined");
535 		return ret;
536 	}
537 	if (targethd->type_defined)
538 	{
539 MYLOG(DETAIL_LOG_LEVEL, "source type=%d -> target type=%d\n", srchd->desc_type, targethd->desc_type);
540 		if (SQL_ATTR_IMP_ROW_DESC == targethd->desc_type)
541 		{
542 			MYLOG(0, "can't modify IRD\n");
543 			DC_set_error(target, DESC_EXEC_ERROR, "can't copy to IRD");
544 			return ret;
545 		}
546 		else if (targethd->desc_type != srchd->desc_type)
547 		{
548 			if (targethd->embedded)
549 			{
550 				MYLOG(0, "src type != target type\n");
551 				DC_set_error(target, DESC_EXEC_ERROR, "copying different type descriptor to embedded one");
552 				return ret;
553 			}
554 		}
555 		DC_Destructor(target);
556 	}
557 	ret = SQL_SUCCESS;
558 	switch (srchd->desc_type)
559 	{
560 		case SQL_ATTR_APP_ROW_DESC:
561 MYLOG(DETAIL_LOG_LEVEL, "src=%p target=%p type=%d", src, target, srchd->desc_type);
562 			if (!targethd->type_defined)
563 			{
564 				targethd->desc_type = srchd->desc_type;
565 			}
566 			ard_src = &(src->ardf);
567 MYPRINTF(DETAIL_LOG_LEVEL, " rowset_size=" FORMAT_LEN " bind_size=" FORMAT_UINTEGER " ope_ptr=%p off_ptr=%p\n",
568 ard_src->size_of_rowset, ard_src->bind_size,
569 ard_src->row_operation_ptr, ard_src->row_offset_ptr);
570 			ard_tgt = &(target->ardf);
571 MYPRINTF(DETAIL_LOG_LEVEL, " target=%p", ard_tgt);
572 			ARDFields_copy(ard_src, ard_tgt);
573 MYPRINTF(DETAIL_LOG_LEVEL, " offset_ptr=%p\n", ard_tgt->row_offset_ptr);
574 			break;
575 		case SQL_ATTR_APP_PARAM_DESC:
576 			if (!targethd->type_defined)
577 			{
578 				targethd->desc_type = srchd->desc_type;
579 			}
580 			apd_src = &(src->apdf);
581 			apd_tgt = &(target->apdf);
582 			APDFields_copy(apd_src, apd_tgt);
583 			break;
584 		case SQL_ATTR_IMP_PARAM_DESC:
585 			if (!targethd->type_defined)
586 			{
587 				targethd->desc_type = srchd->desc_type;
588 			}
589 			ipd_src = &(src->ipdf);
590 			ipd_tgt = &(target->ipdf);
591 			IPDFields_copy(ipd_src, ipd_tgt);
592 			break;
593 		default:
594 			MYLOG(0, "invalid descriptor handle type=%d\n", srchd->desc_type);
595 			DC_set_error(target, DESC_EXEC_ERROR, "invalid descriptor type");
596 			ret = SQL_ERROR;
597 	}
598 
599 	if (SQL_SUCCESS == ret)
600 		targethd->type_defined = TRUE;
601         return ret;
602 }
603 
DC_clear_error(DescriptorClass * self)604 void	DC_clear_error(DescriptorClass *self)
605 {
606 	DescriptorHeader *deschd = &(self->deschd);
607 	if (deschd->__error_message)
608 	{
609 		free(deschd->__error_message);
610 		deschd->__error_message = NULL;
611 	}
612 	if (deschd->pgerror)
613 	{
614 		ER_Destructor(deschd->pgerror);
615 		deschd->pgerror = NULL;
616 	}
617 	deschd->__error_number = 0;
618 	deschd->error_row = 0;
619 	deschd->error_index = 0;
620 }
621 
DC_set_error(DescriptorClass * self,int errornumber,const char * errormsg)622 void    DC_set_error(DescriptorClass *self, int errornumber, const char *errormsg)
623 {
624 	DescriptorHeader *deschd = &(self->deschd);
625 	if (deschd->__error_message)
626 		free(deschd->__error_message);
627 	deschd->__error_number = errornumber;
628 	deschd->__error_message = errormsg ? strdup(errormsg) : NULL;
629 }
DC_set_errormsg(DescriptorClass * self,const char * errormsg)630 void    DC_set_errormsg(DescriptorClass *self, const char *errormsg)
631 {
632 	DescriptorHeader *deschd = &(self->deschd);
633 	if (deschd->__error_message)
634 		free(deschd->__error_message);
635 	deschd->__error_message = errormsg ? strdup(errormsg) : NULL;
636 }
DC_get_errormsg(const DescriptorClass * desc)637 const char	*DC_get_errormsg(const DescriptorClass *desc)
638 {
639         return desc->deschd.__error_message;
640 }
DC_get_errornumber(const DescriptorClass * desc)641 int	DC_get_errornumber(const DescriptorClass *desc)
642 {
643         return desc->deschd.__error_number;
644 }
645 
646 /*	Map sql commands to statement types */
647 static const struct
648 {
649 	int		number;
650 	const char	ver3str[6];
651 	const char	ver2str[6];
652 }	Descriptor_sqlstate[] =
653 
654 {
655 	{ DESC_ERROR_IN_ROW, "01S01", "01S01" },
656 	{ DESC_OPTION_VALUE_CHANGED, "01S02", "01S02" },
657 	{ DESC_OK,  "00000", "00000" }, /* OK */
658 	{ DESC_EXEC_ERROR, "HY000", "S1000" }, /* also a general error */
659 	{ DESC_STATUS_ERROR, "HY010", "S1010" },
660 	{ DESC_SEQUENCE_ERROR, "HY010", "S1010" }, /* Function sequence error */
661 	{ DESC_NO_MEMORY_ERROR, "HY001", "S1001" }, /* memory allocation failure */
662 	{ DESC_COLNUM_ERROR, "07009", "S1002" }, /* invalid column number */
663 	{ DESC_NO_STMTSTRING, "HY001", "S1001" }, /* having no stmtstring is also a malloc problem */
664 	{ DESC_ERROR_TAKEN_FROM_BACKEND, "HY000", "S1000" }, /* general error */
665 	{ DESC_INTERNAL_ERROR, "HY000", "S1000" }, /* general error */
666 	{ DESC_STILL_EXECUTING, "HY010", "S1010" },
667 	{ DESC_NOT_IMPLEMENTED_ERROR, "HYC00", "S1C00" }, /* == 'driver not
668 							  * capable' */
669 	{ DESC_BAD_PARAMETER_NUMBER_ERROR, "07009", "S1093" },
670 	{ DESC_OPTION_OUT_OF_RANGE_ERROR, "HY092", "S1092" },
671 	{ DESC_INVALID_COLUMN_NUMBER_ERROR, "07009", "S1002" },
672 	{ DESC_RESTRICTED_DATA_TYPE_ERROR, "07006", "07006" },
673 	{ DESC_INVALID_CURSOR_STATE_ERROR, "07005", "24000" },
674 	{ DESC_CREATE_TABLE_ERROR, "42S01", "S0001" }, /* table already exists */
675 	{ DESC_NO_CURSOR_NAME, "S1015", "S1015" },
676 	{ DESC_INVALID_CURSOR_NAME, "34000", "34000" },
677 	{ DESC_INVALID_ARGUMENT_NO, "HY024", "S1009" }, /* invalid argument value */
678 	{ DESC_ROW_OUT_OF_RANGE, "HY107", "S1107" },
679 	{ DESC_OPERATION_CANCELLED, "HY008", "S1008" },
680 	{ DESC_INVALID_CURSOR_POSITION, "HY109", "S1109" },
681 	{ DESC_VALUE_OUT_OF_RANGE, "HY019", "22003" },
682 	{ DESC_OPERATION_INVALID, "HY011", "S1011" },
683 	{ DESC_PROGRAM_TYPE_OUT_OF_RANGE, "?????", "?????" },
684 	{ DESC_BAD_ERROR, "08S01", "08S01" }, /* communication link failure */
685 	{ DESC_INVALID_OPTION_IDENTIFIER, "HY092", "HY092" },
686 	{ DESC_RETURN_NULL_WITHOUT_INDICATOR, "22002", "22002" },
687 	{ DESC_INVALID_DESCRIPTOR_IDENTIFIER, "HY091", "HY091" },
688 	{ DESC_OPTION_NOT_FOR_THE_DRIVER, "HYC00", "HYC00" },
689 	{ DESC_FETCH_OUT_OF_RANGE, "HY106", "S1106" },
690 	{ DESC_COUNT_FIELD_INCORRECT, "07002", "07002" },
691 };
692 
DC_create_errorinfo(const DescriptorClass * self)693 static	PG_ErrorInfo	*DC_create_errorinfo(const DescriptorClass *self)
694 {
695 	const DescriptorHeader *deschd = &(self->deschd);
696 	PG_ErrorInfo	*error;
697 	ConnectionClass	*conn;
698 	EnvironmentClass	*env;
699 	Int4	errornum;
700 	BOOL		env_is_odbc3 = TRUE;
701 
702 	if (deschd->pgerror)
703 		return deschd->pgerror;
704 	errornum = deschd->__error_number;
705 	error = ER_Constructor(errornum, deschd->__error_message);
706 	if (!error)
707 		return error;
708 	conn = DC_get_conn(self);
709 	if (conn && (env = (EnvironmentClass *) conn->henv))
710 		env_is_odbc3 = EN_is_odbc3(env);
711 	errornum -= LOWEST_DESC_ERROR;
712 	if (errornum < 0 ||
713 	    errornum >= sizeof(Descriptor_sqlstate) / sizeof(Descriptor_sqlstate[0]))
714 		errornum = 1 - LOWEST_DESC_ERROR;
715 	STRCPY_FIXED(error->sqlstate, env_is_odbc3 ? Descriptor_sqlstate[errornum].ver3str : Descriptor_sqlstate[errornum].ver2str);
716         return error;
717 }
718 void
DC_log_error(const char * func,const char * desc,const DescriptorClass * self)719 DC_log_error(const char *func, const char *desc, const DescriptorClass *self)
720 {
721 #define nullcheck(a) (a ? a : "(NULL)")
722 	if (self)
723 	{
724 		MYLOG(0, "DESCRIPTOR ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->deschd.__error_number, nullcheck(self->deschd.__error_message));
725 	}
726 }
727 
728 /*		Returns the next SQL error information. */
729 RETCODE		SQL_API
PGAPI_DescError(SQLHDESC hdesc,SQLSMALLINT RecNumber,SQLCHAR * szSqlState,SQLINTEGER * pfNativeError,SQLCHAR * szErrorMsg,SQLSMALLINT cbErrorMsgMax,SQLSMALLINT * pcbErrorMsg,UWORD flag)730 PGAPI_DescError(SQLHDESC hdesc,
731 				SQLSMALLINT	RecNumber,
732 				SQLCHAR * szSqlState,
733 				SQLINTEGER * pfNativeError,
734 				SQLCHAR * szErrorMsg,
735 				SQLSMALLINT cbErrorMsgMax,
736 				SQLSMALLINT * pcbErrorMsg,
737 				UWORD flag)
738 {
739 	/* CC: return an error of a hdesc  */
740 	DescriptorClass *desc = (DescriptorClass *) hdesc;
741 	DescriptorHeader *deschd = &(desc->deschd);
742 
743 	MYLOG(0, "entering RecN=%hd\n", RecNumber);
744 	deschd->pgerror = DC_create_errorinfo(desc);
745 	return ER_ReturnError(deschd->pgerror, RecNumber, szSqlState,
746 				pfNativeError, szErrorMsg, cbErrorMsgMax,
747 				pcbErrorMsg, flag);
748 }
749