⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prepare.c

📁 MySQL的ODBC接口程序源代码
💻 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) &param,(gptr) old,sizeof(param));
  }
  else
    bzero(&param, 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) &param,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 + -