1 Star 0 Fork 47

zhangminjie / openGauss-connector-odbc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
bind.c 25.36 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
/*-------
* Module: bind.c
*
* Description: This module contains routines related to binding
* columns and parameters.
*
* Classes: BindInfoClass, ParameterInfoClass
*
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
* SQLParamOptions
*
* Comments: See "readme.txt" for copyright and license information.
*-------
*/
#include <string.h>
#include <ctype.h>
#include "bind.h"
#include "misc.h"
#include "environ.h"
#include "statement.h"
#include "descriptor.h"
#include "qresult.h"
#include "pgtypes.h"
#include "multibyte.h"
#include "pgapifunc.h"
/* Bind parameters on a statement handle */
RETCODE SQL_API
PGAPI_BindParameter(HSTMT hstmt,
SQLUSMALLINT ipar,
SQLSMALLINT fParamType,
SQLSMALLINT fCType,
SQLSMALLINT fSqlType,
SQLULEN cbColDef,
SQLSMALLINT ibScale,
PTR rgbValue,
SQLLEN cbValueMax,
SQLLEN * pcbValue)
{
StatementClass *stmt = (StatementClass *) hstmt;
CSTR func = "PGAPI_BindParameter";
APDFields *apdopts;
IPDFields *ipdopts;
PutDataInfo *pdata_info;
MYLOG(0, "entering...\n");
if (!stmt)
{
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
SC_clear_error(stmt);
apdopts = SC_get_APDF(stmt);
if (apdopts->allocated < ipar)
extend_parameter_bindings(apdopts, ipar);
ipdopts = SC_get_IPDF(stmt);
if (ipdopts->allocated < ipar)
extend_iparameter_bindings(ipdopts, ipar);
pdata_info = SC_get_PDTI(stmt);
if (pdata_info->allocated < ipar)
extend_putdata_info(pdata_info, ipar, FALSE);
/* use zero based column numbers for the below part */
ipar--;
/* store the given info */
apdopts->parameters[ipar].buflen = cbValueMax;
apdopts->parameters[ipar].buffer = rgbValue;
apdopts->parameters[ipar].used =
apdopts->parameters[ipar].indicator = pcbValue;
apdopts->parameters[ipar].CType = fCType;
ipdopts->parameters[ipar].SQLType = fSqlType;
ipdopts->parameters[ipar].paramType = fParamType;
ipdopts->parameters[ipar].column_size = cbColDef;
ipdopts->parameters[ipar].decimal_digits = ibScale;
ipdopts->parameters[ipar].precision = 0;
ipdopts->parameters[ipar].scale = 0;
switch (fCType)
{
case SQL_C_NUMERIC:
if (cbColDef > 0)
ipdopts->parameters[ipar].precision = (UInt2) cbColDef;
if (ibScale > 0)
ipdopts->parameters[ipar].scale = ibScale;
break;
case SQL_C_TYPE_TIMESTAMP:
if (ibScale > 0)
ipdopts->parameters[ipar].precision = ibScale;
break;
case SQL_C_INTERVAL_DAY_TO_SECOND:
case SQL_C_INTERVAL_HOUR_TO_SECOND:
case SQL_C_INTERVAL_MINUTE_TO_SECOND:
case SQL_C_INTERVAL_SECOND:
ipdopts->parameters[ipar].precision = 6;
break;
}
apdopts->parameters[ipar].precision = ipdopts->parameters[ipar].precision;
apdopts->parameters[ipar].scale = ipdopts->parameters[ipar].scale;
/*
* If rebinding a parameter that had data-at-exec stuff in it, then
* free that stuff
*/
if (pdata_info->pdata[ipar].EXEC_used)
{
free(pdata_info->pdata[ipar].EXEC_used);
pdata_info->pdata[ipar].EXEC_used = NULL;
}
if (pdata_info->pdata[ipar].EXEC_buffer)
{
free(pdata_info->pdata[ipar].EXEC_buffer);
pdata_info->pdata[ipar].EXEC_buffer = NULL;
}
if (pcbValue && apdopts->param_offset_ptr)
pcbValue = LENADDR_SHIFT(pcbValue, *apdopts->param_offset_ptr);
#ifdef NOT_USED /* evaluation of pcbValue here is dangerous */
/* Data at exec macro only valid for C char/binary data */
if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
*pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
apdopts->parameters[ipar].data_at_exec = TRUE;
else
apdopts->parameters[ipar].data_at_exec = FALSE;
#endif /* NOT_USED */
/* Clear premature result */
if (stmt->status == STMT_DESCRIBED)
SC_recycle_statement(stmt);
MYLOG(0, "ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=" FORMAT_ULEN ", ibScale=%d,", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale);
MYPRINTF(0, "rgbValue=%p(" FORMAT_LEN "), pcbValue=%p\n", rgbValue, cbValueMax, pcbValue);
return SQL_SUCCESS;
}
/* Associate a user-supplied buffer with a database column. */
RETCODE SQL_API
PGAPI_BindCol(HSTMT hstmt,
SQLUSMALLINT icol,
SQLSMALLINT fCType,
PTR rgbValue,
SQLLEN cbValueMax,
SQLLEN * pcbValue)
{
StatementClass *stmt = (StatementClass *) hstmt;
CSTR func = "PGAPI_BindCol";
ARDFields *opts;
GetDataInfo *gdata_info;
BindInfoClass *bookmark;
RETCODE ret = SQL_SUCCESS;
MYLOG(0, "entering...\n");
MYLOG(0, "**** : stmt = %p, icol = %d\n", stmt, icol);
MYLOG(0, "**** : fCType=%d rgb=%p valusMax=" FORMAT_LEN " pcb=%p\n", fCType, rgbValue, cbValueMax, pcbValue);
if (!stmt)
{
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
opts = SC_get_ARDF(stmt);
if (stmt->status == STMT_EXECUTING)
{
SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't bind columns while statement is still executing.", func);
return SQL_ERROR;
}
#define return DONT_CALL_RETURN_FROM_HERE ???
SC_clear_error(stmt);
/* If the bookmark column is being bound, then just save it */
if (icol == 0)
{
bookmark = opts->bookmark;
if (rgbValue == NULL)
{
if (bookmark)
{
bookmark->buffer = NULL;
bookmark->used =
bookmark->indicator = NULL;
}
}
else
{
/* Make sure it is the bookmark data type */
switch (fCType)
{
case SQL_C_BOOKMARK:
case SQL_C_VARBOOKMARK:
break;
default:
SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE, "Bind column 0 is not of type SQL_C_BOOKMARK", func);
MYLOG(DETAIL_LOG_LEVEL, "Bind column 0 is type %d not of type SQL_C_BOOKMARK\n", fCType);
ret = SQL_ERROR;
goto cleanup;
}
bookmark = ARD_AllocBookmark(opts);
bookmark->buffer = rgbValue;
bookmark->used =
bookmark->indicator = pcbValue;
bookmark->buflen = cbValueMax;
bookmark->returntype = fCType;
}
goto cleanup;
}
/*
* Allocate enough bindings if not already done. Most likely,
* execution of a statement would have setup the necessary bindings.
* But some apps call BindCol before any statement is executed.
*/
if (icol > opts->allocated)
extend_column_bindings(opts, icol);
gdata_info = SC_get_GDTI(stmt);
if (icol > gdata_info->allocated)
extend_getdata_info(gdata_info, icol, FALSE);
/* check to see if the bindings were allocated */
if (!opts->bindings || !gdata_info->gdata)
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory for bindings.", func);
ret = SQL_ERROR;
goto cleanup;
}
/* use zero based col numbers from here out */
icol--;
/* Reset for SQLGetData */
GETDATA_RESET(gdata_info->gdata[icol]);
if (rgbValue == NULL)
{
/* we have to unbind the column */
opts->bindings[icol].buflen = 0;
opts->bindings[icol].buffer = NULL;
opts->bindings[icol].used =
opts->bindings[icol].indicator = NULL;
opts->bindings[icol].returntype = SQL_C_CHAR;
opts->bindings[icol].precision = 0;
opts->bindings[icol].scale = 0;
if (gdata_info->gdata[icol].ttlbuf)
free(gdata_info->gdata[icol].ttlbuf);
gdata_info->gdata[icol].ttlbuf = NULL;
gdata_info->gdata[icol].ttlbuflen = 0;
gdata_info->gdata[icol].ttlbufused = 0;
}
else
{
/* ok, bind that column */
opts->bindings[icol].buflen = cbValueMax;
opts->bindings[icol].buffer = rgbValue;
opts->bindings[icol].used =
opts->bindings[icol].indicator = pcbValue;
opts->bindings[icol].returntype = fCType;
opts->bindings[icol].precision = 0;
switch (fCType)
{
case SQL_C_NUMERIC:
opts->bindings[icol].precision = 32;
break;
case SQL_C_TIMESTAMP:
case SQL_C_INTERVAL_DAY_TO_SECOND:
case SQL_C_INTERVAL_HOUR_TO_SECOND:
case SQL_C_INTERVAL_MINUTE_TO_SECOND:
case SQL_C_INTERVAL_SECOND:
opts->bindings[icol].precision = 6;
break;
}
opts->bindings[icol].scale = 0;
MYLOG(0, " bound buffer[%d] = %p\n", icol, opts->bindings[icol].buffer);
}
cleanup:
#undef return
return ret;
}
/*
* Returns the description of a parameter marker.
* This function is listed as not being supported by SQLGetFunctions() because it is
* used to describe "parameter markers" (not bound parameters), in which case,
* the dbms should return info on the markers. Since Postgres doesn't support that,
* it is best to say this function is not supported and let the application assume a
* data type (most likely varchar).
*/
RETCODE SQL_API
PGAPI_DescribeParam(HSTMT hstmt,
SQLUSMALLINT ipar,
SQLSMALLINT * pfSqlType,
SQLULEN * pcbParamDef,
SQLSMALLINT * pibScale,
SQLSMALLINT * pfNullable)
{
StatementClass *stmt = (StatementClass *) hstmt;
CSTR func = "PGAPI_DescribeParam";
IPDFields *ipdopts;
RETCODE ret = SQL_SUCCESS;
int num_params;
OID pgtype;
ConnectionClass *conn;
MYLOG(0, "entering...%d\n", ipar);
if (!stmt)
{
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
conn = SC_get_conn(stmt);
SC_clear_error(stmt);
ipdopts = SC_get_IPDF(stmt);
/*if ((ipar < 1) || (ipar > ipdopts->allocated))*/
num_params = stmt->num_params;
if (num_params < 0)
{
SQLSMALLINT num_p;
PGAPI_NumParams(stmt, &num_p);
num_params = num_p;
}
if ((ipar < 1) || (ipar > num_params))
{
MYLOG(DETAIL_LOG_LEVEL, "num_params=%d\n", stmt->num_params);
SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.", func);
return SQL_ERROR;
}
extend_iparameter_bindings(ipdopts, stmt->num_params);
#define return DONT_CALL_RETURN_FROM_HERE???
if (NOT_YET_PREPARED == stmt->prepared)
{
decideHowToPrepare(stmt, FALSE);
MYLOG(DETAIL_LOG_LEVEL, "howTo=%d\n", SC_get_prepare_method(stmt));
switch (SC_get_prepare_method(stmt))
{
case NAMED_PARSE_REQUEST:
case PARSE_TO_EXEC_ONCE:
case PARSE_REQ_FOR_INFO:
if (ret = prepareParameters(stmt, FALSE), SQL_ERROR == ret)
goto cleanup;
}
}
ipar--;
pgtype = PIC_get_pgtype(ipdopts->parameters[ipar]);
/*
* This implementation is not very good, since it is supposed to
* describe
*/
/* parameter markers, not bound parameters. */
if (pfSqlType)
{
MYLOG(DETAIL_LOG_LEVEL, "[%d].SQLType=%d .PGType=%d\n", ipar, ipdopts->parameters[ipar].SQLType, pgtype);
if (ipdopts->parameters[ipar].SQLType)
*pfSqlType = ipdopts->parameters[ipar].SQLType;
else if (pgtype)
*pfSqlType = pgtype_attr_to_concise_type(conn, pgtype, PG_ATP_UNSET, PG_ADT_UNSET, PG_UNKNOWNS_UNSET);
else
{
ret = SQL_ERROR;
SC_set_error(stmt, STMT_EXEC_ERROR, "Unfortunatley couldn't get this paramater's info", func);
goto cleanup;
}
}
if (pcbParamDef)
{
*pcbParamDef = 0;
if (ipdopts->parameters[ipar].SQLType)
*pcbParamDef = ipdopts->parameters[ipar].column_size;
if (0 == *pcbParamDef && pgtype)
*pcbParamDef = pgtype_attr_column_size(conn, pgtype, PG_ATP_UNSET, PG_ADT_UNSET, PG_UNKNOWNS_UNSET);
}
if (pibScale)
{
*pibScale = 0;
if (ipdopts->parameters[ipar].SQLType)
*pibScale = ipdopts->parameters[ipar].decimal_digits;
else if (pgtype)
*pibScale = pgtype_scale(stmt, pgtype, -1);
}
if (pfNullable)
*pfNullable = pgtype_nullable(SC_get_conn(stmt), ipdopts->parameters[ipar].paramType);
cleanup:
#undef return
return ret;
}
/*
* This function should really talk to the dbms to determine the number of
* "parameter markers" (not bound parameters) in the statement. But, since
* Postgres doesn't support that, the driver should just count the number of markers
* and return that. The reason the driver just can't say this function is unsupported
* like it does for SQLDescribeParam is that some applications don't care and try
* to call it anyway.
* If the statement does not have parameters, it should just return 0.
*/
RETCODE SQL_API
PGAPI_NumParams(HSTMT hstmt,
SQLSMALLINT * pcpar)
{
StatementClass *stmt = (StatementClass *) hstmt;
CSTR func = "PGAPI_NumParams";
MYLOG(0, "entering...\n");
if (!stmt)
{
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (pcpar)
*pcpar = 0;
else
{
SC_set_error(stmt, STMT_EXEC_ERROR, "parameter count address is null", func);
return SQL_ERROR;
}
MYLOG(DETAIL_LOG_LEVEL, "num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
if (stmt->num_params >= 0)
*pcpar = stmt->num_params;
else if (!stmt->statement)
{
/* no statement has been allocated */
SC_set_error(stmt, STMT_SEQUENCE_ERROR, "PGAPI_NumParams called with no statement ready.", func);
return SQL_ERROR;
}
else
{
po_ind_t multi = FALSE, proc_return = 0;
stmt->proc_return = 0;
SC_scanQueryAndCountParams(stmt->statement, SC_get_conn(stmt), NULL, pcpar, &multi, &proc_return);
stmt->num_params = *pcpar;
stmt->proc_return = proc_return;
stmt->multi_statement = multi;
}
MYLOG(DETAIL_LOG_LEVEL, "num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
return SQL_SUCCESS;
}
/*
* Bindings Implementation
*/
static BindInfoClass *
create_empty_bindings(int num_columns)
{
BindInfoClass *new_bindings;
int i;
new_bindings = (BindInfoClass *) malloc(num_columns * sizeof(BindInfoClass));
if (!new_bindings)
return NULL;
for (i = 0; i < num_columns; i++)
{
new_bindings[i].buflen = 0;
new_bindings[i].buffer = NULL;
new_bindings[i].used =
new_bindings[i].indicator = NULL;
}
return new_bindings;
}
void
extend_parameter_bindings(APDFields *self, int num_params)
{
ParameterInfoClass *new_bindings;
MYLOG(0, "entering ... self=%p, parameters_allocated=%d, num_params=%d,%p\n", self, self->allocated, num_params, self->parameters);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_params)
{
new_bindings = (ParameterInfoClass *) realloc(self->parameters, sizeof(ParameterInfoClass) * num_params);
if (!new_bindings)
{
MYLOG(0, "unable to create %d new bindings from %d old bindings\n", num_params, self->allocated);
if (self->parameters)
free(self->parameters);
self->parameters = NULL;
self->allocated = 0;
return;
}
memset(&new_bindings[self->allocated], 0, sizeof(ParameterInfoClass) * (num_params - self->allocated));
self->parameters = new_bindings;
self->allocated = num_params;
}
MYLOG(0, "leaving %p\n", self->parameters);
}
void
extend_iparameter_bindings(IPDFields *self, int num_params)
{
ParameterImplClass *new_bindings;
MYLOG(0, "entering ... self=%p, parameters_allocated=%d, num_params=%d\n", self, self->allocated, num_params);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_params)
{
new_bindings = (ParameterImplClass *) realloc(self->parameters, sizeof(ParameterImplClass) * num_params);
if (!new_bindings)
{
MYLOG(0, "unable to create %d new bindings from %d old bindings\n", num_params, self->allocated);
if (self->parameters)
free(self->parameters);
self->parameters = NULL;
self->allocated = 0;
return;
}
memset(&new_bindings[self->allocated], 0,
sizeof(ParameterImplClass) * (num_params - self->allocated));
self->parameters = new_bindings;
self->allocated = num_params;
}
MYLOG(0, "leaving %p\n", self->parameters);
}
void
reset_a_parameter_binding(APDFields *self, int ipar)
{
MYLOG(0, "entering ... self=%p, parameters_allocated=%d, ipar=%d\n", self, self->allocated, ipar);
if (ipar < 1 || ipar > self->allocated)
return;
ipar--;
self->parameters[ipar].buflen = 0;
self->parameters[ipar].buffer = NULL;
self->parameters[ipar].used =
self->parameters[ipar].indicator = NULL;
self->parameters[ipar].CType = 0;
self->parameters[ipar].data_at_exec = FALSE;
self->parameters[ipar].precision = 0;
self->parameters[ipar].scale = 0;
}
void
reset_a_iparameter_binding(IPDFields *self, int ipar)
{
MYLOG(0, "entering ... self=%p, parameters_allocated=%d, ipar=%d\n", self, self->allocated, ipar);
if (ipar < 1 || ipar > self->allocated)
return;
ipar--;
NULL_THE_NAME(self->parameters[ipar].paramName);
self->parameters[ipar].paramType = 0;
self->parameters[ipar].SQLType = 0;
self->parameters[ipar].column_size = 0;
self->parameters[ipar].decimal_digits = 0;
self->parameters[ipar].precision = 0;
self->parameters[ipar].scale = 0;
PIC_set_pgtype(self->parameters[ipar], 0);
}
int
CountParameters(const StatementClass *self, Int2 *inputCount, Int2 *ioCount, Int2 *outputCount)
{
IPDFields *ipdopts = SC_get_IPDF(self);
int i, num_params, valid_count;
if (inputCount)
*inputCount = 0;
if (ioCount)
*ioCount = 0;
if (outputCount)
*outputCount = 0;
if (!ipdopts) return -1;
num_params = self->num_params;
if (ipdopts->allocated < num_params)
num_params = ipdopts->allocated;
for (i = 0, valid_count = 0; i < num_params; i++)
{
if (SQL_PARAM_OUTPUT == ipdopts->parameters[i].paramType)
{
if (outputCount)
{
(*outputCount)++;
valid_count++;
}
}
else if (SQL_PARAM_INPUT_OUTPUT == ipdopts->parameters[i].paramType)
{
if (ioCount)
{
(*ioCount)++;
valid_count++;
}
}
else if (inputCount)
{
(*inputCount)++;
valid_count++;
}
}
return valid_count;
}
/*
* Free parameters and free the memory.
*/
void
APD_free_params(APDFields *apdopts, char option)
{
MYLOG(0, "entering self=%p\n", apdopts);
if (!apdopts->parameters)
return;
if (option == STMT_FREE_PARAMS_ALL)
{
free(apdopts->parameters);
apdopts->parameters = NULL;
apdopts->allocated = 0;
}
MYLOG(0, "leaving\n");
}
void
PDATA_free_params(PutDataInfo *pdata, char option)
{
int i;
MYLOG(0, "entering self=%p\n", pdata);
if (!pdata->pdata)
return;
for (i = 0; i < pdata->allocated; i++)
{
if (pdata->pdata[i].EXEC_used)
{
free(pdata->pdata[i].EXEC_used);
pdata->pdata[i].EXEC_used = NULL;
}
if (pdata->pdata[i].EXEC_buffer)
{
free(pdata->pdata[i].EXEC_buffer);
pdata->pdata[i].EXEC_buffer = NULL;
}
}
if (option == STMT_FREE_PARAMS_ALL)
{
free(pdata->pdata);
pdata->pdata = NULL;
pdata->allocated = 0;
}
MYLOG(0, "leaving\n");
}
/*
* Free parameters and free the memory.
*/
void
IPD_free_params(IPDFields *ipdopts, char option)
{
MYLOG(0, "entering self=%p\n", ipdopts);
if (!ipdopts->parameters)
return;
if (option == STMT_FREE_PARAMS_ALL)
{
free(ipdopts->parameters);
ipdopts->parameters = NULL;
ipdopts->allocated = 0;
}
MYLOG(0, "leaving\n");
}
void
extend_column_bindings(ARDFields *self, int num_columns)
{
BindInfoClass *new_bindings;
int i;
MYLOG(0, "entering ... self=%p, bindings_allocated=%d, num_columns=%d\n", self, self->allocated, num_columns);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_columns)
{
new_bindings = create_empty_bindings(num_columns);
if (!new_bindings)
{
MYLOG(0, "unable to create %d new bindings from %d old bindings\n", num_columns, self->allocated);
if (self->bindings)
{
free(self->bindings);
self->bindings = NULL;
}
self->allocated = 0;
return;
}
if (self->bindings)
{
for (i = 0; i < self->allocated; i++)
new_bindings[i] = self->bindings[i];
free(self->bindings);
}
self->bindings = new_bindings;
self->allocated = num_columns;
}
/*
* There is no reason to zero out extra bindings if there are more
* than needed. If an app has allocated extra bindings, let it worry
* about it by unbinding those columns.
*/
/* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
/* SQLExecDirect(...) # returns 5 cols */
/* SQLExecDirect(...) # returns 10 cols (now OK) */
MYLOG(0, "leaving %p\n", self->bindings);
}
void
reset_a_column_binding(ARDFields *self, int icol)
{
BindInfoClass *bookmark;
MYLOG(0, "entering ... self=%p, bindings_allocated=%d, icol=%d\n", self, self->allocated, icol);
if (icol > self->allocated)
return;
/* use zero based col numbers from here out */
if (0 == icol)
{
if (bookmark = self->bookmark, bookmark != NULL)
{
bookmark->buffer = NULL;
bookmark->used =
bookmark->indicator = NULL;
}
}
else
{
icol--;
/* we have to unbind the column */
self->bindings[icol].buflen = 0;
self->bindings[icol].buffer = NULL;
self->bindings[icol].used =
self->bindings[icol].indicator = NULL;
self->bindings[icol].returntype = SQL_C_CHAR;
}
}
void ARD_unbind_cols(ARDFields *self, BOOL freeall)
{
Int2 lf;
MYLOG(DETAIL_LOG_LEVEL, "freeall=%d allocated=%d bindings=%p\n", freeall, self->allocated, self->bindings);
for (lf = 1; lf <= self->allocated; lf++)
reset_a_column_binding(self, lf);
if (freeall)
{
if (self->bindings)
free(self->bindings);
self->bindings = NULL;
self->allocated = 0;
}
}
void GDATA_unbind_cols(GetDataInfo *self, BOOL freeall)
{
Int2 lf;
MYLOG(DETAIL_LOG_LEVEL, "freeall=%d allocated=%d gdata=%p\n", freeall, self->allocated, self->gdata);
if (self->fdata.ttlbuf)
{
free(self->fdata.ttlbuf);
self->fdata.ttlbuf = NULL;
}
self->fdata.ttlbuflen = self->fdata.ttlbufused = 0;
GETDATA_RESET(self->fdata);
for (lf = 1; lf <= self->allocated; lf++)
reset_a_getdata_info(self, lf);
if (freeall)
{
if (self->gdata)
free(self->gdata);
self->gdata = NULL;
self->allocated = 0;
}
}
void GetDataInfoInitialize(GetDataInfo *gdata_info)
{
GETDATA_RESET(gdata_info->fdata);
gdata_info->fdata.ttlbuf = NULL;
gdata_info->fdata.ttlbuflen = gdata_info->fdata.ttlbufused = 0;
gdata_info->allocated = 0;
gdata_info->gdata = NULL;
}
static GetDataClass *
create_empty_gdata(int num_columns)
{
GetDataClass *new_gdata;
int i;
new_gdata = (GetDataClass *) malloc(num_columns * sizeof(GetDataClass));
if (!new_gdata)
return NULL;
for (i = 0; i < num_columns; i++)
{
GETDATA_RESET(new_gdata[i]);
new_gdata[i].ttlbuf = NULL;
new_gdata[i].ttlbuflen = 0;
new_gdata[i].ttlbufused = 0;
}
return new_gdata;
}
void
extend_getdata_info(GetDataInfo *self, int num_columns, BOOL shrink)
{
GetDataClass *new_gdata;
MYLOG(0, "entering ... self=%p, gdata_allocated=%d, num_columns=%d\n", self, self->allocated, num_columns);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_columns)
{
new_gdata = create_empty_gdata(num_columns);
if (!new_gdata)
{
MYLOG(0, "unable to create %d new gdata from %d old gdata\n", num_columns, self->allocated);
if (self->gdata)
{
free(self->gdata);
self->gdata = NULL;
}
self->allocated = 0;
return;
}
if (self->gdata)
{
size_t i;
for (i = 0; i < self->allocated; i++)
new_gdata[i] = self->gdata[i];
free(self->gdata);
}
self->gdata = new_gdata;
self->allocated = num_columns;
}
else if (shrink && self->allocated > num_columns)
{
int i;
for (i = self->allocated; i > num_columns; i--)
reset_a_getdata_info(self, i);
self->allocated = num_columns;
if (0 == num_columns)
{
free(self->gdata);
self->gdata = NULL;
}
}
/*
* There is no reason to zero out extra gdata if there are more
* than needed. If an app has allocated extra gdata, let it worry
* about it by unbinding those columns.
*/
MYLOG(0, "leaving %p\n", self->gdata);
}
void reset_a_getdata_info(GetDataInfo *gdata_info, int icol)
{
if (icol < 1 || icol > gdata_info->allocated)
return;
icol--;
if (gdata_info->gdata[icol].ttlbuf)
{
free(gdata_info->gdata[icol].ttlbuf);
gdata_info->gdata[icol].ttlbuf = NULL;
}
gdata_info->gdata[icol].ttlbuflen =
gdata_info->gdata[icol].ttlbufused = 0;
GETDATA_RESET(gdata_info->gdata[icol]);
}
void PutDataInfoInitialize(PutDataInfo *pdata_info)
{
pdata_info->allocated = 0;
pdata_info->pdata = NULL;
}
void
extend_putdata_info(PutDataInfo *self, int num_params, BOOL shrink)
{
PutDataClass *new_pdata;
MYLOG(0, "entering ... self=%p, parameters_allocated=%d, num_params=%d\n", self, self->allocated, num_params);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_params)
{
if (self->allocated <= 0 && self->pdata)
{
MYLOG(0, "??? pdata is not null while allocated == 0\n");
self->pdata = NULL;
}
new_pdata = (PutDataClass *) realloc(self->pdata, sizeof(PutDataClass) * num_params);
if (!new_pdata)
{
MYLOG(0, "unable to create %d new pdata from %d old pdata\n", num_params, self->allocated);
self->pdata = NULL;
self->allocated = 0;
return;
}
memset(&new_pdata[self->allocated], 0,
sizeof(PutDataClass) * (num_params - self->allocated));
self->pdata = new_pdata;
self->allocated = num_params;
}
else if (shrink && self->allocated > num_params)
{
int i;
for (i = self->allocated; i > num_params; i--)
reset_a_putdata_info(self, i);
self->allocated = num_params;
if (0 == num_params)
{
free(self->pdata);
self->pdata = NULL;
}
}
MYLOG(0, "leaving %p\n", self->pdata);
}
void reset_a_putdata_info(PutDataInfo *pdata_info, int ipar)
{
if (ipar < 1 || ipar > pdata_info->allocated)
return;
ipar--;
if (pdata_info->pdata[ipar].EXEC_used)
{
free(pdata_info->pdata[ipar].EXEC_used);
pdata_info->pdata[ipar].EXEC_used = NULL;
}
if (pdata_info->pdata[ipar].EXEC_buffer)
{
free(pdata_info->pdata[ipar].EXEC_buffer);
pdata_info->pdata[ipar].EXEC_buffer = NULL;
}
pdata_info->pdata[ipar].lobj_oid = 0;
}
void SC_param_next(const StatementClass *stmt, int *param_number, ParameterInfoClass **apara, ParameterImplClass **ipara)
{
int next;
IPDFields *ipdopts = SC_get_IPDF(stmt);
if (*param_number < 0)
next = stmt->proc_return;
else
next = *param_number + 1;
if (stmt->discard_output_params)
{
for (;next < ipdopts->allocated && SQL_PARAM_OUTPUT == ipdopts->parameters[next].paramType; next++) ;
}
*param_number = next;
if (ipara)
{
if (next < ipdopts->allocated)
*ipara = ipdopts->parameters + next;
else
*ipara = NULL;
}
if (apara)
{
APDFields *apdopts = SC_get_APDF(stmt);
if (next < apdopts->allocated)
*apara = apdopts->parameters + next;
else
*apara = NULL;
}
}
C
1
https://gitee.com/zhangminjie1997/openGauss-connector-odbc.git
git@gitee.com:zhangminjie1997/openGauss-connector-odbc.git
zhangminjie1997
openGauss-connector-odbc
openGauss-connector-odbc
master

搜索帮助