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

📄 utility.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 */

#include "myodbc.h"

/* Use own fields instead of sql fields */

void mysql_link_fields(STMT *stmt,MYSQL_FIELD *fields,uint field_count)
{
  MYSQL_RES *result=stmt->result;
  result->fields=fields;
  result->field_count=field_count;
  result->current_field=0;
  fix_result_types(stmt);
}


void fix_result_types(STMT *stmt)
{
  uint i;
  MYSQL_RES *result=stmt->result;
  DBUG_ENTER("fix_result_types");

  stmt->state=ST_EXECUTED;			/* Mark set found */
  if ((stmt->odbc_types=(SWORD*) my_malloc(sizeof(SWORD)*result->field_count,
					   MYF(0))))
  {
    for (i=0 ; i < result->field_count ; i++)
    {
      MYSQL_FIELD *field=result->fields+i;
      stmt->odbc_types[i]=(SWORD) unireg_to_c_datatype(field);
    }
  }
  /*
  ** Fix default values for bound columns
  ** Normally there isn't any bound columns at this stage !
  */
  if (stmt->bind)
  {
    if (stmt->bound_columns < result->field_count)
    {
      if (!(stmt->bind=(BIND*) my_realloc((char*) stmt->bind,
					  sizeof(BIND) * result->field_count,
					  MYF(MY_FREE_ON_ERROR))))
      {
	/* We should in principle give an error here */
	stmt->bound_columns=0;
	DBUG_VOID_RETURN;
      }
      bzero((gptr) (stmt->bind+stmt->bound_columns),
	    (result->field_count -stmt->bound_columns)*sizeof(BIND));
      stmt->bound_columns=result->field_count;
    }
    /* Fix default types and pointers to fields */

    mysql_field_seek(result,0);
    for (i=0; i < result->field_count ; i++)
    {
        if (stmt->bind[i].fCType == SQL_C_DEFAULT)
	  stmt->bind[i].fCType=stmt->odbc_types[i];
        stmt->bind[i].field=mysql_fetch_field(result);
    }
  }
  DBUG_VOID_RETURN;
}

	/* change a string + length to a zero terminated string */

char *fix_str(char *to,char *from,int length)
{
  if (!from)
    return "";
  if (length == SQL_NTS)
    return from;
  strmake(to,from,length);
  return to;
}


char *dupp_str(char *from,int length)
{
  char *to;
  if (!from)
    return my_strdup("",MYF(MY_WME));
  if (length == SQL_NTS)
    length=strlen(from);
  if ((to=my_malloc(length+1,MYF(MY_WME))))
  {
    memcpy(to,from,length);
    to[length]=0;
  }
  return to;
}

	/* Return 1 if from is a null pointer or a empty string */

bool empty_str(char *from,int length)
{
  if (!from)
    return 1;
  if (length == SQL_NTS)
    return from[0] == 0;
  return !length;
}

void remove_escape(char *name)
{
  char *to;
  for (to=name ; *name ; name++)
  {
    if (*name == '\\' && name[1])
      name++;
    *to++= *name;
  }
  *to=0;
}

/*
** Return (possibly truncated) results
** If result is truncated the result length contains
** length of the truncted result;
*/

RETCODE copy_result(DBC *dbc,UCHAR FAR *rgbValue,SWORD cbValueMax,
		    SWORD FAR *pcbValue,char FAR *src)
{
  UCHAR FAR *dst=rgbValue;
  SWORD save_ValueMax=cbValueMax;
  if (!dst)
  {
    if (pcbValue)
      *pcbValue=0;
    return SQL_SUCCESS;
  }
  while (--cbValueMax)
  {
    if (! (*dst++ = *src++))
    {
      if (pcbValue)
        *pcbValue= (SWORD) (dst-1 - rgbValue);
      return SQL_SUCCESS;
    }
  }
  *dst=0;
  if (pcbValue)
    *pcbValue=(SWORD) (dst- rgbValue);  /* +strlen(src) */
  if (!*src)
    return SQL_SUCCESS;			/* There was room after all */
  DBUG_PRINT("warning",("Truncated string of length: %d to %d",
			strlen(src)+ (dst-rgbValue)+1, save_ValueMax));
  if (dbc)
    set_error(dbc,"01004","Data truncated",4002);

  return SQL_SUCCESS_WITH_INFO;
}


