NCBI C++ ToolKit
lang_cmd.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: lang_cmd.cpp 63610 2014-07-14 19:00:33Z ucko $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Vladimir Soussov
27  *
28  * File Description: ODBC language command
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
34 #include <dbapi/error_codes.hpp>
35 
36 #include "odbc_utils.hpp"
37 
38 #include <stdio.h>
39 
40 
41 #define NCBI_USE_ERRCODE_X Dbapi_Odbc_Cmds
42 
43 #undef NCBI_DATABASE_THROW
44 #define NCBI_DATABASE_THROW(ex_class, message, err_code, severity) \
45  NCBI_ODBC_THROW(ex_class, message, err_code, severity)
46 // No use of NCBI_DATABASE_RETHROW or DATABASE_DRIVER_*_EX here.
47 
48 // Accommodate all the code of the form
49 // string err_message = "..." + GetDbgInfo();
50 // DATABASE_DRIVER_ERROR(err_message, ...);
51 // which will still pick up the desired context due to
52 // NCBI_DATABASE_THROW's above redefinition.
53 #define GetDbgInfo() 0
54 
56 
57 
58 /////////////////////////////////////////////////////////////////////////////
59 //
60 // CODBC_LangCmd::
61 //
62 
65  const string& lang_query
66  ) :
67  CStatementBase(conn, lang_query),
68  m_Res(NULL)
69 {
70 /* This logic is not working for some reason
71  if ( SQLSetStmtAttr(m_Cmd, SQL_ATTR_ROWS_FETCHED_PTR, &m_RowCount, sizeof(m_RowCount)) != SQL_SUCCESS ) {
72  DATABASE_DRIVER_ERROR( "SQLSetStmtAttr failed (memory corruption suspected)", 420014 );
73  }
74 */
75  SetDbgInfo("SQL Command: \"" + lang_query + "\"");
76 
77 }
78 
79 
81 {
82  Cancel();
83 
84  SetHasFailed(false);
85 
86  CMemPot bindGuard;
87  string q_str;
88 
89  if(GetBindParamsImpl().NofParams() > 0) {
90  SQLLEN* indicator = (SQLLEN*)
91  bindGuard.Alloc(GetBindParamsImpl().NofParams() * sizeof(SQLLEN));
92 
93  if (!x_AssignParams(q_str, bindGuard, indicator)) {
94  ResetParams();
95  SetHasFailed();
96 
97  string err_message = "Cannot assign params." + GetDbgInfo();
98  DATABASE_DRIVER_ERROR( err_message, 420003 );
99  }
100  }
101 
102  const string* real_query;
103  if(!q_str.empty()) {
104  q_str.append(GetQuery());
105  real_query = &q_str;
106  }
107  else {
108  real_query = &GetQuery();
109  }
110 
111  TSqlString ss = x_MakeTSqlString(*real_query, GetClientEncoding());
112  switch (SQLExecDirect(GetHandle(), const_cast<TSqlChar*>(ss.data()),
113  ss.size())) {
114  // switch(SQLExecDirect(GetHandle(), tchar_str, odbc_str.GetSymbolNum())) {
115  case SQL_SUCCESS:
116  m_HasMoreResults = true;
117  break;
118 
119  case SQL_NO_DATA:
120  m_HasMoreResults = false;
121  m_RowCount = 0;
122  break;
123 
124  case SQL_ERROR:
125  ReportErrors();
126  ResetParams();
127  SetHasFailed();
128  {
129  string err_message = "SQLExecDirect failed." + GetDbgInfo();
130  DATABASE_DRIVER_ERROR( err_message, 420001 );
131  }
132 
134  ReportErrors();
135  m_HasMoreResults = true;
136  break;
137 
138  case SQL_STILL_EXECUTING:
139  ReportErrors();
140  ResetParams();
141  SetHasFailed();
142  {
143  string err_message = "Some other query is executing on this connection." + GetDbgInfo();
144  DATABASE_DRIVER_ERROR( err_message, 420002 );
145  }
146 
147  case SQL_INVALID_HANDLE:
148  SetHasFailed();
149  {
150  string err_message = "The statement handler is invalid (memory corruption suspected)." + GetDbgInfo();
151  DATABASE_DRIVER_ERROR( err_message, 420004 );
152  }
153 
154  default:
155  ReportErrors();
156  ResetParams();
157  SetHasFailed();
158  {
159  string err_message = "Unexpected error." + GetDbgInfo();
160  DATABASE_DRIVER_ERROR( err_message, 420005 );
161  }
162 
163  }
164 
165  SetWasSent(true);
166  return true;
167 }
168 
169 
171 {
172  if (WasSent()) {
173  if (m_Res) {
174  delete m_Res;
175  m_Res = 0;
176  }
177 
178  SetWasSent(false);
179 
180  if ( !Close() ) {
181  return false;
182  }
183 
184  ResetParams();
185  // GetQuery().erase();
186  }
187 
188  return true;
189 }
190 
191 
193 {
194  if (m_Res) {
195  delete m_Res;
196  m_Res = 0;
198  }
199 
200  if ( !WasSent() ) {
201  string err_message = "A command has to be sent first." + GetDbgInfo();
202  DATABASE_DRIVER_ERROR( err_message, 420010 );
203  }
204 
205  if(!m_HasMoreResults) {
206  SetWasSent(false);
207  return 0;
208  }
209 
210  SQLSMALLINT nof_cols= 0;
211 
212  while(m_HasMoreResults) {
213  CheckSIE(SQLNumResultCols(GetHandle(), &nof_cols),
214  "SQLNumResultCols failed", 420011);
215 
216  if(nof_cols < 1) { // no data in this result set
217  SQLLEN rc;
218 
220  "SQLRowCount failed", 420013);
221 
222  m_RowCount = rc;
224  continue;
225  }
226 
227  m_Res = new CODBC_RowResult(*this, nof_cols, &m_RowCount);
228  return Create_Result(*m_Res);
229  }
230 
231  SetWasSent(false);
232  return 0;
233 }
234 
235 
237 {
238  return m_HasMoreResults;
239 }
240 
241 
243 {
244  return static_cast<int>(m_RowCount);
245 }
246 
247 
249 {
250  try {
251  DetachInterface();
252 
253  GetConnection().DropCmd(*this);
254 
255  Cancel();
256  }
258 }
259 
260 
261 bool CODBC_LangCmd::x_AssignParams(string& cmd, CMemPot& bind_guard, SQLLEN* indicator)
262 {
263  for (unsigned int n = 0; n < GetBindParamsImpl().NofParams(); ++n) {
264  if(GetBindParamsImpl().GetParamStatus(n) == 0) continue;
265  const string& name = GetBindParamsImpl().GetParamName(n);
266  if (name.empty()) {
267  DATABASE_DRIVER_ERROR( "Binding by position is not supported." + GetDbgInfo(), 420110 );
268  }
269  const CDB_Object& param = *GetBindParamsImpl().GetParam(n);
270 
271  const string type = Type2String(param);
272  if (!x_BindParam_ODBC(param, bind_guard, indicator, n)) {
273  return false;
274  }
275 
276  cmd += "declare " + name + ' ' + type + ";select " + name + " = ?;";
277 
278  if(param.IsNULL()) {
279  indicator[n] = SQL_NULL_DATA;
280  }
281  }
282 
284  return true;
285 }
286 
287 
289 {
290 // int rc = CheckSIE(SQLMoreResults(GetHandle()), "SQLBindParameter failed", 420066);
291 //
292 // return (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS);
293 
294  switch(SQLMoreResults(GetHandle())) {
296  case SQL_SUCCESS: return true;
297  case SQL_NO_DATA: return false;
298  case SQL_ERROR:
299  {
300  ReportErrors();
301 
302  string err_message = "SQLMoreResults failed." + GetDbgInfo();
303  DATABASE_DRIVER_ERROR( err_message, 420014 );
304  }
305  default:
306  {
307  string err_message = "SQLMoreResults failed (memory corruption suspected)." + GetDbgInfo();
308  DATABASE_DRIVER_ERROR( err_message, 420015 );
309  }
310  }
311 }
312 
313 
314 void CODBC_LangCmd::SetCursorName(const string& name) const
315 {
316  // Set statement attributes so server-side cursor is generated
317 
318  // The default ODBC cursor attributes are:
319  // SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY);
320  // SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, SQL_CONCUR_READ_ONLY);
321  // SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, 1);
322 
323  // CheckSIE(SQLSetStmtAttr(GetHandle(), SQL_ROWSET_SIZE, (void*)2, SQL_NTS),
324  // "SQLSetStmtAttr(SQL_ROWSET_SIZE) failed", 420015);
326  "SQLSetStmtAttr(SQL_ATTR_CONCURRENCY) failed", 420017);
328  "SQLSetStmtAttr(SQL_ATTR_CURSOR_TYPE) failed", 420018);
329 
330 
332  CheckSIE(SQLSetCursorName(GetHandle(), const_cast<TSqlChar*>(ss.data()),
333  static_cast<SQLSMALLINT>(ss.size())),
334  "SQLSetCursorName failed", 420016);
335 }
336 
337 
338 bool
340 {
341  bool result = true;
342 
343  try {
345  "SQLCloseCursor failed", 420017);
346  }
347  catch (...)
348  {
349  result = false;
350  }
351 
352  return result;
353 }
354 
356 
357 
Convenience extension of basic_string, supporting implicit conversion to const TChar* in most situati...
Definition: types.hpp:99
void * Alloc(size_t nof_bytes)
CODBC_RowResult * m_Res
Definition: interfaces.hpp:506
void SetCursorName(const string &name) const
Definition: lang_cmd.cpp:314
CODBC_LangCmd(CODBC_Connection &conn, const string &lang_query)
Definition: lang_cmd.cpp:63
virtual int RowCount(void) const
Get the number of rows affected by the command Special case: negative on error or if there is no way ...
Definition: lang_cmd.cpp:242
virtual bool Cancel(void)
Cancel the command execution.
Definition: lang_cmd.cpp:170
virtual ~CODBC_LangCmd(void)
Definition: lang_cmd.cpp:248
bool xCheck4MoreResults(void)
Definition: lang_cmd.cpp:288
virtual bool HasMoreResults(void) const
Definition: lang_cmd.cpp:236
virtual CDB_Result * Result(void)
Get result set.
Definition: lang_cmd.cpp:192
virtual bool Send(void)
Send command to the server.
Definition: lang_cmd.cpp:80
bool m_HasMoreResults
Definition: interfaces.hpp:507
virtual bool CloseCursor(void)
Close the cursor.
Definition: lang_cmd.cpp:339
bool x_AssignParams(string &cmd, CMemPot &bind_guard, SQLLEN *indicator)
Definition: lang_cmd.cpp:261
const CODBC_Connection::TDbgInfo & GetDbgInfo(void) const
Definition: interfaces.hpp:388
bool x_BindParam_ODBC(const CDB_Object &param, CMemPot &bind_guard, SQLLEN *indicator_base, unsigned int pos) const
bool Close(void) const
string Type2String(const CDB_Object &param) const
SQLHSTMT GetHandle(void) const
Definition: interfaces.hpp:369
int CheckSIE(int rc, const char *msg, unsigned int msg_num) const
Definition: connection.cpp:940
bool ResetParams(void) const
Definition: interfaces.hpp:426
EEncoding GetClientEncoding(void) const
Definition: interfaces.hpp:435
void SetDbgInfo(const string &msg)
Definition: interfaces.hpp:383
CODBC_Connection & GetConnection(void)
Definition: interfaces.hpp:373
void ReportErrors(void) const
Definition: interfaces.hpp:393
const string & GetQuery(void) const
virtual void SetHasFailed(bool flag=true)
const CDB_Params & GetBindParamsImpl(void) const
void DetachInterface(void)
void SetWasSent(bool flag=true)
bool WasSent(void) const
static CDB_Result * Create_Result(CResult &result)
void DropCmd(impl::CCommand &cmd)
CDB_Object * GetParam(unsigned int param_no) const
Definition: parameters.hpp:63
void LockBinding(void)
Definition: parameters.hpp:87
const string & GetParamName(unsigned int param_no) const
Definition: parameters.hpp:67
TStatus GetParamStatus(unsigned int param_no) const
Definition: parameters.hpp:83
unsigned int NofParams() const
Definition: parameters.hpp:59
SQLCHAR TSqlChar
Definition: interfaces.hpp:76
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
static CS_CONNECTION * conn
Definition: ct_dynamic.c:25
#define SQLLEN
Definition: odbc.h:52
#define NULL
Definition: ncbistd.hpp:225
#define DATABASE_DRIVER_ERROR(message, err_code)
Definition: exception.hpp:740
bool IsNULL() const
Definition: types.hpp:303
#define NCBI_CURRENT_FUNCTION
Get current function name.
Definition: ncbidiag.hpp:142
#define NCBI_CATCH_ALL_X(err_subcode, message)
Definition: ncbiexpt.hpp:619
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
Definition of all error codes used in dbapi libraries (dbapi_driver.lib and others).
yy_size_t n
TSqlString x_MakeTSqlString(const CTempString &s, EEncoding enc)
Definition: odbc_utils.hpp:107
#define SQL_STILL_EXECUTING
Definition: sql.h:38
SQLRETURN SQLRowCount(SQLHSTMT StatementHandle, SQLINTEGER *RowCount)
SQLRETURN SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength)
Definition: odbc_export.h:812
#define SQL_SUCCESS
Definition: sql.h:31
SQLRETURN SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength)
#define SQL_INVALID_HANDLE
Definition: sql.h:37
#define SQL_SUCCESS_WITH_INFO
Definition: sql.h:32
#define SQL_NTS
Definition: sql.h:49
SQLRETURN SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount)
SQLRETURN SQLCloseCursor(SQLHSTMT StatementHandle)
Definition: odbc.c:4245
#define SQL_NULL_DATA
Definition: sql.h:29
SQLRETURN SQLSetCursorName(SQLHSTMT StatementHandle, SQLCHAR *CursorName, SQLSMALLINT NameLength)
Definition: odbc_export.h:884
#define SQL_ERROR
Definition: sql.h:36
#define SQL_NO_DATA
Definition: sql.h:34
#define SQL_CURSOR_FORWARD_ONLY
Definition: sqlext.h:349
#define SQL_CONCUR_VALUES
Definition: sqlext.h:345
#define SQL_ATTR_CURSOR_TYPE
Definition: sqlext.h:258
SQLRETURN SQLMoreResults(SQLHSTMT hstmt)
Definition: odbc.c:865
#define SQL_ATTR_CONCURRENCY
Definition: sqlext.h:257
signed short int SQLSMALLINT
Definition: sqltypes.h:201
Definition: type.c:6
else result
Definition: token2.c:20
Modified on Fri Sep 20 14:58:10 2024 by modify_doxy.py rev. 669887