Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1133 lines (915 sloc) 23.209 kB
/*
* execute.c
*
* $Id$
*
* Invoke a query
*
* The iODBC driver manager.
*
* Copyright (C) 1995 by Ke Jin <kejin@empress.com>
* Copyright (C) 1996-2015 by OpenLink Software <iodbc@openlinksw.com>
* All Rights Reserved.
*
* This software is released under the terms of either of the following
* licenses:
*
* - GNU Library General Public License (see LICENSE.LGPL)
* - The BSD License (see LICENSE.BSD).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2, dated June 1991.
*
* While not mandated by the BSD license, any patches you make to the
* iODBC source code may be contributed back into the iODBC project
* at your discretion. Contributions will benefit the Open Source and
* Data Access community as a whole. Submissions may be made at:
*
* http://www.iodbc.org
*
*
* GNU Library Generic Public License Version 2
* ============================================
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; only
* Version 2 of the License dated June 1991.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*
* The BSD License
* ===============
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of OpenLink Software Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iodbc.h>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>
#include <unicode.h>
#include <dlproc.h>
#include <herr.h>
#include <henv.h>
#include <hdbc.h>
#include <hstmt.h>
#include <itrace.h>
void
_iodbcdm_do_cursoropen (STMT_t * pstmt)
{
SQLRETURN retcode;
SWORD ncol;
pstmt->state = en_stmt_executed;
retcode = _iodbcdm_NumResultCols ((SQLHSTMT) pstmt, &ncol);
if (SQL_SUCCEEDED (retcode))
{
if (ncol)
{
pstmt->state = en_stmt_cursoropen;
pstmt->cursor_state = en_stmt_cursor_opened;
}
else
{
pstmt->state = en_stmt_executed;
pstmt->cursor_state = en_stmt_cursor_no;
}
}
}
#if (ODBCVER >= 0x0300)
static SQLLEN
GetElementSize (PPARM pparm)
{
SQLLEN elementSize;
if (pparm->pm_c_type == SQL_C_CHAR || pparm->pm_c_type == SQL_C_BINARY)
elementSize = pparm->pm_cbValueMax == 0
? pparm->pm_precision : pparm->pm_cbValueMax;
else if (pparm->pm_c_type == SQL_C_WCHAR)
elementSize = pparm->pm_cbValueMax == 0
? pparm->pm_precision * sizeof(wchar_t) : pparm->pm_cbValueMax;
else /* fixed length types */
elementSize = pparm->pm_size;
return elementSize;
}
static void
_Conv_W2A(wchar_t *wdata, SQLLEN *pInd, UDWORD size)
{
char *data = (char *) wdata;
if (*pInd != SQL_NULL_DATA)
{
char *buf = (char *)dm_SQL_W2A ((SQLWCHAR *) wdata, (ssize_t)*pInd);
if (buf != NULL)
strcpy(data, buf);
MEM_FREE (buf);
if (pInd && *pInd != SQL_NTS)
*pInd /= sizeof (wchar_t);
}
}
static void
_Conv_A2W(char *data, SQLLEN *pInd, UDWORD size)
{
wchar_t *wdata = (wchar_t *) data;
if (*pInd != SQL_NULL_DATA)
{
wchar_t *buf = (wchar_t *)dm_SQL_A2W ((SQLCHAR *) data, (ssize_t)*pInd);
if (buf != NULL)
WCSCPY (wdata, buf);
MEM_FREE (buf);
}
}
static SQLLEN
_ConvParam (STMT_t *pstmt, PPARM pparm, SQLULEN row, BOOL bOutput)
{
SQLLEN octetLen;
void *value;
SQLLEN *pInd = NULL;
SQLLEN elementSize = 0;
if (pparm->pm_c_type != SQL_C_WCHAR)
return 0;
elementSize = GetElementSize (pparm);
if (pstmt->bind_type)
{
/* row-wise binding of parameters in force */
if (pparm->pm_pOctetLength)
octetLen = *(SQLLEN *) ((char *) pparm->pm_pOctetLength
+ row * pstmt->bind_type);
else
octetLen = pparm->pm_size;
if (pparm->pm_pInd)
pInd = (SQLLEN *) ((char *) pparm->pm_pInd
+ row * pstmt->bind_type);
}
else
{
octetLen = pparm->pm_pOctetLength ? pparm->pm_pOctetLength[row] : pparm->pm_size;
if (pparm->pm_pInd)
pInd = pparm->pm_pInd + row;
}
if (!pInd || (pInd && *pInd == SQL_NULL_DATA))
return 0;
if (octetLen == SQL_DATA_AT_EXEC || octetLen <= SQL_LEN_DATA_AT_EXEC_OFFSET)
{
value = NULL;
}
else
value = pparm->pm_data;
if (value == NULL)
return 0;
if (pstmt->bind_type)
/* row-wise binding of parameters in force */
value = (char *) pparm->pm_data + row * pstmt->bind_type;
else
value = (char *) pparm->pm_data + row * elementSize;
if (bOutput)
_Conv_A2W(value, pInd, elementSize);
else
_Conv_W2A(value, pInd, elementSize);
return octetLen;
}
static SQLRETURN
_SQLExecute_ConvParams (SQLHSTMT hstmt, BOOL bOutput)
{
STMT (pstmt, hstmt);
CONN (pdbc, pstmt->hdbc);
ENVR (penv, pdbc->henv);
PPARM pparm;
int maxpar;
int i;
SQLULEN j;
SQLULEN cRows = pstmt->paramset_size;
if (penv->unicode_driver)
return SQL_SUCCESS;
if (cRows == 0)
cRows = 1;
maxpar = pstmt->st_nparam;
pparm = pstmt->st_pparam;
for (i = 0; i < maxpar; i++, pparm++)
{
if (pparm->pm_data == NULL)
continue;
if (bOutput && (pparm->pm_usage == SQL_PARAM_OUTPUT || pparm->pm_usage == SQL_PARAM_INPUT_OUTPUT))
{
if (pparm->pm_c_type_orig != SQL_C_WCHAR)
continue;
for (j = 0; j < cRows; j++)
_ConvParam(pstmt, pparm, j, bOutput);
}
else if (!bOutput && (pparm->pm_usage == SQL_PARAM_INPUT || pparm->pm_usage == SQL_PARAM_INPUT_OUTPUT))
{
if (pparm->pm_c_type != SQL_C_WCHAR)
continue;
for (j = 0; j < cRows; j++)
_ConvParam(pstmt, pparm, j, bOutput);
pparm->pm_c_type = SQL_C_CHAR;
}
} /* next column */
return SQL_SUCCESS;
}
#endif
static SQLRETURN
SQLExecute_Internal (SQLHSTMT hstmt)
{
STMT (pstmt, hstmt);
HPROC hproc = SQL_NULL_HPROC;
SQLRETURN retcode;
sqlstcode_t sqlstat = en_00000;
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
switch (pstmt->state)
{
case en_stmt_allocated:
sqlstat = en_S1010;
break;
case en_stmt_executed_with_info:
case en_stmt_executed:
if (!pstmt->prep_state)
{
sqlstat = en_S1010;
}
break;
case en_stmt_cursoropen:
if (!pstmt->prep_state)
{
sqlstat = en_S1010;
}
break;
case en_stmt_fetched:
case en_stmt_xfetched:
if (!pstmt->prep_state)
{
sqlstat = en_S1010;
}
else
{
sqlstat = en_24000;
}
break;
case en_stmt_needdata:
case en_stmt_mustput:
case en_stmt_canput:
sqlstat = en_S1010;
break;
default:
break;
}
}
else if (pstmt->asyn_on != en_Execute)
{
sqlstat = en_S1010;
}
if (sqlstat == en_00000)
{
hproc = _iodbcdm_getproc (pstmt->hdbc, en_Execute);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM001;
}
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pstmt->herr, sqlstat);
return SQL_ERROR;
}
if ((retcode = _SQLExecute_ConvParams(hstmt, FALSE)) != SQL_SUCCESS)
return retcode;
CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt));
/* stmt state transition */
if (pstmt->asyn_on == en_Execute)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_NEED_DATA:
case SQL_ERROR:
pstmt->asyn_on = en_NullProc;
break;
case SQL_STILL_EXECUTING:
default:
return retcode;
}
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
retcode = _SQLExecute_ConvParams(hstmt, TRUE);
switch (pstmt->state)
{
case en_stmt_prepared:
switch (retcode)
{
case SQL_SUCCESS:
_iodbcdm_do_cursoropen (pstmt);
break;
case SQL_SUCCESS_WITH_INFO:
pstmt->state = en_stmt_executed_with_info;
break;
case SQL_NEED_DATA:
pstmt->state = en_stmt_needdata;
pstmt->need_on = en_Execute;
break;
case SQL_STILL_EXECUTING:
pstmt->asyn_on = en_Execute;
break;
default:
break;
}
break;
case en_stmt_executed:
switch (retcode)
{
case SQL_ERROR:
pstmt->state = en_stmt_prepared;
pstmt->cursor_state = en_stmt_cursor_no;
break;
case SQL_NEED_DATA:
pstmt->state = en_stmt_needdata;
pstmt->need_on = en_Execute;
break;
case SQL_STILL_EXECUTING:
pstmt->asyn_on = en_Execute;
break;
default:
break;
}
break;
default:
break;
}
return retcode;
}
SQLRETURN SQL_API
SQLExecute (SQLHSTMT hstmt)
{
ENTER_STMT (hstmt,
trace_SQLExecute (TRACE_ENTER, hstmt));
retcode = SQLExecute_Internal (hstmt);
LEAVE_STMT (hstmt,
trace_SQLExecute (TRACE_LEAVE, hstmt));
}
SQLRETURN SQL_API
SQLExecDirect_Internal (SQLHSTMT hstmt,
SQLPOINTER szSqlStr,
SQLINTEGER cbSqlStr,
SQLCHAR waMode)
{
STMT (pstmt, hstmt);
CONN (pdbc, pstmt->hdbc);
ENVR (penv, pdbc->henv);
HPROC hproc = SQL_NULL_HPROC;
SQLRETURN retcode = SQL_SUCCESS;
sqlstcode_t sqlstat = en_00000;
void * _SqlStr = NULL;
/* check arguments */
if (szSqlStr == NULL)
{
sqlstat = en_S1009;
}
else if (cbSqlStr < 0 && cbSqlStr != SQL_NTS)
{
sqlstat = en_S1090;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pstmt->herr, sqlstat);
return SQL_ERROR;
}
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
switch (pstmt->state)
{
case en_stmt_fetched:
case en_stmt_xfetched:
sqlstat = en_24000;
break;
case en_stmt_needdata:
case en_stmt_mustput:
case en_stmt_canput:
sqlstat = en_S1010;
break;
default:
break;
}
}
else if (pstmt->asyn_on != en_ExecDirect)
{
sqlstat = en_S1010;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pstmt->herr, sqlstat);
return SQL_ERROR;
}
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
if (waMode != 'W')
{
/* ansi=>unicode*/
_SqlStr = _iodbcdm_conv_var_A2W(pstmt, 0, (SQLCHAR *) szSqlStr, cbSqlStr);
}
else
{
/* unicode=>ansi*/
_SqlStr = _iodbcdm_conv_var_W2A(pstmt, 0, (SQLWCHAR *) szSqlStr, cbSqlStr);
}
szSqlStr = _SqlStr;
cbSqlStr = SQL_NTS;
}
if ((retcode = _SQLExecute_ConvParams(hstmt, FALSE)) != SQL_SUCCESS)
return retcode;
CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver,
en_ExecDirect, (
pstmt->dhstmt,
szSqlStr,
cbSqlStr));
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_FreeStmtVars(pstmt);
PUSHSQLERR (pstmt->herr, en_IM001);
return SQL_ERROR;
}
if (retcode != SQL_STILL_EXECUTING)
_iodbcdm_FreeStmtVars(pstmt);
/* stmt state transition */
if (pstmt->asyn_on == en_ExecDirect)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_NEED_DATA:
case SQL_ERROR:
pstmt->asyn_on = en_NullProc;
break;
case SQL_STILL_EXECUTING:
default:
return retcode;
}
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
retcode = _SQLExecute_ConvParams(hstmt, TRUE);
if (pstmt->state <= en_stmt_executed)
{
switch (retcode)
{
case SQL_SUCCESS:
_iodbcdm_do_cursoropen (pstmt);
pstmt->prep_state = 1;
break;
case SQL_SUCCESS_WITH_INFO:
pstmt->state = en_stmt_executed_with_info;
pstmt->prep_state = 1;
break;
case SQL_NEED_DATA:
pstmt->state = en_stmt_needdata;
pstmt->need_on = en_ExecDirect;
break;
case SQL_STILL_EXECUTING:
pstmt->asyn_on = en_ExecDirect;
break;
case SQL_ERROR:
pstmt->state = en_stmt_allocated;
pstmt->cursor_state = en_stmt_cursor_no;
pstmt->prep_state = 0;
break;
default:
break;
}
}
return retcode;
}
SQLRETURN SQL_API
SQLExecDirect (SQLHSTMT hstmt, SQLCHAR * szSqlStr, SQLINTEGER cbSqlStr)
{
ENTER_STMT (hstmt,
trace_SQLExecDirect (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr));
retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'A');
LEAVE_STMT (hstmt,
trace_SQLExecDirect (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr));
}
#if ODBCVER >= 0x0300
SQLRETURN SQL_API
SQLExecDirectA (SQLHSTMT hstmt, SQLCHAR * szSqlStr, SQLINTEGER cbSqlStr)
{
ENTER_STMT (hstmt,
trace_SQLExecDirect (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr));
retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'A');
LEAVE_STMT (hstmt,
trace_SQLExecDirect (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr));
}
SQLRETURN SQL_API
SQLExecDirectW (SQLHSTMT hstmt, SQLWCHAR * szSqlStr, SQLINTEGER cbSqlStr)
{
ENTER_STMT (hstmt,
trace_SQLExecDirectW (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr));
retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'W');
LEAVE_STMT (hstmt,
trace_SQLExecDirectW (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr));
}
#endif
static SQLRETURN
SQLPutData_Internal (
SQLHSTMT hstmt,
SQLPOINTER rgbValue,
SQLLEN cbValue)
{
STMT (pstmt, hstmt);
HPROC hproc;
SQLRETURN retcode;
/* check argument value */
if (rgbValue == NULL &&
(cbValue != SQL_DEFAULT_PARAM && cbValue != SQL_NULL_DATA))
{
PUSHSQLERR (pstmt->herr, en_S1009);
return SQL_ERROR;
}
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
if (pstmt->state <= en_stmt_xfetched)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
}
else if (pstmt->asyn_on != en_PutData)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
/* call driver */
hproc = _iodbcdm_getproc (pstmt->hdbc, en_PutData);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pstmt->herr, en_IM001);
return SQL_ERROR;
}
CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc,
(pstmt->dhstmt, rgbValue, cbValue));
/* state transition */
if (pstmt->asyn_on == en_PutData)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_ERROR:
pstmt->asyn_on = en_NullProc;
break;
case SQL_STILL_EXECUTING:
default:
return retcode;
}
}
/* must in mustput or canput states */
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
pstmt->state = en_stmt_canput;
break;
case SQL_ERROR:
switch (pstmt->need_on)
{
case en_ExecDirect:
pstmt->state = en_stmt_allocated;
pstmt->need_on = en_NullProc;
break;
case en_Execute:
if (pstmt->prep_state)
{
pstmt->state = en_stmt_prepared;
pstmt->need_on = en_NullProc;
}
break;
case en_SetPos:
/* Is this possible ???? */
pstmt->state = en_stmt_xfetched;
break;
default:
break;
}
break;
case SQL_STILL_EXECUTING:
pstmt->asyn_on = en_PutData;
break;
default:
break;
}
return retcode;
}
SQLRETURN SQL_API
SQLPutData (
SQLHSTMT hstmt,
SQLPOINTER rgbValue,
SQLLEN cbValue)
{
ENTER_STMT (hstmt,
trace_SQLPutData (TRACE_ENTER, hstmt, rgbValue, cbValue));
retcode = SQLPutData_Internal (hstmt, rgbValue, cbValue);
LEAVE_STMT (hstmt,
trace_SQLPutData (TRACE_LEAVE, hstmt, rgbValue, cbValue));
}
static SQLRETURN
SQLParamData_Internal (SQLHSTMT hstmt, SQLPOINTER * prgbValue)
{
STMT (pstmt, hstmt);
HPROC hproc;
SQLRETURN retcode;
/* check argument */
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
if (pstmt->state <= en_stmt_xfetched)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
}
else if (pstmt->asyn_on != en_ParamData)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
/* call driver */
hproc = _iodbcdm_getproc (pstmt->hdbc, en_ParamData);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pstmt->herr, en_IM001);
return SQL_ERROR;
}
CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt, prgbValue));
/* state transition */
if (pstmt->asyn_on == en_ParamData)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_ERROR:
pstmt->asyn_on = en_NullProc;
break;
case SQL_STILL_EXECUTING:
default:
return retcode;
}
}
if (pstmt->state < en_stmt_needdata)
{
return retcode;
}
switch (retcode)
{
case SQL_ERROR:
switch (pstmt->need_on)
{
case en_ExecDirect:
pstmt->state = en_stmt_allocated;
break;
case en_Execute:
pstmt->state = en_stmt_prepared;
break;
case en_SetPos:
pstmt->state = en_stmt_xfetched;
pstmt->cursor_state = en_stmt_cursor_xfetched;
break;
default:
break;
}
pstmt->need_on = en_NullProc;
break;
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
switch (pstmt->state)
{
case en_stmt_needdata:
pstmt->state = en_stmt_mustput;
break;
case en_stmt_canput:
switch (pstmt->need_on)
{
case en_SetPos:
pstmt->state = en_stmt_xfetched;
pstmt->cursor_state = en_stmt_cursor_xfetched;
break;
case en_ExecDirect:
case en_Execute:
_iodbcdm_do_cursoropen (pstmt);
break;
default:
break;
}
break;
default:
break;
}
pstmt->need_on = en_NullProc;
break;
case SQL_NEED_DATA:
pstmt->state = en_stmt_mustput;
break;
default:
break;
}
return retcode;
}
SQLRETURN SQL_API
SQLParamData (SQLHSTMT hstmt, SQLPOINTER * prgbValue)
{
ENTER_STMT (hstmt,
trace_SQLParamData (TRACE_ENTER, hstmt, prgbValue));
retcode = SQLParamData_Internal (hstmt, prgbValue);
LEAVE_STMT (hstmt,
trace_SQLParamData (TRACE_LEAVE, hstmt, prgbValue));
}
static SQLRETURN
SQLNumParams_Internal (SQLHSTMT hstmt, SQLSMALLINT * pcpar)
{
STMT (pstmt, hstmt);
HPROC hproc;
SQLRETURN retcode;
/* check argument */
if (!pcpar)
{
return SQL_SUCCESS;
}
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
switch (pstmt->state)
{
case en_stmt_allocated:
case en_stmt_needdata:
case en_stmt_mustput:
case en_stmt_canput:
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
default:
break;
}
}
else if (pstmt->asyn_on != en_NumParams)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
/* call driver */
hproc = _iodbcdm_getproc (pstmt->hdbc, en_NumParams);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pstmt->herr, en_IM001);
return SQL_ERROR;
}
CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt, pcpar));
/* state transition */
if (pstmt->asyn_on == en_NumParams)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_ERROR:
break;
default:
return retcode;
}
}
if (retcode == SQL_STILL_EXECUTING)
{
pstmt->asyn_on = en_NumParams;
}
return retcode;
}
SQLRETURN SQL_API
SQLNumParams (SQLHSTMT hstmt, SQLSMALLINT * pcpar)
{
ENTER_STMT (hstmt,
trace_SQLNumParams (TRACE_ENTER, hstmt, pcpar));
retcode = SQLNumParams_Internal (hstmt, pcpar);
LEAVE_STMT (hstmt,
trace_SQLNumParams (TRACE_LEAVE, hstmt, pcpar));
}
static SQLRETURN
SQLDescribeParam_Internal (
SQLHSTMT hstmt,
SQLUSMALLINT ipar,
SQLSMALLINT * pfSqlType,
SQLULEN * pcbColDef,
SQLSMALLINT * pibScale,
SQLSMALLINT * pfNullable)
{
STMT (pstmt, hstmt);
CONN (pdbc, pstmt->hdbc);
GENV (genv, pdbc->genv);
HPROC hproc;
SQLRETURN retcode;
/* check argument */
if (ipar == 0)
{
PUSHSQLERR (pstmt->herr, en_S1093);
return SQL_ERROR;
}
/* check state */
if (pstmt->asyn_on == en_NullProc)
{
switch (pstmt->state)
{
case en_stmt_allocated:
case en_stmt_needdata:
case en_stmt_mustput:
case en_stmt_canput:
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
default:
break;
}
}
else if (pstmt->asyn_on != en_DescribeParam)
{
PUSHSQLERR (pstmt->herr, en_S1010);
return SQL_ERROR;
}
/* call driver */
hproc = _iodbcdm_getproc (pstmt->hdbc, en_DescribeParam);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pstmt->herr, en_IM001);
return SQL_ERROR;
}
CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc,
(pstmt->dhstmt, ipar, pfSqlType, pcbColDef, pibScale, pfNullable));
/*
* Convert sql type to ODBC version of application
*/
if (SQL_SUCCEEDED(retcode) && pfSqlType)
*pfSqlType = _iodbcdm_map_sql_type (*pfSqlType, genv->odbc_ver);
/* state transition */
if (pstmt->asyn_on == en_DescribeParam)
{
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
case SQL_ERROR:
break;
default:
return retcode;
}
}
if (retcode == SQL_STILL_EXECUTING)
{
pstmt->asyn_on = en_DescribeParam;
}
return retcode;
}
SQLRETURN SQL_API
SQLDescribeParam (
SQLHSTMT hstmt,
SQLUSMALLINT ipar,
SQLSMALLINT * pfSqlType,
SQLULEN * pcbColDef,
SQLSMALLINT * pibScale,
SQLSMALLINT * pfNullable)
{
ENTER_STMT (hstmt,
trace_SQLDescribeParam (TRACE_ENTER,
hstmt, ipar, pfSqlType,
pcbColDef, pibScale, pfNullable));
retcode = SQLDescribeParam_Internal ( hstmt, ipar, pfSqlType,
pcbColDef, pibScale, pfNullable);
LEAVE_STMT (hstmt,
trace_SQLDescribeParam (TRACE_LEAVE,
hstmt, ipar, pfSqlType,
pcbColDef, pibScale, pfNullable));
}
Jump to Line
Something went wrong with that request. Please try again.