prepare.c
上传用户:jmzj888
上传日期:2007-01-02
资源大小:220k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
  2.    This file is public domain and comes with NO WARRANTY of any kind */
  3. /*
  4. ** PREPARE.C - This is the ODBC sample driver code for
  5. ** preparing SQL Commands and other functions prior to execution.
  6. */
  7. #include "myodbc.h"
  8. #ifndef _UNIX_
  9. #include <dos.h>
  10. #endif /* IS NOT UNIX */
  11. #include <list.h>
  12. //  Allocate a SQL statement
  13. RETCODE SQL_API SQLAllocStmt(HDBC hdbc,HSTMT FAR *phstmt)
  14. {
  15. #ifndef _UNIX_
  16.   HGLOBAL  hstmt;
  17. #endif /* IS NOT UNIX */
  18.   STMT FAR* stmt;
  19.   DBC FAR *dbc=(DBC FAR*) hdbc;
  20.   DBUG_ENTER("SQLAllocStmt");
  21. #ifndef _UNIX_
  22.   hstmt = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (STMT));
  23.   if (!hstmt || (*phstmt = (HSTMT)GlobalLock (hstmt)) == SQL_NULL_HSTMT)
  24.   {
  25.     GlobalFree (hstmt); // Free it if lock fails
  26.     *phstmt = SQL_NULL_HSTMT;
  27.     DBUG_RETURN(SQL_ERROR);
  28.   }
  29. #endif /* IS NOT UNIX */
  30. #ifdef _UNIX_
  31.  *phstmt = (HSTMT)my_malloc(sizeof (STMT), MYF(16));
  32.   if (*phstmt == SQL_NULL_HSTMT)
  33.   {
  34.     *phstmt = SQL_NULL_HSTMT;
  35.     DBUG_RETURN(SQL_ERROR);
  36.   }
  37.   memset( *phstmt, 0, sizeof(STMT) );
  38. #endif /* IS UNIX */
  39.   stmt= *phstmt;
  40.   stmt->dbc=hdbc;
  41.   dbc->statements=list_add(dbc->statements,&stmt->list);
  42.   stmt->list.data=stmt;
  43.   stmt->stmt_options=dbc->stmt_options;
  44.   init_dynamic_array(&stmt->params,sizeof(PARAM_BIND),32,64);
  45.   DBUG_RETURN(SQL_SUCCESS);
  46. }
  47. RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,UWORD fOption)
  48. {
  49.   STMT FAR *stmt=(STMT FAR*) hstmt;
  50.   uint i;
  51.   DBUG_ENTER("SQLFreeStmt");
  52.   DBUG_PRINT("enter",("stmt: %lx  option: %d",hstmt,fOption));
  53.   if (fOption == SQL_UNBIND)
  54.   {
  55.     x_free(stmt->bind);
  56.     stmt->bind=0;
  57.     stmt->bound_columns=0;
  58.     DBUG_RETURN(SQL_SUCCESS);
  59.   }
  60.   for (i=0 ; i < stmt->params.elements ; i++)
  61.   {
  62.     PARAM_BIND *param=dynamic_element(&stmt->params,i,PARAM_BIND*);
  63.     if (param->alloced)
  64.     {
  65.       my_free(param->value,MYF(0));
  66.       param->alloced=0;
  67.     }
  68.     if (fOption == SQL_RESET_PARAMS)
  69.       param->used=0;
  70.   }
  71.   if (fOption == SQL_RESET_PARAMS)
  72.   {
  73.     delete_dynamic(&stmt->params);
  74.     DBUG_RETURN(SQL_SUCCESS);
  75.   }
  76.   mysql_free_result(stmt->result);
  77.   x_free((gptr) stmt->fields);      /* Don't write zero free's to debug log */
  78.   x_free((gptr) stmt->array);
  79.   x_free((gptr) stmt->result_array);
  80.   x_free((gptr) stmt->odbc_types);
  81.   stmt->result=0;
  82.   stmt->result_lengths=0;
  83.   stmt->fields=0;
  84.   stmt->array=0;
  85.   stmt->result_array=0;
  86.   stmt->odbc_types=0;
  87.   stmt->current_values=0; /* For SQLGetData */
  88.   stmt->fix_fields=0;
  89.   stmt->current_row=stmt->rows_found_in_set=stmt->position_in_set=0;
  90.   stmt->state=ST_UNKNOWN;
  91.   /* Free data used by parameters */
  92.   if (fOption != MYSQL_RESET_BUFFERS && fOption != SQL_CLOSE)
  93.   {
  94.     x_free((gptr) stmt->query);
  95.     x_free((gptr) stmt->bind);
  96.     stmt->bind=0;
  97.     stmt->bound_columns=0;
  98.     stmt->query=0;
  99.     stmt->param_count=0;
  100.   }
  101.   if (fOption == SQL_DROP)
  102.   {
  103.     delete_dynamic(&stmt->params);
  104.     stmt->dbc->statements=list_delete(stmt->dbc->statements,&stmt->list);
  105. #ifndef _UNIX_
  106.     GlobalUnlock (GlobalHandle ((HGLOBAL) hstmt));
  107.     GlobalFree (GlobalHandle((HGLOBAL) hstmt));
  108. #endif /* IS NOT UNIX */
  109. #ifdef _UNIX_
  110.   free( hstmt);
  111. #endif /* IS UNIX */
  112.   }
  113.   DBUG_RETURN(SQL_SUCCESS);
  114. }
  115. //  Perform a Prepare on the SQL statement
  116. RETCODE SQL_API SQLPrepare(HSTMT hstmt,UCHAR FAR *szSqlStr, SDWORD cbSqlStr)
  117. {
  118.   return my_SQLPrepare(hstmt,szSqlStr,cbSqlStr);
  119. }
  120. RETCODE my_SQLPrepare(HSTMT hstmt,UCHAR FAR *szSqlStr, SDWORD cbSqlStr)
  121. {
  122.   STMT FAR *stmt=(STMT FAR*) hstmt;
  123.   char in_string,*pos;
  124.   uint param_count;
  125.   DBUG_ENTER("my_SQLPrepare");
  126.   if (stmt->query)
  127.     my_free(stmt->query,MYF(0));
  128.   /* SQLFreeStmt(hstmt,SQL_UNBIND); */ /* Not needed according to VB 5.0 */
  129.   if (!(stmt->query=dupp_str((char*) szSqlStr, cbSqlStr)))
  130.   {
  131.     DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
  132.   }
  133.   DBUG_PRINT("enter",("Query: %s",stmt->query));
  134.   /* Count number of parameters and save position for each parameter */
  135.   /* change also newline and return to space (for easy logging) */
  136.   in_string=0;
  137.   param_count=0;
  138.   for (pos=stmt->query; *pos ; pos++)
  139.   {
  140.     if (*pos == '\' && pos[1]) /* Next char is escaped */
  141.     {
  142.       pos++;
  143.       continue;
  144.     }
  145.     if (*pos == in_string)
  146.     {
  147.       in_string=0;
  148.       continue;
  149.     }
  150.     if (*pos == ''' || *pos == '"') /* Start of string */
  151.     {
  152.       in_string= *pos;
  153.       continue;
  154.     }
  155.     if (!in_string && *pos == '?')
  156.     {
  157.       PARAM_BIND *param;
  158.       if (param_count >= stmt->params.elements)
  159.       {
  160. PARAM_BIND tmp_param;
  161. bzero((gptr) &tmp_param,sizeof(tmp_param));
  162. if (push_dynamic(&stmt->params,(gptr) &tmp_param))
  163. {
  164.   DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
  165. }
  166.       }
  167.       param=dynamic_element(&stmt->params,param_count,PARAM_BIND*);
  168.       param->pos_in_query=pos;
  169.       param_count++;
  170.     }
  171.   }
  172.   stmt->param_count=param_count;
  173.   stmt->query_end=pos;
  174.   stmt->state=ST_PREPARED;
  175.   DBUG_PRINT("exit",("Parameter count: %ld",stmt->param_count));
  176.   DBUG_RETURN(SQL_SUCCESS);
  177. }
  178. // Bind parameters on a statement handle
  179. RETCODE SQL_API SQLBindParameter(HSTMT hstmt,UWORD ipar,SWORD fParamType,
  180.  SWORD fCType,SWORD fSqlType,UDWORD cbColDef,
  181.  SWORD ibScale,PTR  rgbValue,SDWORD cbValueMax,
  182.  SDWORD FAR *pcbValue)
  183. {
  184.   STMT FAR *stmt=(STMT FAR*) hstmt;
  185.   PARAM_BIND param;
  186.   DBUG_ENTER("SQLBindParameter");
  187.   DBUG_PRINT("enter",
  188.      ("ipar: %d  Ctype: %d  SQLtype: %d  ValueMax: %ld  Value: %ld",
  189.       ipar,fCType,fSqlType,cbValueMax,pcbValue ? *pcbValue : 0L));
  190.   if (ipar-- < 1)
  191.   {
  192.     DBUG_RETURN(set_error(stmt->dbc,"S1093","Invalid parameter number",0));
  193.   }
  194.   if (stmt->params.elements > ipar)
  195.   { /* Change old bind parameter */
  196.     PARAM_BIND *old=dynamic_element(&stmt->params,ipar,PARAM_BIND*);
  197.     if (old->alloced)
  198.     {
  199.       my_free(old->value,MYF(0));
  200.       old->alloced=0;
  201.     }
  202.     memcpy((gptr) &param,(gptr) old,sizeof(param));
  203.   }
  204.   else
  205.     bzero(&param, sizeof(param));
  206.   /* Simply record the values. These are used later (SQLExecute) */
  207.   param.used= 1;
  208.   param.SqlType = fSqlType;
  209.   param.CType = (fCType == SQL_C_DEFAULT ? default_c_type(fSqlType) : fCType);
  210.   param.buffer = rgbValue;
  211.   param.ValueMax = cbValueMax;
  212.   param.actual_len= pcbValue;
  213.   if (set_dynamic(&stmt->params,(gptr) &param,ipar))
  214.   {
  215.     DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
  216.   }
  217.   DBUG_RETURN(SQL_SUCCESS);
  218. }
  219. /*
  220. ** Returns the description of a parameter marker.
  221. ** As we can't detect this easily, but MySQL can use strings anywhere
  222. ** we simple say that all parameters can be strings.
  223. */
  224. RETCODE SQL_API SQLDescribeParam(HSTMT hstmt, UWORD ipar, SWORD FAR *pfSqlType,
  225.  UDWORD FAR *pcbColDef, SWORD FAR *pibScale,
  226.  SWORD FAR *pfNullable)
  227. {
  228.   DBUG_ENTER("SQLDescribeParam");
  229.   if (pfSqlType)
  230.     *pfSqlType=SQL_VARCHAR;
  231.   if (pcbColDef)
  232.     *pcbColDef=255;
  233.   if (pfNullable)
  234.     *pfNullable=SQL_NULLABLE_UNKNOWN;
  235.   DBUG_RETURN(SQL_SUCCESS);
  236. }
  237. //  Sets multiple values (arrays) for the set of parameter markers.
  238. RETCODE SQL_API SQLParamOptions(HSTMT hstmt, UDWORD crow, UDWORD FAR *pirow)
  239. {
  240.   DBUG_ENTER("SQLParamOptions");
  241.   DBUG_PRINT("info",("Command ignored"));
  242.   DBUG_RETURN(SQL_SUCCESS);
  243. }
  244. //  Returns the number of parameter markers.
  245. RETCODE SQL_API SQLNumParams(HSTMT hstmt, SWORD FAR *pcpar)
  246. {
  247.   STMT FAR *stmt=(STMT FAR*) hstmt;
  248.   DBUG_ENTER("SQLNumParams");
  249.   if (pcpar)
  250.     *pcpar=stmt->param_count;
  251.   DBUG_RETURN(SQL_SUCCESS);
  252. }
  253. //  Sets options that control the behavior of cursors.
  254. RETCODE SQL_API SQLSetScrollOptions(HSTMT hstmt, UWORD fConcurrency,
  255.     SDWORD crowKeyset, UWORD crowRowset)
  256. {
  257.   STMT FAR *stmt=(STMT FAR*) hstmt;
  258.   DBUG_ENTER("SQLSetScrollOptions");
  259.   stmt->stmt_options.rows_in_set=crowRowset;
  260.   DBUG_RETURN(SQL_SUCCESS);
  261. }
  262. //  Set the cursor name on a statement handle
  263. RETCODE SQL_API SQLSetCursorName(HSTMT  hstmt, UCHAR FAR *szCursor,
  264.  SWORD cbCursor)
  265. {
  266.   DBUG_ENTER("SQLSetCursorName");
  267.   DBUG_PRINT("info",("Command ignored as MyODBC doesn't support cursors"));
  268.   DBUG_RETURN(SQL_SUCCESS);
  269. }
  270. //  Return the cursor name for a statement handle
  271. RETCODE SQL_API SQLGetCursorName(HSTMT hstmt, UCHAR FAR *szCursor,
  272.  SWORD cbCursorMax, SWORD FAR *pcbCursor)
  273. {
  274.   DBUG_ENTER("SQLGetCursorName");
  275.   copy_result(((STMT FAR*) hstmt)->dbc,szCursor,cbCursorMax,pcbCursor,"NO_NAME");
  276.   DBUG_RETURN(SQL_SUCCESS);
  277. }