RETCODE copy_lresult(DBC FAR *dbc,UCHAR FAR *rgbValue,SDWORD cbValueMax,
		     SDWORD FAR *pcbValue,char *src,ulong src_length,
		     ulong max_length,ulong fill_length,ulong *offset)
{
  char *dst=(char*) rgbValue;
  ulong length;

  if (cbValueMax)				/* If not length check */
    cbValueMax--;				/* Room for end null */
  else
    dst=0;					/* Don't copy anything! */
  if (max_length)				/* If limit on char lengths */
  {
    set_if_smaller(cbValueMax,(long) max_length);
    set_if_smaller(src_length,max_length);
    set_if_smaller(fill_length,max_length);
  }
  if (fill_length < src_length || !dbc || !(dbc->flag & FLAG_PAD_SPACE))
    fill_length=src_length;
  if (*offset == (ulong) ~0L)
    *offset=0;					/* First call */
  else if (*offset >= fill_length)
    return SQL_NO_DATA_FOUND;
  src+= *offset ; src_length-= *offset; fill_length-= *offset;
  length=min(fill_length,(ulong) cbValueMax);
  (*offset)+=length;				/* Fix for next call */
  if (pcbValue)
    *pcbValue=fill_length;
  if (dst)					/* Bind allows null pointers */
  {
    ulong copy_length= ((long) src_length >= (long) length ? length :
			((long) src_length >= 0 ? src_length : 0L));
    memcpy(dst,src,copy_length);
    bfill(dst+copy_length,length-copy_length,' ');
    dst[length]=0;
  }
  if ((ulong) cbValueMax >= fill_length)
    return SQL_SUCCESS;
  if (dbc)
    set_error(dbc,"01004","Data truncated",4002);
  return SQL_SUCCESS_WITH_INFO;
}


RETCODE set_error(DBC FAR *dbc,char *state,char *message,uint errcode)
{
  DBUG_ENTER("set_error");
  DBUG_PRINT("error",("message: %s",message));
  strmov(dbc->sqlstate,state);
  strmov(mysql_error(&dbc->mysql),message);
  dbc->mysql.net.last_errno=errcode;
  DBUG_RETURN(SQL_ERROR);
}

/*
** Get type, transfer length and precision for a unireg column
** Note that timestamp is changed to YYYY-MM-DD HH:MM:SS type
*/

