📄 utility.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 + -