![]() |
Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members
Query.cppGo to the documentation of this file.00001 /* 00002 ** Query.cpp 00003 ** 00004 ** Published / author: 2006-03-29 / grymse@alhem.net 00005 **/ 00006 /* 00007 Copyright (C) 2006 Anders Hedstrom 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License 00011 as published by the Free Software Foundation; either version 2 00012 of the License, or (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 */ 00023 #ifdef _WIN32 00024 #pragma warning(disable:4786) 00025 #endif 00026 00027 #ifdef _WIN32 00028 #include <afxdb.h> 00029 #include <sql.h> 00030 #endif 00031 00032 #include "Query.h" 00033 #include "Database.h" 00034 #include "IError.h" 00035 #include "Session.h" 00036 00037 00038 #ifdef ODBCW_NAMESPACE 00039 namespace ODBCW_NAMESPACE { 00040 #endif 00041 00042 00043 Query::Query(Database& dbin) 00044 :m_db(dbin) 00045 ,m_odb(m_db.grabdb()) 00046 ,m_hstmt(NULL) 00047 ,m_hres(NULL) 00048 ,m_currentcolumn(0) 00049 ,m_results(0) 00050 ,m_fetchrows(0) 00051 ,m_qcols(0) 00052 ,m_currentcol(0) 00053 { 00054 } 00055 00056 00057 Query::Query(Database& dbin,const std::string& sql) 00058 :m_db(dbin) 00059 ,m_odb(m_db.grabdb()) 00060 ,m_hstmt(NULL) 00061 ,m_hres(NULL) 00062 ,m_currentcolumn(0) 00063 ,m_results(0) 00064 ,m_fetchrows(0) 00065 ,m_qcols(0) 00066 ,m_currentcol(0) 00067 { 00068 execute(sql); 00069 } 00070 00071 00072 Query::~Query() 00073 { 00074 if (m_hstmt) 00075 { 00076 SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); 00077 } 00078 if (m_hres) 00079 { 00080 delete m_hres; 00081 } 00082 if (m_odb) 00083 { 00084 m_db.freedb(m_odb); 00085 } 00086 } 00087 00088 00089 short Query::execute(const std::string& sql) // query, no result 00090 { 00091 SQLRETURN retcode; 00092 m_last_query = sql; 00093 if (m_odb && m_hres) 00094 { 00095 error("Query::execute(): Query busy"); 00096 } 00097 if (m_odb && !m_hres) 00098 { 00099 m_results = 0; 00100 m_fetchrows = 0; 00101 m_qcols = 0; 00102 m_currentcol = 0; 00103 00104 // Free statement handle 00105 if (m_hstmt) 00106 { 00107 SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); 00108 } 00109 00110 // Allocate statement handle (STMT) 00111 retcode = SQLAllocHandle(SQL_HANDLE_STMT, static_cast<SQLHDBC>(m_odb -> GetHandle()), &m_hstmt); 00112 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 00113 { 00114 error("Query::execute(): Allocate statement handle (STMT) failed"); 00115 return 0; // 0 failed 00116 } 00117 00118 retcode = SQLExecDirect(m_hstmt, (unsigned char *)sql.c_str(), sql.size()); 00119 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) 00120 { 00121 Session *tmp = dynamic_cast<Session *>(m_odb); 00122 if (tmp) 00123 { 00124 tmp -> ShowErrorInfo(retcode, SQL_HANDLE_STMT, m_hstmt); 00125 } 00126 } 00127 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 00128 { 00129 error("Query::execute(): SQL Query failed:"); 00130 error(sql); 00131 return 0; // 0 failed 00132 } 00133 m_results = num_rows(); 00134 return 1; 00135 } 00136 return 0; 00137 } 00138 00139 00140 bool Query::get_result(const std::string& sql,char **attrs) 00141 { 00142 UNUSED_ALWAYS(attrs); 00143 if (m_odb && m_hres) 00144 { 00145 error("Query::get_result(): Query busy"); 00146 } 00147 if (m_odb && !m_hres) 00148 { 00149 if (execute(sql)) 00150 { 00151 return odbc_store_result(); 00152 } 00153 else 00154 { 00155 error("Query::get_result(): Query failed"); 00156 } 00157 } 00158 return false; 00159 } 00160 00161 00162 void Query::free_result() 00163 { 00164 if (m_odb && m_hres) 00165 { 00166 delete m_hres; 00167 m_hres = NULL; 00168 } 00169 while (m_nmap.size()) 00170 { 00171 std::map<std::string,int>::iterator it = m_nmap.begin(); 00172 m_nmap.erase(it); 00173 } 00174 } 00175 00176 00177 bool Query::get_result(SQLSMALLINT func) 00178 { 00179 if (m_odb && m_hres) 00180 { 00181 error("Query::get_result(): Query busy"); 00182 } 00183 if (m_odb && !m_hres) 00184 { 00185 SQLRETURN retcode = SQL_ERROR; 00186 bool result = false; 00187 00188 m_results = 0; 00189 m_fetchrows = 0; 00190 m_qcols = 0; 00191 m_currentcol = 0; 00192 00193 // Free statement handle 00194 if (m_hstmt) 00195 { 00196 SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); 00197 } 00198 00199 // Allocate statement handle (STMT) 00200 retcode = SQLAllocHandle(SQL_HANDLE_STMT, static_cast<SQLHDBC>(m_odb -> GetHandle()), &m_hstmt); 00201 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 00202 { 00203 error("Query::execute(): Allocate statement handle (STMT) failed"); 00204 return 0; // 0 failed 00205 } 00206 00207 switch (func) 00208 { 00209 case SQLGET_CATALOGS: 00210 retcode = SQLTables(m_hstmt, // catalogs, schemas, tables, table types 00211 (unsigned char *)SQL_ALL_CATALOGS, SQL_NTS, 00212 (unsigned char *)NULL, 0, 00213 (unsigned char *)NULL, 0, 00214 (unsigned char *)NULL, 0 00215 ); 00216 break; 00217 case SQLGET_SCHEMAS: 00218 retcode = SQLTables(m_hstmt, // catalogs, schemas, tables, table types 00219 (unsigned char *)NULL, 0, 00220 (unsigned char *)SQL_ALL_SCHEMAS, SQL_NTS, 00221 (unsigned char *)NULL, 0, 00222 (unsigned char *)NULL, 0 00223 ); 00224 break; 00225 case SQLGET_TABLES: 00226 retcode = SQLTables(m_hstmt, // catalogs, schemas, tables, table types 00227 (unsigned char *)SQL_ALL_CATALOGS, SQL_NTS, 00228 (unsigned char *)NULL, 0, 00229 (unsigned char *)"%%", SQL_NTS, // TODO: single %? 00230 (unsigned char *)"TABLE", 5 00231 ); 00232 break; 00233 case SQLGET_VIEWS: 00234 retcode = SQLTables(m_hstmt, // catalogs, schemas, tables, table types 00235 (unsigned char *)SQL_ALL_CATALOGS, SQL_NTS, 00236 (unsigned char *)NULL, 0, 00237 (unsigned char *)"%%", SQL_NTS, // TODO: single %? 00238 (unsigned char *)"VIEW", 4 00239 ); 00240 break; 00241 case SQLGET_TABLETYPES: 00242 retcode = SQLTables(m_hstmt, // catalogs, schemas, tables, table types 00243 (unsigned char *)"", 0, 00244 (unsigned char *)"", 0, 00245 (unsigned char *)"", 0, 00246 (unsigned char *)SQL_ALL_TABLE_TYPES, SQL_NTS 00247 ); 00248 break; 00249 } 00250 00251 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) 00252 { 00253 Session *tmp = dynamic_cast<Session *>(m_odb); 00254 if (tmp) 00255 { 00256 tmp -> ShowErrorInfo(retcode, SQL_HANDLE_STMT, m_hstmt); 00257 } 00258 } 00259 if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 00260 { 00261 result = true; 00262 } 00263 else 00264 { 00265 } 00266 00267 if (result) 00268 { 00269 return odbc_store_result(); 00270 } 00271 else 00272 { 00273 error("Query::get_result(): Query failed"); 00274 } 00275 } 00276 return false; 00277 } 00278 00279 00280 bool Query::get_result(SQLSMALLINT func, const std::string& catalog, const std::string& schema, const std::string& tablename) 00281 { 00282 if (m_odb && m_hres) 00283 { 00284 error("Query::get_result(): Query busy"); 00285 } 00286 if (m_odb && !m_hres) 00287 { 00288 SQLRETURN retcode = SQL_ERROR; 00289 bool result = false; 00290 00291 m_results = 0; 00292 m_fetchrows = 0; 00293 m_qcols = 0; 00294 m_currentcol = 0; 00295 00296 // Free statement handle 00297 if (m_hstmt) 00298 { 00299 SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); 00300 } 00301 00302 // Allocate statement handle (STMT) 00303 retcode = SQLAllocHandle(SQL_HANDLE_STMT, static_cast<SQLHDBC>(m_odb -> GetHandle()), &m_hstmt); 00304 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 00305 { 00306 error("Query::execute(): Allocate statement handle (STMT) failed"); 00307 return 0; // 0 failed 00308 } 00309 00310 switch (func) 00311 { 00312 case SQLGET_COLUMNS: 00313 retcode = SQLColumns(m_hstmt, 00314 (unsigned char *) (catalog.size() ? catalog.c_str() : NULL), (SQLSMALLINT) (catalog.size() ? SQL_NTS : 0), 00315 (unsigned char *) (schema.size() ? schema.c_str() : NULL), (SQLSMALLINT) (schema.size() ? SQL_NTS : 0), 00316 (unsigned char *)tablename.c_str(), (SQLSMALLINT)SQL_NTS, 00317 (unsigned char *)NULL, (SQLSMALLINT)0); 00318 break; 00319 case SQLGET_SPECIALCOLUMNS: 00320 retcode = SQLSpecialColumns(m_hstmt, 00321 SQL_BEST_ROWID, // SQL_ROWVER, 00322 (unsigned char *) (catalog.size() ? catalog.c_str() : NULL), (SQLSMALLINT) (catalog.size() ? SQL_NTS : 0), 00323 (unsigned char *) (schema.size() ? schema.c_str() : NULL), (SQLSMALLINT) (schema.size() ? SQL_NTS : 0), 00324 (unsigned char *)tablename.c_str(), (SQLSMALLINT)SQL_NTS, 00325 SQL_SCOPE_TRANSACTION, // SQL_SCOPE_SESSION, 00326 SQL_NULLABLE); 00327 break; 00328 case SQLGET_PRIMARYKEYS: 00329 retcode = SQLPrimaryKeys(m_hstmt, 00330 (unsigned char *) (catalog.size() ? catalog.c_str() : NULL), (SQLSMALLINT) (catalog.size() ? SQL_NTS : 0), 00331 (unsigned char *) (schema.size() ? schema.c_str() : NULL), (SQLSMALLINT) (schema.size() ? SQL_NTS : 0), 00332 (unsigned char *)tablename.c_str(), (SQLSMALLINT)SQL_NTS 00333 ); 00334 break; 00335 } 00336 00337 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) 00338 { 00339 Session *tmp = dynamic_cast<Session *>(m_odb); 00340 if (tmp) 00341 { 00342 tmp -> ShowErrorInfo(retcode, SQL_HANDLE_STMT, m_hstmt); 00343 } 00344 } 00345 if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 00346 { 00347 result = true; 00348 } 00349 else 00350 { 00351 } 00352 00353 if (result) 00354 { 00355 return odbc_store_result(); 00356 } 00357 else 00358 { 00359 error("Query::get_result(): Query failed"); 00360 } 00361 } 00362 return false; 00363 } 00364 00365 00366 bool Query::fetch_row() 00367 { 00368 m_currentcolumn = 0; // ODBC columns start at 1 00369 m_fetchrows++; 00370 if (m_odb && m_hstmt && m_hres) 00371 { 00372 SQLRETURN retcode = SQLFetch(m_hstmt); 00373 if (retcode == SQL_SUCCESS) 00374 { 00375 return true; 00376 } 00377 } 00378 return false; 00379 } 00380 00381 00382 long Query::insert_id() 00383 { 00384 return -1; 00385 } 00386 00387 00388 long Query::num_rows() 00389 { 00390 SQLINTEGER rowCount; 00391 00392 if (m_hstmt) 00393 { 00394 SQLRETURN retcode = SQLRowCount(m_hstmt, &rowCount); 00395 if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 00396 { 00397 } 00398 } 00399 else 00400 { 00401 rowCount = -1; 00402 } 00403 return rowCount; 00404 } 00405 00406 00407 bool Query::is_null(int x) 00408 { 00409 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00410 { 00411 SQLHCOL *col = m_hres -> m_cols[x + 1]; 00412 if (col -> cbBuffer == SQL_NULL_DATA) 00413 return true; 00414 } 00415 return false; 00416 } 00417 00418 00419 bool Query::is_null() 00420 { 00421 return is_null(m_currentcolumn++); 00422 } 00423 00424 00425 bool Query::is_null(const std::string& x) 00426 { 00427 int index = m_nmap[x] - 1; 00428 if (index >= 0) 00429 return is_null(index); 00430 error("Column name lookup failure: " + x); 00431 return false; 00432 } 00433 00434 00435 const char *Query::getstr(int x) 00436 { 00437 SQLHCOL *col; 00438 char slask[80]; // sprintf format 00439 00440 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00441 { 00442 col = m_hres -> m_cols[x + 1]; 00443 if (col -> nCType == SQL_C_CHAR && !strcmp(col -> szTypeName,"SQL_DECIMAL")) 00444 { 00445 double d = atof(col -> buffer -> String); 00446 char *s; 00447 if (!col -> tmpstr) 00448 { 00449 col -> tmpstr = new char[80]; 00450 } 00451 sprintf(slask,"%%%d.%df",col -> nColumnSizePtr,col -> nDecimalDigitsPtr); 00452 sprintf(col -> tmpstr, slask, d); 00453 if ((s = strstr(col -> tmpstr,".")) != NULL) 00454 { 00455 *s = m_db.GetDecimalChar(); 00456 } 00457 return col -> tmpstr; 00458 } 00459 else 00460 switch (col -> nCType) 00461 { 00462 case SQL_C_CHAR: 00463 return col -> buffer -> String; 00464 case SQL_C_WCHAR: // unicode 00465 return col -> buffer -> String; 00466 // case SQL_C_TCHAR: 00467 // return col -> buffer -> String; 00468 case SQL_C_FLOAT: 00469 if (!col -> tmpstr) 00470 { 00471 col -> tmpstr = new char[80]; 00472 } 00473 sprintf(slask,"%%%d.%df",col -> nColumnSizePtr,col -> nDecimalDigitsPtr); 00474 sprintf(col -> tmpstr, slask, col -> buffer -> f); 00475 return col -> tmpstr; 00476 case SQL_C_DOUBLE: 00477 if (!col -> tmpstr) 00478 { 00479 col -> tmpstr = new char[80]; 00480 } 00481 sprintf(slask,"%%%d.%df",col -> nColumnSizePtr,col -> nDecimalDigitsPtr); 00482 sprintf(col -> tmpstr, slask, col -> buffer -> d); 00483 return col -> tmpstr; 00484 case SQL_C_BIT: 00485 if (!col -> tmpstr) 00486 { 00487 col -> tmpstr = new char[80]; 00488 } 00489 sprintf(col -> tmpstr,"%u",col -> buffer -> c & 1); 00490 return col -> tmpstr; 00491 case SQL_C_STINYINT: 00492 if (!col -> tmpstr) 00493 { 00494 col -> tmpstr = new char[20]; 00495 } 00496 sprintf(slask,"%%%dd",col -> nColumnSizePtr); 00497 sprintf(col -> tmpstr, slask, col -> buffer -> c); 00498 return col -> tmpstr; 00499 case SQL_C_SSHORT: 00500 if (!col -> tmpstr) 00501 { 00502 col -> tmpstr = new char[20]; 00503 } 00504 sprintf(slask,"%%%dd",col -> nColumnSizePtr); 00505 sprintf(col -> tmpstr, slask, col -> buffer -> s); 00506 return col -> tmpstr; 00507 case SQL_C_SLONG: 00508 if (!col -> tmpstr) 00509 { 00510 col -> tmpstr = new char[20]; 00511 } 00512 strcpy(slask,"%ld"); 00513 sprintf(col -> tmpstr, slask, col -> buffer -> l); 00514 return col -> tmpstr; 00515 case SQL_C_SBIGINT: // _int64 00516 if (!col -> tmpstr) 00517 { 00518 col -> tmpstr = new char[80]; 00519 } 00520 sprintf(slask,"%%%dI64d",col -> nColumnSizePtr); 00521 sprintf(col -> tmpstr, slask, col -> buffer -> bigint); 00522 return col -> tmpstr; 00523 case SQL_C_BINARY: 00524 return col -> buffer -> String; 00525 case SQL_C_TYPE_DATE: // SQL_DATE_STRUCT 00526 if (!col -> tmpstr) 00527 { 00528 col -> tmpstr = new char[20]; 00529 } 00530 sprintf(col -> tmpstr,"%d-%02d-%02d", 00531 col -> buffer -> date.year, 00532 col -> buffer -> date.month, 00533 col -> buffer -> date.day); 00534 return col -> tmpstr; 00535 case SQL_C_TYPE_TIME: 00536 if (!col -> tmpstr) 00537 { 00538 col -> tmpstr = new char[20]; 00539 } 00540 sprintf(col -> tmpstr,"%02d:%02d:%02d", 00541 col -> buffer -> time.hour, 00542 col -> buffer -> time.minute, 00543 col -> buffer -> time.second); 00544 return col -> tmpstr; 00545 case SQL_C_TYPE_TIMESTAMP: 00546 if (!col -> tmpstr) 00547 { 00548 col -> tmpstr = new char[80]; 00549 } 00550 sprintf(col -> tmpstr,"%d-%02d-%02d %02d:%02d:%02d", //.%u", 00551 col -> buffer -> timestamp.year, 00552 col -> buffer -> timestamp.month, 00553 col -> buffer -> timestamp.day, 00554 col -> buffer -> timestamp.hour, 00555 col -> buffer -> timestamp.minute, 00556 col -> buffer -> timestamp.second); 00557 return col -> tmpstr; 00558 00559 case SQL_INTERVAL_MONTH: 00560 case SQL_INTERVAL_YEAR: 00561 case SQL_INTERVAL_YEAR_TO_MONTH: 00562 case SQL_INTERVAL_DAY: 00563 case SQL_INTERVAL_HOUR: 00564 case SQL_INTERVAL_MINUTE: 00565 case SQL_INTERVAL_SECOND: 00566 case SQL_INTERVAL_DAY_TO_HOUR: 00567 case SQL_INTERVAL_DAY_TO_MINUTE: 00568 case SQL_INTERVAL_DAY_TO_SECOND: 00569 case SQL_INTERVAL_HOUR_TO_MINUTE: 00570 case SQL_INTERVAL_HOUR_TO_SECOND: 00571 case SQL_INTERVAL_MINUTE_TO_SECOND: 00572 break; 00573 00574 default: 00575 { 00576 char msg[200]; 00577 sprintf(msg, "Query::getstr(): Conversion not supported (%s)\n",col -> szTypeName); 00578 error(msg); 00579 } 00580 break; 00581 } 00582 } 00583 return NULL; 00584 } 00585 00586 00587 double Query::getnum(int x) 00588 { 00589 SQLHCOL *col; 00590 00591 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00592 { 00593 col = m_hres -> m_cols[x + 1]; 00594 switch (col -> nCType) 00595 { 00596 case SQL_C_FLOAT: 00597 return col -> buffer -> f; 00598 case SQL_C_DOUBLE: 00599 return col -> buffer -> d; 00600 case SQL_C_CHAR: 00601 if (!strcmp(col -> szTypeName,"SQL_DECIMAL")) 00602 { 00603 double d = atof(col -> buffer -> String); 00604 return d; 00605 } 00606 { 00607 char msg[200]; 00608 sprintf(msg, "Query::getnum(): Conversion not supported (%s)\n",col -> szTypeName); 00609 error(msg); 00610 } 00611 break; 00612 00613 default: 00614 { 00615 char msg[200]; 00616 sprintf(msg, "Query::getnum(): Conversion not supported (%s)\n",col -> szTypeName); 00617 error(msg); 00618 } 00619 break; 00620 } 00621 } 00622 return 0; 00623 } 00624 00625 00626 long Query::getval(int x) 00627 { 00628 SQLHCOL *col; 00629 long l; 00630 00631 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00632 { 00633 col = m_hres -> m_cols[x + 1]; 00634 switch (col -> nCType) 00635 { 00636 case SQL_C_BIT: 00637 return col -> buffer -> c & 1; 00638 case SQL_C_STINYINT: 00639 return col -> buffer -> c; 00640 case SQL_C_SSHORT: 00641 return col -> buffer -> s; 00642 case SQL_C_SLONG: 00643 return col -> buffer -> l; 00644 case SQL_C_SBIGINT: 00645 l = (long)col -> buffer -> bigint; 00646 return static_cast<long>(col -> buffer -> bigint); 00647 00648 default: 00649 { 00650 char msg[200]; 00651 sprintf(msg, "Query::getval(): Conversion not supported (%s)\n",col -> szTypeName); 00652 error(msg); 00653 } 00654 break; 00655 } 00656 } 00657 return 0L; 00658 } 00659 00660 00661 _int64 Query::getbigint(int x) 00662 { 00663 SQLHCOL *col; 00664 00665 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00666 { 00667 col = m_hres -> m_cols[x + 1]; 00668 switch (col -> nCType) 00669 { 00670 case SQL_C_SBIGINT: 00671 return col -> buffer -> bigint; 00672 00673 default: 00674 { 00675 char msg[200]; 00676 sprintf(msg, "Query::getbigint(): Conversion not supported (%s)\n",col -> szTypeName); 00677 error(msg); 00678 } 00679 break; 00680 } 00681 } 00682 return 0L; 00683 } 00684 00685 00686 SQL_INTERVAL_STRUCT *Query::getinterval(int x) 00687 { 00688 SQLHCOL *col; 00689 00690 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 00691 { 00692 col = m_hres -> m_cols[x + 1]; 00693 switch (col -> nCType) 00694 { 00695 case SQL_INTERVAL_MONTH: 00696 case SQL_INTERVAL_YEAR: 00697 case SQL_INTERVAL_YEAR_TO_MONTH: 00698 case SQL_INTERVAL_DAY: 00699 case SQL_INTERVAL_HOUR: 00700 case SQL_INTERVAL_MINUTE: 00701 case SQL_INTERVAL_SECOND: 00702 case SQL_INTERVAL_DAY_TO_HOUR: 00703 case SQL_INTERVAL_DAY_TO_MINUTE: 00704 case SQL_INTERVAL_DAY_TO_SECOND: 00705 case SQL_INTERVAL_HOUR_TO_MINUTE: 00706 case SQL_INTERVAL_HOUR_TO_SECOND: 00707 case SQL_INTERVAL_MINUTE_TO_SECOND: 00708 return &col -> buffer -> interval; 00709 00710 default: 00711 { 00712 char msg[200]; 00713 sprintf(msg, "Query::getinterval(): Conversion not supported (%s)\n",col -> szTypeName); 00714 error(msg); 00715 } 00716 break; 00717 } 00718 } 00719 return NULL; 00720 } 00721 00722 00723 const char *Query::getstr() 00724 { 00725 return getstr(m_currentcolumn++); 00726 } 00727 00728 00729 double Query::getnum() 00730 { 00731 return getnum(m_currentcolumn++); 00732 } 00733 00734 00735 long Query::getval() 00736 { 00737 return getval(m_currentcolumn++); 00738 } 00739 00740 00741 _int64 Query::getbigint() 00742 { 00743 return getbigint(m_currentcolumn++); 00744 } 00745 00746 00747 SQL_INTERVAL_STRUCT *Query::getinterval() 00748 { 00749 return getinterval(m_currentcolumn++); 00750 } 00751 00752 00753 const char *Query::getstr(const std::string& x) 00754 { 00755 int index = m_nmap[x] - 1; 00756 if (index >= 0) 00757 return getstr(index); 00758 error("Column name lookup failure: " + x); 00759 return ""; 00760 } 00761 00762 00763 double Query::getnum(const std::string& x) 00764 { 00765 int index = m_nmap[x] - 1; 00766 if (index >= 0) 00767 return getnum(index); 00768 error("Column name lookup failure: " + x); 00769 return 0; 00770 } 00771 00772 00773 long Query::getval(const std::string& x) 00774 { 00775 int index = m_nmap[x] - 1; 00776 if (index >= 0) 00777 return getval(index); 00778 error("Column name lookup failure: " + x); 00779 return 0; 00780 } 00781 00782 00783 _int64 Query::getbigint(const std::string& x) 00784 { 00785 int index = m_nmap[x] - 1; 00786 if (index >= 0) 00787 return getbigint(index); 00788 error("Column name lookup failure: " + x); 00789 return 0; 00790 } 00791 00792 00793 SQL_INTERVAL_STRUCT *Query::getinterval(const std::string& x) 00794 { 00795 int index = m_nmap[x] - 1; 00796 if (index >= 0) 00797 return getinterval(index); 00798 error("Column name lookup failure: " + x); 00799 return 0; 00800 } 00801 00802 00803 const char *Query::get_string(const std::string& sql) 00804 { 00805 m_tmpstr = ""; 00806 if (get_result(sql)) 00807 { 00808 if (fetch_row()) 00809 { 00810 m_tmpstr = getstr(); 00811 } 00812 free_result(); 00813 } 00814 return m_tmpstr.c_str(); 00815 } 00816 00817 00818 double Query::get_num(const std::string& sql) 00819 { 00820 double l = 0; 00821 00822 if (get_result(sql)) 00823 { 00824 if (fetch_row()) 00825 { 00826 l = getnum(); 00827 } 00828 free_result(); 00829 } 00830 return l; 00831 } 00832 00833 00834 long Query::get_count(const std::string& sql) 00835 { 00836 long l = 0; 00837 00838 if (get_result(sql)) 00839 { 00840 if (fetch_row()) 00841 { 00842 l = getval(); 00843 } 00844 free_result(); 00845 } 00846 return l; 00847 } 00848 00849 00850 bool Query::odbc_store_result() 00851 { 00852 SQLRETURN retcode; 00853 SQLHCOL *tmp; 00854 SQLSMALLINT q; 00855 long buf_len; 00856 00857 retcode = SQLNumResultCols(m_hstmt, &q); 00858 m_qcols = q; 00859 00860 m_hres = new DSQLHRES(q); 00861 00862 for (int i = 1; i <= m_hres -> m_num_cols; i++) 00863 { 00864 tmp = new SQLHCOL; 00865 retcode = SQLDescribeCol(m_hstmt, (SQLSMALLINT)i, tmp -> szColumnName, STR_LEN, 00866 &tmp -> nNameLengthPtr,&tmp -> nDataTypePtr,&tmp -> nColumnSizePtr, 00867 &tmp -> nDecimalDigitsPtr,&tmp -> nNullablePtr); 00868 m_nmap[ (char *)tmp -> szColumnName] = i; 00869 if (tmp -> nColumnSizePtr == 0x7fffffff) 00870 { 00871 buf_len = BUF_LEN; 00872 } 00873 else 00874 { 00875 buf_len = (tmp -> nColumnSizePtr > BUF_LEN ? tmp -> nColumnSizePtr : BUF_LEN) + 1; 00876 } 00877 tmp -> buffer = (SQLUNIONBUFFER *)new char[buf_len]; 00878 *tmp -> szTypeName = 0; 00879 switch (tmp -> nDataTypePtr) 00880 { 00881 case SQL_CHAR: 00882 strcpy(tmp -> szTypeName, "SQL_CHAR"); 00883 tmp -> nCType = SQL_C_TCHAR; // SQL_C_CHAR; 00884 break; 00885 case SQL_VARCHAR: 00886 strcpy(tmp -> szTypeName, "SQL_VARCHAR"); 00887 tmp -> nCType = SQL_C_TCHAR; // SQL_C_CHAR; 00888 break; 00889 case SQL_LONGVARCHAR: 00890 strcpy(tmp -> szTypeName, "SQL_LONGVARCHAR"); 00891 tmp -> nCType = SQL_C_TCHAR; // SQL_C_CHAR; 00892 break; 00893 case SQL_WCHAR: 00894 strcpy(tmp -> szTypeName, "SQL_WCHAR"); 00895 tmp -> nCType = SQL_C_TCHAR; // SQL_C_WCHAR; 00896 break; 00897 case SQL_WVARCHAR: 00898 strcpy(tmp -> szTypeName, "SQL_WVARCHAR"); 00899 tmp -> nCType = SQL_C_TCHAR; // SQL_C_WCHAR; 00900 break; 00901 case SQL_WLONGVARCHAR: 00902 strcpy(tmp -> szTypeName, "SQL_WLONGVARCHAR"); 00903 tmp -> nCType = SQL_C_TCHAR; // SQL_C_WCHAR; 00904 break; 00905 case SQL_DECIMAL: 00906 strcpy(tmp -> szTypeName, "SQL_DECIMAL"); 00907 tmp -> nCType = SQL_C_CHAR; 00908 break; 00909 case SQL_NUMERIC: 00910 strcpy(tmp -> szTypeName, "SQL_NUMERIC"); 00911 tmp -> nCType = SQL_C_CHAR; 00912 break; 00913 case SQL_SMALLINT: 00914 strcpy(tmp -> szTypeName, "SQL_SMALLINT"); 00915 tmp -> nCType = SQL_C_SSHORT; // SQL_C_USHORT 00916 break; 00917 case SQL_INTEGER: 00918 strcpy(tmp -> szTypeName, "SQL_INTEGER"); 00919 tmp -> nCType = SQL_C_SLONG; // SQL_C_ULONG 00920 break; 00921 case SQL_REAL: 00922 strcpy(tmp -> szTypeName, "SQL_REAL"); 00923 tmp -> nCType = SQL_C_FLOAT; 00924 break; 00925 case SQL_FLOAT: 00926 strcpy(tmp -> szTypeName, "SQL_FLOAT"); 00927 tmp -> nCType = SQL_C_DOUBLE; 00928 break; 00929 case SQL_DOUBLE: 00930 strcpy(tmp -> szTypeName, "SQL_DOUBLE"); 00931 tmp -> nCType = SQL_C_DOUBLE; 00932 break; 00933 case SQL_BIT: 00934 strcpy(tmp -> szTypeName, "SQL_BIT"); 00935 tmp -> nCType = SQL_C_BIT; 00936 break; 00937 case SQL_TINYINT: 00938 strcpy(tmp -> szTypeName, "SQL_TINYINT"); 00939 tmp -> nCType = SQL_C_STINYINT; // SQL_C_UTINYINT 00940 break; 00941 case SQL_BIGINT: 00942 strcpy(tmp -> szTypeName, "SQL_BIGINT"); 00943 tmp -> nCType = SQL_C_SBIGINT; // SQL_C_UBININT 00944 break; 00945 case SQL_BINARY: 00946 strcpy(tmp -> szTypeName, "SQL_BINARY"); 00947 tmp -> nCType = SQL_C_BINARY; 00948 break; 00949 case SQL_VARBINARY: 00950 strcpy(tmp -> szTypeName, "SQL_VARBINARY"); 00951 tmp -> nCType = SQL_C_BINARY; 00952 break; 00953 case SQL_LONGVARBINARY: 00954 strcpy(tmp -> szTypeName, "SQL_LONGVARBINARY"); 00955 tmp -> nCType = SQL_C_BINARY; 00956 break; 00957 case SQL_TYPE_DATE: 00958 strcpy(tmp -> szTypeName, "SQL_TYPE_DATE"); 00959 tmp -> nCType = SQL_C_TYPE_DATE; 00960 break; 00961 case SQL_TYPE_TIME: 00962 strcpy(tmp -> szTypeName, "SQL_TYPE_TIME"); 00963 tmp -> nCType = SQL_C_TYPE_TIME; 00964 break; 00965 case SQL_TYPE_TIMESTAMP: 00966 strcpy(tmp -> szTypeName, "SQL_TYPE_TIMESTAMP"); 00967 tmp -> nCType = SQL_C_TYPE_TIMESTAMP; 00968 break; 00969 case SQL_INTERVAL_MONTH: 00970 strcpy(tmp -> szTypeName, "SQL_INTERVAL_MONTH"); 00971 tmp -> nCType = SQL_C_INTERVAL_MONTH; 00972 break; 00973 case SQL_INTERVAL_YEAR: 00974 strcpy(tmp -> szTypeName, "SQL_INTERVAL_YEAR"); 00975 tmp -> nCType = SQL_C_INTERVAL_YEAR; 00976 break; 00977 case SQL_INTERVAL_YEAR_TO_MONTH: 00978 strcpy(tmp -> szTypeName, "SQL_INTERVAL_YEAR_TO_MONTH"); 00979 tmp -> nCType = SQL_C_INTERVAL_YEAR_TO_MONTH; 00980 break; 00981 case SQL_INTERVAL_DAY: 00982 strcpy(tmp -> szTypeName, "SQL_INTERVAL_DAY"); 00983 tmp -> nCType = SQL_C_INTERVAL_DAY; 00984 break; 00985 case SQL_INTERVAL_HOUR: 00986 strcpy(tmp -> szTypeName, "SQL_INTERVAL_HOUR"); 00987 tmp -> nCType = SQL_C_INTERVAL_HOUR; 00988 break; 00989 case SQL_INTERVAL_MINUTE: 00990 strcpy(tmp -> szTypeName, "SQL_INTERVAL_MINUTE"); 00991 tmp -> nCType = SQL_C_INTERVAL_MINUTE; 00992 break; 00993 case SQL_INTERVAL_SECOND: 00994 strcpy(tmp -> szTypeName, "SQL_INTERVAL_SECOND"); 00995 tmp -> nCType = SQL_C_INTERVAL_SECOND; 00996 break; 00997 case SQL_INTERVAL_DAY_TO_HOUR: 00998 strcpy(tmp -> szTypeName, "SQL_INTERVAL_DAY_TO_HOUR"); 00999 tmp -> nCType = SQL_C_INTERVAL_DAY_TO_HOUR; 01000 break; 01001 case SQL_INTERVAL_DAY_TO_MINUTE: 01002 strcpy(tmp -> szTypeName, "SQL_INTERVAL_DAY_TO_MINUTE"); 01003 tmp -> nCType = SQL_C_INTERVAL_DAY_TO_MINUTE; 01004 break; 01005 case SQL_INTERVAL_DAY_TO_SECOND: 01006 strcpy(tmp -> szTypeName, "SQL_INTERVAL_DAY_TO_SECOND"); 01007 tmp -> nCType = SQL_C_INTERVAL_DAY_TO_SECOND; 01008 break; 01009 case SQL_INTERVAL_HOUR_TO_MINUTE: 01010 strcpy(tmp -> szTypeName, "SQL_INTERVAL_HOUR_TO_MINUTE"); 01011 tmp -> nCType = SQL_C_INTERVAL_HOUR_TO_MINUTE; 01012 break; 01013 case SQL_INTERVAL_HOUR_TO_SECOND: 01014 strcpy(tmp -> szTypeName, "SQL_INTERVAL_HOUR_TO_SECOND"); 01015 tmp -> nCType = SQL_C_INTERVAL_HOUR_TO_SECOND; 01016 break; 01017 case SQL_INTERVAL_MINUTE_TO_SECOND: 01018 strcpy(tmp -> szTypeName, "SQL_INTERVAL_MINUTE_TO_SECOND"); 01019 tmp -> nCType = SQL_C_INTERVAL_MINUTE_TO_SECOND; 01020 break; 01021 case SQL_GUID: 01022 strcpy(tmp -> szTypeName, "SQL_GUID"); 01023 tmp -> nCType = SQL_C_CHAR; 01024 break; 01025 default: 01026 sprintf(tmp -> szTypeName, "<Unknown type id#%d>", tmp -> nDataTypePtr); 01027 tmp -> nCType = -1; 01028 error("Query::get_result(): Unknown result set column data type"); 01029 } 01030 memset(tmp -> buffer -> String, 0, buf_len); 01031 m_hres -> add_col(tmp); 01032 tmp -> cbBuffer = buf_len; 01033 tmp -> tmpstr = NULL; 01034 retcode = SQLBindCol(m_hstmt, (SQLSMALLINT)i, tmp -> nCType, (SQLPOINTER)tmp -> buffer, buf_len, &tmp -> cbBuffer); 01035 } 01036 return true; 01037 } 01038 01039 01040 bool Query::GetColumnInfo(short x,SQLHCOL& hc) 01041 { 01042 if (m_odb && m_hstmt && m_hres && x >= 0 && x < m_hres -> m_num_cols) 01043 { 01044 memmove(&hc, m_hres -> m_cols[x + 1], sizeof(SQLHCOL)); 01045 hc.next = NULL; 01046 hc.buffer = NULL; 01047 hc.tmpstr = NULL; 01048 return true; 01049 } 01050 return false; 01051 } 01052 01053 01054 bool Query::GotMore() 01055 { 01056 return (m_fetchrows < m_results) ? true : false; 01057 } 01058 01059 01060 DSQLHRES::DSQLHRES(int q) : m_num_cols((SQLSMALLINT)q) 01061 { 01062 m_colbase = NULL; 01063 m_cols = new SQLHCOL *[q + 1]; 01064 for (int i = 0; i <= q; i++) 01065 { 01066 m_cols[i] = NULL; 01067 } 01068 m_qcols = 0; 01069 } 01070 01071 01072 DSQLHRES::~DSQLHRES() 01073 { 01074 SQLHCOL *tmp; 01075 01076 while (m_colbase) 01077 { 01078 tmp = m_colbase -> next; 01079 // ta bort members i m_colbase 01080 delete m_colbase -> buffer; 01081 if (m_colbase -> tmpstr) 01082 { 01083 delete m_colbase -> tmpstr; 01084 } 01085 // ta bort m_colbase 01086 delete m_colbase; 01087 m_colbase = tmp; 01088 } 01089 delete m_cols; 01090 } 01091 01092 01093 void DSQLHRES::add_col(SQLHCOL *item) 01094 { 01095 SQLHCOL *q = m_colbase; 01096 01097 item -> next = NULL; 01098 if (!q) 01099 { 01100 m_colbase = item; 01101 } 01102 else 01103 { 01104 while (q -> next) 01105 { 01106 q = q -> next; 01107 } 01108 q -> next = item; 01109 } 01110 m_qcols++; 01111 m_cols[m_qcols] = item; 01112 } 01113 01114 01115 void Query::ReturnRowAsXML(std::string& xml,const std::string& strObjectName,long dwFlags) 01116 { 01117 SQLHCOL *col; 01118 std::string typ; 01119 std::string str; 01120 bool endtag = (dwFlags & DQ_XML_ENDTAG) ? true : false; 01121 bool cdata = (dwFlags & DQ_XML_CDATASTRINGS) ? true : false; 01122 bool typeinfo = (dwFlags & DQ_XML_TYPEINFO) ? true : false; 01123 bool append = (dwFlags & DQ_XML_APPEND) ? true : false; 01124 bool xmlbegin = (dwFlags & DQ_XML_BEGIN) ? true : false; 01125 bool xmlend = (dwFlags & DQ_XML_END) ? true : false; 01126 char slask[32000]; 01127 01128 if (m_odb && m_hstmt && m_hres) 01129 { 01130 if (!append) 01131 { 01132 xml = ""; 01133 } 01134 if (xmlbegin) 01135 { 01136 xml += "<xml version=\"1.0\" encoding=\"ISO-8859-1\">\n"; 01137 } 01138 if (strObjectName != "") 01139 { 01140 xml += "<"; 01141 xml += strObjectName; 01142 xml += ">\n"; 01143 } 01144 for (int x = 0; x < m_hres -> m_num_cols; x++) 01145 { 01146 col = m_hres -> m_cols[x + 1]; 01147 // xml'safe data std::string 01148 // --- 01149 if (typeinfo) 01150 { 01151 sprintf(slask," TYPE=\"%s\"", col -> szTypeName); 01152 typ = slask; 01153 } 01154 else 01155 { 01156 typ = ""; 01157 } 01158 if (!*getstr(x)) 01159 { 01160 sprintf(slask,"<%s%s/>", col -> szColumnName, typ); 01161 str = slask; 01162 } 01163 else 01164 if (cdata && (col -> nCType == SQL_C_CHAR || col -> nCType == SQL_C_TCHAR)) 01165 { 01166 sprintf(slask,"<%s%s><![CDATA[%s]]></%s>\n", col -> szColumnName, typ, m_db.xmlsafestr(getstr(x)), col -> szColumnName); 01167 str = slask; 01168 } 01169 else 01170 { 01171 sprintf(slask,"<%s%s>%s</%s>\n", col -> szColumnName, typ, m_db.xmlsafestr(getstr(x)), col -> szColumnName); 01172 str = slask; 01173 } 01174 xml += str; 01175 } 01176 if (endtag && strObjectName != "") 01177 { 01178 xml += "</"; 01179 xml += strObjectName; 01180 xml += ">\n"; 01181 } 01182 if (xmlend) 01183 { 01184 xml += "</xml>\n"; 01185 } 01186 } 01187 } 01188 01189 01190 int Query::num_cols() 01191 { 01192 return m_qcols; 01193 } 01194 01195 01196 bool Query::getcol(std::string& colname,std::string& coltype,int& width,int& dec,int& nullable) 01197 { 01198 return getcol(m_currentcol++, colname, coltype, width, dec, nullable); 01199 } 01200 01201 01202 bool Query::getcol(int x,std::string& colname,std::string& coltype,int& width,int& dec,int& nullable) 01203 { 01204 if (x < m_qcols) 01205 { 01206 SQLHCOL *col; 01207 01208 col = m_hres -> m_cols[x + 1]; 01209 colname = (char *)(col -> szColumnName); 01210 coltype = col -> szTypeName; 01211 width = col -> nColumnSizePtr; 01212 dec = col -> nDecimalDigitsPtr; 01213 nullable = col -> nNullablePtr; 01214 return true; 01215 } 01216 else 01217 { 01218 return false; 01219 } 01220 } 01221 01222 01223 void Query::error(const std::string& text) 01224 { 01225 if (m_db.GetErrHandler()) 01226 { 01227 m_db.GetErrHandler() -> error(m_db, *this, text); 01228 } 01229 } 01230 01231 01232 bool Query::Connected() 01233 { 01234 return true; // TODO: implement 01235 } 01236 01237 01238 Database& Query::GetDatabase() const 01239 { 01240 return m_db; 01241 } 01242 01243 01244 const std::string& Query::GetLastQuery() 01245 { 01246 return m_last_query; 01247 } 01248 01249 01250 const std::string& Query::GetError() 01251 { 01252 m_errtext = ""; 01253 if (m_odb) 01254 { 01255 m_odb->GetLastError(m_sql_state, m_errtext); 01256 } 01257 return m_errtext; 01258 } 01259 01260 01261 int Query::GetErrno() 01262 { 01263 if (m_odb) 01264 { 01265 return m_odb->GetLastError(m_sql_state, m_errtext); 01266 } 01267 return -1; 01268 } 01269 01270 01271 #ifdef ODBCW_NAMESPACE 01272 } // namespace ODBCW_NAMESPACE { 01273 #endif |