Version: 1.0.0
tds_resultset.cpp
Go to the documentation of this file.
1 #include "wx/database/wxprec.h"
2 
3 #if wxUSE_DATABASE_TDS
4 
5 // ctor
6 wxTdsResultSet::wxTdsResultSet(TDSSOCKET* pDatabase)
8 {
9  m_pDatabase = pDatabase;
10  m_pResultSetMetaData = NULL;
11  m_pResultInfo = NULL;
12 }
13 
14 // dtor
16 {
17  Close();
18 }
19 
20 
22 {
23  //fprintf(stderr, "wxTdsResultSet::Close()\n");
24 
25  CloseMetaData();
26 
27  //if (m_pResultInfo == NULL)
28  //fprintf(stderr, "m_pResultInfo is still NULL!!!\n");
29 
30  //AML if (m_pResultInfo != NULL)
31  //AML tds_free_results(m_pResultInfo);
32 
34 }
35 
37 {
38  //fprintf(stderr, "In wxTdsResultSet::FreeResultSets()\n");
39  int rc;
40  int result_type;
41  //while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCEED)
42  while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_RETURN_ROW|TDS_TOKEN_RESULTS|TDS_RETURN_COMPUTE)) == /*AML TDS_SUCCEED*/TDS_SUCCESS)
43  // while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS|TDS_RETURN_ROWFMT|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)) == TDS_SUCCEED)
44  {
45  switch (result_type)
46  {
47  case TDS_DONE_RESULT:
48  case TDS_DONEPROC_RESULT:
49  case TDS_DONEINPROC_RESULT:
50  /* ignore possible spurious result (TDS7+ send it) */
51  case TDS_STATUS_RESULT:
52  break;
53  case TDS_ROWFMT_RESULT:
54  case TDS_COMPUTEFMT_RESULT:
55  case TDS_DESCRIBE_RESULT:
56  break;
57  case TDS_ROW_RESULT:
58  //fprintf(stderr, "Warning: wxTdsResultSet query should not return results. Type: %d\n", result_type);
59 //AML start/*
60  if (m_pDatabase->current_results && m_pDatabase->current_results->num_cols > 0)
61  {
62  fprintf(stderr, "Info: wxTdsResultSet processing tokens\n");
63  while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_RETURN_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW) == /*AML TDS_SUCCEED*/TDS_SUCCESS)
64  {
65  //fprintf(stderr, "Warning: wxTdsResultSet TDS_ROW_RESULT query should not return results. Type: %d\n", result_type);
66  if (result_type != TDS_ROW_RESULT)
67  break;
68 
69  if (!m_pDatabase->current_results)
70  continue;
71  }
72  fprintf(stderr, "Info: wxTdsResultSet done processing tokens\n");
73  }
74  else
75  {
76  fprintf(stderr, "Info: wxTdsResultSet NOT processing tokens\n");
77  }
78 //AML end*/
79  if (m_pDatabase != NULL)
80  tds_free_all_results(m_pDatabase);
81  return;
82 //AML break;
83  default:
84  //fprintf(stderr, "Error: wxTdsResultSet query should not return results. Type: %d\n", result_type);
85  // Clean up after ourselves
86  if (m_pDatabase != NULL)
87  tds_free_all_results(m_pDatabase);
88  return;
89  }
90  }
91 
92  // Clean up after ourselves
93  if (m_pDatabase != NULL)
94  tds_free_all_results(m_pDatabase);
95 
96  if (rc == TDS_FAIL)
97  {
98  //fprintf(stderr, "tds_process_tokens() returned TDS_FAIL\n");
101  return;
102  }
103  else if (rc != TDS_NO_MORE_RESULTS)
104  {
105  //fprintf(stderr, "tds_process_tokens() unexpected return\n");
108  return;
109  }
110 }
111 
112 
114 {
115  //fprintf(stderr, "In wxTdsResultSet::Next()\n");
116  int nResultType;
117  int nReturn = tds_process_tokens(m_pDatabase, &nResultType, NULL, TDS_RETURN_ROWFMT|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
118 
119  //fprintf(stderr, "Result type: %d, Looking for %d\n", nResultType, TDS_ROWFMT_RESULT);
120  if (nReturn == /*AML TDS_SUCCEED*/TDS_SUCCESS && nResultType == TDS_ROWFMT_RESULT)
121  {
124  // Go to the next row since the first call only returned the column names
125  nReturn = tds_process_tokens(m_pDatabase, &nResultType, NULL, TDS_RETURN_ROWFMT|TDS_RETURN_ROW);//|TDS_RETURN_COMPUTE);
126  }
127 
128  //fprintf(stderr, "tds_process_tokens returned %d (%d ?)\n", nReturn, TDS_SUCCEED);
129  return (nReturn == /*AML TDS_SUCCEED*/TDS_SUCCESS);
130 }
131 
133 {
134  //fprintf(stderr, "In wxTdsResultSet::PopulateFieldMap()\n");
135 
136  TDSCOLUMN* curcol;
137  //switch (nResultType)
138  //{
139  // case TDS_ROW_RESULT:
140  m_pResultInfo = m_pDatabase->res_info;
141  for (int i = 0; i < m_pResultInfo->num_cols; i++)
142  {
143  curcol = m_pResultInfo->columns[i];
144  char* pCharBuffer = new char[(curcol->column_name/*AML len*/->dstr_size)+1];
145  memset(pCharBuffer, 0, (curcol->column_name/*AML len*/->dstr_size)+1);
146  strncpy(pCharBuffer, curcol->column_name->dstr_s, curcol->column_name/*AML len*/->dstr_size);
147  wxString colName = ConvertFromUnicodeStream(pCharBuffer);
148  wxDELETEA(pCharBuffer);
149  //fprintf(stderr, "column name(%d) = '%s'\n", i, colName.c_str());
150  m_FieldLookupMap[colName] = i;
151 
152  /*
153  src = curcol->column_data;
154  if (verbose)
155  {
156  srctype = curcol->column_type;
157  srclen = curcol->column_size;
158  tds_convert(&ctx, srctype, (TDS_CHAR *) src, srclen, SYBCHAR, &cr);
159  printf("col %i is %s\n", i, cr.c);
160  }
161  if (i == 0)
162  {
163  src_id = *(int *) src;
164  }
165  else
166  {
167  src_val = *(float *) src;
168  src_err = src_val - sybreal[src_id];
169  if (src_err != 0.0)
170  {
171  src_err = src_err / src_val;
172  }
173  if (src_err < -tolerance || src_err > tolerance)
174  {
175  //fprintf(stderr, "SYBREAL expected %.8g got %.8g\n",
176  sybreal[src_id], src_val);
177  //fprintf(stderr, "Error was %.4g%%\n", 100 * src_err);
178  return 1;
179  }
180  }*/
181  }
182  // row_count++;
183  // case TDS_COMPUTE_RESULT:
184  // break;
185  // default:
186  // fprintf(stderr, "tds_process_tokens() unexpected result\n");
187  // break;
188  //}
189 }
190 
191 
192 // get field
193 int wxTdsResultSet::GetResultInt(int nField)
194 {
195  return (int)GetResultLong(nField);
196 }
197 
198 wxString wxTdsResultSet::GetResultString(int nField)
199 {
200  TDSCOLUMN *curcol = m_pDatabase->current_results->columns[nField-1];
201  TDS_CHAR *src = (TDS_CHAR *) curcol->column_data;
202 
203  wxString strValue = wxEmptyString;
204  if (curcol->column_cur_size > 0)
205  {
206  char* pCharBuffer = new char[(curcol->column_cur_size)+1];
207  memset(pCharBuffer, 0, (curcol->column_cur_size)+1);
208  strncpy(pCharBuffer, src, curcol->column_cur_size);
209  //fprintf(stderr, "char buffer: '%s'\n", pCharBuffer);
210  strValue = ConvertFromUnicodeStream(pCharBuffer);
211  //fprintf(stderr, "strValue: '%s'\n", strValue.c_str());
212  wxDELETEA(pCharBuffer);
213  }
214 
215  return strValue;
216 }
217 
218 long wxTdsResultSet::GetResultLong(int nField)
219 {
220  //fprintf(stderr, "In GetResultLong(%d)\n", nField);
221  TDSCOLUMN* curcol = m_pDatabase->current_results->columns[nField-1];
222  const int* src = (const int*) curcol->column_data;
223  //fprintf(stderr, "%d\n", *src);
224 
225  long nValue = 0;
226  wxString strValue = wxString::Format(_("%d"), *src);
227  strValue.ToLong(&nValue);
228 
229  return nValue;
230 }
231 
232 bool wxTdsResultSet::GetResultBool(int nField)
233 {
234  long nValue = GetResultLong(nField);
235 
236  return (nValue != 0);
237 }
238 
239 wxDateTime wxTdsResultSet::GetResultDate(int nField)
240 {
241  // Don't use nField-1 here since GetResultString will take care of that
242  TDSCOLUMN* curcol = m_pDatabase->current_results->columns[nField-1];
243  TDS_DATETIME* dateTime = (TDS_DATETIME*) curcol->column_data;
244  //fprintf(stderr, "Retrieved dtdays = %d, dttime = %d\n", dateTime->dtdays, dateTime->dttime);
245 
246  if (curcol->column_cur_size < 0)
247  return wxInvalidDateTime;
248 
249  TDSDATEREC dateRec;
250  TDS_INT nReturn = tds_datecrack(/*curcol->on_server.column_type*/SYBDATETIME, dateTime, &dateRec);
251  if (nReturn == TDS_FAIL)
252  return wxInvalidDateTime;
253 
254  //fprintf(stderr, "Second retrieved as %d\n", dateRec.second);
255 
256  wxDateTime date;
257  date.Set(dateRec.day, wxDateTime::Month(dateRec.month), dateRec.year,
258  dateRec.hour, dateRec.minute, dateRec.second, dateRec./*AML millisecond*/decimicrosecond*10000);
259 
260  return date;
261 }
262 
263 double wxTdsResultSet::GetResultDouble(int nField)
264 {
265  TDSCOLUMN *curcol = m_pDatabase->current_results->columns[nField-1];
266  const double* src = (const double*) curcol->column_data;
267 
268  double dblValue = *src;
269 
270  return dblValue;
271 }
272 
273 void* wxTdsResultSet::GetResultBlob(int nField, wxMemoryBuffer& Buffer)
274 {
275  TDSCOLUMN *curcol = m_pDatabase->current_results->columns[nField-1];
276  TDS_CHAR *src = (TDS_CHAR *) curcol->column_data;
277 
278  if (curcol->column_cur_size < 0)
279  return NULL;
280 
281  if (is_blob_type(curcol->column_type))
282  {
283  TDSBLOB *blob = (TDSBLOB*) src;
284 
285  src = blob->textvalue;
286  }
287  else
288  {
289  //fprintf(stderr, "Not a blob!!!\n");
290  return NULL;
291  }
292 
293  int nLength = curcol->column_cur_size;
294  //fprintf(stderr, "Blob size = %d\n", nLength);
295  void* pBuffer = Buffer.GetWriteBuf(nLength);
296  memcpy(pBuffer, src, nLength);
297  //AML start
298  Buffer.SetDataLen(nLength);
299  //AML end
300 
301  return Buffer.GetData();
302 
303 /*
304  CONV_RESULT cr;
305  int conv_type = tds_get_conversion_type(curcol->column_type, curcol->column_size);
306  if (tds_convert(test_context, conv_type, src, curcol->column_cur_size, SYBVARCHAR, &cr) < 0)
307  {
308  //fprintf(stderr, "Error converting\n");
309  free(cr.c);
310  return NULL;
311  }
312  else
313  {
314  if (strcmp(data[i_row].result, cr.c) != 0)
315  {
316  //fprintf(stderr, "Failed! Is \n%s\nShould be\n%s\n", cr.c, data[i_row].result);
317  free(cr.c);
318  return NULL;
319  }
320  free(cr.c);
321  }
322 
323  return Buffer.GetData();
324 */
325 }
326 
327 bool wxTdsResultSet::IsFieldNull(int nField)
328 {
329  TDSCOLUMN *curcol = m_pDatabase->current_results->columns[nField-1];
330  if (curcol == NULL)
331  return true;
332  if (curcol->column_cur_size < 0)
333  return true;
334 
335  return false;
336 }
337 
338 int wxTdsResultSet::LookupField(const wxString& strField)
339 {
340  StringToIntMap::iterator SearchIterator = m_FieldLookupMap.find(strField);
341  if (SearchIterator == m_FieldLookupMap.end())
342  {
343  wxString msg(_("Field '") + strField + _("' not found in the resultset"));
344 #if wxUSE_DATABASE_EXCEPTIONS
345  wxDatabaseException error(wxDATABASE_FIELD_NOT_IN_RESULTSET, msg);
346  throw error;
347 #else
348  wxLogError(msg);
349 #endif
350  //return -1;
351  }
352  else
353  {
354  return ((*SearchIterator).second + 1); // Add +1 to make the result set 1-based rather than 0-based
355  }
356 }
357 
359 {
362 }
363 
365 {
366  if (m_pResultSetMetaData == NULL)
367  {
368  // Just grab the result set info
369  int nResultType;
370  int nReturn = tds_process_tokens(m_pDatabase, &nResultType, NULL, TDS_RETURN_ROWFMT);
371 
372  if (nReturn == /*AML TDS_SUCCEED*/TDS_SUCCESS && nResultType == TDS_ROWFMT_RESULT)
373  {
376  }
377  }
378 
379  return m_pResultSetMetaData;
380 }
381 
383 {
384  wxTdsDatabase* pDatabase = wxTdsDatabase::LookupTdsLayer(/*AML m_pDatabase->tds_ctx*/tds_get_ctx(m_pDatabase));
385  if (pDatabase != NULL)
386  {
387  SetErrorCode(pDatabase->GetErrorCode());
388  SetErrorMessage(pDatabase->GetErrorMessage());
389  }
390 }
391 
392 #endif//wxUSE_DATABASE_TDS
void FreeResultSets()
virtual wxString GetResultString(int nField)
Retrieve a wxString from the result set by the 1-based field index.
void SetErrorInformationFromDatabaseLayer()
wxResultSetMetaData * m_pResultSetMetaData
Definition: tds_resultset.h:45
virtual bool IsFieldNull(int nField)
Check if a field in the current result set record is NULL.
static wxTdsDatabase * LookupTdsLayer(const TDSCONTEXT *pContext)
void LogMetaDataForCleanup(wxResultSetMetaData *pMetaData)
Add meta data object pointer to the list for "garbage collection".
Definition: resultset.h:70
wxTdsResultSet(TDSSOCKET *pDatabase)
virtual int GetResultInt(int nField)
Retrieve an integer from the result set by the 1-based field index.
virtual bool GetResultBool(int nField)
Retrieve a boolean from the result set by the 1-based field index.
virtual ~wxTdsResultSet()
virtual long GetResultLong(int nField)
Retrieve a long from the result set by the 1-based field index.
virtual bool Next()
Move to the next record in the result set.
#define wxDATABASE_FIELD_NOT_IN_RESULTSET
Definition: errorcodes.h:12
const wxString & GetErrorMessage()
virtual wxResultSetMetaData * GetMetaData()
Retrieve the MetaData associated with this result set.
TDSSOCKET * m_pDatabase
Definition: tds_resultset.h:43
void CloseMetaData()
Close all meta data objects that have been generated but not yet closed.
Definition: resultset.cpp:96
void SetErrorMessage(const wxString &strErrorMessage)
virtual void Close()
Close the result set (call wxDatabase::CloseResultSet() instead on the result set)
virtual void * GetResultBlob(int nField, wxMemoryBuffer &Buffer)
Retrieve a BLOB from the result set by the 1-based field index.
StringToIntMap m_FieldLookupMap
Definition: tds_resultset.h:41
void CreateResultSetMetaData()
virtual int LookupField(const wxString &strField)
void PopulateFieldMap()
void SetErrorCode(int nErrorCode)
TDSRESULTINFO * m_pResultInfo
Definition: tds_resultset.h:44
virtual wxDateTime GetResultDate(int nField)
Retrieve a wxDateTime from the result set by the 1-based field index.
virtual wxString ConvertFromUnicodeStream(const char *inputBuffer)
virtual double GetResultDouble(int nField)
Retrieve a double from the result set by the 1-based field index.