diff options
author | Marc G. Fournier <scrappy@hub.org> | 1998-04-13 15:02:05 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1998-04-13 15:02:05 +0000 |
commit | 9e3382dfc5affce3b653534714343d5e546e1a3e (patch) | |
tree | e5627cb0e135d52c2e4af55a239795d18ba5e7f9 /src/interfaces/odbc/bind.c | |
parent | d4d26f9c33791f7aefd667e3688d9a18400006e1 (diff) |
Replace old PostODBC driver with new one...
This one is based on an older PostODBC driver, rewritten and maintained by
InsightDist(?)
Diffstat (limited to 'src/interfaces/odbc/bind.c')
-rw-r--r-- | src/interfaces/odbc/bind.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c new file mode 100644 index 00000000000..c01f61ab7fd --- /dev/null +++ b/src/interfaces/odbc/bind.c @@ -0,0 +1,340 @@ +
+/* Module: bind.c
+ *
+ * Description: This module contains routines related to binding
+ * columns and parameters.
+ *
+ * Classes: BindInfoClass, ParameterInfoClass
+ *
+ * API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
+ * SQLParamOptions(NI)
+ *
+ * Comments: See "notice.txt" for copyright and license information.
+ *
+ */
+#include "bind.h" +#include "environ.h" +#include "statement.h" +#include "qresult.h" +#include "pgtypes.h" +#include <stdlib.h> +#include <malloc.h> +#include <sql.h>
+#include <sqlext.h>
+ +// Bind parameters on a statement handle + +RETCODE SQL_API SQLBindParameter( + HSTMT hstmt, + UWORD ipar, + SWORD fParamType, + SWORD fCType, + SWORD fSqlType, + UDWORD cbColDef, + SWORD ibScale, + PTR rgbValue, + SDWORD cbValueMax, + SDWORD FAR *pcbValue) +{ +StatementClass *stmt = (StatementClass *) hstmt; + + if( ! stmt) + return SQL_INVALID_HANDLE; + + 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"; + 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].EXEC_used = NULL;
+ stmt->parameters[i].EXEC_buffer = NULL;
+ } + } + + ipar--; /* use zero based column numbers for the below part */ + + // 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;
+
+ /* If rebinding a parameter that had data-at-exec stuff in it,
+ then free that stuff
+ */
+ if (stmt->parameters[ipar].EXEC_used) {
+ free(stmt->parameters[ipar].EXEC_used);
+ stmt->parameters[ipar].EXEC_used = NULL;
+ }
+
+ if (stmt->parameters[ipar].EXEC_buffer) {
+ free(stmt->parameters[ipar].EXEC_buffer);
+ stmt->parameters[ipar].EXEC_buffer = NULL;
+ }
+
+ if (pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
+ stmt->parameters[ipar].data_at_exec = TRUE;
+ else
+ stmt->parameters[ipar].data_at_exec = FALSE;
+
+ + return SQL_SUCCESS; +} + +// - - - - - - - - - + +// Associate a user-supplied buffer with a database column. +RETCODE SQL_API SQLBindCol( + HSTMT hstmt, + UWORD icol, + SWORD fCType, + PTR rgbValue, + SDWORD cbValueMax, + SDWORD FAR *pcbValue) +{ +StatementClass *stmt = (StatementClass *) hstmt; +Int2 numcols; + +mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); + + if ( ! stmt) + return SQL_INVALID_HANDLE; + + if (icol < 1) { + /* currently we do not support bookmarks */ + stmt->errormsg = "Bookmarks are not currently supported."; + stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; + return SQL_ERROR; + } + + icol--; /* use zero based col numbers */ + + SC_clear_error(stmt); + + if( ! stmt->result) { + stmt->errormsg = "Can't bind columns with a NULL query result structure."; + stmt->errornumber = STMT_SEQUENCE_ERROR; + return SQL_ERROR; + } + + if( stmt->status == STMT_EXECUTING) { + stmt->errormsg = "Can't bind columns while statement is still executing."; + stmt->errornumber = STMT_SEQUENCE_ERROR; + return SQL_ERROR; + } + + numcols = QR_NumResultCols(stmt->result); + + mylog("SQLBindCol: numcols = %d\n", numcols); + + if (icol >= numcols) { + stmt->errornumber = STMT_COLNUM_ERROR; + stmt->errormsg = "Column number too big"; + return SQL_ERROR; + } + + if ( ! stmt->bindings) { + stmt->errormsg = "Bindings were not allocated properly."; + stmt->errornumber = STMT_SEQUENCE_ERROR; + return SQL_ERROR; + } + + if ((cbValueMax == 0) || (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; + } 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; + } + + return SQL_SUCCESS; +} + +// - - - - - - - - - + +// Returns the description of a parameter marker. + +RETCODE SQL_API SQLDescribeParam( + HSTMT hstmt, + UWORD ipar, + SWORD FAR *pfSqlType, + UDWORD FAR *pcbColDef, + SWORD FAR *pibScale, + SWORD FAR *pfNullable) +{ +StatementClass *stmt = (StatementClass *) hstmt; + + if( ! stmt) + return SQL_INVALID_HANDLE; + + if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) { + stmt->errormsg = "Invalid parameter number for SQLDescribeParam."; + stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR; + return SQL_ERROR; + } + + ipar--; + + if(pfSqlType) + *pfSqlType = stmt->parameters[ipar].SQLType; + + if(pcbColDef) + *pcbColDef = stmt->parameters[ipar].precision; + + if(pibScale) + *pibScale = stmt->parameters[ipar].scale; + + if(pfNullable) + *pfNullable = pgtype_nullable(stmt->parameters[ipar].paramType); + + return SQL_SUCCESS; +} + +// - - - - - - - - - + +// Sets multiple values (arrays) for the set of parameter markers. + +RETCODE SQL_API SQLParamOptions( + HSTMT hstmt, + UDWORD crow, + UDWORD FAR *pirow) +{ + return SQL_ERROR; +} + +// - - - - - - - - - + +// Returns the number of parameter markers. + +RETCODE SQL_API SQLNumParams( + HSTMT hstmt, + SWORD FAR *pcpar) +{ +StatementClass *stmt = (StatementClass *) hstmt; +unsigned int i; + + // I guess this is the number of actual parameter markers + // in the statement, not the number of parameters that are bound. + // why does this have to be driver-specific? + + if(!stmt) + return SQL_INVALID_HANDLE; + + if(!stmt->statement) { + // no statement has been allocated + *pcpar = 0; + stmt->errormsg = "SQLNumParams called with no statement ready."; + stmt->errornumber = STMT_SEQUENCE_ERROR; + return SQL_ERROR; + } else { + *pcpar = 0; + for(i=0; i < strlen(stmt->statement); i++) { + if(stmt->statement[i] == '?') + (*pcpar)++; + } + + return SQL_SUCCESS; + } +} + +/******************************************************************** + * Bindings Implementation + */ +BindInfoClass * +create_empty_bindings(int num_columns) +{ +BindInfoClass *new_bindings; +int i; + + new_bindings = (BindInfoClass *)malloc(num_columns * sizeof(BindInfoClass)); + if(!new_bindings) { + return 0; + } + + for(i=0; i < num_columns; i++) { + new_bindings[i].buflen = 0; + new_bindings[i].buffer = NULL; + new_bindings[i].used = NULL; + } + + return new_bindings; +} + +void +extend_bindings(StatementClass *stmt, int num_columns) +{ +BindInfoClass *new_bindings; +int i; + + mylog("in extend_bindings\n"); + + /* if we have too few, allocate room for more, and copy the old */ + /* entries into the new structure */ + if(stmt->bindings_allocated < num_columns) { + + new_bindings = create_empty_bindings(num_columns); + + if(stmt->bindings) { + for(i=0; i<stmt->bindings_allocated; i++) + new_bindings[i] = stmt->bindings[i]; + + free(stmt->bindings); + } + + stmt->bindings = new_bindings; // null indicates error + + } else { + /* if we have too many, make sure the extra ones are emptied out */ + /* so we don't accidentally try to use them for anything */ + for(i = num_columns; i < stmt->bindings_allocated; i++) { + stmt->bindings[i].buflen = 0; + stmt->bindings[i].buffer = NULL; + stmt->bindings[i].used = NULL; + } + } + + mylog("exit extend_bindings\n"); +} |