Version: 1.0.0
tds_database.cpp
Go to the documentation of this file.
1 #include "wx/database/wxprec.h"
2 
3 #if wxUSE_DATABASE_TDS
4 
5 TdsContextToDatabaseLayerMap wxTdsDatabase::m_ContextLookupMap;
6 
7 //AML start
8 static int tsql_handle_common(const TDSCONTEXT * pContext, TDSSOCKET * WXUNUSED(pTdsSocket), TDSMESSAGE * pMessage, bool error)
9 {
10  if (pMessage->msgno != 5701 && pMessage->msgno != 5703 && pMessage->msgno != 20018)
11  {
12  char message[1024];
13  sprintf(message, "%s %d, Level %d, State %d, Server %s, Line %d\n%s", error ? "Err" : "Msg", pMessage->msgno, pMessage->severity, pMessage->state, pMessage->server, pMessage->line_number, pMessage->message);
14  wxTdsDatabase* pLayer = wxTdsDatabase::LookupTdsLayer(pContext);
15  if (pLayer == NULL)
16  {
17  fprintf(stderr, "%s\n", message);
18  }
19  else
20  {
21  pLayer->SetError(pMessage->msgno, wxDatabaseStringConverter::ConvertFromUnicodeStream(message, "UTF-8"));
22  }
23  }
24  return TDS_INT_CANCEL;
25 }
26 //AML end
27 
28 static int tsql_handle_message(const TDSCONTEXT * pContext, TDSSOCKET * pTdsSocket, TDSMESSAGE * pMessage)
29 {
30  return tsql_handle_common(pContext, pTdsSocket, pMessage, false); // AML
31  /*AML
32  //fprintf(stderr, "In tsql_handle_message: %d\n", pMessage->msgno);
33  if (pMessage->msgno != 5701 && pMessage->msgno != 5703 && pMessage->msgno != 20018)
34  {
35  wxTdsDatabase* pLayer = wxTdsDatabase::LookupTdsLayer(pContext);
36  if (pLayer != NULL)
37  {
38  pLayer->SetError(pMessage->msgno, wxDatabaseStringConverter::ConvertFromUnicodeStream(pMessage->message, "UTF-8"));
39  }
40  else
41  {
42  //fprintf(stderr, "In tsql_handle_message (%d)\n", pMessage->msgno);
43  if (pMessage->msgno == 0)
44  {
45  //fprintf(stderr, "%s\n", pMessage->message);
46  return 0;
47  }
48 
49  }
50  }
51  return 0;
52  AML*/
53 }
54 
55 static int tsql_handle_error(const TDSCONTEXT * pContext, TDSSOCKET * pTdsSocket, TDSMESSAGE * pMessage)
56 {
57  return tsql_handle_common(pContext, pTdsSocket, pMessage, true); // AML
58  /*AML
59  //fprintf(stderr, "In tsql_handle_error: %d\n", pMessage->msgno);
60  if (pMessage->msgno != 5701 && pMessage->msgno != 5703 && pMessage->msgno != 20018)
61  {
62  wxTdsDatabase* pLayer = wxTdsDatabase::LookupTdsLayer(pContext);
63  if (pLayer != NULL)
64  {
65  pLayer->SetError(pMessage->msgno, wxDatabaseStringConverter::ConvertFromUnicodeStream(pMessage->message, "UTF-8"));
66  }
67  else
68  {
69  //fprintf(stderr, "In tsql_handle_error (%d)\n", pMessage->msgno);
70  if (pMessage->msgno == 0)
71  {
72  //fprintf(stderr, "%s\n", pMessage->message);
73  return 0;
74  }
75  fprintf(stderr, "Msg %d, Level %d, State %d, Server %s, Line %d\n%s\n",
76  pMessage->msgno, pMessage->severity, pMessage->state, pMessage->server, pMessage->line_number, pMessage->message);
77  }
78  }
79  return 0;
80  AML*/
81 }
82 
83 wxString RemoveLastSemiColon(const wxString& strvalue)
84 {
85  wxString result = strvalue;
86 
87  if (result.size() == 0)
88  return result;
89 
90  if (result[result.size()-1] == ';' )
91  {
92  result.RemoveLast();
93  }
94  return result;
95 }
96 
97 
98 // ctor()
100 : wxDatabase()
101 {
102  m_pDatabase = NULL;
103  m_pLogin = NULL;
104  m_pContext = NULL;
105  m_nTdsVersion = TDS_80;
106  wxCSConv conv(_("UTF-8"));
107  SetEncoding(&conv);
108 }
109 
110 wxTdsDatabase::wxTdsDatabase(const wxString& strFreeTDS, const wxString& strServer, const wxString& strDatabase, const wxString& strUser, const wxString& strPassword, int nTdsVersion)
111 : wxDatabase()
112 {
113  m_pDatabase = NULL;
114  m_pLogin = NULL;
115  m_pContext = NULL;
116  wxCSConv conv(_("UTF-8"));
117  SetEncoding(&conv);
118  m_strFreeTDS = strFreeTDS;
119  m_strServer = strServer;
120  m_strLogin = strUser;
121  m_strPassword = strPassword;
122  m_nTdsVersion = nTdsVersion;
123  Open(strDatabase);
124 }
125 
126 // dtor()
128 {
129  //wxPrintf(_("~wxTdsDatabase()\n"));
130  Close();
131  //wxDELETE(m_pDatabase);
132 }
133 
134 // open database
135 bool wxTdsDatabase::Open(const wxString& strDatabase)
136 {
137  ResetErrorCodes();
138 
139  m_strDatabase = strDatabase;
140 
141  if (!Connect())
142  {
143  //SetErrorCode(wxTdsDatabase::TranslateErrorCode(???));
144  //SetErrorMessage(ConvertFromUnicodeStream(???));
145  return false;
146  }
147 
148  // Change the database
149  if (!RunQuery(_("USE ") + strDatabase, false))
150  {
151  return false;
152  }
153 
154  return true;
155 }
156 
157 // Connect to the server
159 {
160  m_pLogin = tds_alloc_login(/*AML*/1);
161  if (m_pLogin == NULL)
162  {
163  //fprintf(stderr, "tds_alloc_login() failed.\n");
164  SetError(wxDATABASE_ERROR, wxT("Failed to allocate login"));
165  // Reset the variables so there are not mistaken as initialized
166  m_pDatabase = NULL;
167  m_pLogin = NULL;
168  if (m_pContext)
169  {
170  tds_free_context(m_pContext);
171  m_pContext = NULL;
172  }
174  return false;
175  }
176  wxCharBuffer freeTDSBuffer = ConvertToUnicodeStream(m_strFreeTDS);
177  tds_set_interfaces_file_loc(freeTDSBuffer);
178  wxCharBuffer serverBuffer = ConvertToUnicodeStream(m_strServer);
179  tds_set_server(m_pLogin, serverBuffer);
180  wxCharBuffer loginBuffer = ConvertToUnicodeStream(m_strLogin);
181  tds_set_user(m_pLogin, loginBuffer);
182  wxCharBuffer passwordBuffer = ConvertToUnicodeStream(m_strPassword);
183  tds_set_passwd(m_pLogin, passwordBuffer);
184  tds_set_app(m_pLogin, "wxDatabase");
185  tds_set_library(m_pLogin, "TDS-Library");
186  tds_set_client_charset(m_pLogin, "UTF-8");
187  switch (m_nTdsVersion)
188  {
189  case TDS_42:
190  tds_set_version(m_pLogin, 4, 2);
191  break;
192  case TDS_46:
193  tds_set_version(m_pLogin, 4, 6);
194  break;
195  case TDS_50:
196  tds_set_version(m_pLogin, 5, 0); // Sybase
197  break;
198  case TDS_70:
199  tds_set_version(m_pLogin, 7, 0); // SQL Server 7.0
200  break;
201  case TDS_71:
202  case TDS_80:
203  tds_set_version(m_pLogin, 7, 1); // SQL Server 2000
204  break;
205  case TDS_72:
206  tds_set_version(m_pLogin, 7, 2); // SQL Server 2005
207  break;
208  case TDS_73:
209  tds_set_version(m_pLogin, 7, 3); // SQL Server 2008
210  break;
211  case TDS_74:
212  tds_set_version(m_pLogin, 7, 4); // SQL Server 2012
213  break;
214  default:
215  tds_set_version(m_pLogin, 0, 0);
216  break;
217  };
218 
219  m_pContext = tds_alloc_context(NULL);
220  if (m_pContext == NULL)
221  {
222  //fprintf(stderr, "tds_alloc_context() failed.\n");
223  SetError(wxDATABASE_ERROR, wxT("Failed to allocate context"));
224  // Reset the variables so there are not mistaken as initialized
225  m_pDatabase = NULL;
226  if (m_pLogin)
227  {
228  tds_free_login(m_pLogin);
229  m_pLogin = NULL;
230  }
231  if (m_pContext)
232  {
233  tds_free_context(m_pContext);
234  m_pContext = NULL;
235  }
237  return false;
238  }
239  m_pContext->msg_handler = tsql_handle_message;
240  m_pContext->err_handler = tsql_handle_error;
241 
242  // Add the context (and this databaselayer) from the lookup map
243  // used by the error handler
245 
246  m_pDatabase = tds_alloc_socket(m_pContext, 512);
247  if (m_pDatabase == NULL)
248  {
249  //fprintf(stderr, "tds_alloc_socket() failed.\n");
250  SetError(wxDATABASE_ERROR, wxT("Failed to allocate socket"));
251  // Reset the variables so there are not mistaken as initialized
252  m_pDatabase = NULL;
253  if (m_pLogin)
254  {
255  tds_free_login(m_pLogin);
256  m_pLogin = NULL;
257  }
258  if (m_pContext)
259  {
260  tds_free_context(m_pContext);
261  m_pContext = NULL;
262  }
264  return false;
265  }
266  tds_set_parent(m_pDatabase, NULL);
267 
268  TDSLOGIN* pConnection = tds_read_config_info(NULL, m_pLogin, m_pContext->locale);
269 
270  if (!pConnection || tds_connect_and_login(m_pDatabase, pConnection) == TDS_FAIL)
271  {
272  if (pConnection)
273  {
274  tds_free_socket(m_pDatabase);
275  //m_pDatabase = NULL;
276  tds_free_login(pConnection);
277  }
278  //fprintf(stderr, "tds_connect() failed\n");
279  if (GetErrorCode() == wxDATABASE_OK)
280  {
281  SetError(wxDATABASE_ERROR, wxT("Database connection failed"));
282  }
283  // Reset the variables so there are not mistaken as initialized
284  m_pDatabase = NULL;
285  if (m_pLogin)
286  {
287  tds_free_login(m_pLogin);
288  m_pLogin = NULL;
289  }
290  if (m_pContext)
291  {
292  tds_free_context(m_pContext);
293  m_pContext = NULL;
294  }
296  return false;
297  }
298  tds_free_login(pConnection);
299 
300  return true;
301 }
302 
303 // close database
305 {
306  //puts("Resetting error codes");
307  ResetErrorCodes();
308 
309  //puts("Closing result sets");
310  CloseResultSets();
311  //puts("Closing statements");
312  CloseStatements();
313 
314  if (m_pDatabase != NULL)
315  {
316  //puts("Freeing socket");
317  tds_free_socket(m_pDatabase);
318  m_pDatabase = NULL;
319  }
320  if (m_pLogin != NULL)
321  {
322  //puts("Freeing login");
323  tds_free_login(m_pLogin);
324  m_pLogin = NULL;
325  }
326  if (m_pContext != NULL)
327  {
328  // Remove the context (and this databaselayer) from the lookup map
329  // used by the error handler
330  //puts("Removing TDS layer from hash");
332 
333  // Free the context
334  //puts("Freeing context");
335  tds_free_context(m_pContext);
336  m_pContext = NULL;
337  }
338 
339  return true;
340 }
341 
343 {
344  return (m_pDatabase != NULL);
345 }
346 
347 void wxTdsDatabase::FreeAllocatedResultSets(/*AML start*/status_t* status/*AML end*/)
348 {
349  //fprintf(stderr, "In FreeAllocatedResultSets\n");
350  int rc;
351  int result_type;
352  //while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCESS)
353  while ((rc = tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)) == TDS_SUCCESS)
354  {
355  switch (result_type)
356  {
357  case TDS_DONE_RESULT:
358  case TDS_DONEPROC_RESULT:
359  case TDS_DONEINPROC_RESULT:
360  case TDS_STATUS_RESULT:
361  case TDS_ROWFMT_RESULT:
362  case TDS_COMPUTEFMT_RESULT:
363  case TDS_DESCRIBE_RESULT:
364  break;
365  case TDS_ROW_RESULT:
366  //fprintf(stderr, "Warning (%d): wxTdsDatabase query should not return results. Type: %d\n", result_type, result_type);
367  if (m_pDatabase->current_results && m_pDatabase->current_results->num_cols > 0)
368  {
369  while (tds_process_tokens(m_pDatabase, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW) == /*AML TDS_SUCCEED*/TDS_SUCCESS)
370  {
371  //fprintf(stderr, "Warning: wxTdsDatabase TDS_ROW_RESULT query should not return results. Type: %d\n", result_type);
372  if (result_type != TDS_ROW_RESULT)
373  break;
374 
375  if (!m_pDatabase->current_results)
376  continue;
377  }
378  }
379  if (m_pDatabase != NULL)
380  tds_free_all_results(m_pDatabase);
381  return;
382  break;
383  default:
384  //fprintf(stderr, "Error: wxTdsDatabase query should not return results. Type: %d\n", result_type);
385  return;
386  //break;
387  }
388  }
389 
390  //AML start
391  if (m_pDatabase != NULL && status != NULL)
392  {
393  status->has = m_pDatabase->has_status;
394  status->ret = m_pDatabase->ret_status;
395  }
396  //AML end
397 
398  // Make sure to clean up after ourselves
399  if (m_pDatabase != NULL)
400  tds_free_all_results(m_pDatabase);
401 
402  if (rc == TDS_FAIL)
403  {
405  //fprintf(stderr, "tds_process_tokens() returned TDS_FAIL\n");
406  return;
407  }
408  else if (rc != TDS_NO_MORE_RESULTS)
409  {
411  //fprintf(stderr, "tds_process_tokens() unexpected return\n");
412  return;
413  }
414 }
415 
417 {
418  wxLogDebug(_("Beginning transaction"));
419  RunQuery(_("begin transaction;"), false);
420 }
421 
423 {
424  wxLogDebug(_("Commiting transaction"));
425  RunQuery(_("commit transaction;"), false);
426 }
427 
429 {
430  wxLogDebug(_("Rolling back transaction"));
431  RunQuery(_("rollback transaction;"), false);
432 }
433 
434 // query database
435 int wxTdsDatabase::RunQuery(const wxString& strQuery, bool bParseQuery)
436 {
437  ResetErrorCodes();
438 
439  if (m_pDatabase == NULL)
440  return false;
441 
443 
444  wxArrayString QueryArray;
445  if (bParseQuery)
446  QueryArray = ParseQueries(strQuery);
447  else
448  QueryArray.push_back(strQuery);
449 
450  wxArrayString::iterator start = QueryArray.begin();
451  wxArrayString::iterator stop = QueryArray.end();
452 
453  //AML start
454  status_t status;
455  status.has = false;
456  status.ret = 0;
457  //AML end
458 
459  while (start != stop)
460  {
461  //char* szErrorMessage = NULL;
462  wxString strErrorMessage = _("");
463  wxString sql = RemoveLastSemiColon(*start);
464  wxCharBuffer sqlBuffer = ConvertToUnicodeStream(sql);
465 
466  //fprintf(stderr, "Running query '%s'\n", (const char*)sqlBuffer);
467  int nReturn = tds_submit_query(m_pDatabase, sqlBuffer);
468  if (nReturn != /*AML TDS_SUCCEED*/TDS_SUCCESS)
469  {
470  //fprintf(stderr, "tds_submit_query() failed for query '%s'\n", sqlBuffer);
471  //fprintf(stderr, "tds_submit_query() failed for query '%s'\n", (sql).c_str());
474  return false;
475  }
476  FreeAllocatedResultSets(/*AML start*/&status/*AML end*/);
477 
478  start++;
479  }
480  //AML start
481  //AML return true;
482  return (status.has ? status.ret : m_pDatabase->rows_affected);
483  //AML end
484 }
485 
487 {
488  ResetErrorCodes();
489 
490  if (m_pDatabase != NULL)
491  {
493 
494  wxArrayString QueryArray = ParseQueries(strQuery);
495 
496  for (unsigned int i=0; i<(QueryArray.size()-1); i++)
497  {
498  //char* szErrorMessage = NULL;
499  wxString strErrorMessage = _("");
500  wxString sql = RemoveLastSemiColon(QueryArray[i]);
501  wxCharBuffer sqlBuffer = ConvertToUnicodeStream(sql);
502 
503  //fprintf(stderr, "Running query '%s'\n", sqlBuffer);
504  int nReturn = tds_submit_query(m_pDatabase, sqlBuffer);
505  if (nReturn != TDS_SUCCESS)
506  {
507  //fprintf(stderr, "tds_submit_query() failed for query '%s'\n", sql.c_str());
510  return NULL;
511  }
513  }
514 
515  // Create a Prepared statement for the last SQL statement and get a result set from it
516  wxString strQuery = RemoveLastSemiColon(QueryArray[QueryArray.size()-1]);
517  wxCharBuffer sqlBuffer = ConvertToUnicodeStream(strQuery);
518  //fprintf(stderr, "Running query (with results) '%s'\n", sqlBuffer);
519  int nReturn = tds_submit_query(m_pDatabase, sqlBuffer);
520  if (nReturn != /*AML TDS_SUCCEED*/TDS_SUCCESS)
521  {
522  //fprintf(stderr, "tds_submit_query() failed for query '%s'\n", sqlBuffer);
523  //fprintf(stderr, "tds_submit_query() failed for query '%s'\n", strQuery.c_str());
526  return NULL;
527  }
528  wxTdsResultSet* pResultSet = new wxTdsResultSet(m_pDatabase);
529  if (pResultSet)
530  pResultSet->SetEncoding(GetEncoding());
531 
532  LogResultSetForCleanup(pResultSet);
533  //fprintf(stderr, "Returning result set\n");
534  return pResultSet;
535  }
536  else
537  {
538  return NULL;
539  }
540 }
541 
542 wxPreparedStatement* wxTdsDatabase::PrepareStatement(const wxString& strQuery)
543 {
544  ResetErrorCodes();
545 
546  if (m_pDatabase != NULL)
547  {
548  wxString sql = RemoveLastSemiColon(strQuery);
549 
550  wxCharBuffer sqlBuffer = ConvertToUnicodeStream(sql);
551  TDSDYNAMIC* pStatement = NULL;
552  TDSPARAMINFO* pParameters = GetParameters(strQuery);
553  int nReturn = tds_submit_prepare(m_pDatabase, sqlBuffer, NULL, &pStatement, pParameters);
554  if (nReturn != TDS_SUCCESS)
555  {
556  //fprintf(stderr, "tds_submit_prepare() failed for query '%s'\n", strQuery.c_str());
557 
558  if (pStatement != NULL)
559  tds_release_dynamic(&pStatement);
560 
563  return NULL;
564  }
565  if (pParameters != NULL)
566  tds_free_param_results(pParameters);
568 
569  wxTdsPreparedStatement* pReturnStatement = new wxTdsPreparedStatement(m_pDatabase, pStatement, strQuery);
570  if (pReturnStatement)
571  pReturnStatement->SetEncoding(GetEncoding());
572 
573  if (pReturnStatement != NULL)
574  LogStatementForCleanup(pReturnStatement);
575  return pReturnStatement;
576  }
577  else
578  {
579  return NULL;
580  }
581 }
582 
583 bool wxTdsDatabase::TableExists(const wxString& table)
584 {
585  // Initialize variables
586  bool bReturn = false;
587  // Keep these variables outside of scope so that we can clean them up
588  // in case of an error
589  wxPreparedStatement* pStatement = NULL;
590  wxDatabaseResultSet* pResult = NULL;
591 
592 #if wxUSE_DATABASE_EXCEPTIONS
593  try
594  {
595 #endif
596  wxString query = _("exec sp_tables ?, NULL, NULL, '''TABLE'''");
597  pStatement = PrepareStatement(query);
598  if (pStatement)
599  {
600  pStatement->SetParamString(1, table);
601  pResult = pStatement->ExecuteQuery();
602  if (pResult)
603  {
604  if (pResult->Next())
605  {
606  //wxPrintf(_("Table found: '%s'\n"), pResult->GetResultString(_("TABLE_NAME")));
607  if(table.CmpNoCase(pResult->GetResultString(_("TABLE_NAME"))) == 0)
608  {
609  bReturn = true;
610  }
611  }
612  }
613  }
614 #if wxUSE_DATABASE_EXCEPTIONS
615  }
616  catch (wxDatabaseException& e)
617  {
618  if (pResult != NULL)
619  {
620  CloseResultSet(pResult);
621  pResult = NULL;
622  }
623 
624  if (pStatement != NULL)
625  {
626  CloseStatement(pStatement);
627  pStatement = NULL;
628  }
629 
630  throw e;
631  }
632 #endif
633 
634  if (pResult != NULL)
635  {
636  CloseResultSet(pResult);
637  pResult = NULL;
638  }
639 
640  if (pStatement != NULL)
641  {
642  CloseStatement(pStatement);
643  pStatement = NULL;
644  }
645 
646  return bReturn;
647 }
648 
649 bool wxTdsDatabase::ViewExists(const wxString& view)
650 {
651  bool bReturn = false;
652  // Keep these variables outside of scope so that we can clean them up
653  // in case of an error
654  wxPreparedStatement* pStatement = NULL;
655  wxDatabaseResultSet* pResult = NULL;
656 
657 #if wxUSE_DATABASE_EXCEPTIONS
658  try
659  {
660 #endif
661  wxString query = _("exec sp_tables ?, NULL, NULL, '''VIEW'''");
662  pStatement = PrepareStatement(query);
663  if (pStatement)
664  {
665  pStatement->SetParamString(1, view);
666  pResult = pStatement->ExecuteQuery();
667  if (pResult)
668  {
669  if (pResult->Next())
670  {
671  //wxPrintf(_("View found: '%s'\n"), pResult->GetResultString(_("TABLE_NAME")));
672  if(view.CmpNoCase(pResult->GetResultString(_("TABLE_NAME"))) == 0)
673  {
674  bReturn = true;
675  }
676  }
677  }
678  }
679 #if wxUSE_DATABASE_EXCEPTIONS
680  }
681  catch (wxDatabaseException& e)
682  {
683  if (pResult != NULL)
684  {
685  CloseResultSet(pResult);
686  pResult = NULL;
687  }
688 
689  if (pStatement != NULL)
690  {
691  CloseStatement(pStatement);
692  pStatement = NULL;
693  }
694 
695  throw e;
696  }
697 #endif
698 
699  if (pResult != NULL)
700  {
701  CloseResultSet(pResult);
702  pResult = NULL;
703  }
704 
705  if (pStatement != NULL)
706  {
707  CloseStatement(pStatement);
708  pStatement = NULL;
709  }
710 
711  return bReturn;
712 }
713 
714 wxArrayString wxTdsDatabase::GetTables()
715 {
716  wxArrayString returnArray;
717 
718  wxDatabaseResultSet* pResult = NULL;
719 #if wxUSE_DATABASE_EXCEPTIONS
720  try
721  {
722 #endif
723  wxString query = _("sp_tables NULL, NULL, NULL, '''TABLE'''");
724  pResult = ExecuteQuery(query);
725 
726  while (pResult->Next())
727  {
728  //wxPrintf(_("Adding table: '%s'\n"), pResult->GetResultString(_("TABLE_NAME")).Trim());
729  returnArray.Add(pResult->GetResultString(_("TABLE_NAME")).Trim());
730  }
731 #if wxUSE_DATABASE_EXCEPTIONS
732  }
733  catch (wxDatabaseException& e)
734  {
735  if (pResult != NULL)
736  {
737  CloseResultSet(pResult);
738  pResult = NULL;
739  }
740 
741  throw e;
742  }
743 #endif
744 
745  if (pResult != NULL)
746  {
747  CloseResultSet(pResult);
748  pResult = NULL;
749  }
750 
751  return returnArray;
752 }
753 
754 wxArrayString wxTdsDatabase::GetViews()
755 {
756  wxArrayString returnArray;
757 
758  wxDatabaseResultSet* pResult = NULL;
759 #if wxUSE_DATABASE_EXCEPTIONS
760  try
761  {
762 #endif
763  wxString query = _("sp_tables NULL, NULL, NULL, '''VIEW'''");
764  pResult = ExecuteQuery(query);
765 
766  while (pResult->Next())
767  {
768  //wxPrintf(_("Adding view: '%s'\n"), pResult->GetResultString(_("TABLE_NAME")).Trim());
769  returnArray.Add(pResult->GetResultString(_("TABLE_NAME")).Trim());
770  }
771 #if wxUSE_DATABASE_EXCEPTIONS
772  }
773  catch (wxDatabaseException& e)
774  {
775  if (pResult != NULL)
776  {
777  CloseResultSet(pResult);
778  pResult = NULL;
779  }
780 
781  throw e;
782  }
783 #endif
784 
785  if (pResult != NULL)
786  {
787  CloseResultSet(pResult);
788  pResult = NULL;
789  }
790 
791  return returnArray;
792 }
793 
794 wxArrayString wxTdsDatabase::GetColumns(const wxString& table)
795 {
796  wxArrayString returnArray;
797 
798  wxDatabaseResultSet* pResult = NULL;
799 #if wxUSE_DATABASE_EXCEPTIONS
800  try
801  {
802 #endif
803  wxString query = wxString::Format(_("sp_columns %s;"), table.c_str());
804  pResult = ExecuteQuery(query);
805 
806  while (pResult->Next())
807  {
808  //wxPrintf(_("Adding column: '%s'\n"), pResult->GetResultString(_("COLUMN_NAME")).Trim());
809  returnArray.Add(pResult->GetResultString(_("COLUMN_NAME")).Trim());
810  }
811 #if wxUSE_DATABASE_EXCEPTIONS
812  }
813  catch (wxDatabaseException& e)
814  {
815  if (pResult != NULL)
816  {
817  CloseResultSet(pResult);
818  pResult = NULL;
819  }
820 
821  throw e;
822  }
823 #endif
824 
825  if (pResult != NULL)
826  {
827  CloseResultSet(pResult);
828  pResult = NULL;
829  }
830 
831  return returnArray;
832 }
833 
834 wxArrayString wxTdsDatabase::GetPKColumns(const wxString& table)
835 {
836  wxArrayString returnArray;
837 
838  // Keep these variables outside of scope so that we can clean them up
839  // in case of an error
840  wxDatabaseResultSet* pResult = NULL;
841 #if wxUSE_DATABASE_EXCEPTIONS
842  try
843  {
844 #endif
845  wxString query = wxString::Format(_("sp_pkeys %s;"), table.c_str());
846  pResult = ExecuteQuery(query);
847 
848  while (pResult->Next())
849  {
850  //wxPrintf(_("Adding column: '%s'\n"), pResult->GetResultString(_("COLUMN_NAME")).Trim());
851  returnArray.Add(pResult->GetResultString(_("COLUMN_NAME")).Trim());
852  }
853 #if wxUSE_DATABASE_EXCEPTIONS
854  }
855  catch (wxDatabaseException& e)
856  {
857  if (pResult != NULL)
858  {
859  CloseResultSet(pResult);
860  pResult = NULL;
861  }
862 
863  throw e;
864  }
865 #endif
866 
867  if (pResult != NULL)
868  {
869  CloseResultSet(pResult);
870  pResult = NULL;
871  }
872 
873  return returnArray;
874 }
875 
876 void wxTdsDatabase::SetError(int nCode, const wxString& strMessage)
877 {
879  wxString msg = GetErrorMessage();
880  if (msg.Length() > 0)
881  {
882  msg += "\n" + strMessage;
883  }
884  else
885  {
886  msg = strMessage;
887  }
888  SetErrorMessage(msg);
889 
890  // We really don't want to throw the exception here since it removes
891  // the ability of the calling code to cleanup any memory usage
892  //wxPrintf(_("wxTdsDatabase SetError() throwing exception\n"));
893  //ThrowDatabaseException();
894 }
895 
897 {
898  // Ultimately, this will probably be a map of TDS database error code values to wxDatabase values
899  // For now though, we'll just return error
900  int nReturn = nCode;
901  return nReturn;
902 }
903 
904 wxTdsDatabase* wxTdsDatabase::LookupTdsLayer(const TDSCONTEXT* pContext)
905 {
906  wxTdsDatabase* pLayer = NULL;
907  TdsContextToDatabaseLayerMap::iterator finder = wxTdsDatabase::m_ContextLookupMap.find(pContext);
908  if (finder != wxTdsDatabase::m_ContextLookupMap.end())
909  pLayer = finder->second;
910 
911  return pLayer;
912 }
913 
914 void wxTdsDatabase::AddTdsLayer(TDSCONTEXT* pContext, wxTdsDatabase* pLayer)
915 {
916  wxTdsDatabase::m_ContextLookupMap[pContext] = pLayer;
917 }
918 
919 void wxTdsDatabase::RemoveTdsLayer(TDSCONTEXT* pContext)
920 {
921  wxTdsDatabase::m_ContextLookupMap.erase(pContext);
922 }
923 
924 TDSPARAMINFO* wxTdsDatabase::GetParameters(const wxString& strQuery)
925 {
926  TDSPARAMINFO* params = NULL;
927  wxChar previous = '\0';
928  bool bUnicode = false;
929  bool bInStringLiteral = false;
930  for (size_t i = 0; i < strQuery.length(); i++)
931  {
932  wxChar character = strQuery[i];
933  if ('\'' == character)
934  {
935  // Signify that we are inside a string literal inside the SQL
936  bInStringLiteral = !bInStringLiteral;
937  // Is it a unicode string literal
938  if (bInStringLiteral && previous == 'N') bUnicode = true;
939  }
940  else if (('?' == character) && !bInStringLiteral)
941  {
942  params = tds_alloc_param_result(params);
943  TDSCOLUMN* col = params->columns[params->num_cols-1];
944  if (bUnicode)
945  {
946  tds_set_param_type(m_pDatabase->conn, col, XSYBNVARCHAR);
947  col->column_varint_size = 8;
948  }
949  else
950  {
951  tds_set_param_type(m_pDatabase->conn, col, XSYBVARCHAR);
952  col->column_size = 8000;
953  col->on_server.column_size = 8000;
954  col->column_cur_size = 8000;
955  }
956  bUnicode = false;
957  }
958  previous = character;
959  }
960  return params;
961 }
962 
963 #endif//wxUSE_DATABASE_TDS
virtual bool ViewExists(const wxString &view)
Check for the existence of a view by name.
wxString m_strFreeTDS
Definition: tds_database.h:95
virtual void RollBack()
Rollback the current transaction.
wxString m_strDatabase
Definition: tds_database.h:97
virtual bool IsOpen()
Is the connection to the database open?
virtual wxArrayString GetPKColumns(const wxString &table)
get Primary keys column names
static wxTdsDatabase * LookupTdsLayer(const TDSCONTEXT *pContext)
virtual wxString GetResultString(int nField)=0
Retrieve a wxString from the result set by the 1-based field index.
TDSLOGIN * m_pLogin
Definition: tds_database.h:103
TDSSOCKET * m_pDatabase
Definition: tds_database.h:102
wxDatabaseResultSet * ExecuteQuery(const wxString &strQuery)
See RunQueryWithResults.
Definition: database.h:64
static void AddTdsLayer(TDSCONTEXT *pContext, wxTdsDatabase *pLayer)
virtual wxPreparedStatement * PrepareStatement(const wxString &strQuery)
Prepare a SQL statement which can be reused with different parameters.
virtual int RunQuery(const wxString &strQuery, bool bParseQuery)
Run an insert, update, or delete query on the database.
virtual ~wxTdsDatabase()
wxString m_strPassword
Definition: tds_database.h:99
const wxString & GetErrorMessage()
#define wxDATABASE_OK
Definition: errorcodes.h:4
wxString m_strLogin
Definition: tds_database.h:98
virtual wxArrayString GetColumns(const wxString &table)
Retrieve all column names for a table.
virtual void Commit()
Commit the current transaction.
virtual bool CloseStatement(wxPreparedStatement *pStatement)
Close a prepared statement previously prepared by the database.
Definition: database.cpp:95
static int TranslateErrorCode(int nCode)
#define wxDATABASE_ERROR
Definition: errorcodes.h:5
virtual wxDatabaseResultSet * RunQueryWithResults(const wxString &strQuery)
Run a select query on the database.
virtual wxArrayString GetViews()
Retrieve all view names.
virtual bool Open(const wxString &strDatabase)
void SetErrorMessage(const wxString &strErrorMessage)
wxDatabaseResultSet * ExecuteQuery()
See RunQueryWithResults.
void SetError(int nCode, const wxString &strMessage)
virtual bool Next()=0
Move to the next record in the result set.
wxArrayString ParseQueries(const wxString &strQuery)
void LogStatementForCleanup(wxPreparedStatement *pStatement)
Add prepared statement object pointer to the list for "garbage collection".
Definition: database.h:183
static TdsContextToDatabaseLayerMap m_ContextLookupMap
Definition: tds_database.h:93
void SetEncoding(wxFontEncoding encoding)
void LogResultSetForCleanup(wxDatabaseResultSet *pResultSet)
Add result set object pointer to the list for "garbage collection".
Definition: database.h:181
static void RemoveTdsLayer(TDSCONTEXT *pContext)
virtual wxArrayString GetTables()
Retrieve all table names.
wxString m_strServer
Definition: tds_database.h:96
TDSCONTEXT * m_pContext
Definition: tds_database.h:104
void SetErrorCode(int nErrorCode)
void CloseStatements()
Close all prepared statement objects that have been generated but not yet closed.
Definition: database.cpp:38
virtual wxString ConvertFromUnicodeStream(const char *inputBuffer)
const wxCSConv * GetEncoding()
virtual bool Close()
close database
virtual const wxCharBuffer ConvertToUnicodeStream(const wxString &inputString)
void FreeAllocatedResultSets(status_t *status=NULL)
virtual void BeginTransaction()
Begin a transaction.
virtual bool TableExists(const wxString &table)
Check for the existence of a table by name.
TDSPARAMINFO * GetParameters(const wxString &strQuery)
void CloseResultSets()
Close all result set objects that have been generated but not yet closed.
Definition: database.cpp:24
virtual bool CloseResultSet(wxDatabaseResultSet *pResultSet)
Close a result set returned by the database or a prepared statement previously.
Definition: database.cpp:52
virtual void SetParamString(int nPosition, const wxString &strValue)=0
Set the parameter at the 1-based position to a wxString value.