mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
903 lines
28 KiB
903 lines
28 KiB
/***************************************************************************/
|
|
/* PREPARE.C */
|
|
/* Copyright (C) 1995-96 SYWARE Inc., All rights reserved */
|
|
/***************************************************************************/
|
|
// Commenting #define out - causing compiler error - not sure if needed, compiles
|
|
// okay without it.
|
|
//#define WINVER 0x0400
|
|
#include "precomp.h"
|
|
|
|
#include "wbemidl.h"
|
|
|
|
#include <comdef.h>
|
|
//smart pointer
|
|
_COM_SMARTPTR_TYPEDEF(IWbemServices, IID_IWbemServices);
|
|
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, IID_IEnumWbemClassObject);
|
|
//_COM_SMARTPTR_TYPEDEF(IWbemContext, IID_IWbemContext );
|
|
_COM_SMARTPTR_TYPEDEF(IWbemLocator, IID_IWbemLocator);
|
|
|
|
#include "drdbdr.h"
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLAllocStmt(
|
|
HDBC hdbc,
|
|
HSTMT FAR *phstmt)
|
|
{
|
|
LPDBC lpdbc;
|
|
LPSTMT lpstmt;
|
|
HGLOBAL hstmt;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
/* Get connection handle */
|
|
lpdbc = (LPDBC) hdbc;
|
|
lpdbc->errcode = ERR_SUCCESS;
|
|
|
|
/* Allocate memory for the statement */
|
|
hstmt = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (STMT));
|
|
if (hstmt == NULL || (lpstmt = (LPSTMT)GlobalLock (hstmt)) == NULL) {
|
|
|
|
if (hstmt)
|
|
GlobalFree(hstmt);
|
|
|
|
lpdbc->errcode = ERR_MEMALLOCFAIL;
|
|
*phstmt = SQL_NULL_HSTMT;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Put statement on the list of statements for the connection */
|
|
lpstmt->lpNext = lpdbc->lpstmts;
|
|
lpdbc->lpstmts = lpstmt;
|
|
|
|
/* Initialize the statement handle */
|
|
lpstmt->lpdbc = lpdbc;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
((char*)lpstmt->szError)[0] = 0;
|
|
((char*)lpstmt->szISAMError)[0] = 0;
|
|
((char*)lpstmt->szCursor)[0] = 0;
|
|
lpstmt->fStmtType = STMT_TYPE_NONE;
|
|
lpstmt->fStmtSubtype = STMT_SUBTYPE_NONE;
|
|
lpstmt->irow = AFTER_LAST_ROW;
|
|
lpstmt->fSqlType = 0;
|
|
lpstmt->lpISAMTableList = NULL;
|
|
((char*)lpstmt->szTableName)[0] = 0;
|
|
lpstmt->lpISAMQualifierList = NULL;
|
|
((char*)lpstmt->szQualifierName)[0] = 0;
|
|
((char*)lpstmt->szTableType)[0] = 0;
|
|
lpstmt->fSyncMode = SQL_ASYNC_ENABLE_OFF; //default value
|
|
lpstmt->lpISAMTableDef = NULL;
|
|
lpstmt->lpKeyInfo = NULL;
|
|
lpstmt->lpSqlStmt = NULL;
|
|
lpstmt->fPreparedSql = FALSE;
|
|
lpstmt->lpISAMStatement = NULL;
|
|
lpstmt->fNeedData = FALSE;
|
|
lpstmt->idxParameter = NO_SQLNODE;
|
|
lpstmt->cbParameterOffset = -1;
|
|
lpstmt->icol = NO_COLUMN;
|
|
lpstmt->cRowCount = -1;
|
|
lpstmt->cbOffset = 0;
|
|
lpstmt->fISAMTxnStarted = FALSE;
|
|
lpstmt->fDMLTxn = FALSE;
|
|
|
|
/* So far no bound columns */
|
|
lpstmt->lpBound = NULL;
|
|
|
|
/* So far no parameters */
|
|
lpstmt->lpParameter = NULL;
|
|
|
|
/* Return the statement handle */
|
|
*phstmt = (HSTMT FAR *) lpstmt;
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLFreeStmt(
|
|
HSTMT hstmt,
|
|
UWORD fOption)
|
|
{
|
|
LPSTMT lpstmt;
|
|
LPSTMT lpstmtPrev;
|
|
LPBOUND lpBound;
|
|
LPPARAMETER lpParameter;
|
|
RETCODE err;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
/* Get statement handle */
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
|
|
// ODBCTRACE(_T("\nWBEM ODBC Driver : SQLFreeStmt\n"));
|
|
// MyImpersonator im (lpstmt);
|
|
|
|
/* Do the operation */
|
|
switch (fOption) {
|
|
case SQL_CLOSE:
|
|
|
|
/* End the transaction if need be */
|
|
if ((lpstmt->fStmtType == STMT_TYPE_SELECT) &&
|
|
(lpstmt->lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) &&
|
|
lpstmt->lpdbc->fAutoCommitTxn) {
|
|
err = SQLTransact(SQL_NULL_HENV, (HDBC)lpstmt->lpdbc, SQL_COMMIT);
|
|
if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) {
|
|
lpstmt->errcode = lpstmt->lpdbc->errcode;
|
|
s_lstrcpy(lpstmt->szISAMError, lpstmt->lpdbc->szISAMError);
|
|
return err;
|
|
}
|
|
}
|
|
|
|
/* Terminate the active statement */
|
|
lpstmt->fStmtType = STMT_TYPE_NONE;
|
|
lpstmt->fStmtSubtype = STMT_SUBTYPE_NONE;
|
|
lpstmt->irow = AFTER_LAST_ROW;
|
|
lpstmt->fSqlType = 0;
|
|
if (lpstmt->lpISAMTableList != NULL) {
|
|
ISAMFreeTableList(lpstmt->lpISAMTableList);
|
|
lpstmt->lpISAMTableList = NULL;
|
|
}
|
|
if (lpstmt->lpISAMQualifierList != NULL) {
|
|
ISAMFreeQualifierList(lpstmt->lpISAMQualifierList);
|
|
lpstmt->lpISAMQualifierList = NULL;
|
|
}
|
|
(lpstmt->szTableName)[0] = 0;
|
|
(lpstmt->szTableType)[0] = 0;
|
|
(lpstmt->szQualifierName)[0] = 0;
|
|
if (lpstmt->lpISAMTableDef != NULL) {
|
|
ISAMCloseTable(lpstmt->lpISAMTableDef);
|
|
lpstmt->lpISAMTableDef = NULL;
|
|
}
|
|
(lpstmt->szColumnName)[0] = 0;
|
|
if (lpstmt->lpKeyInfo != NULL) {
|
|
GlobalUnlock (GlobalPtrHandle(lpstmt->lpKeyInfo));
|
|
GlobalFree (GlobalPtrHandle(lpstmt->lpKeyInfo));
|
|
}
|
|
if ((lpstmt->lpSqlStmt != NULL) && !(lpstmt->fPreparedSql)) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
lpstmt->fPreparedSql = FALSE;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
}
|
|
lpstmt->fNeedData = FALSE;
|
|
lpstmt->idxParameter = NO_SQLNODE;
|
|
lpstmt->cbParameterOffset = -1;
|
|
|
|
lpstmt->icol = NO_COLUMN;
|
|
lpstmt->cbOffset = 0;
|
|
break;
|
|
|
|
case SQL_DROP:
|
|
|
|
/* Terminate the active statement */
|
|
err = SQLFreeStmt(hstmt, SQL_CLOSE);
|
|
if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) {
|
|
lpstmt->fStmtType = STMT_TYPE_NONE;
|
|
err = SQLTransact(SQL_NULL_HENV, (HDBC)lpstmt->lpdbc, SQL_ROLLBACK);
|
|
SQLFreeStmt(hstmt, SQL_CLOSE);
|
|
}
|
|
if (lpstmt->lpSqlStmt != NULL) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
lpstmt->fPreparedSql = FALSE;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
}
|
|
lpstmt->fNeedData = FALSE;
|
|
lpstmt->idxParameter = NO_SQLNODE;
|
|
lpstmt->cbParameterOffset = -1;
|
|
lpstmt->cRowCount = -1;
|
|
|
|
/*/ Unbind everything */
|
|
SQLFreeStmt(hstmt, SQL_UNBIND);
|
|
|
|
/* Reset the parameters */
|
|
SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
|
|
|
|
/* Take statement off of list of statements for the connection */
|
|
if (lpstmt->lpdbc->lpstmts == lpstmt) {
|
|
lpstmt->lpdbc->lpstmts = lpstmt->lpNext;
|
|
}
|
|
else {
|
|
lpstmtPrev = lpstmt->lpdbc->lpstmts;
|
|
while (lpstmtPrev->lpNext != lpstmt)
|
|
lpstmtPrev = lpstmtPrev->lpNext;
|
|
lpstmtPrev->lpNext = lpstmt->lpNext;
|
|
}
|
|
|
|
/* Dealloate the memory */
|
|
GlobalUnlock (GlobalPtrHandle(hstmt));
|
|
GlobalFree (GlobalPtrHandle(hstmt));
|
|
break;
|
|
|
|
case SQL_UNBIND:
|
|
|
|
/* Remove all the bindings */
|
|
while (lpstmt->lpBound != NULL) {
|
|
lpBound = lpstmt->lpBound->lpNext;
|
|
GlobalUnlock (GlobalPtrHandle(lpstmt->lpBound));
|
|
GlobalFree (GlobalPtrHandle(lpstmt->lpBound));
|
|
lpstmt->lpBound = lpBound;
|
|
}
|
|
break;
|
|
|
|
case SQL_RESET_PARAMS:
|
|
|
|
/* It is not possible to reset the parameters while setting them */
|
|
if (lpstmt->fNeedData) {
|
|
lpstmt->errcode = ERR_CURSORSTATE;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Reset all the parameters */
|
|
while (lpstmt->lpParameter != NULL) {
|
|
lpParameter = lpstmt->lpParameter->lpNext;
|
|
GlobalUnlock (GlobalPtrHandle(lpstmt->lpParameter));
|
|
GlobalFree (GlobalPtrHandle(lpstmt->lpParameter));
|
|
lpstmt->lpParameter = lpParameter;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLPrepare(
|
|
HSTMT hstmt,
|
|
UCHAR FAR *szSqlStr,
|
|
SDWORD cbSqlStr)
|
|
{
|
|
LPSTMT lpstmt;
|
|
LPSQLNODE lpSqlNode;
|
|
UCHAR szCursorname[MAX_CURSOR_NAME_LENGTH];
|
|
int i;
|
|
UCHAR szSimpleSql[21 + MAX_TABLE_NAME_LENGTH + 1];
|
|
UWORD parameterCount;
|
|
SQLNODEIDX idxParameter;
|
|
SQLNODEIDX idxParameterPrev;
|
|
UWORD id;
|
|
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
/* Get statement handle */
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
CString myInputString;
|
|
myInputString.Format("\nWBEM ODBC Driver :SQLPrepare :\nszSqlStr = %s\ncbSqlStr = %ld\n",
|
|
szSqlStr, cbSqlStr);
|
|
ODBCTRACE(myInputString);
|
|
|
|
MyImpersonator im (lpstmt,"SQLPrepare");
|
|
|
|
/* Error if in the middle of a statement already */
|
|
if (lpstmt->fStmtType != STMT_TYPE_NONE) {
|
|
lpstmt->errcode = ERR_CURSORSTATE;
|
|
return SQL_ERROR;
|
|
}
|
|
if (lpstmt->fNeedData) {
|
|
lpstmt->errcode = ERR_CURSORSTATE;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Free previously prepared statement if any */
|
|
if (lpstmt->lpSqlStmt != NULL) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
lpstmt->fPreparedSql = FALSE;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
lpstmt->fNeedData = FALSE;
|
|
lpstmt->idxParameter = NO_SQLNODE;
|
|
lpstmt->cbParameterOffset = -1;
|
|
lpstmt->cRowCount = -1;
|
|
}
|
|
|
|
/* Count of rows is not available */
|
|
lpstmt->cRowCount = -1;
|
|
|
|
/* Try passing the statement down to the ISAM layer */
|
|
if (cbSqlStr == SQL_NTS)
|
|
{
|
|
if (szSqlStr)
|
|
cbSqlStr = s_lstrlen((char*)szSqlStr);
|
|
else
|
|
cbSqlStr = 0;
|
|
}
|
|
szSimpleSql[0] = 0;
|
|
s_lstrcpy(szSimpleSql, "SELECT * FROM \"");
|
|
lpstmt->errcode = ISAMPrepare(lpstmt->lpdbc->lpISAM, szSqlStr, cbSqlStr,
|
|
&(lpstmt->lpISAMStatement), (LPUSTR) (szSimpleSql + 15),
|
|
¶meterCount, lpstmt);
|
|
if (lpstmt->errcode == ISAM_NOTSUPPORTED)
|
|
{
|
|
//Check if we are in passthrough only mode
|
|
if (lpstmt->lpdbc->lpISAM->fPassthroughOnly)
|
|
{
|
|
ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
|
|
return SQL_ERROR;
|
|
}
|
|
else
|
|
{
|
|
lpstmt->lpISAMStatement = NULL;
|
|
parameterCount = 0;
|
|
}
|
|
}
|
|
else if (lpstmt->errcode != NO_ISAM_ERR) {
|
|
ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
|
|
return SQL_ERROR;
|
|
}
|
|
else
|
|
lpstmt->fISAMTxnStarted = TRUE;
|
|
|
|
|
|
/* Was the SQL passthrough rejected or is it returning a result set? */
|
|
if ((lpstmt->errcode == ISAM_NOTSUPPORTED) ||
|
|
(s_lstrlen((szSimpleSql + 15)) != 0)) {
|
|
|
|
/* Yes. Parse the statement */
|
|
if (lpstmt->errcode == ISAM_NOTSUPPORTED) {
|
|
lpstmt->errcode = Parse(lpstmt, lpstmt->lpdbc->lpISAM, (LPUSTR)szSqlStr,
|
|
cbSqlStr, &(lpstmt->lpSqlStmt));
|
|
}
|
|
else {
|
|
s_lstrcat(szSimpleSql, "\"");
|
|
|
|
//NEW
|
|
//Sai Wong - removed this Parse as it has already been
|
|
//done in ISAMPrepare
|
|
|
|
//Changed again
|
|
//Parse SELECT * from WBEMDR32VirtualTable
|
|
lpstmt->errcode = Parse(lpstmt, lpstmt->lpdbc->lpISAM,
|
|
szSimpleSql, s_lstrlen(szSimpleSql), &(lpstmt->lpSqlStmt));
|
|
}
|
|
if (lpstmt->errcode != SQL_SUCCESS) {
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Semanticize the parsed statement */
|
|
lpstmt->errcode = SemanticCheck(lpstmt, &(lpstmt->lpSqlStmt),
|
|
ROOT_SQLNODE, FALSE, ISAMCaseSensitive(lpstmt->lpdbc->lpISAM),
|
|
NO_SQLNODE, NO_SQLNODE);
|
|
if (lpstmt->errcode != SQL_SUCCESS) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Optimize execution */
|
|
lpstmt->errcode = Optimize(lpstmt->lpSqlStmt,
|
|
ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE)->node.root.sql,
|
|
ISAMCaseSensitive(lpstmt->lpdbc->lpISAM));
|
|
if (lpstmt->errcode != SQL_SUCCESS) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
return SQL_ERROR;
|
|
}
|
|
#if ISAM_TRACE
|
|
ShowSemantic(lpstmt->lpSqlStmt, ROOT_SQLNODE, 0);
|
|
#endif
|
|
}
|
|
else {
|
|
|
|
#ifdef IMPLTMT_PASSTHROUGH
|
|
//No nothing
|
|
#else
|
|
/* No. Create a PASSTHROUGH parse tree */
|
|
lpstmt->errcode = Parse(lpstmt, lpstmt->lpdbc->lpISAM, (LPUSTR) "SQL",
|
|
3, &(lpstmt->lpSqlStmt));
|
|
if (lpstmt->errcode != SQL_SUCCESS) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
return SQL_ERROR;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Are there pass through parameters? */
|
|
if (parameterCount != 0) {
|
|
|
|
/* Yes. Create them */
|
|
idxParameterPrev = NO_SQLNODE;
|
|
for (id = 1; id <= parameterCount; id++) {
|
|
|
|
/* Create the next parameter */
|
|
idxParameter = AllocateNode(&(lpstmt->lpSqlStmt),
|
|
NODE_TYPE_PARAMETER);
|
|
if (idxParameter == NO_SQLNODE) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
lpstmt->errcode = ERR_MEMALLOCFAIL;
|
|
return SQL_ERROR;
|
|
}
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, idxParameter);
|
|
lpSqlNode->node.parameter.Id = id;
|
|
lpSqlNode->node.parameter.Next = NO_SQLNODE;
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
lpSqlNode->node.parameter.AtExec = FALSE;
|
|
|
|
/* Put it on the list */
|
|
if (idxParameterPrev == NO_SQLNODE) {
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE);
|
|
lpSqlNode->node.root.parameters = idxParameter;
|
|
lpSqlNode->node.root.passthroughParams = TRUE;
|
|
}
|
|
else {
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, idxParameterPrev);
|
|
lpSqlNode->node.parameter.Next = idxParameter;
|
|
}
|
|
idxParameterPrev = idxParameter;
|
|
|
|
/* Semantic check the newly created parameter */
|
|
lpstmt->errcode = SemanticCheck(lpstmt, &(lpstmt->lpSqlStmt),
|
|
idxParameter, FALSE, ISAMCaseSensitive(lpstmt->lpdbc->lpISAM),
|
|
NO_SQLNODE, NO_SQLNODE);
|
|
if (lpstmt->errcode != SQL_SUCCESS) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* All passthrough parameters are strings */
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, idxParameter);
|
|
lpSqlNode->sqlDataType = TYPE_CHAR;
|
|
lpSqlNode->sqlSqlType = SQL_VARCHAR;
|
|
lpSqlNode->sqlPrecision = MAX_CHAR_LITERAL_LENGTH;
|
|
lpSqlNode->sqlScale = NO_SCALE;
|
|
}
|
|
}
|
|
|
|
/* Allocate space for the parameters */
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE);
|
|
for (idxParameter = lpSqlNode->node.root.parameters;
|
|
idxParameter != NO_SQLNODE;
|
|
idxParameter = lpSqlNode->node.parameter.Next) {
|
|
|
|
/* Get parameter node */
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, idxParameter);
|
|
|
|
/* Allocate space for the parameter value */
|
|
switch (lpSqlNode->sqlDataType) {
|
|
case TYPE_DOUBLE:
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
break;
|
|
case TYPE_NUMERIC:
|
|
lpSqlNode->node.parameter.Value = AllocateSpace(&(lpstmt->lpSqlStmt),
|
|
(SWORD)(lpSqlNode->sqlPrecision + 2 + 1));
|
|
if (lpSqlNode->node.parameter.Value == NO_STRING) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
lpstmt->errcode = ERR_MEMALLOCFAIL;
|
|
return SQL_ERROR;
|
|
}
|
|
break;
|
|
case TYPE_INTEGER:
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
break;
|
|
case TYPE_CHAR:
|
|
lpSqlNode->node.parameter.Value = AllocateSpace(&(lpstmt->lpSqlStmt),
|
|
MAX_CHAR_LITERAL_LENGTH+1);
|
|
if (lpSqlNode->node.parameter.Value == NO_STRING) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
lpstmt->errcode = ERR_MEMALLOCFAIL;
|
|
return SQL_ERROR;
|
|
}
|
|
break;
|
|
case TYPE_BINARY:
|
|
lpSqlNode->node.parameter.Value = AllocateSpace(&(lpstmt->lpSqlStmt),
|
|
MAX_BINARY_LITERAL_LENGTH + sizeof(SDWORD));
|
|
if (lpSqlNode->node.parameter.Value == NO_STRING) {
|
|
FreeTree(lpstmt->lpSqlStmt);
|
|
lpstmt->lpSqlStmt = NULL;
|
|
if (lpstmt->lpISAMStatement != NULL) {
|
|
ISAMFreeStatement(lpstmt->lpISAMStatement);
|
|
lpstmt->lpISAMStatement = NULL;
|
|
}
|
|
lpstmt->errcode = ERR_MEMALLOCFAIL;
|
|
return SQL_ERROR;
|
|
}
|
|
break;
|
|
case TYPE_DATE:
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
break;
|
|
case TYPE_TIME:
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
break;
|
|
case TYPE_TIMESTAMP:
|
|
lpSqlNode->node.parameter.Value = NO_STRING;
|
|
break;
|
|
case TYPE_UNKNOWN:
|
|
/* Error if '?' used in a select list */
|
|
if (parameterCount == 0)
|
|
lpstmt->errcode = ERR_PARAMINSELECT;
|
|
else
|
|
lpstmt->errcode = ERR_INTERNAL;
|
|
return SQL_ERROR;
|
|
default:
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Was a SELECT statement preprared? */
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE);
|
|
lpSqlNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.root.sql);
|
|
if (lpSqlNode->sqlNodeType == NODE_TYPE_SELECT) {
|
|
|
|
/* Yes. Is a cursor name needed? */
|
|
if (s_lstrlen(lpstmt->szCursor) == 0) {
|
|
|
|
/* Yes. Assign one */
|
|
for (i=0; TRUE; i++) {
|
|
wsprintf((LPSTR)szCursorname, "CUR%05d", (SWORD)i);
|
|
if (SQLSetCursorName(hstmt, (LPUSTR) szCursorname, SQL_NTS) ==
|
|
SQL_SUCCESS)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Mark the statement as from SQLPrepare() */
|
|
lpstmt->fPreparedSql = TRUE;
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
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)
|
|
{
|
|
LPSTMT lpstmt;
|
|
LPPARAMETER lpParameter;
|
|
HGLOBAL hParameter;
|
|
LPSQLTYPE lpSqlType;
|
|
UWORD i;
|
|
|
|
/* Get statement handle */
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
MyImpersonator im (lpstmt, "SQLBindParameter");
|
|
|
|
/* Error if in the middle of a statement already */
|
|
if (lpstmt->fNeedData) {
|
|
lpstmt->errcode = ERR_CURSORSTATE;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* If SQL_C_DEFAULT was specified as the type, figure out the real type */
|
|
if (fCType == SQL_C_DEFAULT) {
|
|
switch (fSqlType) {
|
|
case SQL_CHAR:
|
|
case SQL_VARCHAR:
|
|
case SQL_LONGVARCHAR:
|
|
fCType = SQL_C_CHAR;
|
|
break;
|
|
case SQL_BIGINT:
|
|
case SQL_DECIMAL:
|
|
case SQL_NUMERIC:
|
|
fCType = SQL_C_CHAR;
|
|
break;
|
|
case SQL_DOUBLE:
|
|
case SQL_FLOAT:
|
|
fCType = SQL_C_DOUBLE;
|
|
break;
|
|
case SQL_BIT:
|
|
fCType = SQL_C_BIT;
|
|
break;
|
|
case SQL_REAL:
|
|
fCType = SQL_C_FLOAT;
|
|
break;
|
|
case SQL_INTEGER:
|
|
fCType = SQL_C_LONG;
|
|
break;
|
|
case SQL_SMALLINT:
|
|
fCType = SQL_C_SHORT;
|
|
break;
|
|
case SQL_TINYINT:
|
|
fCType = SQL_C_TINYINT;
|
|
break;
|
|
case SQL_DATE:
|
|
fCType = SQL_C_DATE;
|
|
break;
|
|
case SQL_TIME:
|
|
fCType = SQL_C_TIME;
|
|
break;
|
|
case SQL_TIMESTAMP:
|
|
fCType = SQL_C_TIMESTAMP;
|
|
break;
|
|
case SQL_BINARY:
|
|
case SQL_VARBINARY:
|
|
case SQL_LONGVARBINARY:
|
|
fCType = SQL_C_BINARY;
|
|
break;
|
|
default:
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
|
|
/* If C type is SQL_C_TINYINT, figure out if it is signed or unsigned */
|
|
if (fCType == SQL_C_TINYINT) {
|
|
lpSqlType = NULL;
|
|
for (i = 0; i < lpstmt->lpdbc->lpISAM->cSQLTypes; i++) {
|
|
if (lpstmt->lpdbc->lpISAM->SQLTypes[i].type == SQL_TINYINT) {
|
|
lpSqlType = &(lpstmt->lpdbc->lpISAM->SQLTypes[i]);
|
|
break;
|
|
}
|
|
}
|
|
if (lpSqlType == NULL)
|
|
fCType = SQL_C_STINYINT;
|
|
else if (lpSqlType->unsignedAttribute == TRUE)
|
|
fCType = SQL_C_UTINYINT;
|
|
else
|
|
fCType = SQL_C_STINYINT;
|
|
}
|
|
|
|
/* If C type is SQL_C_SHORT, figure out if it is signed or unsigned */
|
|
if (fCType == SQL_C_SHORT) {
|
|
lpSqlType = NULL;
|
|
for (i = 0; i < lpstmt->lpdbc->lpISAM->cSQLTypes; i++) {
|
|
if (lpstmt->lpdbc->lpISAM->SQLTypes[i].type == SQL_SMALLINT) {
|
|
lpSqlType = &(lpstmt->lpdbc->lpISAM->SQLTypes[i]);
|
|
break;
|
|
}
|
|
}
|
|
if (lpSqlType == NULL)
|
|
fCType = SQL_C_SSHORT;
|
|
else if (lpSqlType->unsignedAttribute == TRUE)
|
|
fCType = SQL_C_USHORT;
|
|
else
|
|
fCType = SQL_C_SSHORT;
|
|
}
|
|
|
|
/* If C type is SQL_C_LONG, figure out if it is signed or unsigned */
|
|
if (fCType == SQL_C_LONG) {
|
|
lpSqlType = NULL;
|
|
for (i = 0; i < lpstmt->lpdbc->lpISAM->cSQLTypes; i++) {
|
|
if (lpstmt->lpdbc->lpISAM->SQLTypes[i].type == SQL_INTEGER) {
|
|
lpSqlType = &(lpstmt->lpdbc->lpISAM->SQLTypes[i]);
|
|
break;
|
|
}
|
|
}
|
|
if (lpSqlType == NULL)
|
|
fCType = SQL_C_SLONG;
|
|
else if (lpSqlType->unsignedAttribute == TRUE)
|
|
fCType = SQL_C_ULONG;
|
|
else
|
|
fCType = SQL_C_SLONG;
|
|
}
|
|
|
|
/* Ignore output parameters */
|
|
if (fParamType == SQL_PARAM_OUTPUT)
|
|
return SQL_SUCCESS;
|
|
|
|
/* Find the parameter is on the list */
|
|
lpParameter = lpstmt->lpParameter;
|
|
while (lpParameter != NULL) {
|
|
if (lpParameter->ipar == ipar)
|
|
break;
|
|
lpParameter = lpParameter->lpNext;
|
|
}
|
|
|
|
/* No. Was it on the list? */
|
|
if (lpParameter == NULL) {
|
|
|
|
/* No. Make an entry for it */
|
|
hParameter = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (PARAMETER));
|
|
if (hParameter == NULL || (lpParameter = (LPPARAMETER)GlobalLock (hParameter)) == NULL) {
|
|
|
|
if (hParameter)
|
|
GlobalFree(hParameter);
|
|
|
|
lpstmt->errcode = ERR_MEMALLOCFAIL;
|
|
return SQL_ERROR;
|
|
}
|
|
lpParameter->lpNext = lpstmt->lpParameter;
|
|
lpstmt->lpParameter = lpParameter;
|
|
lpParameter->ipar = ipar;
|
|
}
|
|
|
|
/* Save the bound description */
|
|
lpParameter->fCType = fCType;
|
|
lpParameter->rgbValue = rgbValue;
|
|
lpParameter->pcbValue = pcbValue;
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLDescribeParam(
|
|
HSTMT hstmt,
|
|
UWORD ipar,
|
|
SWORD FAR *pfSqlType,
|
|
UDWORD FAR *pcbColDef,
|
|
SWORD FAR *pibScale,
|
|
SWORD FAR *pfNullable)
|
|
{
|
|
LPSTMT lpstmt;
|
|
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLParamOptions(
|
|
HSTMT hstmt,
|
|
UDWORD crow,
|
|
UDWORD FAR *pirow)
|
|
{
|
|
LPSTMT lpstmt;
|
|
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLNumParams(
|
|
HSTMT hstmt,
|
|
SWORD FAR *pcpar)
|
|
{
|
|
LPSTMT lpstmt;
|
|
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLSetScrollOptions(
|
|
HSTMT hstmt,
|
|
UWORD fConcurrency,
|
|
SDWORD crowKeyset,
|
|
UWORD crowRowset)
|
|
{
|
|
LPSTMT lpstmt;
|
|
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_NOTSUPPORTED;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLSetCursorName(
|
|
HSTMT hstmt,
|
|
UCHAR FAR *szCursor,
|
|
SWORD cbCursor)
|
|
{
|
|
SWORD cbIn;
|
|
LPSTMT lpstmt;
|
|
UCHAR szCursorname[MAX_CURSOR_NAME_LENGTH];
|
|
LPSTMT lpstmtOther;
|
|
|
|
/* Get statement handle */
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
MyImpersonator im (lpstmt, "SQLSetCursorName");
|
|
|
|
/* Get length of cursor name */
|
|
if (cbCursor == SQL_NTS)
|
|
cbIn = (SWORD) s_lstrlen(szCursor);
|
|
else
|
|
cbIn = cbCursor;
|
|
|
|
if ((cbIn <= 0) || (cbIn >= MAX_CURSOR_NAME_LENGTH)) {
|
|
lpstmt->errcode = ERR_INVALIDCURSORNAME;
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* Make a null terminated copy of the cursor name */
|
|
_fmemcpy(szCursorname, szCursor, cbIn);
|
|
szCursorname[cbIn] = '\0';
|
|
|
|
/* Make sure name is not already in use */
|
|
for (lpstmtOther = lpstmt->lpdbc->lpstmts;
|
|
lpstmtOther != NULL;
|
|
lpstmtOther = lpstmtOther->lpNext) {
|
|
if (lpstmtOther != lpstmt) {
|
|
if (!s_lstrcmpi(lpstmtOther->szCursor, szCursorname)) {
|
|
lpstmt->errcode = ERR_CURSORNAMEINUSE;
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Save cursor name */
|
|
s_lstrcpy(lpstmt->szCursor, szCursorname);
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
RETCODE SQL_API SQLGetCursorName(
|
|
HSTMT hstmt,
|
|
UCHAR FAR *szCursor,
|
|
SWORD cbCursorMax,
|
|
SWORD FAR *pcbCursor)
|
|
{
|
|
LPSTMT lpstmt;
|
|
|
|
/* Get statement handle */
|
|
lpstmt = (LPSTMT) hstmt;
|
|
lpstmt->errcode = ERR_SUCCESS;
|
|
|
|
//To make guarentee Ole is initialized per thread
|
|
COleInitializationManager myOleManager;
|
|
|
|
MyImpersonator im (lpstmt, "SQLGetCursorName");
|
|
|
|
/* Return cursor name */
|
|
lpstmt->errcode = ReturnString(szCursor, cbCursorMax,
|
|
pcbCursor, (LPUSTR)lpstmt->szCursor);
|
|
if (lpstmt->errcode == ERR_DATATRUNCATED)
|
|
return SQL_SUCCESS_WITH_INFO;
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
/***************************************************************************/
|