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

📄 results.c

📁 MySQL的ODBC接口程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
   This file is public domain and comes with NO WARRANTY of any kind */

/*
** Returning results and information about results.
*/


#include "myodbc.h"
#include <m_ctype.h>
#include <locale.h>

#define digit(A) ((int) (A - '0'))

RETCODE SQL_API sql_get_data(STMT *stm,SWORD fCType,MYSQL_FIELD *field,
			     PTR rgbValue,
			     SDWORD  cbValueMax, SDWORD FAR *pcbValue,
			     char *value,uint length);


/*
** Execute the query if it is only prepared. This is needed because the ODBC
** standard allows calling some functions before SQLExecute(). (Stupid!)
*/

static RETCODE check_result(STMT FAR *stmt)
{
  RETCODE error;
  DBUG_ENTER("check_result");

  switch (stmt->state) {
  case ST_UNKNOWN:
    error=set_error(stmt->dbc,"24000","Invalid cursor state",0);
    break;
  case ST_PREPARED:
    if ((error=my_SQLExecute(stmt)) == SQL_SUCCESS)
      stmt->state=ST_PRE_EXECUTED;	/* mark for execute */
    break;
  case ST_PRE_EXECUTED:
  case ST_EXECUTED:
    error=SQL_SUCCESS;
   }
   DBUG_RETURN(error);
}


//      This returns the number of columns associated with the database
//      attached to "hstmt".

RETCODE SQL_API SQLNumResultCols(HSTMT  hstmt, SWORD FAR *pccol)
{
  RETCODE error;
  STMT FAR *stmt=(STMT FAR*) hstmt;
  DBUG_ENTER("SQLNumResultCols");

  if ((error=check_result(stmt)) != SQL_SUCCESS)
    DBUG_RETURN(error);
  if (!stmt->result)
    *pccol=0;					/* Not a select */
  else
    *pccol=stmt->result->field_count;
  DBUG_PRINT("exit",("columns: %d",*pccol));
  DBUG_RETURN(SQL_SUCCESS);
}


//      Return information about the database column the user wants
//      information about.

RETCODE SQL_API SQLDescribeCol(HSTMT hstmt, UWORD icol, UCHAR FAR *szColName,
			       SWORD cbColNameMax, SWORD FAR *pcbColName,
			       SWORD FAR *pfSqlType, UDWORD FAR *pcbColDef,
			       SWORD FAR *pibScale, SWORD FAR *pfNullable)
{
  RETCODE error;
  MYSQL_FIELD *field;
  STMT FAR *stmt=(STMT FAR*) hstmt;
  ulong transfer_length,precision,display_size;
  int type;
  DBUG_ENTER("SQLDescribeCol");

  if ((error=check_result(stmt)) != SQL_SUCCESS)
    DBUG_RETURN(error);
  mysql_field_seek(stmt->result,icol-1);
  if (!(field=mysql_fetch_field(stmt->result)))
    DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
  type=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,&display_size);
  if (pfSqlType)
    *pfSqlType=type;
  if (pcbColDef)
    *pcbColDef=precision;
  if (pibScale)
    *pibScale=field->decimals;
  if (pfNullable)
    *pfNullable= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
                 SQL_NO_NULLS : SQL_NULLABLE;
  DBUG_PRINT("info",("col: %d type: %d  precision: %ld  decimals: %d",
                      icol,type,precision,field->decimals));
  DBUG_RETURN(copy_result(stmt->dbc,szColName,cbColNameMax,pcbColName,
			  field->name));
}



//      Returns result column descriptor information for a result set.

