// Copyright (c) 1999-2001 David Muse // See the file COPYING for more information #include #include #include #include #include //orbb #include #include #define USER_CODING "UTF8" int ucslen(char* str); char *conv_to_user_coding(char *inbuf); /*void to_log(char *msg) { FILE *f; f=fopen("/var/log/SQLRelay/log","a"); if(f) { fprintf(f,"%s\n",msg); fclose(f); } } void to_wlog(char *msg) { FILE *f; f=fopen("/var/log/SQLRelay/log","a"); if(f) { char *str_u=conv_to_user_coding(msg); fprintf(f,"%s\n",str_u); free(str_u); //int l=ucslen(msg); //fwrite(msg,2,l,f); //fprintf(f,"\n"); fclose(f); } }*/ //orbb //orbb char *buffers[200]; int nextbuf=0; int ucslen(char* str) { char *ptr=str; int res=0; while(!(*ptr==0 && *(ptr+1)==0)) { res++; ptr+=2; } return res; } char *conv_to_user_coding(char *inbuf) { char *outbuf; size_t insize = 0; char *wrptr; iconv_t cd; size_t avail; insize=ucslen(inbuf)*2; avail=insize+4; outbuf=(char*)malloc(avail); wrptr = (char *) outbuf; cd = iconv_open (USER_CODING, "UCS-2"); if (cd == (iconv_t) -1) { /* Something went wrong. */ perror ("error in iconv_open"); /* Terminate the output string. */ *outbuf = '\0'; return outbuf; } size_t nconv; char *inptr = inbuf; #ifdef ICONV_CONST_CHAR nconv = iconv (cd, (const char **)&inptr, &insize, &wrptr, &avail); #else nconv = iconv (cd, &inptr, &insize, &wrptr, &avail); #endif if (nconv == (size_t) -1) { printf("conv_to_user_coding: error in iconv\n"); } /* Terminate the output string. */ *(wrptr) = '\0'; if (nconv == (size_t) -1) { printf("wrptr='%s'\n",wrptr); } if (iconv_close (cd) != 0) perror ("iconv_close"); return outbuf; } char *conv_to_ucs(char *inbuf) { char *outbuf; size_t insize = 0; char *wrptr; iconv_t cd; size_t avail; insize=charstring::length(inbuf); avail=insize*2+4; outbuf=(char*)malloc(avail); wrptr = (char *) outbuf; cd = iconv_open ("UCS-2", USER_CODING); if(cd == (iconv_t) -1) { /* Something went wrong. */ perror ("error in iconv_open"); /* Terminate the output string. */ *outbuf = L'\0'; return outbuf; } size_t nconv; char *inptr = inbuf; #ifdef ICONV_CONST_CHAR nconv = iconv (cd, (const char **)&inptr, &insize, &wrptr, &avail); #else nconv = iconv (cd, &inptr, &insize, &wrptr, &avail); #endif if (nconv == (size_t) -1) { printf("conv_to_ucs: error in iconv\n"); } /* Terminate the output string. */ *((wchar_t *) wrptr) = L'\0'; if (nconv == (size_t) -1) { printf("inbuf='%s'\n",inbuf); } if (iconv_close (cd) != 0) perror ("error in iconv_close"); // FILE *ff; // char fname[200]; // sprintf(fname,"/home/orbb/temp/result_conv_to_ucs.txt_%d",charstring::length(inbuf)); // ff=fopen(fname,"wb"); // fwrite(outbuf,1,wrptr-outbuf,ff); // fclose(ff); return outbuf; } //orbb uint16_t odbcconnection::getNumberOfConnectStringVars() { return NUM_CONNECT_STRING_VARS; } void odbcconnection::handleConnectString() { dsn=connectStringValue("dsn"); setUser(connectStringValue("user")); setPassword(connectStringValue("password")); const char *autocom=connectStringValue("autocommit"); setAutoCommitBehavior((autocom && !charstring::compareIgnoringCase(autocom,"yes"))); } bool odbcconnection::logIn(bool printerrors) { // allocate environment handle #if (ODBCVER >= 0x0300) erg=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&env); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { SQLFreeHandle(SQL_HANDLE_ENV,env); return false; } erg=SQLSetEnvAttr(env,SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3,0); #else erg=SQLAllocEnv(&env); #endif if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { #if (ODBCVER >= 0x0300) SQLFreeHandle(SQL_HANDLE_ENV,env); #else SQLFreeEnv(env); #endif return false; } // allocate connection handle #if (ODBCVER >= 0x0300) erg=SQLAllocHandle(SQL_HANDLE_DBC,env,&dbc); #else erg=SQLAllocConnect(env,&dbc); #endif if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { #if (ODBCVER >= 0x0300) SQLFreeHandle(SQL_HANDLE_ENV,env); SQLFreeHandle(SQL_HANDLE_DBC,dbc); #else SQLFreeConnect(dbc); SQLFreeEnv(env); #endif return false; } // set the connect timeout #if (ODBCVER >= 0x0300) SQLSetConnectAttr(dbc,SQL_LOGIN_TIMEOUT,(SQLPOINTER *)5,0); #endif // connect to the database // erg=SQLConnect(dbc,(SQLCHAR *)dsn,SQL_NTS, // (SQLCHAR *)getUser(),SQL_NTS, // (SQLCHAR *)getPassword(),SQL_NTS); //orbb //orbb char *user_asc=(char*)getUser(); char *password_asc=(char*)getPassword(); char *dsn_asc=(char*)dsn; char *user_ucs=(char*)conv_to_ucs(user_asc); char *password_ucs=(char*)conv_to_ucs(password_asc); char *dsn_ucs=(char*)conv_to_ucs(dsn_asc); erg=SQLConnectW(dbc,(SQLWCHAR *)dsn_ucs,SQL_NTS, (SQLWCHAR *)user_ucs,SQL_NTS, (SQLWCHAR *)password_ucs,SQL_NTS); if(user_ucs)free(user_ucs); if(password_ucs)free(password_ucs); if(dsn_ucs)free(dsn_ucs); //orbb if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { #if (ODBCVER >= 0x0300) SQLFreeHandle(SQL_HANDLE_ENV,env); SQLFreeHandle(SQL_HANDLE_DBC,dbc); #else SQLFreeConnect(dbc); SQLFreeEnv(env); #endif return false; } return true; } sqlrcursor_svr *odbcconnection::initCursor() { return (sqlrcursor_svr *)new odbccursor((sqlrconnection_svr *)this); } void odbcconnection::deleteCursor(sqlrcursor_svr *curs) { delete (odbccursor *)curs; } void odbcconnection::logOut() { SQLDisconnect(dbc); #if (ODBCVER >= 0x0300) SQLFreeHandle(SQL_HANDLE_DBC,dbc); SQLFreeHandle(SQL_HANDLE_ENV,env); #else SQLFreeConnect(dbc); SQLFreeEnv(env); #endif } bool odbcconnection::ping() { return true; } const char *odbcconnection::identify() { return "odbc"; } #if (ODBCVER >= 0x0300) bool odbcconnection::autoCommitOn() { return (SQLSetConnectAttr(dbc,SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, sizeof(SQLINTEGER))==SQL_SUCCESS); } bool odbcconnection::autoCommitOff() { return (SQLSetConnectAttr(dbc,SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, sizeof(SQLINTEGER))==SQL_SUCCESS); } bool odbcconnection::commit() { return (SQLEndTran(SQL_HANDLE_ENV,env,SQL_COMMIT)==SQL_SUCCESS); } bool odbcconnection::rollback() { return (SQLEndTran(SQL_HANDLE_ENV,env,SQL_ROLLBACK)==SQL_SUCCESS); } #endif odbccursor::odbccursor(sqlrconnection_svr *conn) : sqlrcursor_svr(conn) { errormsg=NULL; odbcconn=(odbcconnection *)conn; stmt=NULL; } odbccursor::~odbccursor() { if (errormsg) { delete errormsg; } } bool odbccursor::prepareQuery(const char *query, uint32_t length) { if (stmt) { #if (ODBCVER >= 0x0300) SQLFreeHandle(SQL_HANDLE_STMT,stmt); #else SQLFreeStmt(stmt,SQL_DROP); #endif } // allocate the cursor #if (ODBCVER >= 0x0300) erg=SQLAllocHandle(SQL_HANDLE_STMT,odbcconn->dbc,&stmt); #else erg=SQLAllocStmt(odbcconn->dbc,&stmt); #endif if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // this code is here in case unixodbc or iodbc ever // successfully support array fetches /*#if (ODBCVER >= 0x0300) // set the row array size erg=SQLSetStmtAttr(stmt,SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)FETCH_AT_ONCE,0); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } #endif*/ // prepare the query // erg=SQLPrepare(stmt,(SQLCHAR *)query,length); //orbb //free allocated buffers while(nextbuf>0) { nextbuf--; if(buffers[nextbuf])free(buffers[nextbuf]); } char *query_ucs=conv_to_ucs((char*)query); erg=SQLPrepareW(stmt,(SQLWCHAR *)query_ucs,SQL_NTS); if(query_ucs)free(query_ucs); //orbb if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::inputBindString(const char *variable, uint16_t variablesize, const char *value, uint16_t valuesize, short *isnull) { //orbb char *value_ucs=conv_to_ucs((char*)value); valuesize=ucslen(value_ucs)*2; buffers[nextbuf]=value_ucs; nextbuf++; //orbb if (*isnull==SQL_NULL_DATA) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_INPUT, SQL_C_WCHAR,//orbb SQL_CHAR, 0, 0, (SQLPOINTER)value_ucs, //orbb valuesize, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)isnull #else (SQLINTEGER *)isnull #endif ); } else { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_INPUT, SQL_C_WCHAR,//orbb SQL_CHAR, 0, 0, (SQLPOINTER)value_ucs, //orbb valuesize, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)NULL #else (SQLINTEGER *)NULL #endif ); } if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::inputBindInteger(const char *variable, uint16_t variablesize, int64_t *value) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, value, sizeof(int64_t), #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)NULL #else (SQLINTEGER *)NULL #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::inputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t precision, uint32_t scale) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DECIMAL, precision, scale, value, sizeof(double), #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)NULL #else (SQLINTEGER *)NULL #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::outputBindString(const char *variable, uint16_t variablesize, const char *value, uint16_t valuesize, short *isnull) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)value, valuesize, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)isnull #else (SQLINTEGER *)isnull #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::outputBindInteger(const char *variable, uint16_t variablesize, int64_t *value, int16_t *isnull) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, value, sizeof(int64_t), #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)isnull #else (SQLINTEGER *)isnull #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } bool odbccursor::outputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t *precision, uint32_t *scale, int16_t *isnull) { erg=SQLBindParameter(stmt, charstring::toInteger(variable+1), SQL_PARAM_OUTPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, value, sizeof(double), #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)isnull #else (SQLINTEGER *)isnull #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } short odbccursor::nonNullBindValue() { return 0; } short odbccursor::nullBindValue() { return SQL_NULL_DATA; } bool odbccursor::bindValueIsNull(short isnull) { return (isnull==SQL_NULL_DATA); } bool odbccursor::executeQuery(const char *query, uint32_t length, bool execute) { // initialize counts ncols=0; row=0; maxrow=0; totalrows=0; // execute the query erg=SQLExecute(stmt); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO #if defined(SQL_NO_DATA) && erg!=SQL_NO_DATA #elif defined(SQL_NO_DATA_FOUND) && erg!=SQL_NO_DATA_FOUND #endif ) { return false; } checkForTempTable(query,length); // get the column count erg=SQLNumResultCols(stmt,&ncols); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } if (ncols>MAX_SELECT_LIST_SIZE) { ncols=MAX_SELECT_LIST_SIZE; } // run through the columns for (SQLSMALLINT i=0; isendColumnInfo()) { #if (ODBCVER >= 0x0300) // column name erg=SQLColAttribute(stmt,i+1,SQL_DESC_LABEL, col[i].name,MAX_ITEM_BUFFER_SIZE, (SQLSMALLINT *)&(col[i].namelength), #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)NULL #else NULL #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } //orbb col[i].namelength=charstring::length(col[i].name); //orbb // column length erg=SQLColAttribute(stmt,i+1,SQL_DESC_LENGTH, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].length) #else &(col[i].length) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column type erg=SQLColAttribute(stmt,i+1,SQL_DESC_TYPE, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].type) #else &(col[i].type) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column precision erg=SQLColAttribute(stmt,i+1,SQL_DESC_PRECISION, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].precision) #else &(col[i].precision) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column scale erg=SQLColAttribute(stmt,i+1,SQL_DESC_SCALE, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].scale) #else &(col[i].scale) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column nullable erg=SQLColAttribute(stmt,i+1,SQL_DESC_NULLABLE, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].nullable) #else &(col[i].nullable) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // primary key // unique // part of key // unsigned number erg=SQLColAttribute(stmt,i+1,SQL_DESC_UNSIGNED, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].unsignednumber) #else &(col[i].unsignednumber) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // zero fill // binary // autoincrement erg=SQLColAttribute(stmt,i+1,SQL_DESC_AUTO_UNIQUE_VALUE, NULL,0,NULL, #ifdef SQLCOLATTRIBUTE_SQLLEN (SQLLEN *)&(col[i].autoincrement) #else &(col[i].autoincrement) #endif ); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } #else // column name erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_LABEL, col[i].name,MAX_ITEM_BUFFER_SIZE, (SQLSMALLINT *)&(col[i].namelength), NULL); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column length erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_LENGTH, NULL,0,NULL, (SQLINTEGER *)&(col[i].length)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column type erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_TYPE, NULL,0,NULL, (SQLINTEGER *)&(col[i].type)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column precision erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_PRECISION, NULL,0,NULL, (SQLINTEGER *)&(col[i].precision)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column scale erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_SCALE, NULL,0,NULL, (SQLINTEGER *)&(col[i].scale)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // column nullable erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_NULLABLE, NULL,0,NULL, (SQLINTEGER *)&(col[i].nullable)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // primary key // unique // part of key // unsigned number erg=SQLColAttributes(stmt,i+1,SQL_COLUMN_UNSIGNED, NULL,0,NULL, (SQLINTEGER *)&(col[i].unsignednumber)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } // zero fill // binary // autoincrement #ifdef SQL_DESC_AUTO_UNIQUE_VALUE erg=SQLColAttributes(stmt,i+1, SQL_COLUMN_AUTO_UNIQUE_VALUE, NULL,0,NULL, (SQLINTEGER *)&(col[i].autoincrement)); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } #else col[i].autoincrement=0; #endif #endif } // bind the column to a buffer // erg=SQLBindCol(stmt,i+1,SQL_C_CHAR, // field[i],MAX_ITEM_BUFFER_SIZE, // #ifdef SQLBINDPARAMETER_SQLLEN // (SQLLEN *)&indicator[i] // #else // (SQLINTEGER *)&indicator[i] // #endif // ); //orbb if(col[i].type==-9 || col[i].type==-8) { //bind varchar and char fields as wchar // bind the column to a buffer // erg=SQLBindCol(stmt,i+1,SQL_C_WCHAR, // field[i],MAX_ITEM_BUFFER_SIZE, // (SQLINTEGER *)&indicator[i]); erg=SQLBindCol(stmt,i+1,SQL_C_WCHAR, field[i],MAX_ITEM_BUFFER_SIZE, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)&indicator[i] #else (SQLINTEGER *)&indicator[i] #endif ); } else { // bind the column to a buffer if(col[i].type==93 || col[i].type==91) { // erg=SQLBindCol(stmt,i+1,SQL_C_BINARY, // field[i],MAX_ITEM_BUFFER_SIZE, // (SQLINTEGER *)&indicator[i]); erg=SQLBindCol(stmt,i+1,SQL_C_BINARY, field[i],MAX_ITEM_BUFFER_SIZE, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)&indicator[i] #else (SQLINTEGER *)&indicator[i] #endif ); } else { // erg=SQLBindCol(stmt,i+1,SQL_C_CHAR, // field[i],MAX_ITEM_BUFFER_SIZE, // (SQLINTEGER *)&indicator[i]); erg=SQLBindCol(stmt,i+1,SQL_C_CHAR, field[i],MAX_ITEM_BUFFER_SIZE, #ifdef SQLBINDPARAMETER_SQLLEN (SQLLEN *)&indicator[i] #else (SQLINTEGER *)&indicator[i] #endif ); } } //orbb if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } } // get the row count #ifdef SQLROWCOUNT_SQLLEN erg=SQLRowCount(stmt,(SQLLEN *)&affectedrows); #else erg=SQLRowCount(stmt,&affectedrows); #endif if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } return true; } const char *odbccursor::errorMessage(bool *liveconnection) { SQLCHAR error[501]; SQLCHAR state[10]; SQLINTEGER nativeerrnum; SQLSMALLINT errnum; // need to use SQLGetDiagRec and SQLGetDiagField here... SQLError(odbcconn->env,odbcconn->dbc,stmt,state,&nativeerrnum, error,500,&errnum); if (errormsg) { delete errormsg; } errormsg=new stringbuffer(); errormsg->append((const char *)error); *liveconnection=true; return errormsg->getString(); } bool odbccursor::knowsRowCount() { return false; } uint64_t odbccursor::rowCount() { return 0; } bool odbccursor::knowsAffectedRows() { return true; } uint64_t odbccursor::affectedRows() { return affectedrows; } uint32_t odbccursor::colCount() { return ncols; } const char * const * odbccursor::columnNames() { for (SQLSMALLINT i=0; isendColumnDefinition(col[i].name,col[i].namelength,type, col[i].length,col[i].precision, col[i].scale,col[i].nullable, 0,0,0, col[i].unsignednumber,0,binary, col[i].autoincrement); } } bool odbccursor::noRowsToReturn() { // if there are no columns, then there can't be any rows either return (!ncols); } bool odbccursor::skipRow() { return fetchRow(); } bool odbccursor::fetchRow() { // this code is here in case unixodbc ever // successfully supports array fetches /*#if (ODBCVER >= 0x0300) if (row==FETCH_AT_ONCE) { row=0; } if (row>0 && row==maxrow) { return false; } if (!row) { erg=SQLFetchScroll(stmt,SQL_FETCH_NEXT,0); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } SQLGetStmtAttr(stmt,SQL_ATTR_ROW_NUMBER, (SQLPOINTER)&rownumber,0,NULL); if (rownumber==totalrows) { return false; } maxrow=rownumber-totalrows; totalrows=rownumber; } return true; #else*/ erg=SQLFetch(stmt); if (erg!=SQL_SUCCESS && erg!=SQL_SUCCESS_WITH_INFO) { return false; } //orbb //convert char and varchar data to user coding from ucs-2 for (int i=0; i= 0x0300) for (SQLSMALLINT index=0; indexsendNullField(); continue; } // handle a non-null field conn->sendField(field[index][row],indicator[index][row]); } row++; #else*/ for (SQLSMALLINT index=0; indexsendNullField(); continue; } // handle a non-null field conn->sendField(field[index],indicator[index]); } //#endif }