int unireg_to_sql_datatype(STMT FAR *stmt, MYSQL_FIELD *field, char *buff,
			   ulong *transfer_length,ulong *precision,
			   ulong *display_size)
{
  char *pos;
  if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
    *transfer_length= *precision= *display_size= max(field->length,
						     field->max_length);
  else
    *transfer_length= *precision= *display_size= field->max_length;

  switch(field->type) {
  case FIELD_TYPE_DECIMAL:
    if (buff) strmov(buff,"decimal");
    return SQL_DECIMAL;
  case FIELD_TYPE_CHAR:
    if (buff)
    {
      pos=strmov(buff,"tinyint");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=1;
    return SQL_TINYINT;
  case FIELD_TYPE_SHORT:
    if (buff)
    {
      pos=strmov(buff,"smallint");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=2;
    return SQL_SMALLINT;
  case FIELD_TYPE_INT24:
    if (buff)
    {
      pos=strmov(buff,"mediumint");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=4;
    return SQL_INTEGER;
  case FIELD_TYPE_LONG:
    if (buff)
    {
      pos= strmov(buff,"int");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=4;
    return SQL_INTEGER;
  case FIELD_TYPE_LONGLONG:
    if (buff)
    {
      pos= strmov(buff,"bigint");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=20;
    return SQL_BIGINT;
  case FIELD_TYPE_FLOAT:
    if (buff)
    {
      pos= strmov(buff,"float");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=4;
    return SQL_REAL;
  case FIELD_TYPE_DOUBLE:
    if (buff)
    {
      pos= strmov(buff,"double");
      if (field->flags & UNSIGNED_FLAG)
	strmov(pos," unsigned");
    }
    *transfer_length=8;
    return SQL_DOUBLE;
  case FIELD_TYPE_NULL:
    if (buff) strmov(buff,"null");
    return SQL_VARCHAR;
  case FIELD_TYPE_YEAR:
    if (buff)
      pos=strmov(buff,"year");
    *transfer_length=2;
    return SQL_SMALLINT;
  case FIELD_TYPE_TIMESTAMP:
    if (buff) strmov(buff,"timestamp");
    *transfer_length=16;			/* size of timestamp_struct */
    *precision= *display_size=19;
    return SQL_TIMESTAMP;
  case FIELD_TYPE_DATETIME:
    if (buff) strmov(buff,"datetime");
    *transfer_length=16;			/* size of timestamp_struct */
    *precision= *display_size=19;
    return SQL_TIMESTAMP;
  case FIELD_TYPE_NEWDATE:
  case FIELD_TYPE_DATE:
    if (buff) strmov(buff,"date");
    *transfer_length=6;				/* size of date struct */
    *precision= *display_size=10;
    return SQL_DATE;
  case FIELD_TYPE_TIME:
    if (buff) strmov(buff,"time");
    *transfer_length=6;				/* size of time struct */
    *precision= *display_size=8;
    return SQL_TIME;
  case FIELD_TYPE_STRING:
    if (buff) strmov(buff,"char");
    return SQL_CHAR;
  case FIELD_TYPE_VAR_STRING:
    if (buff) strmov(buff,"varchar");
    return SQL_VARCHAR;
  case FIELD_TYPE_TINY_BLOB:
    if (buff)
      strmov(buff,(field->flags & BINARY_FLAG) ? "tinyblob" : "tinytext");
    if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
      *transfer_length= *precision= *display_size= 255;
    return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  case FIELD_TYPE_BLOB:
    if (buff)
      strmov(buff,(field->flags & BINARY_FLAG) ? "blob" : "text");
    if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
      *transfer_length= *precision= *display_size= 65535;
    return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  case FIELD_TYPE_MEDIUM_BLOB:
    if (buff)
      strmov(buff,((field->flags & BINARY_FLAG) ? "mediumblob" : "mediumtext"));
    if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
      *transfer_length= *precision= *display_size= (1L << 24)-1L;
    return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  case FIELD_TYPE_LONG_BLOB:
    if (buff)
      strmov(buff,((field->flags & BINARY_FLAG) ? "longblob": "longtext"));
    if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
      *transfer_length= *precision= *display_size= INT_MAX32;
    return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  case FIELD_TYPE_ENUM:
    if (buff) strmov(buff,"enum");
    return SQL_CHAR;
  case FIELD_TYPE_SET:
    if (buff) strmov(buff,"set");
    return SQL_CHAR;
  }
}


int unireg_to_c_datatype(MYSQL_FIELD *field)
{
  switch(field->type) {
  case FIELD_TYPE_LONGLONG:		/* Must be returned as char */
  default:
    return SQL_C_CHAR;
  case FIELD_TYPE_CHAR:
    return SQL_C_TINYINT;
  case FIELD_TYPE_YEAR:
  case FIELD_TYPE_SHORT:
    return SQL_C_SHORT;
  case FIELD_TYPE_INT24:
  case FIELD_TYPE_LONG:
    return SQL_C_LONG;
  case FIELD_TYPE_FLOAT:
    return SQL_C_FLOAT;
  case FIELD_TYPE_DOUBLE:
    return SQL_C_DOUBLE;
  case FIELD_TYPE_TIMESTAMP:
  case FIELD_TYPE_DATETIME:
    return SQL_C_TIMESTAMP;
  case FIELD_TYPE_NEWDATE:
  case FIELD_TYPE_DATE:
    return SQL_C_DATE;
  case FIELD_TYPE_TIME:
    return SQL_C_TIME;
  }
}

int default_c_type(int sql_data_type)
{
  switch (sql_data_type) {
  case SQL_CHAR:
  case SQL_VARCHAR:
  case SQL_LONGVARCHAR:
  case SQL_DECIMAL:
  case SQL_NUMERIC:
  case SQL_BIGINT:			/* This is according to standard */
    return SQL_C_CHAR;
  case SQL_BIT:
    return SQL_C_BIT;
  case SQL_TINYINT:
    return SQL_C_TINYINT;
  case SQL_SMALLINT:
    return SQL_C_SHORT;
  case SQL_INTEGER:
    return SQL_C_LONG;
  case SQL_REAL:
  case SQL_FLOAT:
    return SQL_C_FLOAT;
  case SQL_DOUBLE:
    return SQL_C_DOUBLE;
  case SQL_BINARY:
  case SQL_VARBINARY:
  case SQL_LONGVARBINARY:
    return SQL_C_BINARY;
  case SQL_DATE:
    return SQL_C_DATE;
  case SQL_TIME:
    return SQL_C_TIME;
  case SQL_TIMESTAMP:
    return SQL_C_TIMESTAMP;
  }
}

ulong bind_length(int sql_data_type,ulong length)
{
  switch (sql_data_type) {
  default:			/* For CHAR, VARCHAR, BLOB... */
    return length;
  case SQL_C_BIT:
  case SQL_C_TINYINT:
  case SQL_C_STINYINT:
  case SQL_C_UTINYINT:
    return 1;
  case SQL_C_SHORT:
  case SQL_C_SSHORT:
  case SQL_C_USHORT:
    return 2;
  case SQL_C_LONG:
  case SQL_C_SLONG:
  case SQL_C_ULONG:
    return sizeof(long);
  case SQL_C_FLOAT:
    return sizeof(float);
  case SQL_C_DOUBLE:
    return sizeof(double);
  case SQL_C_DATE:
    return sizeof(DATE_STRUCT);
  case SQL_C_TIME:
    return sizeof(TIME_STRUCT);
  case SQL_C_TIMESTAMP:
    return sizeof(TIMESTAMP_STRUCT);
#if (ODBCVER >= 0x0300)
  case SQL_C_SBIGINT:
  case SQL_C_UBIGINT:
    return sizeof(longlong);
#endif
  }
}

/* convert a possible string to a data value */

my_bool str_to_date(DATE_STRUCT *rgbValue, const char *str,uint length)
{
  uint field_length,year_length,digits,i,date[3];
  const char *pos;
  const char *end=str+length;
  for (; !isdigit(*str) && str != end ; str++) ;
  /*
  ** calculate first number of digits.
  ** If length= 4, 8 or >= 14 then year is of format YYYY
     (YYYY-MM-DD,  YYYYMMDD)
  */
  for (pos=str; pos != end && isdigit(*pos) ; pos++) ;
  digits= (uint) (pos-str);
  year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
  field_length=year_length-1;

  for (i=0 ; i < 3 && str != end; i++)
  {
    uint tmp_value=(uint) (uchar) (*str++ - '0');
    while (str != end && isdigit(str[0]) && field_length--)
    {
      tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
      str++;
    }
    date[i]=tmp_value;
    while (str != end && !isdigit(*str))
      str++;
    field_length=1;				/* Rest fields can only be 2 */
  }
  if (i <= 1 || date[1] == 0)			/* Wrong date */
    return 1;
  while (i < 3)
    date[i++]=1;

  rgbValue->year=date[0];
  rgbValue->month=date[1];
  rgbValue->day=date[2];
  return 0;
}


/*****************************************************************************
** convert a time string to a (ulong) value.
** At least following formats are recogniced
** HHMMSS HHMM HH HH.MM.SS   {t HH:MM:SS }
** Return: HHMMSS
*****************************************************************************/

ulong str_to_time(const char *str,uint length)
{
  uint i,date[3];
  const char *end=str+length;
  for (; !isdigit(*str) && str != end ; str++) ;

  for (i=0 ; i < 3 && str != end; i++)
  {
    uint tmp_value=(uint) (uchar) (*str++ - '0');
    if (str != end && isdigit(str[0]))
    {
      tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
      str++;
    }
    date[i]=tmp_value;
    while (str != end && !isdigit(*str))
      str++;
  }
  while (i < 3)
    date[i++]=0;
  return (ulong) date[0]*10000L + (ulong) (date[1]*100+date[2]);
}


#ifndef _UNIX_

/* Define functions that dosen't exist in a dll */

/* _exit is called by safemalloc, mystatic & my_malloc */

#ifndef WIN32
void exit(int exit)
{
	abort();
}
#endif

/* perror is called by dbug.c */

void perror(const char *str)
{
}

/* clock is called by dbug.c when profiling */

long clock(void)
{
  return 0L;
}

char *intern_filename(char *home_dir_buff,const char *home_dir)
{
  return "\\";		/* only used by my_init */
}

#ifndef THREAD
long getpid()
{
  return 0;
}

void my_init()
{}
#else
int pthread_dummy(int return_value)
{
  return return_value;
}
#endif
#endif /* IS NOT UNIX */

⌨️ 快捷键说明

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