results.c
上传用户:jmzj888
上传日期:2007-01-02
资源大小:220k
文件大小:26k
- /* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
- This file is public domain and comes with NO WARRANTY of any kind */
- /*
- ** Returning results and information about results.
- */
- #include "myodbc.h"
- #include <m_ctype.h>
- #include <locale.h>
- #define digit(A) ((int) (A - '0'))
- RETCODE SQL_API sql_get_data(STMT *stm,SWORD fCType,MYSQL_FIELD *field,
- PTR rgbValue,
- SDWORD cbValueMax, SDWORD FAR *pcbValue,
- char *value,uint length);
- /*
- ** Execute the query if it is only prepared. This is needed because the ODBC
- ** standard allows calling some functions before SQLExecute(). (Stupid!)
- */
- static RETCODE check_result(STMT FAR *stmt)
- {
- RETCODE error;
- DBUG_ENTER("check_result");
- switch (stmt->state) {
- case ST_UNKNOWN:
- error=set_error(stmt->dbc,"24000","Invalid cursor state",0);
- break;
- case ST_PREPARED:
- if ((error=my_SQLExecute(stmt)) == SQL_SUCCESS)
- stmt->state=ST_PRE_EXECUTED; /* mark for execute */
- break;
- case ST_PRE_EXECUTED:
- case ST_EXECUTED:
- error=SQL_SUCCESS;
- }
- DBUG_RETURN(error);
- }
- // This returns the number of columns associated with the database
- // attached to "hstmt".
- RETCODE SQL_API SQLNumResultCols(HSTMT hstmt, SWORD FAR *pccol)
- {
- RETCODE error;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- DBUG_ENTER("SQLNumResultCols");
- if ((error=check_result(stmt)) != SQL_SUCCESS)
- DBUG_RETURN(error);
- if (!stmt->result)
- *pccol=0; /* Not a select */
- else
- *pccol=stmt->result->field_count;
- DBUG_PRINT("exit",("columns: %d",*pccol));
- DBUG_RETURN(SQL_SUCCESS);
- }
- // Return information about the database column the user wants
- // information about.
- RETCODE SQL_API SQLDescribeCol(HSTMT hstmt, UWORD icol, UCHAR FAR *szColName,
- SWORD cbColNameMax, SWORD FAR *pcbColName,
- SWORD FAR *pfSqlType, UDWORD FAR *pcbColDef,
- SWORD FAR *pibScale, SWORD FAR *pfNullable)
- {
- RETCODE error;
- MYSQL_FIELD *field;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- ulong transfer_length,precision,display_size;
- int type;
- DBUG_ENTER("SQLDescribeCol");
- if ((error=check_result(stmt)) != SQL_SUCCESS)
- DBUG_RETURN(error);
- mysql_field_seek(stmt->result,icol-1);
- if (!(field=mysql_fetch_field(stmt->result)))
- DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
- type=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,&display_size);
- if (pfSqlType)
- *pfSqlType=type;
- if (pcbColDef)
- *pcbColDef=precision;
- if (pibScale)
- *pibScale=field->decimals;
- if (pfNullable)
- *pfNullable= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
- SQL_NO_NULLS : SQL_NULLABLE;
- DBUG_PRINT("info",("col: %d type: %d precision: %ld decimals: %d",
- icol,type,precision,field->decimals));
- DBUG_RETURN(copy_result(stmt->dbc,szColName,cbColNameMax,pcbColName,
- field->name));
- }
- // Returns result column descriptor information for a result set.
- RETCODE SQL_API SQLColAttributes(HSTMT hstmt,UWORD icol,UWORD fDescType,
- SQLPOINTER rgbDesc, SWORD cbDescMax,
- SWORD FAR *pcbDesc, SDWORD FAR *pfDesc)
- {
- MYSQL_FIELD *field;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- SWORD dummy;
- ulong transfer_length,precision,display_size;
- RETCODE error;
- DBUG_ENTER("SQLColAttributes");
- DBUG_PRINT("enter",("type: %d",fDescType));
- if (!pcbDesc)
- pcbDesc= &dummy;
- if ((error=check_result(stmt)) != SQL_SUCCESS)
- DBUG_RETURN(error);
- mysql_field_seek(stmt->result,icol-1);
- if (!(field=mysql_fetch_field(stmt->result)))
- DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
- switch (fDescType) {
- case SQL_COLUMN_COUNT:
- *pfDesc= stmt->result->field_count;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_LABEL:
- case SQL_COLUMN_NAME:
- DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
- field->name));
- case SQL_COLUMN_TYPE:
- *pfDesc=unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
- &display_size);
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_DISPLAY_SIZE:
- (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
- &display_size);
- *pfDesc=display_size;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_PRECISION:
- (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
- &display_size);
- *pfDesc=precision;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_LENGTH:
- (void) unireg_to_sql_datatype(stmt,field,0,&transfer_length,&precision,
- &display_size);
- *pfDesc=transfer_length;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_SCALE:
- *pfDesc=field->decimals;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_NULLABLE:
- *pfDesc= (field->flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG ?
- SQL_NO_NULLS : SQL_NULLABLE;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_SEARCHABLE:
- *pfDesc= SQL_SEARCHABLE;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_UNSIGNED:
- if (pfDesc)
- *pfDesc= field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_MONEY:
- *pfDesc=0;
- break;
- case SQL_COLUMN_AUTO_INCREMENT:
- if (pfDesc)
- *pfDesc= field->flags & AUTO_INCREMENT_FLAG ? TRUE : FALSE;
- break;
- case SQL_COLUMN_CASE_SENSITIVE:
- *pfDesc= field->flags & BINARY_FLAG ? FALSE : TRUE;
- *pcbDesc=sizeof(int);
- break;
- case SQL_COLUMN_UPDATABLE:
- *pfDesc = (field->table && field->table[0] ? SQL_COLUMN_UPDATABLE :
- SQL_ATTR_READONLY);
- *pcbDesc= sizeof(int);
- break;
- case SQL_COLUMN_TYPE_NAME:
- {
- char buff[40];
- (void) unireg_to_sql_datatype(stmt,field,buff,&transfer_length,&precision,&display_size);
- DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,
- buff));
- }
- case SQL_COLUMN_OWNER_NAME:
- case SQL_COLUMN_QUALIFIER_NAME:
- DBUG_RETURN(copy_result(stmt->dbc,(uchar*) rgbDesc,cbDescMax,pcbDesc,""));
- }
- DBUG_RETURN(SQL_SUCCESS);
- }
- // Associate a user-supplied buffer with a database column.
- RETCODE SQL_API SQLBindCol(HSTMT hstmt, UWORD icol, SWORD fCType, PTR rgbValue,
- SDWORD cbValueMax, SDWORD FAR *pcbValue)
- {
- BIND *bind;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- RETCODE error;
- DBUG_ENTER("SQLBindCol");
- DBUG_PRINT("enter",
- ("icol: %d Type: %d ValueMax: %ld Valueptr: %lx Value: %ld",
- icol,fCType,(long) cbValueMax,pcbValue,
- (long) (pcbValue ? *pcbValue : 0L)));
- icol--;
- /*
- ** The next case if because of VB 5.0 that binds columns before preparing
- ** a statement
- */
- if (stmt->state == ST_UNKNOWN)
- {
- DBUG_PRINT("info",("Binding columns without a statement; Hope you know what you are doing"));
- if (icol >= stmt->bound_columns)
- {
- if (!(stmt->bind=(BIND*) my_realloc((char*) stmt->bind,
- (icol+1)*sizeof(BIND),
- MYF(MY_ALLOW_ZERO_PTR |
- MY_FREE_ON_ERROR))))
- {
- stmt->bound_columns=0;
- DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
- }
- bzero((gptr) (stmt->bind+stmt->bound_columns),
- (icol+1-stmt->bound_columns)*sizeof(BIND));
- stmt->bound_columns=icol+1;
- }
- }
- else
- {
- /* Bind parameter to current set ( The normal case ) */
- if ((error=check_result(stmt)) != SQL_SUCCESS)
- DBUG_RETURN(error);
- if (!stmt->result || (uint) icol >= stmt->result->field_count)
- {
- DBUG_RETURN(set_error(stmt->dbc,"S1002","Invalid column number",0));
- }
- if (!stmt->bind)
- {
- if (!(stmt->bind=(BIND*) my_malloc(sizeof(BIND)*
- stmt->result->field_count,
- MYF(MY_ZEROFILL))))
- DBUG_RETURN(set_error(stmt->dbc,"S1001","Not enough memory",4001));
- stmt->bound_columns=stmt->result->field_count;
- }
- mysql_field_seek(stmt->result,icol);
- stmt->bind[icol].field=mysql_fetch_field(stmt->result);
- }
- bind=stmt->bind+icol;
- bind->fCType=fCType;
- if (fCType == SQL_C_DEFAULT && stmt->odbc_types)
- bind->fCType=stmt->odbc_types[icol];
- bind->rgbValue=rgbValue;
- bind->cbValueMax=bind_length(bind->fCType,cbValueMax);
- bind->pcbValue=pcbValue;
- DBUG_RETURN(SQL_SUCCESS);
- }
- // Returns data for bound columns in the current row ("stmt->iCursor"),
- // advances the cursor.
- RETCODE SQL_API SQLFetch(HSTMT hstmt)
- {
- MYSQL_ROW values;
- RETCODE res,tmp_res;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- DBUG_ENTER("SQLFetch");
- if (!stmt->result)
- DBUG_RETURN(set_error(stmt->dbc,"24000","Fetch without a SELECT",0));
- if (stmt->result_array)
- {
- if (stmt->current_row >= stmt->result->row_count)
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- values=stmt->result_array+(stmt->current_row++)*
- stmt->result->field_count;
- }
- else
- {
- if (!(values=mysql_fetch_row(stmt->result)))
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- stmt->current_row++; /* For SQLGetStmtOption */
- if (stmt->fix_fields)
- values=(*stmt->fix_fields)(stmt,values);
- else
- stmt->result_lengths=mysql_fetch_lengths(stmt->result);
- }
- stmt->current_values=values; /* For SQLGetData */
- stmt->last_getdata_col= (uint) ~0;
- res=SQL_SUCCESS;
- if (stmt->bind)
- {
- uint *lengths=stmt->result_lengths;
- BIND *bind,*end;
- setlocale(LC_NUMERIC,"English"); /* force use of '.' as decimal point */
- for (bind=stmt->bind,end=bind + stmt->result->field_count ;
- bind < end ;
- bind++,values++)
- {
- if (bind->rgbValue || bind->pcbValue)
- {
- stmt->getdata_offset= (ulong) ~0L;
- if ((tmp_res=sql_get_data(stmt,bind->fCType,bind->field,bind->rgbValue,
- bind->cbValueMax,bind->pcbValue,
- *values, lengths ? *lengths : *values ?
- strlen(*values) : 0) )
- != SQL_SUCCESS)
- {
- if (tmp_res == SQL_SUCCESS_WITH_INFO)
- {
- DBUG_PRINT("info",("Problem with column: %d, value: '%s'",
- (int) (bind - stmt->bind)+1,
- *values ? *values : "NULL"));
- if (res == SQL_SUCCESS)
- res= tmp_res;
- }
- else
- res=SQL_ERROR;
- }
- }
- if (lengths)
- lengths++;
- }
- setlocale(LC_NUMERIC,default_locale);
- }
- stmt->getdata_offset= (ulong) ~0L;
- DBUG_RETURN(res);
- }
- // Returns result data for a single column in the current row.
- RETCODE SQL_API SQLGetData(HSTMT hstmt,UWORD icol,SWORD fCType,PTR rgbValue,
- SDWORD cbValueMax, SDWORD FAR *pcbValue)
- {
- STMT FAR *stmt=(STMT FAR*) hstmt;
- RETCODE result;
- DBUG_ENTER("SQLGetData");
- if (!stmt->result || !stmt->current_values)
- {
- set_error(stmt->dbc,"24000","SQLGetData without a preceding SELECT",0);
- DBUG_RETURN(SQL_ERROR);
- }
- icol--; /* Easier code if start from 0 */
- if (icol != stmt->last_getdata_col)
- { /* New column. Reset old offset */
- stmt->last_getdata_col=icol;
- stmt->getdata_offset= (ulong) ~0L;
- }
- #ifdef LOG_ALL
- DBUG_PRINT("QQ",("icol: %d fCType: %d default: %d value: %.10s",
- icol+1,fCType,
- stmt->odbc_types[icol],
- (stmt->current_values[icol] ? stmt->current_values[icol] :
- "NULL")));
- #endif
- setlocale(LC_NUMERIC,"English");
- result=sql_get_data(stmt,
- (SWORD) (fCType == SQL_C_DEFAULT ?
- stmt->odbc_types[icol] :
- fCType),
- stmt->result->fields+icol,
- rgbValue,cbValueMax,pcbValue,
- stmt->current_values[icol],
- (stmt->result_lengths ? stmt->result_lengths[icol] :
- (stmt->current_values[icol] ?
- strlen(stmt->current_values[icol]) : 0 )));
- setlocale(LC_NUMERIC,default_locale);
- DBUG_RETURN(result);
- }
- /*
- ** Get data. rgbValue or pcbValue may be NULL pointers!
- */
- RETCODE SQL_API sql_get_data(STMT *stmt,SWORD fCType,MYSQL_FIELD *field,
- PTR rgbValue, SDWORD cbValueMax,
- SDWORD FAR *pcbValue,
- char *value, uint length)
- {
- DBC *dbc=stmt->dbc;
- long tmp;
- if (!pcbValue)
- pcbValue= &tmp; /* Easier code */
- if (!value)
- {
- *pcbValue=SQL_NULL_DATA;
- }
- else switch (fCType) {
- case SQL_C_BINARY:
- case SQL_C_CHAR:
- {
- char buff[21];
- if (field->type == FIELD_TYPE_TIMESTAMP && length != 19)
- {
- /* MySQL doesn't have '-' in timestamp */
- /* Convert timestamp to ANSI format */
- char *pos;
- uint i;
- if (length == 6 || length == 12) /* YYMMDD or YYMMDDHHMMSS timestamp */
- {
- if (value[0] <= '6')
- {
- buff[0]='2';
- buff[1]='0';
- }
- else
- {
- buff[0]='1';
- buff[1]='9';
- }
- }
- else
- {
- buff[0]=value[0];
- buff[1]=value[1];
- value+=2;
- length-=2;
- }
- buff[2]= *value++;
- buff[3]= *value++;
- buff[4]='-';
- if (value[0] == '0' && value[1] == '0')
- {
- *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
- break;
- }
- pos=buff+5;
- length&= 30; /* Ensure that length is ok */
- for (i=1, length-=2 ; (int) length > 0 ; length-=2,i++)
- {
- *pos++= *value++;
- *pos++= *value++;
- *pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
- }
- for ( ; pos != buff+20 ; i++)
- {
- *pos++= '0';
- *pos++= '0';
- *pos++= i < 2 ? '-' : (i == 2) ? ' ' : ':';
- }
- value=buff;
- length=19;
- }
- return copy_lresult(dbc,(char*) rgbValue,cbValueMax,pcbValue,value,
- length,stmt->stmt_options.max_length,
- field->type == FIELD_TYPE_STRING ? field->length : 0L,
- &stmt->getdata_offset);
- }
- case SQL_C_BIT:
- if (rgbValue)
- *((char*) rgbValue)= (atoi(value) == 0 ? 0 : 1);
- *pcbValue=1;
- break;
- case SQL_C_TINYINT:
- case SQL_C_STINYINT:
- if (rgbValue)
- *((char*) rgbValue)= ((char) atoi(value));
- *pcbValue=1;
- break;
- case SQL_C_UTINYINT:
- if (rgbValue)
- *((uchar*) rgbValue)= ((uchar) (uint) atoi(value));
- *pcbValue=1;
- break;
- case SQL_C_SHORT:
- case SQL_C_SSHORT:
- if (rgbValue)
- *((short*) rgbValue)= (short) atoi(value);
- *pcbValue=sizeof(short);
- break;
- case SQL_C_USHORT:
- if (rgbValue)
- *((ushort*) rgbValue)= (ushort) (uint) atol(value);
- *pcbValue=sizeof(short);
- break;
- case SQL_C_LONG:
- case SQL_C_SLONG:
- if (rgbValue)
- *((long*) rgbValue)= (long) atol(value);
- *pcbValue=sizeof(long);
- break;
- case SQL_C_ULONG:
- if (rgbValue)
- {
- char *end_ptr;
- *((ulong*) rgbValue)= strtoul(value,&end_ptr,10);
- }
- *pcbValue=sizeof(long);
- break;
- case SQL_C_FLOAT:
- if (rgbValue)
- *((float*) rgbValue)= (float) atof(value);
- *pcbValue=sizeof(float);
- break;
- case SQL_C_DOUBLE:
- if (rgbValue)
- *((double*) rgbValue)= (double) atof(value);
- *pcbValue=sizeof(double);
- break;
- case SQL_C_DATE:
- {
- DATE_STRUCT tmp_date;
- if (!rgbValue)
- rgbValue=(char*) &tmp_date;
- if (!str_to_date((DATE_STRUCT *) rgbValue,value,length))
- *pcbValue=sizeof(DATE_STRUCT);
- else
- {
- *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
- }
- break;
- }
- case SQL_C_TIME:
- {
- if (rgbValue)
- {
- ulong time=str_to_time(value,length);
- TIME_STRUCT *time_info=(TIME_STRUCT *) rgbValue;
- time_info->hour= (UWORD) (time/10000);
- time_info->minute=(UWORD) (time/100%100);
- time_info->second=(UWORD) (time%100);
- }
- *pcbValue=sizeof(TIME_STRUCT);
- break;
- }
- case SQL_C_TIMESTAMP:
- {
- uint year,length;
- char buff[15],*to;
- TIMESTAMP_STRUCT tmp_timestamp;
- TIMESTAMP_STRUCT *time_stamp;
- if (!rgbValue)
- rgbValue= (char*) &tmp_timestamp;
- time_stamp=(TIMESTAMP_STRUCT *) rgbValue;
- for (to=buff ; *value && to < buff+sizeof(buff)-1 ; value++)
- {
- if (isdigit(*value))
- *to++ = *value;
- }
- length= (uint) (to-buff);
- if (length == 6 || length == 12) /* YYMMDD or YYMMDDHHMMSS */
- {
- bmove_upp(to+2,to,length);
- if (buff[0] <= '6')
- {
- buff[0]='2';
- buff[1]='0';
- }
- else
- {
- buff[0]='1';
- buff[1]='9';
- }
- length+=2;
- }
- if (length < 14)
- strfill(to,14 - length,'0');
- else
- *to=0;
- year=(digit(buff[0])*1000+digit(buff[1])*100+digit(buff[2])*10+
- digit(buff[3]));
- if (buff[4] == '0' && buff[5] == '0')
- *pcbValue=SQL_NULL_DATA; /* ODBC can't handle 0000-00-00 dates */
- else
- {
- time_stamp->year= year;
- time_stamp->month= digit(buff[4])*10+digit(buff[5]);
- time_stamp->day= digit(buff[6])*10+digit(buff[7]);
- time_stamp->hour= digit(buff[8])*10+digit(buff[9]);
- time_stamp->minute= digit(buff[10])*10+digit(buff[11]);
- time_stamp->second= digit(buff[12])*10+digit(buff[13]);
- time_stamp->fraction=0;
- *pcbValue=sizeof(*time_stamp);
- }
- break;
- }
- #if (ODBCVER >= 0x0300)
- case SQL_C_SBIGINT:
- {
- if (rgbValue)
- *((longlong*) rgbValue)= atoll(value);
- *pcbValue=sizeof(longlong);
- break;
- }
- case SQL_C_UBIGINT:
- {
- if (rgbValue)
- *((ulonglong*) rgbValue)= (ulonglong) atoll(value);
- *pcbValue=sizeof(ulonglong);
- break;
- }
- #endif
- }
- if (stmt->getdata_offset != (ulong) ~0L) /* Second call to getdata */
- {
- return SQL_NO_DATA_FOUND;
- }
- stmt->getdata_offset=0L; /* All data is retrevied */
- return SQL_SUCCESS;
- }
- // This determines whether there are more results sets available for
- // the "hstmt".
- RETCODE SQL_API SQLMoreResults(HSTMT hstmt)
- {
- DBUG_ENTER("SQLMoreResults");
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- }
- // This returns the number of rows affected byt an UPDATE, INSERT or
- // DELETE statement
- RETCODE SQL_API SQLRowCount(HSTMT hstmt, SDWORD FAR *pcrow)
- {
- STMT FAR *stmt=(STMT FAR*) hstmt;
- DBUG_ENTER("SQLRowCount");
- if (stmt->result)
- {
- *pcrow=mysql_num_rows(stmt->result);
- DBUG_PRINT("exit",("Rows in set: %ld",*pcrow));
- }
- else
- {
- *pcrow=mysql_affected_rows(&stmt->dbc->mysql);
- DBUG_PRINT("exit",("Affected rows: %ld",*pcrow));
- }
- DBUG_RETURN(SQL_SUCCESS);
- }
- // This positions the cursor within a block of data.
- RETCODE SQL_API SQLSetPos(HSTMT hstmt, UWORD irow, UWORD fRefresh, UWORD fLock)
- {
- STMT FAR *stmt=(STMT FAR*) hstmt;
- DBUG_ENTER("SQLSetPos");
- if (!stmt->result || !stmt->rows_found_in_set)
- {
- set_error(stmt->dbc,"S1010",
- "SQLSetPos without a preceding SQLExtendedFetch",0);
- DBUG_RETURN(SQL_ERROR);
- }
- irow--;
- if ((uint) irow >= stmt->rows_found_in_set)
- {
- DBUG_PRINT("error",("Tried to get irow: %d from a set of %d rows",
- irow,stmt->rows_found_in_set));
- set_error(stmt->dbc,"S1107","SQLSetpos: Row is out of range",4000);
- DBUG_RETURN(SQL_ERROR);
- }
- stmt->position_in_set=irow;
- if (stmt->result_array)
- stmt->current_values=stmt->result_array+((stmt->current_row+irow)*
- stmt->result->field_count);
- else
- {
- mysql_data_seek(stmt->result,stmt->current_row+irow);
- stmt->current_values=mysql_fetch_row(stmt->result);
- if (stmt->fix_fields)
- stmt->current_values=(*stmt->fix_fields)(stmt,stmt->current_values);
- else
- stmt->result_lengths=mysql_fetch_lengths(stmt->result);
- }
- if (fLock || fRefresh)
- {
- set_error(stmt->dbc,"S1109",
- "SQLSetPos with lock or refresh is not supported",4000);
- DBUG_RETURN(SQL_ERROR);
- }
- DBUG_RETURN(SQL_SUCCESS);
- }
- // This fetchs a block of data (rowset).
- RETCODE SQL_API SQLExtendedFetch(HSTMT hstmt, UWORD fFetchType, SDWORD irow,
- UDWORD FAR *pcrow, UWORD FAR *rgfRowStatus)
- {
- ulong cur_row,max_row,rows_to_fetch;
- uint i;
- RETCODE res,tmp_res;
- STMT FAR *stmt=(STMT FAR*) hstmt;
- MYSQL_ROW values;
- MYSQL_ROW_OFFSET save_position;
- DBUG_ENTER("SQLExtendedFetch");
- if (!stmt->result)
- DBUG_RETURN(set_error(stmt->dbc,"24000","Fetch without a SELECT",0));
- DBUG_PRINT("enter",
- ("fetchtype: %d row: %ld current top-row: %ld rows_found: %ld",
- fFetchType,irow,stmt->current_row,stmt->rows_found_in_set));
- max_row=mysql_num_rows(stmt->result);
- stmt->last_getdata_col=(uint) ~0;
- stmt->current_values=0; /* For SQLGetData */
- stmt->position_in_set=0;
- switch (fFetchType) {
- case SQL_FETCH_NEXT:
- cur_row=stmt->current_row+stmt->rows_found_in_set;
- break;
- case SQL_FETCH_PRIOR:
- cur_row=stmt->current_row-stmt->stmt_options.rows_in_set;
- break;
- case SQL_FETCH_FIRST:
- cur_row=0L;
- break;
- case SQL_FETCH_LAST:
- cur_row=max_row-stmt->stmt_options.rows_in_set;
- break;
- case SQL_FETCH_ABSOLUTE:
- if (irow == 0)
- {
- *pcrow=stmt->rows_found_in_set=0;
- stmt->current_row=0; /* Fix for next fetch */
- mysql_data_seek(stmt->result,0L);
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- }
- else if (irow < 0)
- {
- cur_row=(ulong) (max_row+irow);
- }
- else
- {
- cur_row=(ulong) irow-1;
- }
- break;
- case SQL_FETCH_RELATIVE:
- cur_row=(ulong) stmt->current_row +(ulong) irow;
- break;
- default:
- DBUG_RETURN(set_error(stmt->dbc,"S1106","Fetch type out of range",0));
- }
- if ((long) cur_row < 0)
- {
- if (-((long) cur_row) >= (long) stmt->stmt_options.rows_in_set)
- { /* Does not overlap start of set */
- stmt->current_row=0; /* Fix for next fetch */
- if (pcrow)
- *pcrow=0;
- stmt->rows_found_in_set=0; /* Return nothing */
- mysql_data_seek(stmt->result,0L);
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- }
- /* max_row= stmt->stmt_options.rows_in_set + cur_row; */
- cur_row=0; /* Fix seek for overlapping start */
- }
- if (cur_row > max_row)
- cur_row=max_row;
- if (!stmt->result_array)
- {
- if (cur_row && cur_row == stmt->current_row + stmt->rows_found_in_set)
- mysql_row_seek(stmt->result,stmt->end_of_set);
- else
- mysql_data_seek(stmt->result,cur_row);
- }
- stmt->current_row=cur_row;
- rows_to_fetch=min(max_row-cur_row,stmt->stmt_options.rows_in_set);
- if (!rows_to_fetch)
- {
- if (pcrow)
- *pcrow=0;
- stmt->rows_found_in_set=0;
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- }
- setlocale(LC_NUMERIC,"English");
- res=SQL_SUCCESS;
- for (i=0 ; i < rows_to_fetch ; i++)
- {
- if (stmt->result_array)
- {
- values=stmt->result_array+cur_row*stmt->result->field_count;
- if (i == 0)
- stmt->current_values=values;
- }
- else
- {
- if (i == 0)
- save_position=mysql_row_tell(stmt->result);
- if (!(values=mysql_fetch_row(stmt->result)))
- break; /* This shouldn't never happen */
- if (stmt->fix_fields)
- values=(*stmt->fix_fields)(stmt,values);
- else
- stmt->result_lengths=mysql_fetch_lengths(stmt->result);
- stmt->current_values=values;
- }
- if (rgfRowStatus)
- rgfRowStatus[i]=SQL_ROW_SUCCESS;
- if (stmt->bind)
- { /* Should always be true */
- uint *lengths=stmt->result_lengths;
- BIND *bind,*end;
- for (bind=stmt->bind,end=bind + stmt->result->field_count ;
- bind < end ;
- bind++,values++)
- {
- if (bind->rgbValue || bind->pcbValue)
- {
- ulong offset,pcb_offset;
- if (stmt->stmt_options.bind_type == SQL_BIND_BY_COLUMN)
- {
- offset=bind->cbValueMax*i;
- pcb_offset=sizeof(SDWORD)*i;
- }
- else
- pcb_offset=offset=stmt->stmt_options.bind_type*i;
- stmt->getdata_offset= (ulong) ~0L;
- if ((tmp_res=sql_get_data(stmt,bind->fCType,
- bind->field,
- (bind->rgbValue ?
- (char*) bind->rgbValue + offset : 0),
- bind->cbValueMax,
- (bind->pcbValue ?
- (SDWORD*) ((char*) bind->pcbValue +
- pcb_offset) : 0),
- *values,
- (lengths ? *lengths : *values ?
- strlen(*values) : 0)))
- != SQL_SUCCESS)
- {
- if (tmp_res == SQL_SUCCESS_WITH_INFO)
- {
- if (res == SQL_SUCCESS)
- res= tmp_res;
- }
- else
- res=SQL_ERROR;
- }
- }
- if (lengths)
- lengths++;
- }
- }
- cur_row++;
- }
- stmt->rows_found_in_set=i;
- if (pcrow)
- *pcrow=i;
- if (rgfRowStatus)
- for ( ; i < stmt->stmt_options.rows_in_set ; i++)
- rgfRowStatus[i]=SQL_ROW_NOROW;
- if (!stmt->result_array)
- { /* read data from first row */
- stmt->end_of_set=mysql_row_seek(stmt->result,save_position);
- if (i > 1)
- {
- stmt->current_values=mysql_fetch_row(stmt->result);
- if (stmt->fix_fields)
- stmt->current_values=(*stmt->fix_fields)(stmt,stmt->current_values);
- else
- stmt->result_lengths=mysql_fetch_lengths(stmt->result);
- }
- }
- setlocale(LC_NUMERIC,default_locale);
- DBUG_RETURN(res);
- }
- // Returns the next SQL error information.
- RETCODE SQL_API SQLError(HENV henv, HDBC hdbc, HSTMT hstmt,
- UCHAR FAR *szSqlState, SDWORD FAR *pfNativeError,
- UCHAR FAR *szErrorMsg, SWORD cbErrorMsgMax,
- SWORD FAR *pcbErrorMsg)
- {
- char *errmsg;
- RETCODE error;
- SWORD tmp_size;
- DBUG_ENTER("SQLError");
- DBUG_PRINT("enter",("szErrorMsg: %lx",szErrorMsg));
- if (!pcbErrorMsg)
- pcbErrorMsg= &tmp_size;
- *pcbErrorMsg=0;
- if (!hstmt && !hdbc)
- goto no_error;
- if (hstmt && !hdbc)
- hdbc=(HDBC) ((STMT FAR*) hstmt)->dbc;
- if (!(errmsg=mysql_error(&((DBC FAR*) hdbc)->mysql))[0])
- goto no_error;
- if (szSqlState)
- strmov((char*) szSqlState,((DBC FAR*) hdbc)->sqlstate);
- if (pfNativeError)
- *pfNativeError=mysql_errno(&((DBC FAR*) hdbc)->mysql);
- DBUG_PRINT("error",("Message: %s",errmsg));
- if ((error=copy_result((DBC FAR*) 0,szErrorMsg,cbErrorMsgMax,pcbErrorMsg,
- "[TCX][MyODBC]")) == SQL_SUCCESS)
- {
- int start_length= *pcbErrorMsg;
- cbErrorMsgMax-= start_length;
- szErrorMsg+= start_length;
- error=copy_result((DBC FAR*) 0,szErrorMsg,cbErrorMsgMax,pcbErrorMsg,
- errmsg);
- (*pcbErrorMsg)+= start_length;
- }
- errmsg[0]=0; /* Clear for next loop */
- DBUG_RETURN(error);
- no_error:
- if (cbErrorMsgMax)
- *szErrorMsg=0;
- if (pcbErrorMsg)
- *pcbErrorMsg=0; /* Some extra safety */
- if (szSqlState)
- strmov(szSqlState,"00000");
- DBUG_RETURN(SQL_NO_DATA_FOUND);
- }