📄 prepare.c
字号:
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
This file is public domain and comes with NO WARRANTY of any kind */
/*
** PREPARE.C - This is the ODBC sample driver code for
** preparing SQL Commands and other functions prior to execution.
*/
#include "myodbc.h"
#ifndef _UNIX_
#include <dos.h>
#endif /* IS NOT UNIX */
#include <list.h>
// Allocate a SQL statement
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,HSTMT FAR *phstmt)
{
#ifndef _UNIX_
HGLOBAL hstmt;
#endif /* IS NOT UNIX */
STMT FAR* stmt;
DBC FAR *dbc=(DBC FAR*) hdbc;
DBUG_ENTER("SQLAllocStmt");
#ifndef _UNIX_
hstmt = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (STMT));
if (!hstmt || (*phstmt = (HSTMT)GlobalLock (hstmt)) == SQL_NULL_HSTMT)
{
GlobalFree (hstmt); // Free it if lock fails
*phstmt = SQL_NULL_HSTMT;
DBUG_RETURN(SQL_ERROR);
}
#endif /* IS NOT UNIX */
#ifdef _UNIX_
*phstmt = (HSTMT)my_malloc(sizeof (STMT), MYF(16));
if (*phstmt == SQL_NULL_HSTMT)
{
*phstmt = SQL_NULL_HSTMT;
DBUG_RETURN(SQL_ERROR);
}
memset( *phstmt, 0, sizeof(STMT) );
#endif /* IS UNIX */
stmt= *phstmt;
stmt->dbc=hdbc;
dbc->statements=list_add(dbc->statements,&stmt->list);
stmt->list.data=stmt;
stmt->stmt_options=dbc->stmt_options;
init_dynamic_array(&stmt->params,sizeof(PARAM_BIND),32,64);
DBUG_RETURN(SQL_SUCCESS);
}
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,UWORD fOption)
{
STMT FAR *stmt=(STMT FAR*) hstmt;
uint i;
DBUG_ENTER("SQLFreeStmt");
DBUG_PRINT("enter",("stmt: %lx option: %d",hstmt,fOption));
if (fOption == SQL_UNBIND)
{
x_free(stmt->bind);
stmt->bind=0;
stmt->bound_columns=0;
DBUG_RETURN(SQL_SUCCESS);
}
for (i=0 ; i < stmt->params.elements ; i++)
{
PARAM_BIND *param=dynamic_element(&stmt->params,i,PARAM_BIND*);
if (param->alloced)
{
my_free(param->value,MYF(0));
param->alloced=0;
}
if (fOption == SQL_RESET_PARAMS)
param->used=0;
}
if (fOption == SQL_RESET_PARAMS)
{
delete_dynamic(&stmt->params);
DBUG_RETURN(SQL_SUCCESS);
}
mysql_free_result(stmt->result);
x_free((gptr) stmt->fields); /* Don't write zero free's to debug log */
x_free((gptr) stmt->array);
x_free((gptr) stmt->result_array);
x_free((gptr) stmt->odbc_types);
stmt->result=0;
stmt->result_lengths=0;
stmt->fields=0;
stmt->array=0;
stmt->result_array=0;
stmt->odbc_types=0;
stmt->current_values=0; /* For SQLGetData */
stmt->fix_fields=0;
stmt->current_row=stmt->rows_found_in_set=stmt->position_in_set=0;
stmt->state=ST_UNKNOWN;
/* Free data used by parameters */
if (fOption != MYSQL_RESET_BUFFERS && fOption != SQL_CLOSE)
{
x_free((gptr) stmt->query);
x_free((gptr) stmt->bind);
stmt->bind=0;
stmt->bound_columns=0;
stmt->query=0;
stmt->param_count=0;
}
if (fOption == SQL_DROP)
{
delete_dynamic(&stmt->params);
stmt->dbc->statements=list_delete(stmt->dbc->statements,&stmt->list);
#ifndef _UNIX_
GlobalUnlock (GlobalHandle ((HGLOBAL) hstmt));
GlobalFree (GlobalHandle((HGLOBAL) hstmt));
#endif /* IS NOT UNIX */
#ifdef _UNIX_
free( hstmt);
#endif /* IS UNIX */
}
DBUG_RETURN(SQL_SUCCESS);
}
// Perform a Prepare on the SQL statement
RETCODE SQL_API SQLPrepare(HSTMT hstmt,UCHAR FAR *szSqlStr, SDWORD cbSqlStr)
{
return my_SQLPrepare(hstmt,szSqlStr,cbSqlStr);
}
RETCODE my_SQLPrepare(HSTMT hstmt,UCHAR FAR *szSqlStr, SDWORD cbSqlStr)
{
STMT FAR *stmt=(STMT FAR*) hstmt;
char in_string,*pos;
uint param_count;
DBUG_ENTER("my_SQLPrepare");
if (stmt->query)
my_free(stmt->query,MYF(0));
/* SQLFreeStmt(hstmt,SQL_UNBIND); */ /* Not needed according to VB 5.0 */
if (!(stmt->query=dupp_str((char*) szSqlStr, cbSqlStr)))
{
DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
}
DBUG_PRINT("enter",("Query: %s",stmt->query));
/* Count number of parameters and save position for each parameter */
/* change also newline and return to space (for easy logging) */
in_string=0;
param_count=0;
for (pos=stmt->query; *pos ; pos++)
{
if (*pos == '\\' && pos[1]) /* Next char is escaped */
{
pos++;
continue;
}
if (*pos == in_string)
{
in_string=0;
continue;
}
if (*pos == '\'' || *pos == '"') /* Start of string */
{
in_string= *pos;
continue;
}
if (!in_string && *pos == '?')
{
PARAM_BIND *param;
if (param_count >= stmt->params.elements)
{
PARAM_BIND tmp_param;
bzero((gptr) &tmp_param,sizeof(tmp_param));
if (push_dynamic(&stmt->params,(gptr) &tmp_param))
{
DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
}
}
param=dynamic_element(&stmt->params,param_count,PARAM_BIND*);
param->pos_in_query=pos;
param_count++;
}
}
stmt->param_count=param_count;
stmt->query_end=pos;
stmt->state=ST_PREPARED;
DBUG_PRINT("exit",("Parameter count: %ld",stmt->param_count));
DBUG_RETURN(SQL_SUCCESS);
}
// 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)
{
STMT FAR *stmt=(STMT FAR*) hstmt;
PARAM_BIND param;
DBUG_ENTER("SQLBindParameter");
DBUG_PRINT("enter",
("ipar: %d Ctype: %d SQLtype: %d ValueMax: %ld Value: %ld",
ipar,fCType,fSqlType,cbValueMax,pcbValue ? *pcbValue : 0L));
if (ipar-- < 1)
{
DBUG_RETURN(set_error(stmt->dbc,"S1093","Invalid parameter number",0));
}
if (stmt->params.elements > ipar)
{ /* Change old bind parameter */
PARAM_BIND *old=dynamic_element(&stmt->params,ipar,PARAM_BIND*);
if (old->alloced)
{
my_free(old->value,MYF(0));
old->alloced=0;
}
memcpy((gptr) ¶m,(gptr) old,sizeof(param));
}
else
bzero(¶m, sizeof(param));
/* Simply record the values. These are used later (SQLExecute) */
param.used= 1;
param.SqlType = fSqlType;
param.CType = (fCType == SQL_C_DEFAULT ? default_c_type(fSqlType) : fCType);
param.buffer = rgbValue;
param.ValueMax = cbValueMax;
param.actual_len= pcbValue;
if (set_dynamic(&stmt->params,(gptr) ¶m,ipar))
{
DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
}
DBUG_RETURN(SQL_SUCCESS);
}
/*
** Returns the description of a parameter marker.
** As we can't detect this easily, but MySQL can use strings anywhere
** we simple say that all parameters can be strings.
*/
RETCODE SQL_API SQLDescribeParam(HSTMT hstmt, UWORD ipar, SWORD FAR *pfSqlType,
UDWORD FAR *pcbColDef, SWORD FAR *pibScale,
SWORD FAR *pfNullable)
{
DBUG_ENTER("SQLDescribeParam");
if (pfSqlType)
*pfSqlType=SQL_VARCHAR;
if (pcbColDef)
*pcbColDef=255;
if (pfNullable)
*pfNullable=SQL_NULLABLE_UNKNOWN;
DBUG_RETURN(SQL_SUCCESS);
}
// Sets multiple values (arrays) for the set of parameter markers.
RETCODE SQL_API SQLParamOptions(HSTMT hstmt, UDWORD crow, UDWORD FAR *pirow)
{
DBUG_ENTER("SQLParamOptions");
DBUG_PRINT("info",("Command ignored"));
DBUG_RETURN(SQL_SUCCESS);
}
// Returns the number of parameter markers.
RETCODE SQL_API SQLNumParams(HSTMT hstmt, SWORD FAR *pcpar)
{
STMT FAR *stmt=(STMT FAR*) hstmt;
DBUG_ENTER("SQLNumParams");
if (pcpar)
*pcpar=stmt->param_count;
DBUG_RETURN(SQL_SUCCESS);
}
// Sets options that control the behavior of cursors.
RETCODE SQL_API SQLSetScrollOptions(HSTMT hstmt, UWORD fConcurrency,
SDWORD crowKeyset, UWORD crowRowset)
{
STMT FAR *stmt=(STMT FAR*) hstmt;
DBUG_ENTER("SQLSetScrollOptions");
stmt->stmt_options.rows_in_set=crowRowset;
DBUG_RETURN(SQL_SUCCESS);
}
// Set the cursor name on a statement handle
RETCODE SQL_API SQLSetCursorName(HSTMT hstmt, UCHAR FAR *szCursor,
SWORD cbCursor)
{
DBUG_ENTER("SQLSetCursorName");
DBUG_PRINT("info",("Command ignored as MyODBC doesn't support cursors"));
DBUG_RETURN(SQL_SUCCESS);
}
// Return the cursor name for a statement handle
RETCODE SQL_API SQLGetCursorName(HSTMT hstmt, UCHAR FAR *szCursor,
SWORD cbCursorMax, SWORD FAR *pcbCursor)
{
DBUG_ENTER("SQLGetCursorName");
copy_result(((STMT FAR*) hstmt)->dbc,szCursor,cbCursorMax,pcbCursor,"NO_NAME");
DBUG_RETURN(SQL_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -