std::string GetAsString() const { SQLINTEGER Needed = 0; const unsigned BufSize = 256; char SmallBuff[BufSize] = { 0 }; RETCODE Ret = SQLGetData(Stmt.GetHolder().GetHandle(), static_cast<SQLUSMALLINT>(Index), SQL_C_CHAR, SmallBuff, BufSize, //reinterpret_cast for x64 reinterpret_cast<SQLLEN *>(&Needed)); if (TIODBC_SUCCESS_CODE(Ret)) return std::string(SmallBuff); if (Needed > 0) { SQLINTEGER Buff = Needed + 1; std::vector<char> Data(Buff, 0); Ret = SQLGetData(Stmt.GetHolder().GetHandle(), static_cast<SQLUSMALLINT>(Index), SQL_C_CHAR, reinterpret_cast<SQLTCHAR *>(&Data.front()), Buff, //reinterpret_cast for x64 reinterpret_cast<SQLLEN *>(&Needed)); if (TIODBC_SUCCESS_CODE(Ret)) return std::string(&Data[0], Data.size()); throw FieldException("Error get field", feErrorGetField); } return std::string(); }
bool statement::describe_cols() { RETCODE rc; SQLSMALLINT ncols; rc = SQLNumResultCols(stmt_h, &ncols); if (!TIODBC_SUCCESS_CODE(rc)) return false; std::vector<col_descr> cols_info; for (int i = 0; i < ncols; ++i) { col_descr col_info; rc = SQLDescribeCol(stmt_h, i + 1, col_info.name, sizeof(col_info.name), &col_info.name_len, &col_info.type, &col_info.col_size, &col_info.decimal_digits, &col_info.nullable); if (!TIODBC_SUCCESS_CODE(rc)) return false; cols_info.push_back(col_info); } m_cols.swap(cols_info); return true; }
// Get field as string _tstring field_impl::as_string() const { if (is_null_flag != -1) return str_buf; SQLLEN sz_needed = 0; SQLTCHAR small_buff[256]; RETCODE rc; // Try with small buffer is_null_flag = 0; rc = SQLGetData(stmt_h, col_num, SQL_C_TCHAR, small_buff, sizeof(small_buff), &sz_needed); if (TIODBC_SUCCESS_CODE(rc)) { if (sz_needed == SQL_NULL_DATA) { is_null_flag = 1; return _tstring(); } str_buf = sqltchar2ybstring(small_buff, ""); return str_buf; } else if (sz_needed > 0) { // A bigger buffer is needed SQLINTEGER sz_buff = sz_needed + 1; SQLTCHAR_buf buff(sz_buff); SQLGetData(stmt_h, col_num, SQL_C_TCHAR, buff.data, sz_buff, &sz_needed); str_buf = sqltchar2ybstring(buff.data, ""); return str_buf; } return _tstring(); // Empty }
// open a connection with a data_source bool connection::connect(const _tstring & _dsn, const _tstring & _user, const _tstring & _pass, int _timeout, bool _autocommit) { cleanup(); // Allocate handles b_own_handle = true; __allocate_handle(env_h, conn_h); if (_timeout != -1) { // Set connection timeout SQLSetConnectAttr(conn_h, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)(size_t)_timeout, 0); } b_autocommit = _autocommit; if (!b_autocommit) { // Set manual commit mode SQLSetConnectAttr(conn_h, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0); } // Connect! SQLTCHAR_buf s_dsn = ybstring2sqltchar(_dsn, ""), s_user = ybstring2sqltchar(_user, ""), s_pass = ybstring2sqltchar(_pass, ""); RETCODE rc = SQLConnect(conn_h, s_dsn.data, SQL_NTS, s_user.data, SQL_NTS, s_pass.data, SQL_NTS); if (TIODBC_SUCCESS_CODE(rc)) { b_connected = true; } return b_connected; }
// Get an error of an ODBC handle bool __get_error(SQLSMALLINT _handle_type, SQLHANDLE _handle, _tstring & _error_desc, _tstring & _status_code) { SQLTCHAR status_code[64], error_message[511]; SQLINTEGER i_native_error = 0; SQLSMALLINT total_bytes = 0; RETCODE rc; // Ask for info rc = SQLGetDiagRec( _handle_type, _handle, 1, status_code, &i_native_error, error_message, sizeof(error_message), &total_bytes); if (TIODBC_SUCCESS_CODE(rc)) { _status_code = sqltchar2ybstring(status_code, ""); _error_desc = sqltchar2ybstring(error_message, ""); return true; } _error_desc = _T("Can't get error message"); _status_code = _T("UNKNOWN"); return false; }
// Count columns of the result int statement::count_columns() const { SQLSMALLINT _total_cols; RETCODE rc; if (!is_open()) return -1; rc = SQLNumResultCols(stmt_h, &_total_cols); if (!TIODBC_SUCCESS_CODE(rc)) return -1; return _total_cols; }
T __get_data(HSTMT _stmt, int _col, SQLSMALLINT _ttype, const T &error_value, int &is_null_flag) { T tmp_storage; SQLLEN cb_needed = 0; RETCODE rc; rc = SQLGetData(_stmt, _col, _ttype, &tmp_storage, sizeof(tmp_storage), &cb_needed); if (!TIODBC_SUCCESS_CODE(rc) || cb_needed == SQL_NULL_DATA) { is_null_flag = 1; return error_value; } is_null_flag = 0; return tmp_storage; }
// Fetch next bool statement::fetch_next() { RETCODE rc; if (!is_open()) return false; if (b_col_info_needed) { b_col_info_needed = false; describe_cols(); } rc = SQLFetch(stmt_h); if (TIODBC_SUCCESS_CODE(rc)) return true; return false; }
// Used to create a statement (used automatically by the other functions) bool statement::open(connection & _conn) { RETCODE rc; // close previous one close(); // Allocate statement rc = SQLAllocHandle(SQL_HANDLE_STMT, _conn.native_dbc_handle(), &stmt_h); if (!TIODBC_SUCCESS_CODE(rc)) { stmt_h = NULL; b_open = false; return false; } b_open = true; return true; }
void __bind_param(HSTMT _stmt, int _parnum, SQLSMALLINT _ctype, SQLSMALLINT _sqltype, void * dst_buf, SQLLEN & StrLenOrInPoint, int sz = 0, int buf_sz = 0) { RETCODE rc = SQLBindParameter(_stmt, _parnum, SQL_PARAM_INPUT, _ctype, _sqltype, sz, 0, (SQLPOINTER *)dst_buf, buf_sz, &StrLenOrInPoint); if (!TIODBC_SUCCESS_CODE(rc)) throw bind_error(_parnum); }
// Prepare statement bool statement::prepare(connection & _conn, const _tstring & _stmt) { RETCODE rc; // Close previous close(); // open a new one if (!open(_conn)) return false; // Prepare statement SQLTCHAR_buf buff = ybstring2sqltchar(_stmt, ""); rc = SQLPrepare(stmt_h, buff.data, SQL_NTS); if (!TIODBC_SUCCESS_CODE(rc)) return false; return true; }
// Execute statement bool statement::execute() { RETCODE rc; if (!is_open()) return false; rc = SQLExecute(stmt_h); if (!TIODBC_SUCCESS_CODE(rc)) { if (rc == SQL_NEED_DATA) { SQLPOINTER val_ptr; SQLParamData(stmt_h, &val_ptr); // Very strange bug on Intel Atom: // without this call SQLExecute sometimes // gives SQL_NEED_DATA } return false; } b_col_info_needed = true; return true; }
// Execute direct a query bool statement::execute_direct(connection & _conn, const _tstring & _query) { RETCODE rc; // Close previous close(); // open a new one if (!open(_conn)) return false; // Execute directly statement SQLTCHAR_buf buff = ybstring2sqltchar(_query, ""); rc = SQLExecDirect(stmt_h, buff.data, SQL_NTS); if (!TIODBC_SUCCESS_CODE(rc) && rc != SQL_NO_DATA) return false; b_col_info_needed = true; return true; }
bool connection::rollback() { RETCODE rc; rc = SQLEndTran(SQL_HANDLE_DBC, conn_h, SQL_ROLLBACK); return TIODBC_SUCCESS_CODE(rc); }
bool connection::commit() { RETCODE rc; rc = SQLEndTran(SQL_HANDLE_DBC, conn_h, SQL_COMMIT); return TIODBC_SUCCESS_CODE(rc); }