utility.c
上传用户:jmzj888
上传日期:2007-01-02
资源大小:220k
文件大小:15k
- /* 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 */