aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/bind.c')
-rw-r--r--src/interfaces/odbc/bind.c347
1 files changed, 234 insertions, 113 deletions
diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c
index 4635706a866..397d984ec6c 100644
--- a/src/interfaces/odbc/bind.c
+++ b/src/interfaces/odbc/bind.c
@@ -17,6 +17,7 @@
#include "environ.h"
#include "statement.h"
+#include "descriptor.h"
#include "qresult.h"
#include "pgtypes.h"
#include <stdlib.h>
@@ -41,6 +42,7 @@ PGAPI_BindParameter(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_BindParameter";
+ APDFields *opts;
mylog("%s: entering...\n", func);
@@ -51,103 +53,54 @@ PGAPI_BindParameter(
}
SC_clear_error(stmt);
- if (stmt->parameters_allocated < ipar)
- {
- ParameterInfoClass *old_parameters;
- int i,
- old_parameters_allocated;
-
- old_parameters = stmt->parameters;
- old_parameters_allocated = stmt->parameters_allocated;
-
- stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass) * (ipar));
- if (!stmt->parameters)
- {
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- stmt->errormsg = "Could not allocate memory for statement parameters";
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
-
- stmt->parameters_allocated = ipar;
-
- /* copy the old parameters over */
- for (i = 0; i < old_parameters_allocated; i++)
- {
- /* a structure copy should work */
- stmt->parameters[i] = old_parameters[i];
- }
-
- /* get rid of the old parameters, if there were any */
- if (old_parameters)
- free(old_parameters);
-
- /*
- * zero out the newly allocated parameters (in case they skipped
- * some,
- */
- /* so we don't accidentally try to use them later) */
- for (; i < stmt->parameters_allocated; i++)
- {
- stmt->parameters[i].buflen = 0;
- stmt->parameters[i].buffer = 0;
- stmt->parameters[i].used = 0;
- stmt->parameters[i].paramType = 0;
- stmt->parameters[i].CType = 0;
- stmt->parameters[i].SQLType = 0;
- stmt->parameters[i].precision = 0;
- stmt->parameters[i].scale = 0;
- stmt->parameters[i].data_at_exec = FALSE;
- stmt->parameters[i].lobj_oid = 0;
- stmt->parameters[i].EXEC_used = NULL;
- stmt->parameters[i].EXEC_buffer = NULL;
- }
- }
+ opts = SC_get_APD(stmt);
+ if (opts->allocated < ipar)
+ extend_parameter_bindings(opts, ipar);
/* use zero based column numbers for the below part */
ipar--;
/* store the given info */
- stmt->parameters[ipar].buflen = cbValueMax;
- stmt->parameters[ipar].buffer = rgbValue;
- stmt->parameters[ipar].used = pcbValue;
- stmt->parameters[ipar].paramType = fParamType;
- stmt->parameters[ipar].CType = fCType;
- stmt->parameters[ipar].SQLType = fSqlType;
- stmt->parameters[ipar].precision = cbColDef;
- stmt->parameters[ipar].scale = ibScale;
+ opts->parameters[ipar].buflen = cbValueMax;
+ opts->parameters[ipar].buffer = rgbValue;
+ opts->parameters[ipar].used = pcbValue;
+ opts->parameters[ipar].paramType = fParamType;
+ opts->parameters[ipar].CType = fCType;
+ opts->parameters[ipar].SQLType = fSqlType;
+ opts->parameters[ipar].precision = cbColDef;
+ opts->parameters[ipar].scale = ibScale;
/*
* If rebinding a parameter that had data-at-exec stuff in it, then
* free that stuff
*/
- if (stmt->parameters[ipar].EXEC_used)
+ if (opts->parameters[ipar].EXEC_used)
{
- free(stmt->parameters[ipar].EXEC_used);
- stmt->parameters[ipar].EXEC_used = NULL;
+ free(opts->parameters[ipar].EXEC_used);
+ opts->parameters[ipar].EXEC_used = NULL;
}
- if (stmt->parameters[ipar].EXEC_buffer)
+ if (opts->parameters[ipar].EXEC_buffer)
{
- if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
- free(stmt->parameters[ipar].EXEC_buffer);
- stmt->parameters[ipar].EXEC_buffer = NULL;
+ if (opts->parameters[ipar].SQLType != SQL_LONGVARBINARY)
+ free(opts->parameters[ipar].EXEC_buffer);
+ opts->parameters[ipar].EXEC_buffer = NULL;
}
- if (pcbValue && stmt->options.param_offset_ptr)
- pcbValue += (*stmt->options.param_offset_ptr >> 2);
+ if (pcbValue && opts->param_offset_ptr)
+ pcbValue += (*opts->param_offset_ptr >> 2);
/* 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))
- stmt->parameters[ipar].data_at_exec = TRUE;
+ opts->parameters[ipar].data_at_exec = TRUE;
else
- stmt->parameters[ipar].data_at_exec = FALSE;
+ opts->parameters[ipar].data_at_exec = FALSE;
/* Clear premature result */
if (stmt->status == STMT_PREMATURE)
SC_recycle_statement(stmt);
- mylog("PGAPI_BindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, stmt->parameters[ipar].data_at_exec);
+ mylog("PGAPI_BindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, opts->parameters[ipar].data_at_exec);
return SQL_SUCCESS;
}
@@ -165,6 +118,7 @@ PGAPI_BindCol(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_BindCol";
+ ARDFields *opts;
mylog("%s: entering...\n", func);
@@ -178,8 +132,8 @@ PGAPI_BindCol(
}
- SC_clear_error(stmt);
+ opts = SC_get_ARD(stmt);
if (stmt->status == STMT_EXECUTING)
{
stmt->errormsg = "Can't bind columns while statement is still executing.";
@@ -188,13 +142,14 @@ PGAPI_BindCol(
return SQL_ERROR;
}
+ SC_clear_error(stmt);
/* If the bookmark column is being bound, then just save it */
if (icol == 0)
{
if (rgbValue == NULL)
{
- stmt->bookmark.buffer = NULL;
- stmt->bookmark.used = NULL;
+ opts->bookmark->buffer = NULL;
+ opts->bookmark->used = NULL;
}
else
{
@@ -215,8 +170,8 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
return SQL_ERROR;
}
- stmt->bookmark.buffer = rgbValue;
- stmt->bookmark.used = pcbValue;
+ opts->bookmark->buffer = rgbValue;
+ opts->bookmark->used = pcbValue;
}
return SQL_SUCCESS;
}
@@ -226,11 +181,11 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
* execution of a statement would have setup the necessary bindings.
* But some apps call BindCol before any statement is executed.
*/
- if (icol > stmt->bindings_allocated)
- extend_bindings(stmt, icol);
+ if (icol > opts->allocated)
+ extend_column_bindings(opts, icol);
/* check to see if the bindings were allocated */
- if (!stmt->bindings)
+ if (!opts->bindings)
{
stmt->errormsg = "Could not allocate memory for bindings.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
@@ -242,25 +197,29 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
icol--;
/* Reset for SQLGetData */
- stmt->bindings[icol].data_left = -1;
+ opts->bindings[icol].data_left = -1;
if (rgbValue == NULL)
{
/* we have to unbind the column */
- stmt->bindings[icol].buflen = 0;
- stmt->bindings[icol].buffer = NULL;
- stmt->bindings[icol].used = NULL;
- stmt->bindings[icol].returntype = SQL_C_CHAR;
+ opts->bindings[icol].buflen = 0;
+ opts->bindings[icol].buffer = NULL;
+ opts->bindings[icol].used = NULL;
+ opts->bindings[icol].returntype = SQL_C_CHAR;
+ if (opts->bindings[icol].ttlbuf)
+ free(opts->bindings[icol].ttlbuf);
+ opts->bindings[icol].ttlbuf = NULL;
+ opts->bindings[icol].ttlbuflen = 0;
}
else
{
/* ok, bind that column */
- stmt->bindings[icol].buflen = cbValueMax;
- stmt->bindings[icol].buffer = rgbValue;
- stmt->bindings[icol].used = pcbValue;
- stmt->bindings[icol].returntype = fCType;
+ opts->bindings[icol].buflen = cbValueMax;
+ opts->bindings[icol].buffer = rgbValue;
+ opts->bindings[icol].used = pcbValue;
+ opts->bindings[icol].returntype = fCType;
- mylog(" bound buffer[%d] = %u\n", icol, stmt->bindings[icol].buffer);
+ mylog(" bound buffer[%d] = %u\n", icol, opts->bindings[icol].buffer);
}
return SQL_SUCCESS;
@@ -286,6 +245,7 @@ PGAPI_DescribeParam(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_DescribeParam";
+ APDFields *opts;
mylog("%s: entering...\n", func);
@@ -296,7 +256,8 @@ PGAPI_DescribeParam(
}
SC_clear_error(stmt);
- if ((ipar < 1) || (ipar > stmt->parameters_allocated))
+ opts = SC_get_APD(stmt);
+ if ((ipar < 1) || (ipar > opts->allocated))
{
stmt->errormsg = "Invalid parameter number for PGAPI_DescribeParam.";
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
@@ -312,16 +273,16 @@ PGAPI_DescribeParam(
*/
/* parameter markers, not bound parameters. */
if (pfSqlType)
- *pfSqlType = stmt->parameters[ipar].SQLType;
+ *pfSqlType = opts->parameters[ipar].SQLType;
if (pcbColDef)
- *pcbColDef = stmt->parameters[ipar].precision;
+ *pcbColDef = opts->parameters[ipar].precision;
if (pibScale)
- *pibScale = stmt->parameters[ipar].scale;
+ *pibScale = opts->parameters[ipar].scale;
if (pfNullable)
- *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
+ *pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
return SQL_SUCCESS;
}
@@ -336,11 +297,13 @@ PGAPI_ParamOptions(
{
static char *func = "PGAPI_ParamOptions";
StatementClass *stmt = (StatementClass *) hstmt;
+ APDFields *opts;
mylog("%s: entering... %d %x\n", func, crow, pirow);
- stmt->options.paramset_size = crow;
- stmt->options.param_processed_ptr = (SQLUINTEGER *)pirow;
+ opts = SC_get_APD(stmt);
+ opts->paramset_size = crow;
+ SC_get_IPD(stmt)->param_processed_ptr = (UInt4 *) pirow;
return SQL_SUCCESS;
}
@@ -433,46 +396,156 @@ create_empty_bindings(int num_columns)
return new_bindings;
}
+void
+extend_parameter_bindings(APDFields *self, int num_params)
+{
+ static char *func = "extend_parameter_bindings";
+ ParameterInfoClass *new_bindings;
+
+ mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, 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 = (ParameterInfoClass *) realloc(self->parameters, sizeof(ParameterInfoClass) * num_params);
+ if (!new_bindings)
+ {
+ mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
+
+ 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("exit extend_parameter_bindings\n");
+}
+
+void
+reset_a_parameter_binding(APDFields *self, int ipar)
+{
+ static char *func = "reset_a_parameter_binding";
+
+ mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
+
+ if (ipar < 1 || ipar > self->allocated)
+ return;
+
+ ipar--;
+ self->parameters[ipar].buflen = 0;
+ self->parameters[ipar].buffer = 0;
+ self->parameters[ipar].used = 0;
+ self->parameters[ipar].paramType = 0;
+ self->parameters[ipar].CType = 0;
+ if (self->parameters[ipar].EXEC_used)
+ {
+ free(self->parameters[ipar].EXEC_used);
+ self->parameters[ipar].EXEC_used = NULL;
+ }
+
+ if (self->parameters[ipar].EXEC_buffer)
+ {
+ if (self->parameters[ipar].SQLType != SQL_LONGVARBINARY)
+ free(self->parameters[ipar].EXEC_buffer);
+ self->parameters[ipar].EXEC_buffer = NULL;
+ }
+ self->parameters[ipar].SQLType = 0;
+ self->parameters[ipar].precision = 0;
+ self->parameters[ipar].scale = 0;
+ self->parameters[ipar].data_at_exec = FALSE;
+ self->parameters[ipar].lobj_oid = 0;
+}
+
+/*
+ * Free parameters and free the memory.
+ */
+void
+APD_free_params(APDFields *self, char option)
+{
+ int i;
+
+ mylog("APD_free_params: ENTER, self=%d\n", self);
+
+ if (!self->parameters)
+ return;
+
+ for (i = 0; i < self->allocated; i++)
+ {
+ if (self->parameters[i].data_at_exec)
+ {
+ if (self->parameters[i].EXEC_used)
+ {
+ free(self->parameters[i].EXEC_used);
+ self->parameters[i].EXEC_used = NULL;
+ }
+
+ if (self->parameters[i].EXEC_buffer)
+ {
+ if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
+ free(self->parameters[i].EXEC_buffer);
+ self->parameters[i].EXEC_buffer = NULL;
+ }
+ }
+ }
+
+ if (option == STMT_FREE_PARAMS_ALL)
+ {
+ if (self->parameters);
+ free(self->parameters);
+ self->parameters = NULL;
+ self->allocated = 0;
+ }
+
+ mylog("APD_free_params: EXIT\n");
+}
void
-extend_bindings(StatementClass *stmt, int num_columns)
+extend_column_bindings(ARDFields *self, int num_columns)
{
- static char *func = "extend_bindings";
+ static char *func = "extend_column_bindings";
BindInfoClass *new_bindings;
int i;
- mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
+ mylog("%s: entering ... self=%u, bindings_allocated=%d, num_columns=%d\n", func, self, self->allocated, num_columns);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
- if (stmt->bindings_allocated < num_columns)
+ if (self->allocated < num_columns)
{
new_bindings = create_empty_bindings(num_columns);
if (!new_bindings)
{
- mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated);
+ mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, self->allocated);
- if (stmt->bindings)
+ if (self->bindings)
{
- free(stmt->bindings);
- stmt->bindings = NULL;
+ free(self->bindings);
+ self->bindings = NULL;
}
- stmt->bindings_allocated = 0;
+ self->allocated = 0;
return;
}
- if (stmt->bindings)
+ if (self->bindings)
{
- for (i = 0; i < stmt->bindings_allocated; i++)
- new_bindings[i] = stmt->bindings[i];
+ for (i = 0; i < self->allocated; i++)
+ new_bindings[i] = self->bindings[i];
- free(stmt->bindings);
+ free(self->bindings);
}
- stmt->bindings = new_bindings;
- stmt->bindings_allocated = num_columns;
+ self->bindings = new_bindings;
+ self->allocated = num_columns;
}
/*
@@ -485,5 +558,53 @@ extend_bindings(StatementClass *stmt, int num_columns)
/* SQLExecDirect(...) # returns 5 cols */
/* SQLExecDirect(...) # returns 10 cols (now OK) */
- mylog("exit extend_bindings\n");
+ mylog("exit extend_column_bindings\n");
+}
+
+void
+reset_a_column_binding(ARDFields *self, int icol)
+{
+ static char *func = "reset_a_column_binding";
+
+ mylog("%s: entering ... self=%u, bindings_allocated=%d, icol=%d\n", func, self, self->allocated, icol);
+
+ if (icol > self->allocated)
+ return;
+
+ /* use zero based col numbers from here out */
+ if (0 == icol)
+ {
+ self->bookmark->buffer = NULL;
+ self->bookmark->used = NULL;
+ }
+ else
+ {
+ icol--;
+
+ /* we have to unbind the column */
+ self->bindings[icol].buflen = 0;
+ self->bindings[icol].buffer = NULL;
+ self->bindings[icol].used = NULL;
+ self->bindings[icol].data_left = -1;
+ self->bindings[icol].returntype = SQL_C_CHAR;
+ if (self->bindings[icol].ttlbuf)
+ free(self->bindings[icol].ttlbuf);
+ self->bindings[icol].ttlbuf = NULL;
+ self->bindings[icol].ttlbuflen = 0;
+ }
}
+
+void ARD_unbind_cols(ARDFields *self, BOOL freeall)
+{
+ Int2 lf;
+
+ 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;
+ }
+}