1 Star 0 Fork 46

卢乾辅@swy.com / openGauss-connector-odbc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
descriptor.c 18.65 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
/*-------
* Module: descriptor.c
*
* Description: This module contains functions related to creating
* and manipulating a statement.
*
* Classes: DescriptorClass (Functions prefix: "DC_")
*
*
* Comments: See "readme.txt" for copyright and license information.
*-------
*/
#include "environ.h"
#include "connection.h"
#include "descriptor.h"
#include "statement.h"
#include "qresult.h"
#include "misc.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "pgapifunc.h"
void TI_Constructor(TABLE_INFO *self, const ConnectionClass *conn)
{
memset(self, 0, sizeof(TABLE_INFO));
TI_set_updatable(self);
}
void TI_Destructor(TABLE_INFO **ti, int count)
{
int i;
MYLOG(DETAIL_LOG_LEVEL, "entering count=%d\n", count);
if (ti)
{
for (i = 0; i < count; i++)
{
if (ti[i])
{
COL_INFO *coli = ti[i]->col_info;
if (coli)
{
MYLOG(0, "!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
coli->refcnt--;
if (coli->refcnt <= 0 && 0 == coli->acc_time) /* acc_time == 0 means the table is dropped */
free_col_info_contents(coli);
}
NULL_THE_NAME(ti[i]->schema_name);
NULL_THE_NAME(ti[i]->table_name);
NULL_THE_NAME(ti[i]->table_alias);
NULL_THE_NAME(ti[i]->bestitem);
NULL_THE_NAME(ti[i]->bestqual);
TI_Destroy_IH(ti[i]);
free(ti[i]);
ti[i] = NULL;
}
}
}
}
void FI_Constructor(FIELD_INFO *self, BOOL reuse)
{
MYLOG(DETAIL_LOG_LEVEL, "entering reuse=%d\n", reuse);
if (reuse)
FI_Destructor(&self, 1, FALSE);
memset(self, 0, sizeof(FIELD_INFO));
self->nullable = TRUE;
self->columnkey = -1;
self->typmod = -1;
}
void FI_Destructor(FIELD_INFO **fi, int count, BOOL freeFI)
{
int i;
MYLOG(DETAIL_LOG_LEVEL, "entering count=%d\n", count);
if (fi)
{
for (i = 0; i < count; i++)
{
if (fi[i])
{
NULL_THE_NAME(fi[i]->column_name);
NULL_THE_NAME(fi[i]->column_alias);
NULL_THE_NAME(fi[i]->schema_name);
NULL_THE_NAME(fi[i]->before_dot);
if (freeFI)
{
free(fi[i]);
fi[i] = NULL;
}
}
}
if (freeFI)
free(fi);
}
}
static const pgNAME invNAME = {NULL};
#define INIT_IH 32
void TI_Create_IH(TABLE_INFO *ti)
{
int alloc = INIT_IH;
InheritanceClass *ih;
ih = (InheritanceClass *) malloc(sizeof(InheritanceClass) + (alloc - 1) * sizeof(ih->inf[0]));
memset(ih, 0, sizeof(InheritanceClass));
ih->allocated = alloc;
ti->ih = ih;
}
void TI_Destroy_IH(TABLE_INFO *ti)
{
InheritanceClass *ih;
int i;
if (NULL == (ih = ti->ih))
return;
for (i = 0; i < ih->count; i++)
{
NULL_THE_NAME(ih->inf[i].fullTable);
}
free(ih);
ti->ih = NULL;
}
const pgNAME TI_From_IH(TABLE_INFO *ti, OID tableoid)
{
InheritanceClass *ih;
int i;
if (NULL == (ih = ti->ih))
return invNAME;
if (tableoid == ih->cur_tableoid)
return ih->cur_fullTable;
for (i = 0; i < ih->count; i++)
{
if (ih->inf[i].tableoid == tableoid)
{
ih->cur_tableoid = tableoid;
ih->cur_fullTable = ih->inf[i].fullTable;
return ih->cur_fullTable;
}
}
return invNAME;
}
const pgNAME TI_Ins_IH(TABLE_INFO *ti, OID tableoid, const char *fullName)
{
InheritanceClass *ih;
int count;
if (NULL == (ih = ti->ih))
{
TI_Create_IH(ti);
if (ih = ti->ih, NULL == ih)
return invNAME;
}
if ((count = ih->count) >= ih->allocated)
{
int alloc = ih->allocated * 2;
InheritanceClass *nih;
if (nih = (InheritanceClass *) realloc(ih, sizeof(InheritanceClass) + (alloc - 1) * sizeof(ih->inf[0])), NULL == nih)
{
TI_Destroy_IH(ti);
return invNAME;
}
ti->ih = ih = nih;
ih->allocated = alloc;
}
ih->inf[count].tableoid = tableoid;
INIT_NAME(ih->inf[count].fullTable);
STR_TO_NAME(ih->inf[count].fullTable, fullName);
ih->cur_tableoid = tableoid;
ih->cur_fullTable = ih->inf[count].fullTable;
ih->count++;
return ih->inf[count].fullTable;
}
void DC_Constructor(DescriptorClass *self, BOOL embedded, StatementClass *stmt)
{
memset(self, 0, sizeof(DescriptorClass));
self->deschd.embedded = embedded;
}
static void ARDFields_free(ARDFields * self)
{
MYLOG(DETAIL_LOG_LEVEL, "entering %p bookmark=%p\n", self, self->bookmark);
if (self->bookmark)
{
free(self->bookmark);
self->bookmark = NULL;
}
/*
* the memory pointed to by the bindings is not deallocated by the
* driver but by the application that uses that driver, so we don't
* have to care
*/
ARD_unbind_cols(self, TRUE);
}
static void APDFields_free(APDFields * self)
{
if (self->bookmark)
{
free(self->bookmark);
self->bookmark = NULL;
}
/* param bindings */
APD_free_params(self, STMT_FREE_PARAMS_ALL);
}
static void IRDFields_free(IRDFields * self)
{
/* Free the parsed field information */
if (self->fi)
{
FI_Destructor(self->fi, self->allocated, TRUE);
self->fi = NULL;
}
self->allocated = 0;
self->nfields = 0;
}
static void IPDFields_free(IPDFields * self)
{
/* param bindings */
IPD_free_params(self, STMT_FREE_PARAMS_ALL);
}
void DC_Destructor(DescriptorClass *self)
{
DescriptorHeader *deschd = &(self->deschd);
if (deschd->__error_message)
{
free(deschd->__error_message);
deschd->__error_message = NULL;
}
if (deschd->pgerror)
{
ER_Destructor(deschd->pgerror);
deschd->pgerror = NULL;
}
if (deschd->type_defined)
{
switch (deschd->desc_type)
{
case SQL_ATTR_APP_ROW_DESC:
ARDFields_free(&(self->ardf));
break;
case SQL_ATTR_APP_PARAM_DESC:
APDFields_free(&(self->apdf));
break;
case SQL_ATTR_IMP_ROW_DESC:
IRDFields_free(&(self->irdf));
break;
case SQL_ATTR_IMP_PARAM_DESC:
IPDFields_free(&(self->ipdf));
break;
}
}
}
void InitializeEmbeddedDescriptor(DescriptorClass *self, StatementClass *stmt,
UInt4 desc_type)
{
DescriptorHeader *deschd = &(self->deschd);
DC_Constructor(self, TRUE, stmt);
DC_get_conn(self) = SC_get_conn(stmt);
deschd->type_defined = TRUE;
deschd->desc_type = desc_type;
switch (desc_type)
{
case SQL_ATTR_APP_ROW_DESC:
memset(&(self->ardf), 0, sizeof(ARDFields));
stmt->ard = self;
break;
case SQL_ATTR_APP_PARAM_DESC:
memset(&(self->apdf), 0, sizeof(APDFields));
stmt->apd = self;
break;
case SQL_ATTR_IMP_ROW_DESC:
memset(&(self->irdf), 0, sizeof(IRDFields));
stmt->ird = self;
stmt->ird->irdf.stmt = stmt;
break;
case SQL_ATTR_IMP_PARAM_DESC:
memset(&(self->ipdf), 0, sizeof(IPDFields));
stmt->ipd = self;
break;
}
}
/*
* ARDFields initialize
*/
void
InitializeARDFields(ARDFields *opt)
{
memset(opt, 0, sizeof(ARDFields));
opt->size_of_rowset = 1;
opt->bind_size = 0; /* default is to bind by column */
opt->size_of_rowset_odbc2 = 1;
}
/*
* APDFields initialize
*/
void
InitializeAPDFields(APDFields *opt)
{
memset(opt, 0, sizeof(APDFields));
opt->paramset_size = 1;
opt->param_bind_type = 0; /* default is to bind by column */
opt->paramset_size_dummy = 1; /* dummy setting */
}
BindInfoClass *ARD_AllocBookmark(ARDFields *ardopts)
{
if (!ardopts->bookmark)
{
ardopts->bookmark = (BindInfoClass *) malloc(sizeof(BindInfoClass));
if (ardopts->bookmark)
memset(ardopts->bookmark, 0, sizeof(BindInfoClass));
}
return ardopts->bookmark;
}
#define DESC_INCREMENT 10
char CC_add_descriptor(ConnectionClass *self, DescriptorClass *desc)
{
int i;
int new_num_descs;
DescriptorClass **descs;
MYLOG(0, "entering self=%p, desc=%p\n", self, desc);
for (i = 0; i < self->num_descs; i++)
{
if (!self->descs[i])
{
DC_get_conn(desc) = self;
self->descs[i] = desc;
return TRUE;
}
}
/* no more room -- allocate more memory */
new_num_descs = DESC_INCREMENT + self->num_descs;
descs = (DescriptorClass **) realloc(self->descs, sizeof(DescriptorClass *) * new_num_descs);
if (!descs)
return FALSE;
self->descs = descs;
memset(&self->descs[self->num_descs], 0, sizeof(DescriptorClass *) *
DESC_INCREMENT);
DC_get_conn(desc) = self;
self->descs[self->num_descs] = desc;
self->num_descs = new_num_descs;
return TRUE;
}
/*
* This API allocates a Application descriptor.
*/
RETCODE SQL_API
PGAPI_AllocDesc(HDBC ConnectionHandle,
SQLHDESC *DescriptorHandle)
{
CSTR func = "PGAPI_AllocDesc";
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
RETCODE ret = SQL_SUCCESS;
DescriptorClass *desc;
MYLOG(0, "entering...\n");
desc = (DescriptorClass *) malloc(sizeof(DescriptorClass));
if (desc)
{
memset(desc, 0, sizeof(DescriptorClass));
DC_get_conn(desc) = conn;
if (CC_add_descriptor(conn, desc))
*DescriptorHandle = desc;
else
{
free(desc);
CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of descriptors exceeded", func);
ret = SQL_ERROR;
}
}
else
{
CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory ti allocate a further descriptor", func);
ret = SQL_ERROR;
}
return ret;
}
RETCODE SQL_API
PGAPI_FreeDesc(SQLHDESC DescriptorHandle)
{
DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
RETCODE ret = SQL_SUCCESS;
MYLOG(0, "entering...\n");
DC_Destructor(desc);
if (!desc->deschd.embedded)
{
int i;
ConnectionClass *conn = DC_get_conn(desc);
for (i = 0; i < conn->num_descs; i++)
{
if (conn->descs[i] == desc)
{
conn->descs[i] = NULL;
break;
}
}
free(desc);
}
return ret;
}
static void BindInfoClass_copy(const BindInfoClass *src, BindInfoClass *target)
{
memcpy(target, src, sizeof(BindInfoClass));
}
static void ARDFields_copy(const ARDFields *src, ARDFields *target)
{
memcpy(target, src, sizeof(ARDFields));
target->bookmark = NULL;
if (src->bookmark)
{
BindInfoClass *bookmark = ARD_AllocBookmark(target);
if (bookmark)
BindInfoClass_copy(src->bookmark, bookmark);
}
if (src->allocated <= 0)
{
target->allocated = 0;
target->bindings = NULL;
}
else
{
int i;
target->bindings = malloc(target->allocated * sizeof(BindInfoClass));
if (!target->bindings)
target->allocated = 0;
for (i = 0; i < target->allocated; i++)
BindInfoClass_copy(&src->bindings[i], &target->bindings[i]);
}
}
static void ParameterInfoClass_copy(const ParameterInfoClass *src, ParameterInfoClass *target)
{
memcpy(target, src, sizeof(ParameterInfoClass));
}
static void APDFields_copy(const APDFields *src, APDFields *target)
{
memcpy(target, src, sizeof(APDFields));
if (src->bookmark)
{
target->bookmark = malloc(sizeof(ParameterInfoClass));
if (target->bookmark)
ParameterInfoClass_copy(src->bookmark, target->bookmark);
}
if (src->allocated <= 0)
{
target->allocated = 0;
target->parameters = NULL;
}
else
{
int i;
target->parameters = malloc(target->allocated * sizeof(ParameterInfoClass));
if (!target->parameters)
target->allocated = 0;
for (i = 0; i < target->allocated; i++)
ParameterInfoClass_copy(&src->parameters[i], &target->parameters[i]);
}
}
static void ParameterImplClass_copy(const ParameterImplClass *src, ParameterImplClass *target)
{
memcpy(target, src, sizeof(ParameterImplClass));
}
static void IPDFields_copy(const IPDFields *src, IPDFields *target)
{
memcpy(target, src, sizeof(IPDFields));
if (src->allocated <= 0)
{
target->allocated = 0;
target->parameters = NULL;
}
else
{
int i;
target->parameters = (ParameterImplClass *) malloc(target->allocated * sizeof(ParameterImplClass));
if (!target->parameters)
target->allocated = 0;
for (i = 0; i < target->allocated; i++)
ParameterImplClass_copy(&src->parameters[i], &target->parameters[i]);
}
}
RETCODE SQL_API
PGAPI_CopyDesc(SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle)
{
RETCODE ret = SQL_ERROR;
DescriptorClass *src, *target;
DescriptorHeader *srchd, *targethd;
ARDFields *ard_src, *ard_tgt;
APDFields *apd_src, *apd_tgt;
IPDFields *ipd_src, *ipd_tgt;
MYLOG(0, "entering...\n");
src = (DescriptorClass *) SourceDescHandle;
target = (DescriptorClass *) TargetDescHandle;
srchd = &(src->deschd);
targethd = &(target->deschd);
if (!srchd->type_defined)
{
MYLOG(0, "source type undefined\n");
DC_set_error(target, DESC_EXEC_ERROR, "source handle type undefined");
return ret;
}
if (targethd->type_defined)
{
MYLOG(DETAIL_LOG_LEVEL, "source type=%d -> target type=%d\n", srchd->desc_type, targethd->desc_type);
if (SQL_ATTR_IMP_ROW_DESC == targethd->desc_type)
{
MYLOG(0, "can't modify IRD\n");
DC_set_error(target, DESC_EXEC_ERROR, "can't copy to IRD");
return ret;
}
else if (targethd->desc_type != srchd->desc_type)
{
if (targethd->embedded)
{
MYLOG(0, "src type != target type\n");
DC_set_error(target, DESC_EXEC_ERROR, "copying different type descriptor to embedded one");
return ret;
}
}
DC_Destructor(target);
}
ret = SQL_SUCCESS;
switch (srchd->desc_type)
{
case SQL_ATTR_APP_ROW_DESC:
MYLOG(DETAIL_LOG_LEVEL, "src=%p target=%p type=%d", src, target, srchd->desc_type);
if (!targethd->type_defined)
{
targethd->desc_type = srchd->desc_type;
}
ard_src = &(src->ardf);
MYPRINTF(DETAIL_LOG_LEVEL, " rowset_size=" FORMAT_LEN " bind_size=%d ope_ptr=%p off_ptr=%p\n",
ard_src->size_of_rowset, ard_src->bind_size,
ard_src->row_operation_ptr, ard_src->row_offset_ptr);
ard_tgt = &(target->ardf);
MYPRINTF(DETAIL_LOG_LEVEL, " target=%p", ard_tgt);
ARDFields_copy(ard_src, ard_tgt);
MYPRINTF(DETAIL_LOG_LEVEL, " offset_ptr=%p\n", ard_tgt->row_offset_ptr);
break;
case SQL_ATTR_APP_PARAM_DESC:
if (!targethd->type_defined)
{
targethd->desc_type = srchd->desc_type;
}
apd_src = &(src->apdf);
apd_tgt = &(target->apdf);
APDFields_copy(apd_src, apd_tgt);
break;
case SQL_ATTR_IMP_PARAM_DESC:
if (!targethd->type_defined)
{
targethd->desc_type = srchd->desc_type;
}
ipd_src = &(src->ipdf);
ipd_tgt = &(target->ipdf);
IPDFields_copy(ipd_src, ipd_tgt);
break;
default:
MYLOG(0, "invalid descriptor handle type=%d\n", srchd->desc_type);
DC_set_error(target, DESC_EXEC_ERROR, "invalid descriptor type");
ret = SQL_ERROR;
}
if (SQL_SUCCESS == ret)
targethd->type_defined = TRUE;
return ret;
}
void DC_clear_error(DescriptorClass *self)
{
DescriptorHeader *deschd = &(self->deschd);
if (deschd->__error_message)
{
free(deschd->__error_message);
deschd->__error_message = NULL;
}
if (deschd->pgerror)
{
ER_Destructor(deschd->pgerror);
deschd->pgerror = NULL;
}
deschd->__error_number = 0;
deschd->error_row = 0;
deschd->error_index = 0;
}
void DC_set_error(DescriptorClass *self, int errornumber, const char *errormsg)
{
DescriptorHeader *deschd = &(self->deschd);
if (deschd->__error_message)
free(deschd->__error_message);
deschd->__error_number = errornumber;
deschd->__error_message = errormsg ? strdup(errormsg) : NULL;
}
void DC_set_errormsg(DescriptorClass *self, const char *errormsg)
{
DescriptorHeader *deschd = &(self->deschd);
if (deschd->__error_message)
free(deschd->__error_message);
deschd->__error_message = errormsg ? strdup(errormsg) : NULL;
}
const char *DC_get_errormsg(const DescriptorClass *desc)
{
return desc->deschd.__error_message;
}
int DC_get_errornumber(const DescriptorClass *desc)
{
return desc->deschd.__error_number;
}
/* Map sql commands to statement types */
static const struct
{
int number;
const char ver3str[6];
const char ver2str[6];
} Descriptor_sqlstate[] =
{
{ DESC_ERROR_IN_ROW, "01S01", "01S01" },
{ DESC_OPTION_VALUE_CHANGED, "01S02", "01S02" },
{ DESC_OK, "00000", "00000" }, /* OK */
{ DESC_EXEC_ERROR, "HY000", "S1000" }, /* also a general error */
{ DESC_STATUS_ERROR, "HY010", "S1010" },
{ DESC_SEQUENCE_ERROR, "HY010", "S1010" }, /* Function sequence error */
{ DESC_NO_MEMORY_ERROR, "HY001", "S1001" }, /* memory allocation failure */
{ DESC_COLNUM_ERROR, "07009", "S1002" }, /* invalid column number */
{ DESC_NO_STMTSTRING, "HY001", "S1001" }, /* having no stmtstring is also a malloc problem */
{ DESC_ERROR_TAKEN_FROM_BACKEND, "HY000", "S1000" }, /* general error */
{ DESC_INTERNAL_ERROR, "HY000", "S1000" }, /* general error */
{ DESC_STILL_EXECUTING, "HY010", "S1010" },
{ DESC_NOT_IMPLEMENTED_ERROR, "HYC00", "S1C00" }, /* == 'driver not
* capable' */
{ DESC_BAD_PARAMETER_NUMBER_ERROR, "07009", "S1093" },
{ DESC_OPTION_OUT_OF_RANGE_ERROR, "HY092", "S1092" },
{ DESC_INVALID_COLUMN_NUMBER_ERROR, "07009", "S1002" },
{ DESC_RESTRICTED_DATA_TYPE_ERROR, "07006", "07006" },
{ DESC_INVALID_CURSOR_STATE_ERROR, "07005", "24000" },
{ DESC_CREATE_TABLE_ERROR, "42S01", "S0001" }, /* table already exists */
{ DESC_NO_CURSOR_NAME, "S1015", "S1015" },
{ DESC_INVALID_CURSOR_NAME, "34000", "34000" },
{ DESC_INVALID_ARGUMENT_NO, "HY024", "S1009" }, /* invalid argument value */
{ DESC_ROW_OUT_OF_RANGE, "HY107", "S1107" },
{ DESC_OPERATION_CANCELLED, "HY008", "S1008" },
{ DESC_INVALID_CURSOR_POSITION, "HY109", "S1109" },
{ DESC_VALUE_OUT_OF_RANGE, "HY019", "22003" },
{ DESC_OPERATION_INVALID, "HY011", "S1011" },
{ DESC_PROGRAM_TYPE_OUT_OF_RANGE, "?????", "?????" },
{ DESC_BAD_ERROR, "08S01", "08S01" }, /* communication link failure */
{ DESC_INVALID_OPTION_IDENTIFIER, "HY092", "HY092" },
{ DESC_RETURN_NULL_WITHOUT_INDICATOR, "22002", "22002" },
{ DESC_INVALID_DESCRIPTOR_IDENTIFIER, "HY091", "HY091" },
{ DESC_OPTION_NOT_FOR_THE_DRIVER, "HYC00", "HYC00" },
{ DESC_FETCH_OUT_OF_RANGE, "HY106", "S1106" },
{ DESC_COUNT_FIELD_INCORRECT, "07002", "07002" },
};
static PG_ErrorInfo *DC_create_errorinfo(const DescriptorClass *self)
{
const DescriptorHeader *deschd = &(self->deschd);
PG_ErrorInfo *error;
ConnectionClass *conn;
EnvironmentClass *env;
Int4 errornum;
BOOL env_is_odbc3 = TRUE;
if (deschd->pgerror)
return deschd->pgerror;
errornum = deschd->__error_number;
error = ER_Constructor(errornum, deschd->__error_message);
if (!error)
return error;
conn = DC_get_conn(self);
if (conn && (env = (EnvironmentClass *) conn->henv))
env_is_odbc3 = EN_is_odbc3(env);
errornum -= LOWEST_DESC_ERROR;
if (errornum < 0 ||
errornum >= sizeof(Descriptor_sqlstate) / sizeof(Descriptor_sqlstate[0]))
errornum = 1 - LOWEST_DESC_ERROR;
STRCPY_FIXED(error->sqlstate, env_is_odbc3 ? Descriptor_sqlstate[errornum].ver3str : Descriptor_sqlstate[errornum].ver2str);
return error;
}
void
DC_log_error(const char *func, const char *desc, const DescriptorClass *self)
{
#define nullcheck(a) (a ? a : "(NULL)")
if (self)
{
MYLOG(0, "DESCRIPTOR ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->deschd.__error_number, nullcheck(self->deschd.__error_message));
}
}
/* Returns the next SQL error information. */
RETCODE SQL_API
PGAPI_DescError(SQLHDESC hdesc,
SQLSMALLINT RecNumber,
SQLCHAR * szSqlState,
SQLINTEGER * pfNativeError,
SQLCHAR * szErrorMsg,
SQLSMALLINT cbErrorMsgMax,
SQLSMALLINT * pcbErrorMsg,
UWORD flag)
{
/* CC: return an error of a hdesc */
DescriptorClass *desc = (DescriptorClass *) hdesc;
DescriptorHeader *deschd = &(desc->deschd);
MYLOG(0, "entering RecN=%hd\n", RecNumber);
deschd->pgerror = DC_create_errorinfo(desc);
return ER_ReturnError(deschd->pgerror, RecNumber, szSqlState,
pfNativeError, szErrorMsg, cbErrorMsgMax,
pcbErrorMsg, flag);
}
C
1
https://gitee.com/wx_79982d16d3/openGauss-connector-odbc.git
git@gitee.com:wx_79982d16d3/openGauss-connector-odbc.git
wx_79982d16d3
openGauss-connector-odbc
openGauss-connector-odbc
master

搜索帮助