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

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. #include "myodbc.h"
  4. /* Use own fields instead of sql fields */
  5. void mysql_link_fields(STMT *stmt,MYSQL_FIELD *fields,uint field_count)
  6. {
  7.   MYSQL_RES *result=stmt->result;
  8.   result->fields=fields;
  9.   result->field_count=field_count;
  10.   result->current_field=0;
  11.   fix_result_types(stmt);
  12. }
  13. void fix_result_types(STMT *stmt)
  14. {
  15.   uint i;
  16.   MYSQL_RES *result=stmt->result;
  17.   DBUG_ENTER("fix_result_types");
  18.   stmt->state=ST_EXECUTED; /* Mark set found */
  19.   if ((stmt->odbc_types=(SWORD*) my_malloc(sizeof(SWORD)*result->field_count,
  20.    MYF(0))))
  21.   {
  22.     for (i=0 ; i < result->field_count ; i++)
  23.     {
  24.       MYSQL_FIELD *field=result->fields+i;
  25.       stmt->odbc_types[i]=(SWORD) unireg_to_c_datatype(field);
  26.     }
  27.   }
  28.   /*
  29.   ** Fix default values for bound columns
  30.   ** Normally there isn't any bound columns at this stage !
  31.   */
  32.   if (stmt->bind)
  33.   {
  34.     if (stmt->bound_columns < result->field_count)
  35.     {
  36.       if (!(stmt->bind=(BIND*) my_realloc((char*) stmt->bind,
  37.   sizeof(BIND) * result->field_count,
  38.   MYF(MY_FREE_ON_ERROR))))
  39.       {
  40. /* We should in principle give an error here */
  41. stmt->bound_columns=0;
  42. DBUG_VOID_RETURN;
  43.       }
  44.       bzero((gptr) (stmt->bind+stmt->bound_columns),
  45.     (result->field_count -stmt->bound_columns)*sizeof(BIND));
  46.       stmt->bound_columns=result->field_count;
  47.     }
  48.     /* Fix default types and pointers to fields */
  49.     mysql_field_seek(result,0);
  50.     for (i=0; i < result->field_count ; i++)
  51.     {
  52.         if (stmt->bind[i].fCType == SQL_C_DEFAULT)
  53.   stmt->bind[i].fCType=stmt->odbc_types[i];
  54.         stmt->bind[i].field=mysql_fetch_field(result);
  55.     }
  56.   }
  57.   DBUG_VOID_RETURN;
  58. }
  59. /* change a string + length to a zero terminated string */
  60. char *fix_str(char *to,char *from,int length)
  61. {
  62.   if (!from)
  63.     return "";
  64.   if (length == SQL_NTS)
  65.     return from;
  66.   strmake(to,from,length);
  67.   return to;
  68. }
  69. char *dupp_str(char *from,int length)
  70. {
  71.   char *to;
  72.   if (!from)
  73.     return my_strdup("",MYF(MY_WME));
  74.   if (length == SQL_NTS)
  75.     length=strlen(from);
  76.   if ((to=my_malloc(length+1,MYF(MY_WME))))
  77.   {
  78.     memcpy(to,from,length);
  79.     to[length]=0;
  80.   }
  81.   return to;
  82. }
  83. /* Return 1 if from is a null pointer or a empty string */
  84. bool empty_str(char *from,int length)
  85. {
  86.   if (!from)
  87.     return 1;
  88.   if (length == SQL_NTS)
  89.     return from[0] == 0;
  90.   return !length;
  91. }
  92. void remove_escape(char *name)
  93. {
  94.   char *to;
  95.   for (to=name ; *name ; name++)
  96.   {
  97.     if (*name == '\' && name[1])
  98.       name++;
  99.     *to++= *name;
  100.   }
  101.   *to=0;
  102. }
  103. /*
  104. ** Return (possibly truncated) results
  105. ** If result is truncated the result length contains
  106. ** length of the truncted result;
  107. */
  108. RETCODE copy_result(DBC *dbc,UCHAR FAR *rgbValue,SWORD cbValueMax,
  109.     SWORD FAR *pcbValue,char FAR *src)
  110. {
  111.   UCHAR FAR *dst=rgbValue;
  112.   SWORD save_ValueMax=cbValueMax;
  113.   if (!dst)
  114.   {
  115.     if (pcbValue)
  116.       *pcbValue=0;
  117.     return SQL_SUCCESS;
  118.   }
  119.   while (--cbValueMax)
  120.   {
  121.     if (! (*dst++ = *src++))
  122.     {
  123.       if (pcbValue)
  124.         *pcbValue= (SWORD) (dst-1 - rgbValue);
  125.       return SQL_SUCCESS;
  126.     }
  127.   }
  128.   *dst=0;
  129.   if (pcbValue)
  130.     *pcbValue=(SWORD) (dst- rgbValue);  /* +strlen(src) */
  131.   if (!*src)
  132.     return SQL_SUCCESS; /* There was room after all */
  133.   DBUG_PRINT("warning",("Truncated string of length: %d to %d",
  134. strlen(src)+ (dst-rgbValue)+1, save_ValueMax));
  135.   if (dbc)
  136.     set_error(dbc,"01004","Data truncated",4002);
  137.   return SQL_SUCCESS_WITH_INFO;
  138. }
  139. RETCODE copy_lresult(DBC FAR *dbc,UCHAR FAR *rgbValue,SDWORD cbValueMax,
  140.      SDWORD FAR *pcbValue,char *src,ulong src_length,
  141.      ulong max_length,ulong fill_length,ulong *offset)
  142. {
  143.   char *dst=(char*) rgbValue;
  144.   ulong length;
  145.   if (cbValueMax) /* If not length check */
  146.     cbValueMax--; /* Room for end null */
  147.   else
  148.     dst=0; /* Don't copy anything! */
  149.   if (max_length) /* If limit on char lengths */
  150.   {
  151.     set_if_smaller(cbValueMax,(long) max_length);
  152.     set_if_smaller(src_length,max_length);
  153.     set_if_smaller(fill_length,max_length);
  154.   }
  155.   if (fill_length < src_length || !dbc || !(dbc->flag & FLAG_PAD_SPACE))
  156.     fill_length=src_length;
  157.   if (*offset == (ulong) ~0L)
  158.     *offset=0; /* First call */
  159.   else if (*offset >= fill_length)
  160.     return SQL_NO_DATA_FOUND;
  161.   src+= *offset ; src_length-= *offset; fill_length-= *offset;
  162.   length=min(fill_length,(ulong) cbValueMax);
  163.   (*offset)+=length; /* Fix for next call */
  164.   if (pcbValue)
  165.     *pcbValue=fill_length;
  166.   if (dst) /* Bind allows null pointers */
  167.   {
  168.     ulong copy_length= ((long) src_length >= (long) length ? length :
  169. ((long) src_length >= 0 ? src_length : 0L));
  170.     memcpy(dst,src,copy_length);
  171.     bfill(dst+copy_length,length-copy_length,' ');
  172.     dst[length]=0;
  173.   }
  174.   if ((ulong) cbValueMax >= fill_length)
  175.     return SQL_SUCCESS;
  176.   if (dbc)
  177.     set_error(dbc,"01004","Data truncated",4002);
  178.   return SQL_SUCCESS_WITH_INFO;
  179. }
  180. RETCODE set_error(DBC FAR *dbc,char *state,char *message,uint errcode)
  181. {
  182.   DBUG_ENTER("set_error");
  183.   DBUG_PRINT("error",("message: %s",message));
  184.   strmov(dbc->sqlstate,state);
  185.   strmov(mysql_error(&dbc->mysql),message);
  186.   dbc->mysql.net.last_errno=errcode;
  187.   DBUG_RETURN(SQL_ERROR);
  188. }
  189. /*
  190. ** Get type, transfer length and precision for a unireg column
  191. ** Note that timestamp is changed to YYYY-MM-DD HH:MM:SS type
  192. */
  193. int unireg_to_sql_datatype(STMT FAR *stmt, MYSQL_FIELD *field, char *buff,
  194.    ulong *transfer_length,ulong *precision,
  195.    ulong *display_size)
  196. {
  197.   char *pos;
  198.   if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
  199.     *transfer_length= *precision= *display_size= max(field->length,
  200.      field->max_length);
  201.   else
  202.     *transfer_length= *precision= *display_size= field->max_length;
  203.   switch(field->type) {
  204.   case FIELD_TYPE_DECIMAL:
  205.     if (buff) strmov(buff,"decimal");
  206.     return SQL_DECIMAL;
  207.   case FIELD_TYPE_CHAR:
  208.     if (buff)
  209.     {
  210.       pos=strmov(buff,"tinyint");
  211.       if (field->flags & UNSIGNED_FLAG)
  212. strmov(pos," unsigned");
  213.     }
  214.     *transfer_length=1;
  215.     return SQL_TINYINT;
  216.   case FIELD_TYPE_SHORT:
  217.     if (buff)
  218.     {
  219.       pos=strmov(buff,"smallint");
  220.       if (field->flags & UNSIGNED_FLAG)
  221. strmov(pos," unsigned");
  222.     }
  223.     *transfer_length=2;
  224.     return SQL_SMALLINT;
  225.   case FIELD_TYPE_INT24:
  226.     if (buff)
  227.     {
  228.       pos=strmov(buff,"mediumint");
  229.       if (field->flags & UNSIGNED_FLAG)
  230. strmov(pos," unsigned");
  231.     }
  232.     *transfer_length=4;
  233.     return SQL_INTEGER;
  234.   case FIELD_TYPE_LONG:
  235.     if (buff)
  236.     {
  237.       pos= strmov(buff,"int");
  238.       if (field->flags & UNSIGNED_FLAG)
  239. strmov(pos," unsigned");
  240.     }
  241.     *transfer_length=4;
  242.     return SQL_INTEGER;
  243.   case FIELD_TYPE_LONGLONG:
  244.     if (buff)
  245.     {
  246.       pos= strmov(buff,"bigint");
  247.       if (field->flags & UNSIGNED_FLAG)
  248. strmov(pos," unsigned");
  249.     }
  250.     *transfer_length=20;
  251.     return SQL_BIGINT;
  252.   case FIELD_TYPE_FLOAT:
  253.     if (buff)
  254.     {
  255.       pos= strmov(buff,"float");
  256.       if (field->flags & UNSIGNED_FLAG)
  257. strmov(pos," unsigned");
  258.     }
  259.     *transfer_length=4;
  260.     return SQL_REAL;
  261.   case FIELD_TYPE_DOUBLE:
  262.     if (buff)
  263.     {
  264.       pos= strmov(buff,"double");
  265.       if (field->flags & UNSIGNED_FLAG)
  266. strmov(pos," unsigned");
  267.     }
  268.     *transfer_length=8;
  269.     return SQL_DOUBLE;
  270.   case FIELD_TYPE_NULL:
  271.     if (buff) strmov(buff,"null");
  272.     return SQL_VARCHAR;
  273.   case FIELD_TYPE_YEAR:
  274.     if (buff)
  275.       pos=strmov(buff,"year");
  276.     *transfer_length=2;
  277.     return SQL_SMALLINT;
  278.   case FIELD_TYPE_TIMESTAMP:
  279.     if (buff) strmov(buff,"timestamp");
  280.     *transfer_length=16; /* size of timestamp_struct */
  281.     *precision= *display_size=19;
  282.     return SQL_TIMESTAMP;
  283.   case FIELD_TYPE_DATETIME:
  284.     if (buff) strmov(buff,"datetime");
  285.     *transfer_length=16; /* size of timestamp_struct */
  286.     *precision= *display_size=19;
  287.     return SQL_TIMESTAMP;
  288.   case FIELD_TYPE_NEWDATE:
  289.   case FIELD_TYPE_DATE:
  290.     if (buff) strmov(buff,"date");
  291.     *transfer_length=6; /* size of date struct */
  292.     *precision= *display_size=10;
  293.     return SQL_DATE;
  294.   case FIELD_TYPE_TIME:
  295.     if (buff) strmov(buff,"time");
  296.     *transfer_length=6; /* size of time struct */
  297.     *precision= *display_size=8;
  298.     return SQL_TIME;
  299.   case FIELD_TYPE_STRING:
  300.     if (buff) strmov(buff,"char");
  301.     return SQL_CHAR;
  302.   case FIELD_TYPE_VAR_STRING:
  303.     if (buff) strmov(buff,"varchar");
  304.     return SQL_VARCHAR;
  305.   case FIELD_TYPE_TINY_BLOB:
  306.     if (buff)
  307.       strmov(buff,(field->flags & BINARY_FLAG) ? "tinyblob" : "tinytext");
  308.     if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
  309.       *transfer_length= *precision= *display_size= 255;
  310.     return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  311.   case FIELD_TYPE_BLOB:
  312.     if (buff)
  313.       strmov(buff,(field->flags & BINARY_FLAG) ? "blob" : "text");
  314.     if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
  315.       *transfer_length= *precision= *display_size= 65535;
  316.     return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  317.   case FIELD_TYPE_MEDIUM_BLOB:
  318.     if (buff)
  319.       strmov(buff,((field->flags & BINARY_FLAG) ? "mediumblob" : "mediumtext"));
  320.     if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
  321.       *transfer_length= *precision= *display_size= (1L << 24)-1L;
  322.     return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  323.   case FIELD_TYPE_LONG_BLOB:
  324.     if (buff)
  325.       strmov(buff,((field->flags & BINARY_FLAG) ? "longblob": "longtext"));
  326.     if (stmt->dbc->flag & FLAG_FIELD_LENGTH)
  327.       *transfer_length= *precision= *display_size= INT_MAX32;
  328.     return (field->flags & BINARY_FLAG) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
  329.   case FIELD_TYPE_ENUM:
  330.     if (buff) strmov(buff,"enum");
  331.     return SQL_CHAR;
  332.   case FIELD_TYPE_SET:
  333.     if (buff) strmov(buff,"set");
  334.     return SQL_CHAR;
  335.   }
  336. }
  337. int unireg_to_c_datatype(MYSQL_FIELD *field)
  338. {
  339.   switch(field->type) {
  340.   case FIELD_TYPE_LONGLONG: /* Must be returned as char */
  341.   default:
  342.     return SQL_C_CHAR;
  343.   case FIELD_TYPE_CHAR:
  344.     return SQL_C_TINYINT;
  345.   case FIELD_TYPE_YEAR:
  346.   case FIELD_TYPE_SHORT:
  347.     return SQL_C_SHORT;
  348.   case FIELD_TYPE_INT24:
  349.   case FIELD_TYPE_LONG:
  350.     return SQL_C_LONG;
  351.   case FIELD_TYPE_FLOAT:
  352.     return SQL_C_FLOAT;
  353.   case FIELD_TYPE_DOUBLE:
  354.     return SQL_C_DOUBLE;
  355.   case FIELD_TYPE_TIMESTAMP:
  356.   case FIELD_TYPE_DATETIME:
  357.     return SQL_C_TIMESTAMP;
  358.   case FIELD_TYPE_NEWDATE:
  359.   case FIELD_TYPE_DATE:
  360.     return SQL_C_DATE;
  361.   case FIELD_TYPE_TIME:
  362.     return SQL_C_TIME;
  363.   }
  364. }
  365. int default_c_type(int sql_data_type)
  366. {
  367.   switch (sql_data_type) {
  368.   case SQL_CHAR:
  369.   case SQL_VARCHAR:
  370.   case SQL_LONGVARCHAR:
  371.   case SQL_DECIMAL:
  372.   case SQL_NUMERIC:
  373.   case SQL_BIGINT: /* This is according to standard */
  374.     return SQL_C_CHAR;
  375.   case SQL_BIT:
  376.     return SQL_C_BIT;
  377.   case SQL_TINYINT:
  378.     return SQL_C_TINYINT;
  379.   case SQL_SMALLINT:
  380.     return SQL_C_SHORT;
  381.   case SQL_INTEGER:
  382.     return SQL_C_LONG;
  383.   case SQL_REAL:
  384.   case SQL_FLOAT:
  385.     return SQL_C_FLOAT;
  386.   case SQL_DOUBLE:
  387.     return SQL_C_DOUBLE;
  388.   case SQL_BINARY:
  389.   case SQL_VARBINARY:
  390.   case SQL_LONGVARBINARY:
  391.     return SQL_C_BINARY;
  392.   case SQL_DATE:
  393.     return SQL_C_DATE;
  394.   case SQL_TIME:
  395.     return SQL_C_TIME;
  396.   case SQL_TIMESTAMP:
  397.     return SQL_C_TIMESTAMP;
  398.   }
  399. }
  400. ulong bind_length(int sql_data_type,ulong length)
  401. {
  402.   switch (sql_data_type) {
  403.   default: /* For CHAR, VARCHAR, BLOB... */
  404.     return length;
  405.   case SQL_C_BIT:
  406.   case SQL_C_TINYINT:
  407.   case SQL_C_STINYINT:
  408.   case SQL_C_UTINYINT:
  409.     return 1;
  410.   case SQL_C_SHORT:
  411.   case SQL_C_SSHORT:
  412.   case SQL_C_USHORT:
  413.     return 2;
  414.   case SQL_C_LONG:
  415.   case SQL_C_SLONG:
  416.   case SQL_C_ULONG:
  417.     return sizeof(long);
  418.   case SQL_C_FLOAT:
  419.     return sizeof(float);
  420.   case SQL_C_DOUBLE:
  421.     return sizeof(double);
  422.   case SQL_C_DATE:
  423.     return sizeof(DATE_STRUCT);
  424.   case SQL_C_TIME:
  425.     return sizeof(TIME_STRUCT);
  426.   case SQL_C_TIMESTAMP:
  427.     return sizeof(TIMESTAMP_STRUCT);
  428. #if (ODBCVER >= 0x0300)
  429.   case SQL_C_SBIGINT:
  430.   case SQL_C_UBIGINT:
  431.     return sizeof(longlong);
  432. #endif
  433.   }
  434. }
  435. /* convert a possible string to a data value */
  436. my_bool str_to_date(DATE_STRUCT *rgbValue, const char *str,uint length)
  437. {
  438.   uint field_length,year_length,digits,i,date[3];
  439.   const char *pos;
  440.   const char *end=str+length;
  441.   for (; !isdigit(*str) && str != end ; str++) ;
  442.   /*
  443.   ** calculate first number of digits.
  444.   ** If length= 4, 8 or >= 14 then year is of format YYYY
  445.      (YYYY-MM-DD,  YYYYMMDD)
  446.   */
  447.   for (pos=str; pos != end && isdigit(*pos) ; pos++) ;
  448.   digits= (uint) (pos-str);
  449.   year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
  450.   field_length=year_length-1;
  451.   for (i=0 ; i < 3 && str != end; i++)
  452.   {
  453.     uint tmp_value=(uint) (uchar) (*str++ - '0');
  454.     while (str != end && isdigit(str[0]) && field_length--)
  455.     {
  456.       tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
  457.       str++;
  458.     }
  459.     date[i]=tmp_value;
  460.     while (str != end && !isdigit(*str))
  461.       str++;
  462.     field_length=1; /* Rest fields can only be 2 */
  463.   }
  464.   if (i <= 1 || date[1] == 0) /* Wrong date */
  465.     return 1;
  466.   while (i < 3)
  467.     date[i++]=1;
  468.   rgbValue->year=date[0];
  469.   rgbValue->month=date[1];
  470.   rgbValue->day=date[2];
  471.   return 0;
  472. }
  473. /*****************************************************************************
  474. ** convert a time string to a (ulong) value.
  475. ** At least following formats are recogniced
  476. ** HHMMSS HHMM HH HH.MM.SS   {t HH:MM:SS }
  477. ** Return: HHMMSS
  478. *****************************************************************************/
  479. ulong str_to_time(const char *str,uint length)
  480. {
  481.   uint i,date[3];
  482.   const char *end=str+length;
  483.   for (; !isdigit(*str) && str != end ; str++) ;
  484.   for (i=0 ; i < 3 && str != end; i++)
  485.   {
  486.     uint tmp_value=(uint) (uchar) (*str++ - '0');
  487.     if (str != end && isdigit(str[0]))
  488.     {
  489.       tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
  490.       str++;
  491.     }
  492.     date[i]=tmp_value;
  493.     while (str != end && !isdigit(*str))
  494.       str++;
  495.   }
  496.   while (i < 3)
  497.     date[i++]=0;
  498.   return (ulong) date[0]*10000L + (ulong) (date[1]*100+date[2]);
  499. }
  500. #ifndef _UNIX_
  501. /* Define functions that dosen't exist in a dll */
  502. /* _exit is called by safemalloc, mystatic & my_malloc */
  503. #ifndef WIN32
  504. void exit(int exit)
  505. {
  506. abort();
  507. }
  508. #endif
  509. /* perror is called by dbug.c */
  510. void perror(const char *str)
  511. {
  512. }
  513. /* clock is called by dbug.c when profiling */
  514. long clock(void)
  515. {
  516.   return 0L;
  517. }
  518. char *intern_filename(char *home_dir_buff,const char *home_dir)
  519. {
  520.   return "\"; /* only used by my_init */
  521. }
  522. #ifndef THREAD
  523. long getpid()
  524. {
  525.   return 0;
  526. }
  527. void my_init()
  528. {}
  529. #else
  530. int pthread_dummy(int return_value)
  531. {
  532.   return return_value;
  533. }
  534. #endif
  535. #endif /* IS NOT UNIX */