Version: 1.0.0
odbc_preparedstatement.cpp
Go to the documentation of this file.
1 #include "wx/database/wxprec.h"
2 
3 #if wxUSE_DATABASE_ODBC
4 
5 // ctor
6 wxOdbcPreparedStatement::wxOdbcPreparedStatement(wxOdbcInterface* pInterface, SQLHENV sqlEnvHandle, SQLHDBC sqlHDBC)
8 {
9  m_pInterface = pInterface;
10  m_sqlEnvHandle = sqlEnvHandle;
11  m_sqlHDBC = sqlHDBC;
12  m_bOneTimeStatement = false;
13 }
14 
15 wxOdbcPreparedStatement::wxOdbcPreparedStatement(wxOdbcInterface* pInterface, SQLHENV sqlEnvHandle, SQLHDBC sqlHDBC, SQLHSTMT sqlStatementHandle)
17 {
18  m_pInterface = pInterface;
19  m_sqlEnvHandle = sqlEnvHandle;
20  m_sqlHDBC = sqlHDBC;
21  m_bOneTimeStatement = false;
22  m_Statements.push_back(sqlStatementHandle);
23 }
24 
25 wxOdbcPreparedStatement::wxOdbcPreparedStatement(wxOdbcInterface* pInterface, SQLHENV sqlEnvHandle, SQLHDBC sqlHDBC, wxOdbcStatementVector statements)
27 {
28  m_pInterface = pInterface;
29  m_sqlEnvHandle = sqlEnvHandle;
30  m_sqlHDBC = sqlHDBC;
31  m_bOneTimeStatement = false;
32  m_Statements = statements;
33 }
34 
35 // dtor
37 {
39  Close();
40 }
41 
43 {
45 
46  wxOdbcStatementVector::iterator start = m_Statements.begin();
47  wxOdbcStatementVector::iterator stop = m_Statements.end();
48  while (start != stop)
49  {
50  if ((*start) != NULL)
51  {
52  SQLRETURN nRet = m_pInterface->GetSQLFreeHandle()(SQL_HANDLE_STMT, (SQLHSTMT)*start);
53  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
54  {
55  InterpretErrorCodes(nRet, (SQLHSTMT)*start);
57  return;
58  }
59  (*start) = NULL;
60  }
61  start++;
62  }
63  m_Statements.Clear();
64 }
65 
67 {
68  ArrayOfOdbcParameters::iterator start = m_Parameters.begin();
69  ArrayOfOdbcParameters::iterator stop = m_Parameters.end();
70 
71  while (start != stop)
72  {
73  if ((*start) != NULL)
74  {
75  wxOdbcParameter* pParameter = *start;
76  delete(pParameter);
77  (*start) = NULL;
78  }
79  start++;
80  }
81  m_Parameters.Clear();
82 }
83 
84 void wxOdbcPreparedStatement::AddPreparedStatement(SQLHSTMT sqlStatementHandle)
85 {
86  m_Statements.push_back(sqlStatementHandle);
87 }
88 
89 // get field
90 void wxOdbcPreparedStatement::SetParamInt(int nPosition, int nValue)
91 {
93 
94  wxOdbcParameter* pParameter = new wxOdbcParameter(nValue);
95  SetParam(nPosition, pParameter);
96 }
97 
98 void wxOdbcPreparedStatement::SetParamDouble(int nPosition, double dblValue)
99 {
100  ResetErrorCodes();
101 
102  wxOdbcParameter* pParameter = new wxOdbcParameter(dblValue);
103  SetParam(nPosition, pParameter);
104 }
105 
106 void wxOdbcPreparedStatement::SetParamString(int nPosition, const wxString& strValue)
107 {
108  ResetErrorCodes();
109 
110  wxOdbcParameter* pParameter = new wxOdbcParameter(strValue);
111  SetParam(nPosition, pParameter);
112 }
113 
114 void wxOdbcPreparedStatement::SetParamNull(int nPosition)
115 {
116  ResetErrorCodes();
117 
118  wxOdbcParameter* pParameter = new wxOdbcParameter();
119  SetParam(nPosition, pParameter);
120 }
121 
122 void wxOdbcPreparedStatement::SetParamBlob(int nPosition, const void* pData, long nDataLength)
123 {
124  ResetErrorCodes();
125 
126  wxOdbcParameter* pParameter = new wxOdbcParameter(pData, nDataLength);
127  SetParam(nPosition, pParameter);
128 }
129 
130 void wxOdbcPreparedStatement::SetParamDate(int nPosition, const wxDateTime& dateValue)
131 {
132  ResetErrorCodes();
133 
134  wxOdbcParameter* pParameter = new wxOdbcParameter(dateValue);
135  SetParam(nPosition, pParameter);
136 }
137 
138 void wxOdbcPreparedStatement::SetParamBool(int nPosition, bool bValue)
139 {
140  ResetErrorCodes();
141 
142  wxOdbcParameter* pParameter = new wxOdbcParameter(bValue);
143  SetParam(nPosition, pParameter);
144 }
145 
147 {
148  ResetErrorCodes();
149 
150  int nReturn = 0;
151  wxOdbcStatementVector::iterator start = m_Statements.begin();
152  wxOdbcStatementVector::iterator stop = m_Statements.end();
153  while (start != stop)
154  {
155  SQLSMALLINT num = 0;
156  SQLRETURN nRet = m_pInterface->GetSQLNumParams()(((SQLHSTMT)(*start)), &num);
157  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
158  {
159  InterpretErrorCodes(nRet, (SQLHSTMT)(*start));
161  return -1;
162  }
163  nReturn += num;
164  start++;
165  }
166  return nReturn;
167 }
168 
170 {
171  ResetErrorCodes();
172 
173  BindParameters();
174 
175  SQLLEN nRows = wxDATABASE_QUERY_RESULT_ERROR;
176  wxOdbcStatementVector::iterator start = m_Statements.begin();
177  wxOdbcStatementVector::iterator stop = m_Statements.end();
178  while (start != stop)
179  {
180  SQLRETURN nRet = 0;
181  // Free any previous statement handles
182  nRet = m_pInterface->GetSQLFreeStmt()((SQLHSTMT)(*start), SQL_CLOSE);
183  if (nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO)
184  {
185  InterpretErrorCodes(nRet, (SQLHSTMT)(*start));
188  }
189 
190  // Execute the current statement
191  nRet = m_pInterface->GetSQLExecute()((SQLHSTMT)(*start));
192  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO && nRet != SQL_NO_DATA && nRet != SQL_NEED_DATA)
193  {
194  InterpretErrorCodes(nRet, (SQLHSTMT)(*start));
197  }
198 
199  if ( nRet == SQL_NEED_DATA)
200  {
201  PTR pParmID;
202  nRet = m_pInterface->GetSQLParamData()((SQLHSTMT)(*start), &pParmID);
203  while (nRet == SQL_NEED_DATA)
204  {
205  // Find the parameter
206  for (unsigned int i = 0; i < m_Parameters.size(); i++)
207  {
208  wxOdbcParameter* pParameter = m_Parameters[i];
209  if (pParmID == pParameter->GetDataPtr())
210  {
211  // We found it. Store the parameter.
212  nRet = m_pInterface->GetSQLPutData()((SQLHSTMT)(*start), pParmID, pParameter->GetDataLength());
213  if (nRet != SQL_SUCCESS)
214  {
215  InterpretErrorCodes(nRet, (SQLHSTMT)(*start));
218  }
219  break;
220  }
221  }
222  nRet = m_pInterface->GetSQLParamData()((SQLHSTMT)(*start), &pParmID);
223  }
224 
225  // Check the last return code
226  if (nRet != SQL_SUCCESS && nRet != SQL_NO_DATA_FOUND && nRet != SQL_SUCCESS_WITH_INFO)
227  {
228  InterpretErrorCodes(nRet, (SQLHSTMT)(*start));
231  }
232  }
233 
234  // Get the affected record count
235  if (SQL_SUCCESS != m_pInterface->GetSQLRowCount()((SQLHSTMT)(*start), &nRows))
236  {
238  }
239 
240  // Move to the next query
241  start++;
242  }
243  return nRows;
244 }
245 
247 {
248  return RunQueryWithResults(true);
249 }
250 
252 {
253  ResetErrorCodes();
254  SQLSMALLINT ncol = 0;
255 
256  if (m_Statements.size() > 0)
257  {
258  BindParameters();
259 
260  for (unsigned int i=0; i<m_Statements.size(); i++)
261  {
262  SQLRETURN nRet = 0;
263  nRet = m_pInterface->GetSQLFreeStmt()(m_Statements[i], SQL_CLOSE);
264  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
265  {
268  return NULL;
269  }
270 
272  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
273  {
276  return NULL;
277  }
278 
279  nRet = m_pInterface->GetSQLNumResultCols()(m_Statements[i], &ncol);
280  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
281  {
284  return NULL;
285  }
286  }
287  }
288 
289  // Work off the assumption that only the last statement will return result
290  wxDatabaseResultSet* pResultSet = new wxOdbcResultSet(m_pInterface, this, m_bOneTimeStatement, (int)ncol);
291  if (bLogForCleanup)
292  LogResultSetForCleanup(pResultSet);
293  return pResultSet;
294 }
295 
297 {
298  // Iterate through all of the parameters and bind them to the prepared statement
299  for (unsigned int i = 1; i <= m_Parameters.size(); i++)
300  {
301  int nPosition = i;
302  wxOdbcParameter* pParameter = m_Parameters[i-1];
303  int nIndex = FindStatementAndAdjustPositionIndex(&nPosition);
304 
305  if ((nIndex > -1) && (pParameter != NULL))
306  {
307  // Determine the data type (if supported by the ODBC driver)
308  SQLSMALLINT dataType;
309  SQLULEN dataSize;
310  SQLSMALLINT dataDigits;
311  SQLSMALLINT isNullable;
312  SQLRETURN ret = m_pInterface->GetSQLDescribeParam()(m_Statements[nIndex], nPosition, &dataType, &dataSize,
313  &dataDigits, &isNullable);
314  if ( ret != SQL_SUCCESS )
315  {
316  dataType = pParameter->GetParameterType();
317  dataSize = pParameter->GetColumnSize();
318  dataDigits = pParameter->GetDecimalDigits();
319  }
320 
321  SQLRETURN nRet = m_pInterface->GetSQLBindParameter()(m_Statements[nIndex], nPosition, SQL_PARAM_INPUT,
322  pParameter->GetValueType(), dataType, dataSize, dataDigits, pParameter->GetDataPtr(),
323  pParameter->GetDataLength(), pParameter->GetParameterLengthPtr());
324 
325  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
326  {
327  InterpretErrorCodes(nRet, m_Statements[nIndex]);
329  return;
330  }
331  }
332  }
333 }
334 
336 {
337  // Don't mess around if there's just one entry in the vector
338  if (m_Statements.size() == 0)
339  return 0;
340 
341  // Go through all the elements in the vector
342  // Get the number of parameters in each statement
343  // Adjust the nPosition for the the broken up statements
344  for (unsigned int i=0; i<m_Statements.size(); i++)
345  {
346  SQLSMALLINT num = 0;
347  SQLRETURN nRet = m_pInterface->GetSQLNumParams()(m_Statements[i], &num);
348  if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
349  {
352  return -1;
353  }
354 
355  int nParametersInThisStatement = (int)num;
356  if (*pPosition > nParametersInThisStatement)
357  {
358  *pPosition -= nParametersInThisStatement; // Decrement the position indicator by the number of parameters in this statement
359  }
360  else
361  {
362  // We're in the correct statement, return the index
363  return i;
364  }
365  }
366  return -1;
367 }
368 
369 void wxOdbcPreparedStatement::SetParam(int nPosition, wxOdbcParameter* pParameter)
370 {
371  // First make sure that there are enough elements in the collection
372  while (m_Parameters.size() < (unsigned int)(nPosition))
373  {
374  m_Parameters.push_back(NULL);//EmptyParameter);
375  }
376  // Free up any data that is being replaced so the allocated memory isn't lost
377  if (m_Parameters[nPosition-1] != NULL)
378  {
379  delete (m_Parameters[nPosition-1]);
380  }
381  // Now set the new data
382  m_Parameters[nPosition-1] = pParameter;
383 }
384 
385 void wxOdbcPreparedStatement::InterpretErrorCodes( long WXUNUSED(nCode), SQLHSTMT stmth_ptr )
386 {
387  wxLogDebug(_("OdbcPreparedStatement::InterpretErrorCodes()\n"));
388 
389  //if ((nCode != SQL_SUCCESS) ) // && (nCode != SQL_SUCCESS_WITH_INFO))
390  {
391  SQLINTEGER iNativeCode;
392  SQLTCHAR strState[ERR_STATE_LEN];
393  SQLTCHAR strBuffer[ERR_BUFFER_LEN];
394  SQLSMALLINT iMsgLen;
395 
396  memset(strState, 0, ERR_STATE_LEN*sizeof(SQLTCHAR));
397  memset(strBuffer, 0, ERR_BUFFER_LEN*sizeof(SQLTCHAR));
398 
399  if (stmth_ptr)
400  m_pInterface->GetSQLGetDiagRec()(SQL_HANDLE_STMT, stmth_ptr, 1, strState, &iNativeCode,
401  strBuffer, ERR_BUFFER_LEN, &iMsgLen);
402  else
403  m_pInterface->GetSQLGetDiagRec()(SQL_HANDLE_DBC, m_sqlHDBC, 1, strState, &iNativeCode,
404  strBuffer, ERR_BUFFER_LEN, &iMsgLen);
405 
406  SetErrorCode((int)iNativeCode);
407  SetErrorMessage(ConvertFromUnicodeStream((char*)strBuffer)); //AML
408  //AML SetErrorMessage(wxString((wxChar*)strBuffer));
409  }
410 }
411 
412 #endif//wxUSE_DATABASE_ODBC
413 
SQLFreeStmtType GetSQLFreeStmt()
Definition: odbc_inteface.h:61
virtual void SetParamBool(int nPosition, bool bValue)
Set the parameter at the 1-based position to a boolean value.
long GetDataLength()
virtual int RunQuery()
Run an insert, update, or delete query on the database.
SQLRowCountType GetSQLRowCount()
Definition: odbc_inteface.h:72
SQLNumResultColsType GetSQLNumResultCols()
Definition: odbc_inteface.h:73
SQLLEN * GetParameterLengthPtr()
wxOdbcStatementVector m_Statements
virtual wxDatabaseResultSet * RunQueryWithResults()
Run an insert, update, or delete query on the database.
SQLSMALLINT GetValueType()
#define ERR_BUFFER_LEN
Definition: odbc_database.h:8
SQLBindParameterType GetSQLBindParameter()
Definition: odbc_inteface.h:75
virtual void SetParamBlob(int nPosition, const void *pData, long nDataLength)
Set the parameter at the 1-based position to a Blob value.
int FindStatementAndAdjustPositionIndex(int *pPosition)
virtual ~wxOdbcPreparedStatement()
void * GetDataPtr()
SQLDescribeParamType GetSQLDescribeParam()
Definition: odbc_inteface.h:74
void SetErrorMessage(const wxString &strErrorMessage)
SQLUINTEGER GetColumnSize()
virtual void Close()
Close the result set (call wxDatabase::ClosePreparedStatement() instead on the statement)
void AddPreparedStatement(SQLHSTMT pStatement)
void LogResultSetForCleanup(wxDatabaseResultSet *pResultSet)
Add result set object pointer to the list for "garbage collection".
#define wxDATABASE_QUERY_RESULT_ERROR
Definition: errorcodes.h:21
SQLExecuteType GetSQLExecute()
Definition: odbc_inteface.h:69
virtual void SetParamInt(int nPosition, int nValue)
Set the parameter at the 1-based position to an int value.
virtual void SetParamString(int nPosition, const wxString &strValue)
Set the parameter at the 1-based position to a wxString value.
SQLPutDataType GetSQLPutData()
Definition: odbc_inteface.h:71
SQLSMALLINT GetDecimalDigits()
void CloseResultSets()
Close all result set objects that have been generated but not yet closed.
SQLNumParamsType GetSQLNumParams()
Definition: odbc_inteface.h:68
void SetErrorCode(int nErrorCode)
wxOdbcPreparedStatement(wxOdbcInterface *pInterface, SQLHENV sqlEnvHandle, SQLHDBC sqlHDBC)
SQLGetDiagRecType GetSQLGetDiagRec()
Definition: odbc_inteface.h:67
virtual wxString ConvertFromUnicodeStream(const char *inputBuffer)
SQLParamDataType GetSQLParamData()
Definition: odbc_inteface.h:70
virtual void SetParamNull(int nPosition)
Set the parameter at the 1-based position to a NULL value.
virtual void SetParamDate(int nPosition, const wxDateTime &dateValue)
Set the parameter at the 1-based position to a wxDateTime value.
SQLSMALLINT GetParameterType()
void SetParam(int nPosition, wxOdbcParameter *pParameter)
virtual void SetParamDouble(int nPosition, double dblValue)
Set the parameter at the 1-based position to a double value.
void InterpretErrorCodes(long nCode, SQLHSTMT stmth_ptr=NULL)
#define ERR_STATE_LEN
Definition: odbc_database.h:9
ArrayOfOdbcParameters m_Parameters
virtual int GetParameterCount()
SQLFreeHandleType GetSQLFreeHandle()
Definition: odbc_inteface.h:54