RETCODE SQL_API SQLColAttributes(HSTMT hstmt,UWORD icol,UWORD fDescType,
				 SQLPOINTER rgbDesc, SWORD cbDescMax,
				 SWORD FAR *pcbDesc, SDWORD FAR *pfDesc)
{
  MYSQL_FIELD *field;
  STMT FAR *stmt=(STMT FAR*) hstmt;
  SWORD dummy;
  ulong transfer_length,precision,display_size;
  RETCODE error;
  DBUG_ENTER("SQLColAttributes");
  DBUG_PRINT("enter",("type: %d",fDescType));

  if (!pcbDesc)
    pcbDesc= &dummy;

  if ((error=check_result(stmt)) != SQL_SUCCESS)
    DBUG_RETURN(error);
  mysql_field_seek(stmt->result,icol-1);
  if (!(field=mysql_fetch_field(stmt->result)))
    DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));

  switch (fDescType) {
  case SQL_COLUMN_COUNT:
    *pfDesc= stmt->result->field_count;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_LABEL:
  case SQL_COLUMN_NAME:
    DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
			    field->name));
  case SQL_COLUMN_TYPE:
    *pfDesc=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
				   &display_size);
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_DISPLAY_SIZE:
    (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
				  &display_size);
    *pfDesc=display_size;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_PRECISION:
    (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
				  &display_size);
    *pfDesc=precision;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_LENGTH:
    (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
				  &display_size);
    *pfDesc=transfer_length;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_SCALE:
    *pfDesc=field->decimals;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_NULLABLE:
    *pfDesc= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
             SQL_NO_NULLS : SQL_NULLABLE;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_SEARCHABLE:
    *pfDesc= SQL_SEARCHABLE;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_UNSIGNED:
    if (pfDesc)
      *pfDesc= field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_MONEY:
    *pfDesc=0;
    break;
  case SQL_COLUMN_AUTO_INCREMENT:
    if (pfDesc)
      *pfDesc= field->flags & AUTO_INCREMENT_FLAG ? TRUE : FALSE;
    break;
  case SQL_COLUMN_CASE_SENSITIVE:
    *pfDesc= field->flags & BINARY_FLAG ? FALSE : TRUE;
    *pcbDesc=sizeof(int);
    break;
  case SQL_COLUMN_UPDATABLE:
    *pfDesc = (field->table && field->table[0] ? SQL_COLUMN_UPDATABLE :
	       SQL_ATTR_READONLY);
    *pcbDesc= sizeof(int);
    break;
  case SQL_COLUMN_TYPE_NAME:
  {
    char buff[40];
    (void) unireg_to_sql_datatype(stmt,field,buff,&transfer_length,&precision,&display_size);
    DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
			    buff));
  }
  case SQL_COLUMN_OWNER_NAME:
  case SQL_COLUMN_QUALIFIER_NAME:
    DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,""));
  }
  DBUG_RETURN(SQL_SUCCESS);
}


//      Associate a user-supplied buffer with a database column.

RETCODE SQL_API SQLBindCol(HSTMT hstmt, UWORD icol, SWORD fCType, PTR rgbValue,
			   SDWORD  cbValueMax, SDWORD FAR *pcbValue)
{
  BIND *bind;
  STMT FAR *stmt=(STMT FAR*) hstmt;
  RETCODE error;
  DBUG_ENTER("SQLBindCol");
  DBUG_PRINT("enter",
	     ("icol: %d  Type: %d  ValueMax: %ld  Valueptr: %lx  Value: %ld",
	      icol,fCType,(long) cbValueMax,pcbValue,
	      (long) (pcbValue ? *pcbValue : 0L)));

  icol--;
  /*
  ** The next case if because of VB 5.0 that binds columns before preparing
  ** a statement
  */

  if (stmt->state == ST_UNKNOWN)
  {
    DBUG_PRINT("info",("Binding columns without a statement; Hope you know what you are doing"));
    if (icol >= stmt->bound_columns)
    {
      if (!(stmt->bind=(BIND*) my_realloc((char*) stmt->bind,
					  (icol+1)*sizeof(BIND),
					  MYF(MY_ALLOW_ZERO_PTR |
					      MY_FREE_ON_ERROR))))
      {
	stmt->bound_columns=0;
	DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
      }
      bzero((gptr) (stmt->bind+stmt->bound_columns),
		    (icol+1-stmt->bound_columns)*sizeof(BIND));
      stmt->bound_columns=icol+1;
    }
  }
  else
  {
    /* Bind parameter to current set  ( The normal case ) */
    if ((error=check_result(stmt)) != SQL_SUCCESS)
      DBUG_RETURN(error);

    if (!stmt->result || (uint) icol >= stmt->result->field_count)
    {
      DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
    }
    if (!stmt->bind)
    {
      if (!(stmt->bind=(BIND*) my_malloc(sizeof(BIND)*
					 stmt->result->field_count,
					 MYF(MY_ZEROFILL))))
	DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
      stmt->bound_columns=stmt->result->field_count;
    }
    mysql_field_seek(stmt->result,icol);
    stmt->bind[icol].field=mysql_fetch_field(stmt->result);
  }
  bind=stmt->bind+icol;
  bind->fCType=fCType;
  if (fCType == SQL_C_DEFAULT && stmt->odbc_types)
    bind->fCType=stmt->odbc_types[icol];
  bind->rgbValue=rgbValue;
  bind->cbValueMax=bind_length(bind->fCType,cbValueMax);
  bind->pcbValue=pcbValue;
  DBUG_RETURN(SQL_SUCCESS);
}


