Merge commit 'origin/master'
[versaplex.git] / vxodbc / descriptor.cc
blob3e648ba7ff4460b90541af42582e44826f0aae4b
1 /*
2 * Description: This module contains functions related to creating
3 * and manipulating a statement.
4 */
5 #include "environ.h"
6 #include "connection.h"
7 #include "descriptor.h"
8 #include "statement.h"
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
14 #include "pgapifunc.h"
17 void TI_Constructor(TABLE_INFO * self, const ConnectionClass * conn)
19 memset(self, 0, sizeof(TABLE_INFO));
20 TI_set_updatable(self);
21 if (PG_VERSION_LT(conn, 7.2))
23 char qual[32];
25 STR_TO_NAME(self->bestitem, OID_NAME);
26 sprintf(qual, "\"oid\" = %%u");
27 STR_TO_NAME(self->bestqual, qual);
28 TI_set_hasoids(self);
29 TI_set_hasoids_checked(self);
32 void TI_Destructor(TABLE_INFO ** ti, int count)
34 int i;
36 inolog("TI_Destructor count=%d\n", count);
37 if (ti)
39 for (i = 0; i < count; i++)
41 if (ti[i])
43 NULL_THE_NAME(ti[i]->schema_name);
44 NULL_THE_NAME(ti[i]->table_name);
45 NULL_THE_NAME(ti[i]->table_alias);
46 NULL_THE_NAME(ti[i]->bestitem);
47 NULL_THE_NAME(ti[i]->bestqual);
48 free(ti[i]);
49 ti[i] = NULL;
54 void FI_Constructor(FIELD_INFO * self, BOOL reuse)
56 inolog("FI_Constructor reuse=%d\n", reuse);
57 if (reuse)
58 FI_Destructor(&self, 1, FALSE);
59 memset(self, 0, sizeof(FIELD_INFO));
60 self->nullable = TRUE;
62 void FI_Destructor(FIELD_INFO ** fi, int count, BOOL freeFI)
64 int i;
66 inolog("FI_Destructor count=%d\n", count);
67 if (fi)
69 for (i = 0; i < count; i++)
71 if (fi[i])
73 NULL_THE_NAME(fi[i]->column_name);
74 NULL_THE_NAME(fi[i]->column_alias);
75 NULL_THE_NAME(fi[i]->schema_name);
76 NULL_THE_NAME(fi[i]->before_dot);
77 if (freeFI)
79 free(fi[i]);
80 fi[i] = NULL;
84 if (freeFI)
85 free(fi);
89 void DC_Constructor(DescriptorClass * self, BOOL embedded,
90 StatementClass * stmt)
92 memset(self, 0, sizeof(DescriptorClass));
93 self->embedded = embedded;
96 static void ARDFields_free(ARDFields * self)
98 inolog("ARDFields_free %p bookmark=%p", self, self->bookmark);
99 if (self->bookmark)
101 free(self->bookmark);
102 self->bookmark = NULL;
104 inolog(" hey");
106 * the memory pointed to by the bindings is not deallocated by the
107 * driver but by the application that uses that driver, so we don't
108 * have to care
110 ARD_unbind_cols(self, TRUE);
113 static void APDFields_free(APDFields * self)
115 if (self->bookmark)
117 free(self->bookmark);
118 self->bookmark = NULL;
120 /* param bindings */
121 APD_free_params(self, STMT_FREE_PARAMS_ALL);
124 static void IRDFields_free(IRDFields * self)
126 /* Free the parsed field information */
127 if (self->fi)
129 FI_Destructor(self->fi, self->allocated, TRUE);
130 self->fi = NULL;
132 self->allocated = 0;
133 self->nfields = 0;
136 static void IPDFields_free(IPDFields * self)
138 /* param bindings */
139 IPD_free_params(self, STMT_FREE_PARAMS_ALL);
142 void DC_Destructor(DescriptorClass * self)
144 if (self->__error_message)
146 free(self->__error_message);
147 self->__error_message = NULL;
149 if (self->pgerror)
151 ER_Destructor(self->pgerror);
152 self->pgerror = NULL;
154 if (self->type_defined)
156 switch (self->desc_type)
158 case SQL_ATTR_APP_ROW_DESC:
159 ARDFields_free((ARDFields *) (self + 1));
160 break;
161 case SQL_ATTR_APP_PARAM_DESC:
162 APDFields_free((APDFields *) (self + 1));
163 break;
164 case SQL_ATTR_IMP_ROW_DESC:
165 IRDFields_free((IRDFields *) (self + 1));
166 break;
167 case SQL_ATTR_IMP_PARAM_DESC:
168 IPDFields_free((IPDFields *) (self + 1));
169 break;
174 void InitializeEmbeddedDescriptor(DescriptorClass * desc,
175 StatementClass * stmt,
176 UInt4 desc_type)
178 DC_Constructor(desc, TRUE, stmt);
179 DC_get_conn(desc) = SC_get_conn(stmt);
180 desc->type_defined = TRUE;
181 desc->desc_type = desc_type;
182 switch (desc_type)
184 case SQL_ATTR_APP_ROW_DESC:
185 memset(desc + 1, 0, sizeof(ARDFields));
186 stmt->ard = (ARDClass *) desc;
187 break;
188 case SQL_ATTR_APP_PARAM_DESC:
189 memset(desc + 1, 0, sizeof(APDFields));
190 stmt->apd = (APDClass *) desc;
191 break;
192 case SQL_ATTR_IMP_ROW_DESC:
193 memset(desc + 1, 0, sizeof(IRDFields));
194 stmt->ird = (IRDClass *) desc;
195 stmt->ird->irdopts.stmt = stmt;
196 break;
197 case SQL_ATTR_IMP_PARAM_DESC:
198 memset(desc + 1, 0, sizeof(IPDFields));
199 stmt->ipd = (IPDClass *) desc;
200 break;
205 * ARDFields initialize
207 void InitializeARDFields(ARDFields * opt)
209 memset(opt, 0, sizeof(ARDFields));
210 opt->size_of_rowset = 1;
211 opt->bind_size = 0; /* default is to bind by column */
212 opt->size_of_rowset_odbc2 = 1;
216 * APDFields initialize
218 void InitializeAPDFields(APDFields * opt)
220 memset(opt, 0, sizeof(APDFields));
221 opt->paramset_size = 1;
222 opt->param_bind_type = 0; /* default is to bind by column */
223 opt->paramset_size_dummy = 1; /* dummy setting */
226 BindInfoClass *ARD_AllocBookmark(ARDFields * ardopts)
228 if (!ardopts->bookmark)
230 ardopts->bookmark =
231 (BindInfoClass *) malloc(sizeof(BindInfoClass));
232 memset(ardopts->bookmark, 0, sizeof(BindInfoClass));
234 return ardopts->bookmark;
238 #define DESC_INCREMENT 10
239 char CC_add_descriptor(ConnectionClass * self, DescriptorClass * desc)
241 int i;
243 mylog("CC_add_descriptor: self=%p, desc=%p\n", self, desc);
245 for (i = 0; i < self->num_descs; i++)
247 if (!self->descs[i])
249 DC_get_conn(desc) = self;
250 self->descs[i] = desc;
251 return TRUE;
254 /* no more room -- allocate more memory */
255 self->descs =
256 (DescriptorClass **) realloc(self->descs,
257 sizeof(DescriptorClass *) *
258 (DESC_INCREMENT +
259 self->num_descs));
260 if (!self->descs)
261 return FALSE;
263 memset(&self->descs[self->num_descs], 0, sizeof(DescriptorClass *) *
264 DESC_INCREMENT);
265 DC_get_conn(desc) = self;
266 self->descs[self->num_descs] = desc;
267 self->num_descs += DESC_INCREMENT;
269 return TRUE;
273 * This API allocates a Application descriptor.
275 RETCODE SQL_API PGAPI_AllocDesc(HDBC ConnectionHandle,
276 SQLHDESC * DescriptorHandle)
278 CSTR func = "PGAPI_AllocDesc";
279 ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
280 RETCODE ret = SQL_SUCCESS;
281 DescriptorClass *desc =
282 (DescriptorClass *) malloc(sizeof(DescriptorAlloc));
284 mylog("%s: entering...\n", func);
285 if (desc)
287 memset(desc, 0, sizeof(DescriptorAlloc));
288 DC_get_conn(desc) = conn;
289 if (CC_add_descriptor(conn, desc))
290 *DescriptorHandle = desc;
291 else
293 free(desc);
294 CC_set_error(conn, CONN_STMT_ALLOC_ERROR,
295 "Maximum number of descriptors exceeded",
296 func);
297 ret = SQL_ERROR;
299 } else
301 CC_set_error(conn, CONN_STMT_ALLOC_ERROR,
302 "No more memory ti allocate a further descriptor",
303 func);
304 ret = SQL_ERROR;
306 return ret;
309 RETCODE SQL_API PGAPI_FreeDesc(SQLHDESC DescriptorHandle)
311 CSTR func = "PGAPI_FreeDesc";
312 DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
313 RETCODE ret = SQL_SUCCESS;
315 mylog("%s: entering...\n", func);
316 DC_Destructor(desc);
317 if (!desc->embedded)
319 int i;
320 ConnectionClass *conn = DC_get_conn(desc);
322 for (i = 0; i < conn->num_descs; i++)
324 if (conn->descs[i] == desc)
326 conn->descs[i] = NULL;
327 break;
330 free(desc);
332 return ret;
335 static void BindInfoClass_copy(const BindInfoClass * src,
336 BindInfoClass * target)
338 memcpy(target, src, sizeof(BindInfoClass));
340 static void ARDFields_copy(const ARDFields * src, ARDFields * target)
342 memcpy(target, src, sizeof(ARDFields));
343 target->bookmark = NULL;
344 if (src->bookmark)
346 BindInfoClass *bookmark = ARD_AllocBookmark(target);
347 BindInfoClass_copy(src->bookmark, bookmark);
349 if (src->allocated <= 0)
351 target->allocated = 0;
352 target->bindings = NULL;
353 } else
355 int i;
357 target->bindings = (BindInfoClass *)
358 malloc(target->allocated * sizeof(BindInfoClass));
359 for (i = 0; i < target->allocated; i++)
360 BindInfoClass_copy(&src->bindings[i], &target->bindings[i]);
364 static void ParameterInfoClass_copy(const ParameterInfoClass * src,
365 ParameterInfoClass * target)
367 memcpy(target, src, sizeof(ParameterInfoClass));
369 static void APDFields_copy(const APDFields * src, APDFields * target)
371 memcpy(target, src, sizeof(APDFields));
372 if (src->bookmark)
374 target->bookmark = (ParameterInfoClass *)
375 malloc(sizeof(ParameterInfoClass));
376 ParameterInfoClass_copy(src->bookmark, target->bookmark);
378 if (src->allocated <= 0)
380 target->allocated = 0;
381 target->parameters = NULL;
382 } else
384 int i;
386 target->parameters = (ParameterInfoClass *)
387 malloc(target->allocated * sizeof(ParameterInfoClass));
388 for (i = 0; i < target->allocated; i++)
389 ParameterInfoClass_copy(&src->parameters[i],
390 &target->parameters[i]);
394 static void ParameterImplClass_copy(const ParameterImplClass * src,
395 ParameterImplClass * target)
397 memcpy(target, src, sizeof(ParameterImplClass));
399 static void IPDFields_copy(const IPDFields * src, IPDFields * target)
401 memcpy(target, src, sizeof(IPDFields));
402 if (src->allocated <= 0)
404 target->allocated = 0;
405 target->parameters = NULL;
406 } else
408 int i;
410 target->parameters =
411 (ParameterImplClass *) malloc(target->allocated *
412 sizeof(ParameterInfoClass));
413 for (i = 0; i < target->allocated; i++)
414 ParameterImplClass_copy(&src->parameters[i],
415 &target->parameters[i]);
419 RETCODE SQL_API
420 PGAPI_CopyDesc(SQLHDESC SourceDescHandle, SQLHDESC TargetDescHandle)
422 CSTR func = "PGAPI_CopyDesc";
423 RETCODE ret = SQL_ERROR;
424 DescriptorClass *src, *target;
425 ARDFields *ard_src, *ard_tgt;
426 APDFields *apd_src, *apd_tgt;
427 IPDFields *ipd_src, *ipd_tgt;
429 mylog("%s: entering...\n", func);
430 src = (DescriptorClass *) SourceDescHandle;
431 target = (DescriptorClass *) TargetDescHandle;
432 if (!src->type_defined)
434 mylog("source type undefined\n");
435 DC_set_error(target, DESC_EXEC_ERROR,
436 "source handle type undefined");
437 return ret;
439 if (target->type_defined)
441 inolog("source type=%d -> target type=%d\n", src->desc_type,
442 target->desc_type);
443 if (SQL_ATTR_IMP_ROW_DESC == target->desc_type)
445 mylog("can't modify IRD\n");
446 DC_set_error(target, DESC_EXEC_ERROR, "can't copy to IRD");
447 return ret;
448 } else if (target->desc_type != src->desc_type)
450 mylog("src type != target type\n");
451 DC_set_error(target, DESC_EXEC_ERROR,
452 "src descriptor != target type");
453 return ret;
455 DC_Destructor(target);
457 ret = SQL_SUCCESS;
458 switch (src->desc_type)
460 case SQL_ATTR_APP_ROW_DESC:
461 inolog("src=%p target=%p type=%d", src, target, src->desc_type);
462 if (!target->type_defined)
464 target->desc_type = src->desc_type;
466 ard_src = (ARDFields *) (src + 1);
467 inolog(" rowset_size=%d bind_size=%d ope_ptr=%p off_ptr=%p\n",
468 ard_src->size_of_rowset, ard_src->bind_size,
469 ard_src->row_operation_ptr, ard_src->row_offset_ptr);
470 ard_tgt = (ARDFields *) (target + 1);
471 inolog(" target=%p", ard_tgt);
472 ARDFields_copy(ard_src, ard_tgt);
473 inolog(" offset_ptr=%p\n", ard_tgt->row_offset_ptr);
474 break;
475 case SQL_ATTR_APP_PARAM_DESC:
476 if (!target->type_defined)
478 target->desc_type = src->desc_type;
480 apd_src = (APDFields *) (src + 1);
481 apd_tgt = (APDFields *) (target + 1);
482 APDFields_copy(apd_src, apd_tgt);
483 break;
484 case SQL_ATTR_IMP_PARAM_DESC:
485 if (!target->type_defined)
487 target->desc_type = src->desc_type;
489 ipd_src = (IPDFields *) (src + 1);
490 ipd_tgt = (IPDFields *) (target + 1);
491 IPDFields_copy(ipd_src, ipd_tgt);
492 break;
493 default:
494 mylog("invalid descriptor handle type=%d\n", src->desc_type);
495 DC_set_error(target, DESC_EXEC_ERROR,
496 "invalid descriptor type");
497 ret = SQL_ERROR;
500 if (SQL_SUCCESS == ret)
501 target->type_defined = TRUE;
502 return ret;
505 void DC_clear_error(DescriptorClass * self)
507 if (self->__error_message)
509 free(self->__error_message);
510 self->__error_message = NULL;
512 if (self->pgerror)
514 ER_Destructor(self->pgerror);
515 self->pgerror = NULL;
517 self->__error_number = 0;
518 self->error_row = 0;
519 self->error_index = 0;
522 void DC_set_error(DescriptorClass * desc, int errornumber,
523 const char *errormsg)
525 if (desc->__error_message)
526 free(desc->__error_message);
527 desc->__error_number = errornumber;
528 desc->__error_message = errormsg ? strdup(errormsg) : NULL;
530 void DC_set_errormsg(DescriptorClass * desc, const char *errormsg)
532 if (desc->__error_message)
533 free(desc->__error_message);
534 desc->__error_message = errormsg ? strdup(errormsg) : NULL;
536 const char *DC_get_errormsg(const DescriptorClass * desc)
538 return desc->__error_message;
540 int DC_get_errornumber(const DescriptorClass * desc)
542 return desc->__error_number;
545 /* Map sql commands to statement types */
546 static struct {
547 int number;
548 const char *ver3str;
549 const char *ver2str;
550 } Descriptor_sqlstate[] =
553 DESC_ERROR_IN_ROW, "01S01", "01S01"},
555 DESC_OPTION_VALUE_CHANGED, "01S02", "01S02"},
557 DESC_OK, "00000", "00000"}, /* OK */
559 DESC_EXEC_ERROR, "HY000", "S1000"}, /* also a general error */
561 DESC_STATUS_ERROR, "HY010", "S1010"},
563 DESC_SEQUENCE_ERROR, "HY010", "S1010"}, /* Function sequence error */
565 DESC_NO_MEMORY_ERROR, "HY001", "S1001"}, /* memory allocation failure */
567 DESC_COLNUM_ERROR, "07009", "S1002"}, /* invalid column number */
569 DESC_NO_STMTSTRING, "HY001", "S1001"}, /* having no stmtstring is also a malloc problem */
571 DESC_ERROR_TAKEN_FROM_BACKEND, "HY000", "S1000"}, /* general error */
573 DESC_INTERNAL_ERROR, "HY000", "S1000"}, /* general error */
575 DESC_STILL_EXECUTING, "HY010", "S1010"},
577 DESC_NOT_IMPLEMENTED_ERROR, "HYC00", "S1C00"}, /* == 'driver not
578 * capable' */
580 DESC_BAD_PARAMETER_NUMBER_ERROR, "07009", "S1093"},
582 DESC_OPTION_OUT_OF_RANGE_ERROR, "HY092", "S1092"},
584 DESC_INVALID_COLUMN_NUMBER_ERROR, "07009", "S1002"},
586 DESC_RESTRICTED_DATA_TYPE_ERROR, "07006", "07006"},
588 DESC_INVALID_CURSOR_STATE_ERROR, "07005", "24000"},
590 DESC_CREATE_TABLE_ERROR, "42S01", "S0001"}, /* table already exists */
592 DESC_NO_CURSOR_NAME, "S1015", "S1015"},
594 DESC_INVALID_CURSOR_NAME, "34000", "34000"},
596 DESC_INVALID_ARGUMENT_NO, "HY024", "S1009"}, /* invalid argument value */
598 DESC_ROW_OUT_OF_RANGE, "HY107", "S1107"},
600 DESC_OPERATION_CANCELLED, "HY008", "S1008"},
602 DESC_INVALID_CURSOR_POSITION, "HY109", "S1109"},
604 DESC_VALUE_OUT_OF_RANGE, "HY019", "22003"},
606 DESC_OPERATION_INVALID, "HY011", "S1011"},
608 DESC_PROGRAM_TYPE_OUT_OF_RANGE, "?????", "?????"},
610 DESC_BAD_ERROR, "08S01", "08S01"}, /* communication link failure */
612 DESC_INVALID_OPTION_IDENTIFIER, "HY092", "HY092"},
614 DESC_RETURN_NULL_WITHOUT_INDICATOR, "22002", "22002"},
616 DESC_INVALID_DESCRIPTOR_IDENTIFIER, "HY091", "HY091"},
618 DESC_OPTION_NOT_FOR_THE_DRIVER, "HYC00", "HYC00"},
620 DESC_FETCH_OUT_OF_RANGE, "HY106", "S1106"},
622 DESC_COUNT_FIELD_INCORRECT, "07002", "07002"},};
624 static PG_ErrorInfo *DC_create_errorinfo(const DescriptorClass * desc)
626 PG_ErrorInfo *error;
627 ConnectionClass *conn;
628 EnvironmentClass *env;
629 Int4 errornum;
630 BOOL env_is_odbc3 = TRUE;
632 if (desc->pgerror)
633 return desc->pgerror;
634 errornum = desc->__error_number;
635 error = ER_Constructor(errornum, desc->__error_message);
636 if (!error)
637 return error;
638 conn = DC_get_conn(desc);
639 if (conn && (env = (EnvironmentClass *) conn->henv))
640 env_is_odbc3 = EN_is_odbc3(env);
641 errornum -= LOWEST_DESC_ERROR;
642 if (errornum < 0 ||
643 errornum >=
644 sizeof(Descriptor_sqlstate) / sizeof(Descriptor_sqlstate[0]))
645 errornum = 1 - LOWEST_DESC_ERROR;
646 strcpy(error->sqlstate,
647 env_is_odbc3 ? Descriptor_sqlstate[errornum].
648 ver3str : Descriptor_sqlstate[errornum].ver2str);
649 return error;
651 void
652 DC_log_error(const char *func, const char *desc,
653 const DescriptorClass * self)
655 #define nullcheck(a) (a ? a : "(NULL)")
656 if (self)
658 qlog("DESCRIPTOR ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
659 mylog
660 ("DESCRIPTOR ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n",
661 func, desc, self->__error_number,
662 nullcheck(self->__error_message));
666 /* Returns the next SQL error information. */
667 RETCODE SQL_API
668 PGAPI_DescError(SQLHDESC hdesc,
669 SQLSMALLINT RecNumber,
670 SQLCHAR FAR * szSqlState,
671 SQLINTEGER FAR * pfNativeError,
672 SQLCHAR FAR * szErrorMsg,
673 SQLSMALLINT cbErrorMsgMax,
674 SQLSMALLINT FAR * pcbErrorMsg, UWORD flag)
676 CSTR func = "PGAPI_DescError";
677 /* CC: return an error of a hdesc */
678 DescriptorClass *desc = (DescriptorClass *) hdesc;
680 mylog("%s RecN=%d\n", func);
681 desc->pgerror = DC_create_errorinfo(desc);
682 return ER_ReturnError(&(desc->pgerror), RecNumber, szSqlState,
683 pfNativeError, szErrorMsg, cbErrorMsgMax,
684 pcbErrorMsg, flag);