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

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. /*
  4. ** Returning results and information about results.
  5. */
  6. #include "myodbc.h"
  7. #include <m_ctype.h>
  8. #include <locale.h>
  9. #define digit(A) ((int) (A - '0'))
  10. RETCODE SQL_API sql_get_data(STMT *stm,SWORD fCType,MYSQL_FIELD *field,
  11.      PTR rgbValue,
  12.      SDWORD  cbValueMax, SDWORD FAR *pcbValue,
  13.      char *value,uint length);
  14. /*
  15. ** Execute the query if it is only prepared. This is needed because the ODBC
  16. ** standard allows calling some functions before SQLExecute(). (Stupid!)
  17. */
  18. static RETCODE check_result(STMT FAR *stmt)
  19. {
  20.   RETCODE error;
  21.   DBUG_ENTER("check_result");
  22.   switch (stmt->state) {
  23.   case ST_UNKNOWN:
  24.     error=set_error(stmt->dbc,"24000","Invalid cursor state",0);
  25.     break;
  26.   case ST_PREPARED:
  27.     if ((error=my_SQLExecute(stmt)) == SQL_SUCCESS)
  28.       stmt->state=ST_PRE_EXECUTED; /* mark for execute */
  29.     break;
  30.   case ST_PRE_EXECUTED:
  31.   case ST_EXECUTED:
  32.     error=SQL_SUCCESS;
  33.    }
  34.    DBUG_RETURN(error);
  35. }
  36. //      This returns the number of columns associated with the database
  37. //      attached to "hstmt".
  38. RETCODE SQL_API SQLNumResultCols(HSTMT  hstmt, SWORD FAR *pccol)
  39. {
  40.   RETCODE error;
  41.   STMT FAR *stmt=(STMT FAR*) hstmt;
  42.   DBUG_ENTER("SQLNumResultCols");
  43.   if ((error=check_result(stmt)) != SQL_SUCCESS)
  44.     DBUG_RETURN(error);
  45.   if (!stmt->result)
  46.     *pccol=0; /* Not a select */
  47.   else
  48.     *pccol=stmt->result->field_count;
  49.   DBUG_PRINT("exit",("columns: %d",*pccol));
  50.   DBUG_RETURN(SQL_SUCCESS);
  51. }
  52. //      Return information about the database column the user wants
  53. //      information about.
  54. RETCODE SQL_API SQLDescribeCol(HSTMT hstmt, UWORD icol, UCHAR FAR *szColName,
  55.        SWORD cbColNameMax, SWORD FAR *pcbColName,
  56.        SWORD FAR *pfSqlType, UDWORD FAR *pcbColDef,
  57.        SWORD FAR *pibScale, SWORD FAR *pfNullable)
  58. {
  59.   RETCODE error;
  60.   MYSQL_FIELD *field;
  61.   STMT FAR *stmt=(STMT FAR*) hstmt;
  62.   ulong transfer_length,precision,display_size;
  63.   int type;
  64.   DBUG_ENTER("SQLDescribeCol");
  65.   if ((error=check_result(stmt)) != SQL_SUCCESS)
  66.     DBUG_RETURN(error);
  67.   mysql_field_seek(stmt->result,icol-1);
  68.   if (!(field=mysql_fetch_field(stmt->result)))
  69.     DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
  70.   type=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,&display_size);
  71.   if (pfSqlType)
  72.     *pfSqlType=type;
  73.   if (pcbColDef)
  74.     *pcbColDef=precision;
  75.   if (pibScale)
  76.     *pibScale=field->decimals;
  77.   if (pfNullable)
  78.     *pfNullable= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
  79.                  SQL_NO_NULLS : SQL_NULLABLE;
  80.   DBUG_PRINT("info",("col: %d type: %d  precision: %ld  decimals: %d",
  81.                       icol,type,precision,field->decimals));
  82.   DBUG_RETURN(copy_result(stmt->dbc,szColName,cbColNameMax,pcbColName,
  83.   field->name));
  84. }
  85. //      Returns result column descriptor information for a result set.
  86. RETCODE SQL_API SQLColAttributes(HSTMT hstmt,UWORD icol,UWORD fDescType,
  87.  SQLPOINTER rgbDesc, SWORD cbDescMax,
  88.  SWORD FAR *pcbDesc, SDWORD FAR *pfDesc)
  89. {
  90.   MYSQL_FIELD *field;
  91.   STMT FAR *stmt=(STMT FAR*) hstmt;
  92.   SWORD dummy;
  93.   ulong transfer_length,precision,display_size;
  94.   RETCODE error;
  95.   DBUG_ENTER("SQLColAttributes");
  96.   DBUG_PRINT("enter",("type: %d",fDescType));
  97.   if (!pcbDesc)
  98.     pcbDesc= &dummy;
  99.   if ((error=check_result(stmt)) != SQL_SUCCESS)
  100.     DBUG_RETURN(error);
  101.   mysql_field_seek(stmt->result,icol-1);
  102.   if (!(field=mysql_fetch_field(stmt->result)))
  103.     DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
  104.   switch (fDescType) {
  105.   case SQL_COLUMN_COUNT:
  106.     *pfDesc= stmt->result->field_count;
  107.     *pcbDesc=sizeof(int);
  108.     break;
  109.   case SQL_COLUMN_LABEL:
  110.   case SQL_COLUMN_NAME:
  111.     DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
  112.     field->name));
  113.   case SQL_COLUMN_TYPE:
  114.     *pfDesc=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
  115.    &display_size);
  116.     *pcbDesc=sizeof(int);
  117.     break;
  118.   case SQL_COLUMN_DISPLAY_SIZE:
  119.     (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
  120.   &display_size);
  121.     *pfDesc=display_size;
  122.     *pcbDesc=sizeof(int);
  123.     break;
  124.   case SQL_COLUMN_PRECISION:
  125.     (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
  126.   &display_size);
  127.     *pfDesc=precision;
  128.     *pcbDesc=sizeof(int);
  129.     break;
  130.   case SQL_COLUMN_LENGTH:
  131.     (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
  132.   &display_size);
  133.     *pfDesc=transfer_length;
  134.     *pcbDesc=sizeof(int);
  135.     break;
  136.   case SQL_COLUMN_SCALE:
  137.     *pfDesc=field->decimals;
  138.     *pcbDesc=sizeof(int);
  139.     break;
  140.   case SQL_COLUMN_NULLABLE:
  141.     *pfDesc= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
  142.              SQL_NO_NULLS : SQL_NULLABLE;
  143.     *pcbDesc=sizeof(int);
  144.     break;
  145.   case SQL_COLUMN_SEARCHABLE:
  146.     *pfDesc= SQL_SEARCHABLE;
  147.     *pcbDesc=sizeof(int);
  148.     break;
  149.   case SQL_COLUMN_UNSIGNED:
  150.     if (pfDesc)
  151.       *pfDesc= field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
  152.     *pcbDesc=sizeof(int);
  153.     break;
  154.   case SQL_COLUMN_MONEY:
  155.     *pfDesc=0;
  156.     break;
  157.   case SQL_COLUMN_AUTO_INCREMENT:
  158.     if (pfDesc)
  159.       *pfDesc= field->flags & AUTO_INCREMENT_FLAG ? TRUE : FALSE;
  160.     break;
  161.   case SQL_COLUMN_CASE_SENSITIVE:
  162.     *pfDesc= field->flags & BINARY_FLAG ? FALSE : TRUE;
  163.     *pcbDesc=sizeof(int);
  164.     break;
  165.   case SQL_COLUMN_UPDATABLE:
  166.     *pfDesc = (field->table && field->table[0] ? SQL_COLUMN_UPDATABLE :
  167.        SQL_ATTR_READONLY);
  168.     *pcbDesc= sizeof(int);
  169.     break;
  170.   case SQL_COLUMN_TYPE_NAME:
  171.   {
  172.     char buff[40];
  173.     (void) unireg_to_sql_datatype(stmt,field,buff,&transfer_length,&precision,&display_size);
  174.     DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
  175.     buff));
  176.   }
  177.   case SQL_COLUMN_OWNER_NAME:
  178.   case SQL_COLUMN_QUALIFIER_NAME:
  179.     DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,""));
  180.   }
  181.   DBUG_RETURN(SQL_SUCCESS);
  182. }
  183. //      Associate a user-supplied buffer with a database column.
  184. RETCODE SQL_API SQLBindCol(HSTMT hstmt, UWORD icol, SWORD fCType, PTR rgbValue,
  185.    SDWORD  cbValueMax, SDWORD FAR *pcbValue)
  186. {
  187.   BIND *bind;
  188.   STMT FAR *stmt=(STMT FAR*) hstmt;
  189.   RETCODE error;
  190.   DBUG_ENTER("SQLBindCol");
  191.   DBUG_PRINT("enter",
  192.      ("icol: %d  Type: %d  ValueMax: %ld  Valueptr: %lx  Value: %ld",
  193.       icol,fCType,(long) cbValueMax,pcbValue,
  194.       (long) (pcbValue ? *pcbValue : 0L)));
  195.   icol--;
  196.   /*
  197.   ** The next case if because of VB 5.0 that binds columns before preparing
  198.   ** a statement
  199.   */
  200.   if (stmt->state == ST_UNKNOWN)
  201.   {
  202.     DBUG_PRINT("info",("Binding columns without a statement; Hope you know what you are doing"));
  203.     if (icol >= stmt->bound_columns)
  204.     {
  205.       if (!(stmt->bind=(BIND*) my_realloc((char*) stmt->bind,
  206.   (icol+1)*sizeof(BIND),
  207.   MYF(MY_ALLOW_ZERO_PTR |
  208.       MY_FREE_ON_ERROR))))
  209.       {
  210. stmt->bound_columns=0;
  211. DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
  212.       }
  213.       bzero((gptr) (stmt->bind+stmt->bound_columns),
  214.     (icol+1-stmt->bound_columns)*sizeof(BIND));
  215.       stmt->bound_columns=icol+1;
  216.     }
  217.   }
  218.   else
  219.   {
  220.     /* Bind parameter to current set  ( The normal case ) */
  221.     if ((error=check_result(stmt)) != SQL_SUCCESS)
  222.       DBUG_RETURN(error);
  223.     if (!stmt->result || (uint) icol >= stmt->result->field_count)
  224.     {
  225.       DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
  226.     }
  227.     if (!stmt->bind)
  228.     {
  229.       if (!(stmt->bind=(BIND*) my_malloc(sizeof(BIND)*
  230.  stmt->result->field_count,
  231.  MYF(MY_ZEROFILL))))
  232. DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
  233.       stmt->bound_columns=stmt->result->field_count;
  234.     }
  235.     mysql_field_seek(stmt->result,icol);
  236.     stmt->bind[icol].field=mysql_fetch_field(stmt->result);
  237.   }
  238.   bind=stmt->bind+icol;
  239.   bind->fCType=fCType;
  240.   if (fCType == SQL_C_DEFAULT && stmt->odbc_types)
  241.     bind->fCType=stmt->odbc_types[icol];
  242.   bind->rgbValue=rgbValue;
  243.   bind->cbValueMax=bind_length(bind->fCType,cbValueMax);
  244.   bind->pcbValue=pcbValue;
  245.   DBUG_RETURN(SQL_SUCCESS);
  246. }
  247. //      Returns data for bound columns in the current row ("stmt->iCursor"),
  248. //      advances the cursor.
  249. RETCODE SQL_API SQLFetch(HSTMT hstmt)
  250. {
  251.   MYSQL_ROW values;
  252.   RETCODE res,tmp_res;
  253.   STMT FAR *stmt=(STMT FAR*) hstmt;
  254.   DBUG_ENTER("SQLFetch");
  255.   if (!stmt->result)
  256.     DBUG_RETURN(set_error(stmt->dbc,"24000","Fetch without a SELECT",0));
  257.   if (stmt->result_array)
  258.   {
  259.     if (stmt->current_row >= stmt->result->row_count)
  260.       DBUG_RETURN(SQL_NO_DATA_FOUND);
  261.     values=stmt->result_array+(stmt->current_row++)*
  262.       stmt->result->field_count;
  263.   }
  264.   else
  265.   {
  266.     if (!(values=mysql_fetch_row(stmt->result)))
  267.       DBUG_RETURN(SQL_NO_DATA_FOUND);
  268.     stmt->current_row++; /* For SQLGetStmtOption */
  269.     if (stmt->fix_fields)
  270.       values=(*stmt->fix_fields)(stmt,values);
  271.     else
  272.       stmt->result_lengths=mysql_fetch_lengths(stmt->result);
  273.   }
  274.   stmt->current_values=values; /* For SQLGetData */
  275.   stmt->last_getdata_col= (uint) ~0;
  276.   res=SQL_SUCCESS;
  277.   if (stmt->bind)
  278.   {
  279.     uint *lengths=stmt->result_lengths;
  280.     BIND *bind,*end;
  281.     setlocale(LC_NUMERIC,"English"); /* force use of '.' as decimal point */
  282.     for (bind=stmt->bind,end=bind + stmt->result->field_count ;
  283.  bind < end ;
  284.  bind++,values++)
  285.     {
  286.       if (bind->rgbValue || bind->pcbValue)
  287.       {
  288. stmt->getdata_offset= (ulong) ~0L;
  289.   if ((tmp_res=sql_get_data(stmt,bind->fCType,bind->field,bind->rgbValue,
  290.   bind->cbValueMax,bind->pcbValue,
  291.   *values, lengths ? *lengths : *values ?
  292.   strlen(*values) : 0) )
  293.     != SQL_SUCCESS)
  294. {
  295.   if (tmp_res == SQL_SUCCESS_WITH_INFO)
  296.   {
  297.             DBUG_PRINT("info",("Problem with column: %d, value: '%s'",
  298.                                (int) (bind - stmt->bind)+1,
  299.        *values ? *values : "NULL"));
  300.             if (res == SQL_SUCCESS)
  301.       res= tmp_res;
  302.   }
  303.   else
  304.     res=SQL_ERROR;
  305. }
  306.       }
  307.       if (lengths)
  308. lengths++;
  309.     }
  310.     setlocale(LC_NUMERIC,default_locale);
  311.   }
  312.   stmt->getdata_offset= (ulong) ~0L;
  313.   DBUG_RETURN(res);
  314. }
  315. //  Returns result data for a single column in the current row.
  316. RETCODE SQL_API SQLGetData(HSTMT hstmt,UWORD icol,SWORD fCType,PTR rgbValue,
  317.    SDWORD cbValueMax, SDWORD FAR *pcbValue)
  318. {
  319.   STMT FAR *stmt=(STMT FAR*) hstmt;
  320.   RETCODE result;
  321.   DBUG_ENTER("SQLGetData");
  322.   if (!stmt->result || !stmt->current_values)
  323.   {
  324.     set_error(stmt->dbc,"24000","SQLGetData without a preceding SELECT",0);
  325.     DBUG_RETURN(SQL_ERROR);
  326.   }
  327.   icol--;   /* Easier code if start from 0 */
  328.   if (icol != stmt->last_getdata_col)
  329.   { /* New column. Reset old offset */
  330.     stmt->last_getdata_col=icol;
  331.     stmt->getdata_offset= (ulong) ~0L;
  332.   }
  333. #ifdef LOG_ALL
  334.   DBUG_PRINT("QQ",("icol: %d  fCType: %d  default: %d  value: %.10s",
  335.    icol+1,fCType,
  336.    stmt->odbc_types[icol],
  337.    (stmt->current_values[icol] ? stmt->current_values[icol] :
  338.     "NULL")));
  339. #endif
  340.   setlocale(LC_NUMERIC,"English");
  341.   result=sql_get_data(stmt,
  342.       (SWORD) (fCType == SQL_C_DEFAULT ?
  343.        stmt->odbc_types[icol] :
  344.        fCType),
  345.       stmt->result->fields+icol,
  346.       rgbValue,cbValueMax,pcbValue,
  347.       stmt->current_values[icol],
  348.       (stmt->result_lengths ? stmt->result_lengths[icol] :
  349.        (stmt->current_values[icol] ?
  350. strlen(stmt->current_values[icol]) : 0 )));
  351.   setlocale(LC_NUMERIC,default_locale);
  352.   DBUG_RETURN(result);
  353. }
  354. /*
  355. ** Get data.  rgbValue or pcbValue may be NULL pointers!
  356. */
  357. RETCODE SQL_API sql_get_data(STMT *stmt,SWORD fCType,MYSQL_FIELD *field,
  358.      PTR rgbValue, SDWORD  cbValueMax,
  359.      SDWORD FAR *pcbValue,
  360.      char *value, uint length)
  361. {
  362.   DBC *dbc=stmt->dbc;
  363.   long tmp;
  364.   if (!pcbValue)
  365.     pcbValue= &tmp; /* Easier code */
  366.   if (!value)
  367.   {
  368.     *pcbValue=SQL_NULL_DATA;
  369.   }
  370.   else switch (fCType) {
  371.   case SQL_C_BINARY:
  372.   case SQL_C_CHAR:
  373.   {
  374.     char buff[21];
  375.     if (field->type == FIELD_TYPE_TIMESTAMP && length != 19)
  376.     {
  377.       /* MySQL doesn't have '-' in timestamp */
  378.       /* Convert timestamp to ANSI format */
  379.       char *pos;
  380.       uint i;
  381.       if (length == 6 || length == 12) /* YYMMDD or YYMMDDHHMMSS timestamp */
  382.       {
  383. if (value[0] <= '6')
  384. {
  385.   buff[0]='2';
  386.   buff[1]='0';
  387. }
  388. else
  389. {
  390.   buff[0]='1';
  391.   buff[1]='9';
  392. }
  393.       }
  394.       else
  395.       {
  396. buff[0]=value[0];
  397. buff[1]=value[1];
  398. value+=2;
  399. length-=2;
  400.       }
  401.       buff[2]= *value++;
  402.       buff[3]= *value++;
  403.       buff[4]='-';
  404.       if (value[0] == '0' && value[1] == '0')
  405.       {
  406. *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
  407. break;
  408.       }
  409.       pos=buff+5;
  410.       length&= 30; /* Ensure that length is ok */
  411.       for (i=1, length-=2 ; (int) length > 0 ; length-=2,i++)
  412.       {
  413. *pos++= *value++;
  414. *pos++= *value++;
  415. *pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
  416.       }
  417.       for ( ; pos != buff+20 ; i++)
  418.       {
  419. *pos++= '0';
  420. *pos++= '0';
  421. *pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
  422.       }
  423.       value=buff;
  424.       length=19;
  425.     }
  426.     return copy_lresult(dbc,(char*) rgbValue,cbValueMax,pcbValue,value,
  427. length,stmt->stmt_options.max_length,
  428. field->type == FIELD_TYPE_STRING ? field->length : 0L,
  429. &stmt->getdata_offset);
  430.   }
  431.   case SQL_C_BIT:
  432.     if (rgbValue)
  433.       *((char*) rgbValue)= (atoi(value) == 0 ? 0 : 1);
  434.     *pcbValue=1;
  435.     break;
  436.   case SQL_C_TINYINT:
  437.   case SQL_C_STINYINT:
  438.     if (rgbValue)
  439.       *((char*) rgbValue)= ((char) atoi(value));
  440.     *pcbValue=1;
  441.     break;
  442.   case SQL_C_UTINYINT:
  443.     if (rgbValue)
  444.       *((uchar*) rgbValue)= ((uchar) (uint) atoi(value));
  445.     *pcbValue=1;
  446.     break;
  447.   case SQL_C_SHORT:
  448.   case SQL_C_SSHORT:
  449.     if (rgbValue)
  450.       *((short*) rgbValue)= (short) atoi(value);
  451.     *pcbValue=sizeof(short);
  452.     break;
  453.   case SQL_C_USHORT:
  454.     if (rgbValue)
  455.       *((ushort*) rgbValue)= (ushort) (uint) atol(value);
  456.     *pcbValue=sizeof(short);
  457.     break;
  458.   case SQL_C_LONG:
  459.   case SQL_C_SLONG:
  460.     if (rgbValue)
  461.       *((long*) rgbValue)= (long) atol(value);
  462.     *pcbValue=sizeof(long);
  463.     break;
  464.   case SQL_C_ULONG:
  465.     if (rgbValue)
  466.     {
  467.       char *end_ptr;
  468.       *((ulong*) rgbValue)= strtoul(value,&end_ptr,10);
  469.     }
  470.     *pcbValue=sizeof(long);
  471.     break;
  472.   case SQL_C_FLOAT:
  473.     if (rgbValue)
  474.       *((float*) rgbValue)= (float) atof(value);
  475.     *pcbValue=sizeof(float);
  476.     break;
  477.   case SQL_C_DOUBLE:
  478.     if (rgbValue)
  479.       *((double*) rgbValue)= (double) atof(value);
  480.     *pcbValue=sizeof(double);
  481.     break;
  482.   case SQL_C_DATE:
  483.   {
  484.     DATE_STRUCT tmp_date;
  485.     if (!rgbValue)
  486.       rgbValue=(char*) &tmp_date;
  487.     if (!str_to_date((DATE_STRUCT *) rgbValue,value,length))
  488.       *pcbValue=sizeof(DATE_STRUCT);
  489.     else
  490.     {
  491.       *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
  492.     }
  493.     break;
  494.   }
  495.   case SQL_C_TIME:
  496.   {
  497.     if (rgbValue)
  498.     {
  499.       ulong time=str_to_time(value,length);
  500.       TIME_STRUCT *time_info=(TIME_STRUCT *) rgbValue;
  501.       time_info->hour=  (UWORD) (time/10000);
  502.       time_info->minute=(UWORD) (time/100%100);
  503.       time_info->second=(UWORD) (time%100);
  504.     }
  505.     *pcbValue=sizeof(TIME_STRUCT);
  506.     break;
  507.   }
  508.   case SQL_C_TIMESTAMP:
  509.   {
  510.     uint year,length;
  511.     char buff[15],*to;
  512.     TIMESTAMP_STRUCT tmp_timestamp;
  513.     TIMESTAMP_STRUCT *time_stamp;
  514.     if (!rgbValue)
  515.       rgbValue= (char*) &tmp_timestamp;
  516.     time_stamp=(TIMESTAMP_STRUCT *) rgbValue;
  517.     for (to=buff ; *value && to < buff+sizeof(buff)-1 ; value++)
  518.     {
  519.       if (isdigit(*value))
  520. *to++ = *value;
  521.     }
  522.     length= (uint) (to-buff);
  523.     if (length == 6 || length == 12) /* YYMMDD or YYMMDDHHMMSS */
  524.     {
  525.       bmove_upp(to+2,to,length);
  526.       if (buff[0] <= '6')
  527.       {
  528. buff[0]='2';
  529. buff[1]='0';
  530.       }
  531.       else
  532.       {
  533. buff[0]='1';
  534. buff[1]='9';
  535.       }
  536.       length+=2;
  537.     }
  538.     if (length < 14)
  539.       strfill(to,14 - length,'0');
  540.     else
  541.       *to=0;
  542.     year=(digit(buff[0])*1000+digit(buff[1])*100+digit(buff[2])*10+
  543.   digit(buff[3]));
  544.     if (buff[4] == '0' && buff[5] == '0')
  545.       *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
  546.     else
  547.     {
  548.       time_stamp->year=   year;
  549.       time_stamp->month=  digit(buff[4])*10+digit(buff[5]);
  550.       time_stamp->day=    digit(buff[6])*10+digit(buff[7]);
  551.       time_stamp->hour=   digit(buff[8])*10+digit(buff[9]);
  552.       time_stamp->minute= digit(buff[10])*10+digit(buff[11]);
  553.       time_stamp->second= digit(buff[12])*10+digit(buff[13]);
  554.       time_stamp->fraction=0;
  555.       *pcbValue=sizeof(*time_stamp);
  556.     }
  557.     break;
  558.   }
  559. #if (ODBCVER >= 0x0300)
  560.   case SQL_C_SBIGINT:
  561.   {
  562.     if (rgbValue)
  563.       *((longlong*) rgbValue)= atoll(value);
  564.     *pcbValue=sizeof(longlong);
  565.     break;
  566.   }
  567.   case SQL_C_UBIGINT:
  568.   {
  569.     if (rgbValue)
  570.       *((ulonglong*) rgbValue)= (ulonglong) atoll(value);
  571.     *pcbValue=sizeof(ulonglong);
  572.     break;
  573.   }
  574. #endif
  575.   }
  576.   if (stmt->getdata_offset != (ulong) ~0L) /* Second call to getdata */
  577.   {
  578.     return SQL_NO_DATA_FOUND;
  579.   }
  580.   stmt->getdata_offset=0L; /* All data is retrevied */
  581.   return SQL_SUCCESS;
  582. }
  583. //  This determines whether there are more results sets available for
  584. //  the "hstmt".
  585. RETCODE SQL_API SQLMoreResults(HSTMT  hstmt)
  586. {
  587.   DBUG_ENTER("SQLMoreResults");
  588.   DBUG_RETURN(SQL_NO_DATA_FOUND);
  589. }
  590. //      This returns the number of rows affected byt an UPDATE, INSERT or
  591. // DELETE statement
  592. RETCODE SQL_API SQLRowCount(HSTMT hstmt, SDWORD FAR *pcrow)
  593. {
  594.   STMT FAR *stmt=(STMT FAR*) hstmt;
  595.   DBUG_ENTER("SQLRowCount");
  596.   if (stmt->result)
  597.   {
  598. *pcrow=mysql_num_rows(stmt->result);
  599. DBUG_PRINT("exit",("Rows in set: %ld",*pcrow));
  600.   }
  601.   else
  602.   {
  603. *pcrow=mysql_affected_rows(&stmt->dbc->mysql);
  604. DBUG_PRINT("exit",("Affected rows: %ld",*pcrow));
  605.   }
  606.   DBUG_RETURN(SQL_SUCCESS);
  607. }
  608. //      This positions the cursor within a block of data.
  609. RETCODE SQL_API SQLSetPos(HSTMT hstmt, UWORD irow, UWORD fRefresh, UWORD fLock)
  610. {
  611.   STMT FAR *stmt=(STMT FAR*) hstmt;
  612.   DBUG_ENTER("SQLSetPos");
  613.   if (!stmt->result || !stmt->rows_found_in_set)
  614.   {
  615.     set_error(stmt->dbc,"S1010",
  616.       "SQLSetPos without a preceding SQLExtendedFetch",0);
  617.     DBUG_RETURN(SQL_ERROR);
  618.   }
  619.   irow--;
  620.   if ((uint) irow >= stmt->rows_found_in_set)
  621.   {
  622.     DBUG_PRINT("error",("Tried to get irow: %d from a set of %d rows",
  623.                          irow,stmt->rows_found_in_set));
  624.     set_error(stmt->dbc,"S1107","SQLSetpos: Row is out of range",4000);
  625.     DBUG_RETURN(SQL_ERROR);
  626.   }
  627.   stmt->position_in_set=irow;
  628.   if (stmt->result_array)
  629.     stmt->current_values=stmt->result_array+((stmt->current_row+irow)*
  630.       stmt->result->field_count);
  631.   else
  632.   {
  633.     mysql_data_seek(stmt->result,stmt->current_row+irow);
  634.     stmt->current_values=mysql_fetch_row(stmt->result);
  635.     if (stmt->fix_fields)
  636.       stmt->current_values=(*stmt->fix_fields)(stmt,stmt->current_values);
  637.     else
  638.       stmt->result_lengths=mysql_fetch_lengths(stmt->result);
  639.   }
  640.   if (fLock || fRefresh)
  641.   {
  642.     set_error(stmt->dbc,"S1109",
  643.       "SQLSetPos with lock or refresh is not supported",4000);
  644.     DBUG_RETURN(SQL_ERROR);
  645.   }
  646.   DBUG_RETURN(SQL_SUCCESS);
  647. }
  648. //      This fetchs a block of data (rowset).
  649. RETCODE SQL_API SQLExtendedFetch(HSTMT hstmt, UWORD fFetchType, SDWORD irow,
  650.  UDWORD FAR *pcrow, UWORD FAR *rgfRowStatus)
  651. {
  652.   ulong cur_row,max_row,rows_to_fetch;
  653.   uint i;
  654.   RETCODE res,tmp_res;
  655.   STMT FAR *stmt=(STMT FAR*) hstmt;
  656.   MYSQL_ROW values;
  657.   MYSQL_ROW_OFFSET save_position;
  658.   DBUG_ENTER("SQLExtendedFetch");
  659.   if (!stmt->result)
  660.     DBUG_RETURN(set_error(stmt->dbc,"24000","Fetch without a SELECT",0));
  661.   DBUG_PRINT("enter",
  662.      ("fetchtype: %d  row: %ld  current top-row: %ld  rows_found: %ld",
  663.       fFetchType,irow,stmt->current_row,stmt->rows_found_in_set));
  664.   max_row=mysql_num_rows(stmt->result);
  665.   stmt->last_getdata_col=(uint)  ~0;
  666.   stmt->current_values=0; /* For SQLGetData */
  667.   stmt->position_in_set=0;
  668.   switch (fFetchType) {
  669.   case SQL_FETCH_NEXT:
  670.     cur_row=stmt->current_row+stmt->rows_found_in_set;
  671.     break;
  672.   case SQL_FETCH_PRIOR:
  673.     cur_row=stmt->current_row-stmt->stmt_options.rows_in_set;
  674.     break;
  675.   case SQL_FETCH_FIRST:
  676.     cur_row=0L;
  677.     break;
  678.   case SQL_FETCH_LAST:
  679.     cur_row=max_row-stmt->stmt_options.rows_in_set;
  680.     break;
  681.   case SQL_FETCH_ABSOLUTE:
  682.   if (irow == 0)
  683.   {
  684.     *pcrow=stmt->rows_found_in_set=0;
  685.     stmt->current_row=0; /* Fix for next fetch */
  686.     mysql_data_seek(stmt->result,0L);
  687.     DBUG_RETURN(SQL_NO_DATA_FOUND);
  688.   }
  689.   else if (irow < 0)
  690.   {
  691.     cur_row=(ulong) (max_row+irow);
  692.   }
  693.   else
  694.   {
  695.     cur_row=(ulong) irow-1;
  696.   }
  697.   break;
  698.   case SQL_FETCH_RELATIVE:
  699.     cur_row=(ulong) stmt->current_row +(ulong) irow;
  700.     break;
  701.   default:
  702.     DBUG_RETURN(set_error(stmt->dbc,"S1106","Fetch type out of range",0));
  703.   }
  704.   if ((long) cur_row < 0)
  705.   {
  706.     if (-((long) cur_row) >= (long) stmt->stmt_options.rows_in_set)
  707.     { /* Does not overlap start of set */
  708.       stmt->current_row=0; /* Fix for next fetch */
  709.       if (pcrow)
  710.         *pcrow=0;
  711.       stmt->rows_found_in_set=0;        /* Return nothing */
  712.       mysql_data_seek(stmt->result,0L);
  713.       DBUG_RETURN(SQL_NO_DATA_FOUND);
  714.     }
  715.     /* max_row= stmt->stmt_options.rows_in_set + cur_row; */
  716.     cur_row=0; /* Fix seek for overlapping start */
  717.   }
  718.   if (cur_row > max_row)
  719.     cur_row=max_row;
  720.   if (!stmt->result_array)
  721.   {
  722.     if (cur_row && cur_row == stmt->current_row + stmt->rows_found_in_set)
  723.       mysql_row_seek(stmt->result,stmt->end_of_set);
  724.     else
  725.       mysql_data_seek(stmt->result,cur_row);
  726.   }
  727.   stmt->current_row=cur_row;
  728.   rows_to_fetch=min(max_row-cur_row,stmt->stmt_options.rows_in_set);
  729.   if (!rows_to_fetch)
  730.   {
  731.     if (pcrow)
  732.       *pcrow=0;
  733.     stmt->rows_found_in_set=0;
  734.     DBUG_RETURN(SQL_NO_DATA_FOUND);
  735.   }
  736.   setlocale(LC_NUMERIC,"English");
  737.   res=SQL_SUCCESS;
  738.   for (i=0 ; i < rows_to_fetch ; i++)
  739.   {
  740.     if (stmt->result_array)
  741.     {
  742.       values=stmt->result_array+cur_row*stmt->result->field_count;
  743.       if (i == 0)
  744. stmt->current_values=values;
  745.     }
  746.     else
  747.     {
  748.       if (i == 0)
  749. save_position=mysql_row_tell(stmt->result);
  750.       if (!(values=mysql_fetch_row(stmt->result)))
  751.         break; /* This shouldn't never happen */
  752.       if (stmt->fix_fields)
  753. values=(*stmt->fix_fields)(stmt,values);
  754.       else
  755. stmt->result_lengths=mysql_fetch_lengths(stmt->result);
  756.       stmt->current_values=values;
  757.     }
  758.     if (rgfRowStatus)
  759.       rgfRowStatus[i]=SQL_ROW_SUCCESS;
  760.     if (stmt->bind)
  761.     { /* Should always be true */
  762.       uint *lengths=stmt->result_lengths;
  763.       BIND *bind,*end;
  764.       for (bind=stmt->bind,end=bind + stmt->result->field_count ;
  765.    bind < end ;
  766.    bind++,values++)
  767.       {
  768. if (bind->rgbValue || bind->pcbValue)
  769. {
  770.   ulong offset,pcb_offset;
  771.   if (stmt->stmt_options.bind_type == SQL_BIND_BY_COLUMN)
  772.   {
  773.     offset=bind->cbValueMax*i;
  774.     pcb_offset=sizeof(SDWORD)*i;
  775.   }
  776.   else
  777.     pcb_offset=offset=stmt->stmt_options.bind_type*i;
  778.   stmt->getdata_offset= (ulong) ~0L;
  779.   if ((tmp_res=sql_get_data(stmt,bind->fCType,
  780.     bind->field,
  781.     (bind->rgbValue ?
  782.      (char*) bind->rgbValue + offset : 0),
  783.     bind->cbValueMax,
  784.     (bind->pcbValue ?
  785.     (SDWORD*) ((char*) bind->pcbValue +
  786.        pcb_offset) : 0),
  787.      *values,
  788.     (lengths ? *lengths : *values ?
  789.      strlen(*values) : 0)))
  790.       != SQL_SUCCESS)
  791.   {
  792.     if (tmp_res == SQL_SUCCESS_WITH_INFO)
  793.     {
  794.       if (res == SQL_SUCCESS)
  795. res= tmp_res;
  796.     }
  797.     else
  798.       res=SQL_ERROR;
  799.   }
  800. }
  801. if (lengths)
  802.   lengths++;
  803.       }
  804.     }
  805.     cur_row++;
  806.   }
  807.   stmt->rows_found_in_set=i;
  808.   if (pcrow)
  809.     *pcrow=i;
  810.   if (rgfRowStatus)
  811.     for ( ; i < stmt->stmt_options.rows_in_set ; i++)
  812.       rgfRowStatus[i]=SQL_ROW_NOROW;
  813.   if (!stmt->result_array)
  814.   { /* read data from first row */
  815.     stmt->end_of_set=mysql_row_seek(stmt->result,save_position);
  816.     if (i > 1)
  817.     {
  818.       stmt->current_values=mysql_fetch_row(stmt->result);
  819.       if (stmt->fix_fields)
  820.         stmt->current_values=(*stmt->fix_fields)(stmt,stmt->current_values);
  821.       else
  822.         stmt->result_lengths=mysql_fetch_lengths(stmt->result);
  823.     }
  824.   }
  825.   setlocale(LC_NUMERIC,default_locale);
  826.   DBUG_RETURN(res);
  827. }
  828. //  Returns the next SQL error information.
  829. RETCODE SQL_API SQLError(HENV henv, HDBC hdbc, HSTMT hstmt,
  830.  UCHAR FAR *szSqlState, SDWORD FAR *pfNativeError,
  831.  UCHAR FAR *szErrorMsg, SWORD cbErrorMsgMax,
  832.  SWORD FAR *pcbErrorMsg)
  833. {
  834.   char *errmsg;
  835.   RETCODE error;
  836.   SWORD tmp_size;
  837.   DBUG_ENTER("SQLError");
  838.   DBUG_PRINT("enter",("szErrorMsg: %lx",szErrorMsg));
  839.   if (!pcbErrorMsg)
  840.     pcbErrorMsg= &tmp_size;
  841.   *pcbErrorMsg=0;
  842.   if (!hstmt && !hdbc)
  843.     goto no_error;
  844.   if (hstmt && !hdbc)
  845.     hdbc=(HDBC) ((STMT FAR*) hstmt)->dbc;
  846.   if (!(errmsg=mysql_error(&((DBC FAR*) hdbc)->mysql))[0])
  847.     goto no_error;
  848.   if (szSqlState)
  849.     strmov((char*) szSqlState,((DBC FAR*) hdbc)->sqlstate);
  850.   if (pfNativeError)
  851.     *pfNativeError=mysql_errno(&((DBC FAR*) hdbc)->mysql);
  852.   DBUG_PRINT("error",("Message: %s",errmsg));
  853.   if ((error=copy_result((DBC FAR*) 0,szErrorMsg,cbErrorMsgMax,pcbErrorMsg,
  854.        "[TCX][MyODBC]")) == SQL_SUCCESS)
  855.   {
  856.     int start_length= *pcbErrorMsg;
  857.     cbErrorMsgMax-= start_length;
  858.     szErrorMsg+=    start_length;
  859.     error=copy_result((DBC FAR*) 0,szErrorMsg,cbErrorMsgMax,pcbErrorMsg,
  860.      errmsg);
  861.     (*pcbErrorMsg)+= start_length;
  862.   }
  863.   errmsg[0]=0; /* Clear for next loop */
  864.   DBUG_RETURN(error);
  865. no_error:
  866.   if (cbErrorMsgMax)
  867.     *szErrorMsg=0;
  868.   if (pcbErrorMsg)
  869.     *pcbErrorMsg=0; /* Some extra safety */
  870.   if (szSqlState)
  871.     strmov(szSqlState,"00000");
  872.   DBUG_RETURN(SQL_NO_DATA_FOUND);
  873. }