//      Returns data for bound columns in the current row ("stmt->iCursor"),
//      advances the cursor.

RETCODE SQL_API SQLFetch(HSTMT hstmt)
{
  MYSQL_ROW values;
  RETCODE res,tmp_res;
  STMT FAR *stmt=(STMT FAR*) hstmt;
  DBUG_ENTER("SQLFetch");

  if (!stmt->result)
    DBUG_RETURN(set_error(stmt->dbc,"24000","Fetch without a SELECT",0));
  if (stmt->result_array)
  {
    if (stmt->current_row >= stmt->result->row_count)
      DBUG_RETURN(SQL_NO_DATA_FOUND);
    values=stmt->result_array+(stmt->current_row++)*
      stmt->result->field_count;
  }
  else
  {
    if (!(values=mysql_fetch_row(stmt->result)))
      DBUG_RETURN(SQL_NO_DATA_FOUND);
    stmt->current_row++;		/* For SQLGetStmtOption */
    if (stmt->fix_fields)
      values=(*stmt->fix_fields)(stmt,values);
    else
      stmt->result_lengths=mysql_fetch_lengths(stmt->result);
  }
  stmt->current_values=values;		/* For SQLGetData */
  stmt->last_getdata_col= (uint) ~0;

  res=SQL_SUCCESS;
  if (stmt->bind)
  {
    uint *lengths=stmt->result_lengths;
    BIND *bind,*end;

    setlocale(LC_NUMERIC,"English");	/* force use of '.' as decimal point */
    for (bind=stmt->bind,end=bind + stmt->result->field_count ;
	 bind < end ;
	 bind++,values++)
    {
      if (bind->rgbValue || bind->pcbValue)
      {
	stmt->getdata_offset= (ulong) ~0L;
 	if ((tmp_res=sql_get_data(stmt,bind->fCType,bind->field,bind->rgbValue,
				  bind->cbValueMax,bind->pcbValue,
				  *values, lengths ? *lengths : *values ?
				  strlen(*values) : 0) )
	    != SQL_SUCCESS)
	{
	  if (tmp_res == SQL_SUCCESS_WITH_INFO)
	  {
            DBUG_PRINT("info",("Problem with column: %d, value: '%s'",
                               (int) (bind - stmt->bind)+1,
			       *values ? *values : "NULL"));
            if (res == SQL_SUCCESS)
	      res= tmp_res;
	  }
	  else
	    res=SQL_ERROR;
	}
      }
      if (lengths)
	lengths++;
    }
    setlocale(LC_NUMERIC,default_locale);
  }
  stmt->getdata_offset= (ulong) ~0L;
  DBUG_RETURN(res);
}



//  Returns result data for a single column in the current row.

RETCODE SQL_API SQLGetData(HSTMT hstmt,UWORD icol,SWORD fCType,PTR rgbValue,
			   SDWORD cbValueMax, SDWORD FAR *pcbValue)
{
  STMT FAR *stmt=(STMT FAR*) hstmt;
  RETCODE result;
  DBUG_ENTER("SQLGetData");

  if (!stmt->result || !stmt->current_values)
  {
    set_error(stmt->dbc,"24000","SQLGetData without a preceding SELECT",0);
    DBUG_RETURN(SQL_ERROR);
  }
  icol--;		  /* Easier code if start from 0 */
  if (icol != stmt->last_getdata_col)
  {				/* New column. Reset old offset */
    stmt->last_getdata_col=icol;
    stmt->getdata_offset= (ulong) ~0L;
  }

#ifdef LOG_ALL
  DBUG_PRINT("QQ",("icol: %d  fCType: %d  default: %d  value: %.10s",
		   icol+1,fCType,
		   stmt->odbc_types[icol],
		   (stmt->current_values[icol] ? stmt->current_values[icol] :
		    "NULL")));
#endif
  setlocale(LC_NUMERIC,"English");
  result=sql_get_data(stmt,
		      (SWORD) (fCType == SQL_C_DEFAULT ?
			       stmt->odbc_types[icol] :
			       fCType),
		      stmt->result->fields+icol,
		      rgbValue,cbValueMax,pcbValue,
		      stmt->current_values[icol],
		      (stmt->result_lengths ? stmt->result_lengths[icol] :
		       (stmt->current_values[icol] ?
			strlen(stmt->current_values[icol]) : 0 )));
  setlocale(LC_NUMERIC,default_locale);
  DBUG_RETURN(result);
}

/*
** Get data.  rgbValue or pcbValue may be NULL pointers!
*/

RETCODE SQL_API sql_get_data(STMT *stmt,SWORD fCType,MYSQL_FIELD *field,
			     PTR rgbValue, SDWORD  cbValueMax,
			     SDWORD FAR *pcbValue,
			     char *value, uint length)
{
  DBC *dbc=stmt->dbc;
  long tmp;
  if (!pcbValue)
    pcbValue= &tmp;	/* Easier code */

  if (!value)
  {
    *pcbValue=SQL_NULL_DATA;
  }
  else switch (fCType) {
  case SQL_C_BINARY:
  case SQL_C_CHAR:
  {
    char buff[21];
    if (field->type == FIELD_TYPE_TIMESTAMP && length != 19)
    {
      /* MySQL doesn't have '-' in timestamp */
      /* Convert timestamp to ANSI format */

      char *pos;
      uint i;
      if (length == 6 || length == 12)		/* YYMMDD or YYMMDDHHMMSS timestamp */
      {
	if (value[0] <= '6')
	{
	  buff[0]='2';
	  buff[1]='0';
	}
	else
	{
	  buff[0]='1';
	  buff[1]='9';
	}
      }
      else
      {
	buff[0]=value[0];
	buff[1]=value[1];
	value+=2;
	length-=2;
      }
      buff[2]= *value++;
      buff[3]= *value++;
      buff[4]='-';
      if (value[0] == '0' && value[1] == '0')
      {
	*pcbValue=SQL_NULL_DATA;	/* ODBC can't handle 0000-00-00 dates */
	break;
      }
      pos=buff+5;
      length&= 30;			/* Ensure that length is ok */
      for (i=1, length-=2 ; (int) length > 0 ; length-=2,i++)
      {
	*pos++= *value++;
	*pos++= *value++;
	*pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
      }
      for ( ; pos != buff+20 ; i++)
      {
	*pos++= '0';
	*pos++= '0';
	*pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
      }
      value=buff;
      length=19;
    }
    return copy_lresult(dbc,(char*) rgbValue,cbValueMax,pcbValue,value,
			length,stmt->stmt_options.max_length,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -