]> git.saurik.com Git - wxWidgets.git/blob - src/common/odbc.cpp
bug in SplitPath() corrected - now ".." handled correctly
[wxWidgets.git] / src / common / odbc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: odbc.cpp
3 // Purpose: ODBC implementation
4 // Author: Julian Smart, Olaf Klein (oklein@smallo.ruhr.de),
5 // Patrick Halke (patrick@zaphod.ruhr.de)
6 // Modified by:
7 // Created: 04/01/98
8 // RCS-ID: $Id$
9 // Copyright: (c) Julian Smart and Markus Holzem
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifdef __GNUG__
14 #pragma implementation "odbc.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "wx/defs.h"
25
26 #if USE_ODBC
27
28 #ifndef WX_PRECOMP
29 #include "wx/utils.h"
30 #include "wx/dialog.h"
31 #endif
32
33 #include "wx/string.h"
34 #include "wx/odbc.h"
35
36 #include <math.h>
37 #include <stdlib.h>
38
39 #if defined(__WINDOWS__) && !defined(__WIN32__)
40 #include <print.h>
41 #endif
42
43 HENV wxDatabase::hEnv = 0;
44 int wxDatabase::refCount = 0;
45
46 #if !USE_SHARED_LIBRARY
47 IMPLEMENT_DYNAMIC_CLASS(wxDatabase, wxObject)
48 IMPLEMENT_DYNAMIC_CLASS(wxQueryCol, wxObject)
49 IMPLEMENT_DYNAMIC_CLASS(wxQueryField, wxObject)
50 IMPLEMENT_DYNAMIC_CLASS(wxRecordSet, wxObject)
51 #endif
52
53 wxDatabase::wxDatabase(void)
54 {
55 hDBC = 0;
56 username = NULL;
57 password = NULL;
58 datasource = NULL;
59 dbname = NULL;
60 connectstring = NULL;
61 isOpen = FALSE;
62 refCount ++;
63 retcode = 0;
64 username = NULL;
65 password = NULL;
66 err_occured = FALSE;
67
68 memset(sqlstate, 0, sizeof sqlstate);
69 memset(errmsg, 0, sizeof errmsg);
70
71 if (hEnv == 0)
72 {
73 retcode = SQLAllocEnv(&hEnv);
74
75 if (retcode != SQL_SUCCESS)
76 hEnv = 0;
77 }
78 }
79
80 wxDatabase::~wxDatabase(void)
81 {
82 Close();
83 DeleteRecordSets(); // Added JACS
84
85 if (connectstring)
86 delete[] connectstring;
87 if (datasource)
88 delete[] datasource;
89 if (username)
90 delete[] username;
91 if (password)
92 delete[] password;
93 if (dbname)
94 delete[] dbname;
95
96 refCount --;
97 if (!refCount && hEnv)
98 {
99 retcode = SQLFreeEnv(hEnv);
100 hEnv = 0; // JACS 17/6
101 }
102 }
103
104 void wxDatabase::ErrorSnapshot(HSTMT hstmt)
105 {
106 SWORD len = 0; // JACS: sometimes doesn't get filled in by SQLError.
107
108 err_occured = TRUE;
109 SQLError(hEnv, hDBC, hstmt, (unsigned char *)sqlstate, &nat_err, (unsigned char *)errmsg, SQL_MAX_MESSAGE_LENGTH-1, &len);
110 errmsg[len] = '\0';
111 }
112
113 bool wxDatabase::ErrorOccured(void)
114 {
115 return err_occured;
116 }
117
118 char* wxDatabase::GetErrorMessage(void)
119 {
120 return errmsg;
121 }
122
123 long wxDatabase::GetErrorNumber(void)
124 {
125 return nat_err;
126 }
127
128 char* wxDatabase::GetErrorClass(void) {
129 return sqlstate;
130 }
131
132 bool wxDatabase::Open(char *thedatasource, bool exclusive, bool readOnly, char *username, char *password)
133 {
134 err_occured = FALSE;
135
136 if (isOpen)
137 return FALSE;
138
139 SetUsername(username);
140 SetPassword(password);
141 SetDataSource(thedatasource);
142
143 if (!hEnv)
144 return FALSE;
145
146 retcode = SQLAllocConnect(hEnv, &hDBC);
147 if (retcode != SQL_SUCCESS) {
148 hDBC = 0;
149 return FALSE;
150 }
151
152 retcode = SQLConnect(hDBC, (UCHAR FAR*)thedatasource, strlen(thedatasource), (UCHAR FAR*)username, strlen(username),
153 (UCHAR FAR*)password, strlen(password));
154
155 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
156 ErrorSnapshot();
157 return FALSE;
158 }
159
160 isOpen = TRUE;
161
162 return TRUE;
163 }
164
165 bool wxDatabase::Close(void)
166 {
167 // JACS: make sure the record set statements are all released.
168 ResetRecordSets();
169
170 err_occured = FALSE;
171 if (hDBC != 0)
172 {
173 retcode = SQLDisconnect(hDBC);
174
175 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
176 ErrorSnapshot();
177 return FALSE;
178 }
179
180 retcode = SQLFreeConnect(hDBC);
181
182 hDBC = 0;
183 isOpen = FALSE;
184
185 return TRUE;
186 }
187
188 return FALSE;
189 }
190
191 // Database attributes
192 char *wxDatabase::GetDatabaseName(void)
193 {
194 err_occured = FALSE;
195 if (hDBC == 0)
196 return NULL;
197
198 char nameBuf[400];
199 int nameSize = 0;
200
201 retcode = SQLGetInfo(hDBC, SQL_DATABASE_NAME, nameBuf, sizeof(nameBuf), (short *)&nameSize);
202
203 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
204 return NULL;
205
206 delete[] dbname;
207 dbname = NULL;
208
209 if (nameSize > 0)
210 {
211 dbname = copystring(nameBuf);
212 return dbname;
213 }
214 else
215 return NULL;
216 }
217
218 bool wxDatabase::CanUpdate(void)
219 {
220 return FALSE;
221 }
222
223 bool wxDatabase::CanTransact(void)
224 {
225 return FALSE;
226 }
227
228 bool wxDatabase::InWaitForDataSource(void)
229 {
230 return FALSE;
231 }
232
233 void wxDatabase::SetLoginTimeout(long seconds)
234 {
235 }
236
237 void wxDatabase::SetQueryTimeout(long seconds)
238 {
239 }
240
241 void wxDatabase::SetSynchronousMode(bool synchronous)
242 {
243 }
244
245 // Database operations
246 bool wxDatabase::BeginTrans(void)
247 {
248 return FALSE;
249 }
250
251 bool wxDatabase::CommitTrans(void)
252 {
253 return FALSE;
254 }
255
256 bool wxDatabase::RollbackTrans(void)
257 {
258 return FALSE;
259 }
260
261 void wxDatabase::Cancel(void)
262 {
263 }
264
265 // Overridables
266 void wxDatabase::OnSetOptions(wxRecordSet *recordSet)
267 {
268 }
269
270 void wxDatabase::OnWaitForDataSource(bool stillExecuting)
271 {
272 }
273
274 void wxDatabase::SetPassword(char *s)
275 {
276 if (password)
277 delete[] password;
278 if (s)
279 {
280 password = copystring(s);
281 }
282 else
283 password = NULL;
284 }
285
286 void wxDatabase::SetUsername(char *s)
287 {
288 delete[] username;
289
290 if (s)
291 username = copystring(s);
292 else
293 username = NULL;
294 }
295
296 void wxDatabase::SetDataSource(char *s)
297 {
298 delete[] datasource;
299
300 if (s)
301 datasource = copystring(s);
302 else
303 datasource = NULL;
304 }
305
306 /*
307 * Added by JACS
308 */
309
310 void wxDatabase::DeleteRecordSets(void)
311 {
312 wxNode *node = recordSets.First();
313 while (node)
314 {
315 wxNode *next = node->Next();
316 wxRecordSet *rec = (wxRecordSet *)node->Data();
317 delete rec;
318 // The node is implicitly deleted by ~wxRecordSet
319 node = next;
320 }
321 }
322
323 void wxDatabase::ResetRecordSets(void)
324 {
325 wxNode *node = recordSets.First();
326 while (node)
327 {
328 wxRecordSet *rec = (wxRecordSet *)node->Data();
329 rec->ReleaseHandle();
330
331 node = node->Next();
332 }
333 }
334
335 bool wxDatabase::GetInfo(long infoType, long *buf)
336 {
337 short sz = 0;
338 retcode = SQLGetInfo(hDBC, (UWORD)infoType, (char *)buf, sizeof(buf), &sz);
339
340 if (retcode != SQL_ERROR)
341 return TRUE;
342 else
343 return FALSE;
344 }
345
346 bool wxDatabase::GetInfo(long infoType, char *buf, int bufSize)
347 {
348 if (bufSize == -1)
349 bufSize = sizeof(buf);
350
351 short sz = 0;
352 retcode = SQLGetInfo(hDBC, (UWORD)infoType, buf, bufSize, &sz);
353
354 if (retcode != SQL_ERROR)
355 return TRUE;
356 else
357 return FALSE;
358 }
359
360 wxString wxDatabase::GetODBCVersionString(bool implementation)
361 {
362 char buf[50];
363 if (!implementation)
364 {
365 #ifdef SQL_SPEC_MAJOR
366 sprintf(buf, "%d%d.%d", (int)(SQL_SPEC_MAJOR/10), (int)(SQL_SPEC_MAJOR - (((int)(SQL_SPEC_MAJOR/10))*10)),
367 SQL_SPEC_MINOR);
368 return wxString(buf);
369 #else
370 return wxString("00.00");
371 #endif
372 }
373
374 bool noDBC = FALSE;
375 if (hDBC == 0)
376 {
377 noDBC = TRUE;
378 retcode = SQLAllocConnect(hEnv, &hDBC);
379 if (retcode != SQL_SUCCESS)
380 {
381 hDBC = 0;
382 return wxString("00.00");
383 }
384 }
385
386 int bufSize = sizeof(buf);
387
388 short sz = 0;
389 retcode = SQLGetInfo(hDBC, (UWORD)SQL_ODBC_VER, buf, bufSize, &sz);
390
391 if (hDBC != 0 && noDBC)
392 {
393 retcode = SQLFreeConnect(hDBC);
394 hDBC = 0;
395 }
396
397 if (retcode == SQL_ERROR)
398 return wxString("");
399 else
400 return wxString(buf);
401 }
402
403 float wxDatabase::GetODBCVersionFloat(bool implementation)
404 {
405 if (!implementation)
406 {
407 #ifdef SQL_SPEC_MAJOR
408 return (float)(SQL_SPEC_MAJOR + (SQL_SPEC_MINOR/100.0));
409 #else
410 return 0.0;
411 #endif
412 }
413
414 bool noDBC = FALSE;
415 if (hDBC == 0)
416 {
417 noDBC = TRUE;
418 retcode = SQLAllocConnect(hEnv, &hDBC);
419 if (retcode != SQL_SUCCESS)
420 {
421 hDBC = 0;
422 return (float)0.0;
423 }
424 }
425
426 char buf[50];
427 int bufSize = sizeof(buf);
428
429 short sz = 0;
430 retcode = SQLGetInfo(hDBC, (UWORD)SQL_ODBC_VER, buf, bufSize, &sz);
431
432 if (hDBC != 0 && noDBC)
433 {
434 retcode = SQLFreeConnect(hDBC);
435 hDBC = 0;
436 }
437
438 if (retcode == SQL_ERROR)
439 return 0.0;
440 else
441 return atof(buf);
442 }
443
444 /*
445 * wxRecordSet
446 */
447
448 wxRecordSet::wxRecordSet(wxDatabase *db, int typ, int opt):
449 cols(wxKEY_STRING)
450 {
451 parentdb = db;
452 hStmt = 0;
453 nFields = 0;
454 nParams = 0;
455 recordFilter = NULL;
456 sortString = NULL;
457 retcode = 0;
458 cursor = 0;
459 tablename = NULL;
460 nCols = 0;
461 nRecords = 0;
462
463 type = typ;
464 options = opt;
465
466 // Added JACS
467 if (parentdb)
468 parentdb->GetRecordSets().Append(this);
469 }
470
471 wxRecordSet::~wxRecordSet(void)
472 {
473 ReleaseHandle();
474
475 // JACS
476 if (parentdb)
477 parentdb->GetRecordSets().DeleteObject(this);
478
479 if (recordFilter)
480 delete[] recordFilter;
481 if (sortString)
482 delete[] sortString;
483 if (tablename)
484 delete[] tablename;
485 }
486
487 // If SQL is non-NULL, table and columns can be NULL.
488 bool wxRecordSet::BeginQuery(int openType, char *sql, int options)
489 {
490 // Needs to construct an appropriate SQL statement. By default
491 // (i.e. if table and columns are provided) then
492 // SELECT <columns> FROM <table>
493 // will be used.
494 if (!parentdb)
495 return FALSE;
496 if (!parentdb->GetHDBC())
497 return FALSE;
498
499 if (hStmt)
500 {
501 retcode = SQLFreeStmt(hStmt, SQL_DROP);
502 if (retcode == SQL_ERROR)
503 {
504 parentdb->ErrorSnapshot(hStmt);
505 return FALSE;
506 }
507 hStmt = 0;
508 }
509
510 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
511 if (retcode != SQL_SUCCESS)
512 return FALSE;
513
514 return TRUE;
515 }
516
517 bool wxRecordSet::Query(char *columns, char *table, char *filter)
518 {
519 // Needs to construct an appropriate SQL statement. By default
520 // (i.e. if table and columns are provided) then
521 // SELECT <columns> FROM <table>
522 // will be used.
523
524 char* thetable = table ? table : tablename;
525
526 if (!thetable)
527 return FALSE;
528 if (!columns)
529 return FALSE;
530
531 wxString query;
532
533 query += "SELECT ";
534 query += columns;
535 query += " FROM ";
536 query += thetable;
537
538 if (filter) {
539 query += " WHERE ";
540 query += filter;
541 }
542 retcode = SQLPrepare(hStmt, (UCHAR FAR *)query.GetData(), strlen(query.GetData()));
543 if (retcode != SQL_SUCCESS) {
544 parentdb->ErrorSnapshot(hStmt);
545 return FALSE;
546 }
547
548 retcode = SQLExecute(hStmt);
549
550 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
551 parentdb->ErrorSnapshot(hStmt);
552 return FALSE;
553 }
554
555 return TRUE;
556 }
557
558 bool wxRecordSet::EndQuery(void)
559 {
560 return TRUE;
561 }
562
563 void wxRecordSet::FillVars(int recnum) {
564 wxNode* node = cols.First();
565
566 do {
567 ((wxQueryCol*)node->Data())->FillVar(recnum);
568 } while (node = node->Next());
569 }
570
571 bool wxRecordSet::GetResultSet(void)
572 {
573 // long trash = SQL_NULL_DATA; // value added by JACS
574 long trash;
575 // contains the number of bytes transferred by SQLFetch()
576 // who needs this ?
577 wxNode *currow, *fetch, *curcol;
578
579 retcode = SQLNumResultCols(hStmt, &nCols);
580
581 if (!nCols)
582 return TRUE;
583
584 // delete old data first
585 cols.DeleteContents(TRUE);
586 cols.Clear();
587 fetchbuf.DeleteContents(TRUE);
588 fetchbuf.Clear();
589
590 nRecords = 0;
591 cursor = 0;
592
593 int i;
594 for (i=0; i<nCols; i++) {
595 char name[512];
596 short type, scale, nullable, namelen;
597 unsigned long len;
598
599 retcode = SQLDescribeCol(hStmt, i+1, (unsigned char *)name, 511, &namelen, &type, &len, &scale, &nullable);
600 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
601 parentdb->ErrorSnapshot(hStmt);
602 return FALSE;
603 }
604
605 wxQueryCol *col1 = new wxQueryCol;
606 curcol = cols.Append(name, col1);
607 col1->SetName(name);
608 col1->SetType(type);
609 col1->SetNullable(nullable);
610
611 wxQueryField *field1 = new wxQueryField;
612 fetch = fetchbuf.Append(field1);
613 field1->SetType(type);
614 field1->SetSize(len);
615
616 SQLBindCol(hStmt, i+1, SQL_C_BINARY, field1->GetData(), field1->GetSize(), &trash);
617 }
618
619 switch (type) {
620 case wxOPEN_TYPE_SNAPSHOT:
621 // get it all !
622 // After we've done an SQLFetch, copy the data in the fetch buffer into
623 // new fields, for each column.
624 while (SQL_SUCCESS == (retcode = SQLFetch(hStmt)) || SQL_SUCCESS_WITH_INFO == retcode) {
625 nRecords++;
626
627 curcol = cols.First();
628 fetch = fetchbuf.First();
629 for (i=0; i<nCols; i++) {
630
631 wxQueryField *fetchField = (wxQueryField *)fetch->Data();
632 wxQueryCol *col = (wxQueryCol *)curcol->Data();
633 wxQueryField *field = new wxQueryField;
634
635 currow = col->fields.Append(field);
636
637 field->SetType(fetchField->GetType());
638 field->SetData(fetchField->GetData(), fetchField->GetSize());
639 curcol = curcol->Next();
640 fetchField->ClearData(); // Runs ok if this commented out and SetData commented out
641 fetch = fetch->Next();
642 }
643 }
644 // while loop should only be left, when no more data was found;
645 // otherwise it seems, that there was an error
646 if (SQL_NO_DATA_FOUND != retcode) {
647 parentdb->ErrorSnapshot(hStmt);
648 return FALSE;
649 }
650 break;
651 case wxOPEN_TYPE_DYNASET:
652 // get first record only
653 if (SQL_SUCCESS == (retcode = SQLFetch(hStmt)) || retcode == SQL_SUCCESS_WITH_INFO) {
654 nRecords = 1; // TO DO! # of records in the ODBC result set should be set here.
655
656 curcol = cols.First();
657 fetch = fetchbuf.First();
658 for (i=0; i<nCols; i++) {
659 currow = ((wxQueryCol*)curcol->Data())->fields.Append(new wxQueryField);
660
661 ((wxQueryField*)currow->Data())->SetType(((wxQueryField*)fetch->Data())->GetType());
662 ((wxQueryField*)currow->Data())->SetData(((wxQueryField*)fetch->Data())->GetData(), ((wxQueryField*)fetch->Data())->GetSize());
663 curcol = curcol->Next();
664 ((wxQueryField*)fetch->Data())->ClearData();
665 fetch = fetch->Next();
666 }
667 }
668 if (SQL_NO_DATA_FOUND != retcode) {
669 parentdb->ErrorSnapshot(hStmt);
670 return FALSE;
671 }
672 break;
673 default:
674 return FALSE;
675 }
676
677 FillVars(0);
678
679 return TRUE;
680 }
681
682 bool wxRecordSet::ExecuteSQL(char *sql)
683 {
684 if (hStmt)
685 {
686 retcode = SQLFreeStmt(hStmt, SQL_DROP);
687 if (retcode == SQL_ERROR)
688 {
689 parentdb->ErrorSnapshot(hStmt);
690 return FALSE;
691 }
692 hStmt = NULL;
693 }
694
695 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
696
697 if (SQL_SUCCESS != retcode) {
698 parentdb->ErrorSnapshot(hStmt);
699 return FALSE;
700 }
701
702 retcode = SQLExecDirect(hStmt, (UCHAR FAR*)sql, SQL_NTS);
703
704 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
705 parentdb->ErrorSnapshot(hStmt);
706 return FALSE;
707 }
708
709 return GetResultSet();
710 }
711
712 bool wxRecordSet::GetDataSources(void) {
713
714 char *dsname = "Name", *dsdesc = "Description";
715 char namebuf[64];
716 char descbuf[512];
717 short namelen, desclen;
718
719 cursor = 0;
720
721 // delete old data first
722 cols.DeleteContents(TRUE);
723 cols.Clear();
724 nRecords = 0;
725
726 // JACS This is a snapshot, not a dynaset.
727 type = wxOPEN_TYPE_SNAPSHOT;
728
729 wxNode *namecol, *desccol;
730
731 namecol = cols.Append(dsname, new wxQueryCol);
732 ((wxQueryCol*)namecol->Data())->SetName(dsname);
733 ((wxQueryCol*)namecol->Data())->SetType(SQL_CHAR);
734 desccol = cols.Append(dsdesc, new wxQueryCol);
735 ((wxQueryCol*)desccol->Data())->SetName(dsdesc);
736 ((wxQueryCol*)desccol->Data())->SetType(SQL_CHAR);
737
738 retcode = SQLDataSources(parentdb->GetHENV(), SQL_FETCH_FIRST, (unsigned char *)namebuf, 63, &namelen, (unsigned char *)descbuf, 511, &desclen);
739 while (SQL_SUCCESS == retcode || SQL_SUCCESS_WITH_INFO == retcode) {
740 nRecords++;
741 ((wxQueryCol*)namecol->Data())->AppendField(namebuf, namelen);
742 ((wxQueryCol*)desccol->Data())->AppendField(descbuf, desclen);
743 retcode = SQLDataSources(parentdb->GetHENV(), SQL_FETCH_NEXT, (unsigned char *)namebuf, 63, &namelen, (unsigned char *)descbuf, 511, &desclen);
744 }
745
746 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode && SQL_NO_DATA_FOUND != retcode) {
747 parentdb->ErrorSnapshot();
748 return FALSE;
749 }
750
751 cursor = 0;
752
753 return TRUE;
754 }
755
756 // Attributes
757 void wxRecordSet::SetTableName(char* name) {
758 delete[] tablename;
759 tablename = NULL;
760
761 if (name)
762 tablename = copystring(name);
763 }
764
765 bool wxRecordSet::GetTables(void)
766 {
767 if (hStmt)
768 {
769 retcode = SQLFreeStmt(hStmt, SQL_DROP);
770 if (retcode == SQL_ERROR)
771 {
772 parentdb->ErrorSnapshot(hStmt);
773 return FALSE;
774 }
775
776 hStmt = NULL;
777 }
778
779 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
780
781 if (SQL_SUCCESS != retcode) {
782 parentdb->ErrorSnapshot();
783 return FALSE;
784 }
785
786 retcode = SQLTables(hStmt, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
787
788 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
789 parentdb->ErrorSnapshot(hStmt);
790 return FALSE;
791 }
792
793 return GetResultSet();
794 }
795
796 bool wxRecordSet::GetColumns(char* table)
797 {
798 char* name=NULL;
799 char* wildcard = "%";
800
801 name = table ? table : tablename;
802
803 if (!name)
804 return FALSE;
805
806 if (hStmt)
807 {
808 retcode = SQLFreeStmt(hStmt, SQL_DROP);
809 if (retcode == SQL_ERROR)
810 {
811 parentdb->ErrorSnapshot(hStmt);
812 return FALSE;
813 }
814 hStmt = NULL;
815 }
816
817 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
818
819 if (SQL_SUCCESS != retcode) {
820 parentdb->ErrorSnapshot();
821 return FALSE;
822 }
823
824 //retcode = SQLColumns(hstmt, (unsigned char*)parentdb->GetDataSource(), strlen(parentdb->GetDataSource()), wildcard, 1, name, strlen(name), wildcard, 1);
825 retcode = SQLColumns(hStmt, NULL, 0, NULL, 0, (unsigned char *)name, strlen(name), NULL, 0);
826
827 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
828 parentdb->ErrorSnapshot(hStmt);
829 return FALSE;
830 }
831
832 return GetResultSet();
833 }
834
835 // It is derived from previous GetColumns
836 bool wxRecordSet::GetPrimaryKeys(char* table)
837 {
838 char* name=NULL;
839 char* wildcard = "%";
840
841 name = table ? table : tablename;
842
843 if (!name)
844 return FALSE;
845
846 if (hStmt)
847 {
848 retcode = SQLFreeStmt(hStmt, SQL_DROP);
849 if (retcode == SQL_ERROR)
850 {
851 parentdb->ErrorSnapshot(hStmt);
852 return FALSE;
853 }
854 hStmt = NULL;
855 }
856
857 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
858
859 if (SQL_SUCCESS != retcode) {
860 parentdb->ErrorSnapshot();
861 return FALSE;
862 }
863
864 retcode = SQLPrimaryKeys(hStmt, NULL, 0, NULL, 0, (unsigned char *)name, SQL_NTS);
865
866 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
867 parentdb->ErrorSnapshot(hStmt);
868 return FALSE;
869 }
870
871 return GetResultSet();
872 }
873
874 bool wxRecordSet::GetForeignKeys(char* PkTableName, char * FkTableName)
875 {
876 char* Pkname=NULL;
877 char* Fkname=NULL;
878 char* wildcard = "%";
879
880 // Try to disable situation: both PkTableName and FkTableName are NULL
881 // set Pkname from tablename
882 if( !PkTableName && !FkTableName ) {
883 Pkname = PkTableName ? PkTableName : tablename;
884 Fkname = FkTableName ;
885 if (!Pkname )
886 return FALSE;
887 } else {
888 Pkname = PkTableName ;
889 Fkname = FkTableName ;
890 }
891
892 if (hStmt)
893 {
894 retcode = SQLFreeStmt(hStmt, SQL_DROP);
895 if (retcode == SQL_ERROR)
896 {
897 parentdb->ErrorSnapshot(hStmt);
898 return FALSE;
899 }
900 hStmt = NULL;
901 }
902
903 retcode = SQLAllocStmt(parentdb->GetHDBC(), &hStmt);
904
905 if (SQL_SUCCESS != retcode) {
906 parentdb->ErrorSnapshot();
907 return FALSE;
908 }
909
910 retcode = SQLForeignKeys(hStmt, NULL, 0, NULL, 0, (unsigned char *)Pkname,
911 (Pkname ? SQL_NTS : 0), NULL, 0, NULL, 0, (unsigned char *)Fkname ,(Fkname ?SQL_NTS : 0) );
912
913 if (SQL_SUCCESS != retcode && SQL_SUCCESS_WITH_INFO != retcode) {
914 parentdb->ErrorSnapshot(hStmt);
915 return FALSE;
916 }
917
918 return GetResultSet();
919 }
920
921 long wxRecordSet::GetNumberRecords(void)
922 {
923 return nRecords;
924 }
925
926 long wxRecordSet::GetNumberCols(void)
927 {
928 return nCols;
929 }
930
931 char* wxRecordSet::GetColName(int col)
932 {
933 wxNode* node = cols.Nth(col);
934
935 if (!node)
936 return NULL;
937
938 return ((wxQueryCol*)node->Data())->GetName();
939 }
940
941 short wxRecordSet::GetColType(int col)
942 {
943 wxNode* node = cols.Nth(col);
944
945 if (!node)
946 return SQL_TYPE_NULL;
947
948 return ((wxQueryCol*)node->Data())->GetType();
949 }
950
951 short wxRecordSet::GetColType(const char *col)
952 {
953 wxNode* node = cols.Find(col);
954
955 if (!node)
956 return SQL_TYPE_NULL;
957
958 return ((wxQueryCol*)node->Data())->GetType();
959 }
960
961 bool wxRecordSet::GetFieldData(int col, int type, void* data)
962 {
963 wxNode* node = cols.Nth(col);
964
965 if (!node)
966 return FALSE;
967
968 if (((wxQueryCol*)node->Data())->GetType() != type)
969 return FALSE;
970
971 void* src = ((wxQueryCol*)node->Data())->GetData(cursor);
972
973 if (!src)
974 return FALSE;
975
976 memcpy(data, src, ((wxQueryCol*)node->Data())->GetSize(cursor));
977
978 return TRUE;
979 }
980
981 bool wxRecordSet::GetFieldData(const char* name, int type, void *data)
982 {
983 wxNode* node = cols.Find(name);
984
985 if (!node)
986 return FALSE;
987
988 if (((wxQueryCol*)node->Data())->GetType() != type)
989 return FALSE;
990
991 void* src = ((wxQueryCol*)node->Data())->GetData(cursor);
992
993 if (!src)
994 return FALSE;
995
996 memcpy(data, src, ((wxQueryCol*)node->Data())->GetSize(cursor));
997
998 return TRUE;
999 }
1000
1001 void* wxRecordSet::GetFieldDataPtr(int col, int type)
1002 {
1003 wxNode* node = cols.Nth(col);
1004
1005 if (!node)
1006 return NULL;
1007
1008 if (((wxQueryCol*)node->Data())->GetType() != type)
1009 return NULL;
1010
1011 return ((wxQueryCol*)node->Data())->GetData(cursor);
1012 }
1013
1014 void* wxRecordSet::GetFieldDataPtr(const char* name, int type)
1015 {
1016 wxNode* node = cols.Find(name);
1017
1018 if (!node)
1019 return NULL;
1020
1021 if (((wxQueryCol*)node->Data())->GetType() != type)
1022 return NULL;
1023
1024 return ((wxQueryCol*)node->Data())->GetData(cursor);
1025 }
1026
1027 void* wxRecordSet::BindVar(int col, void* var, long size) {
1028 wxNode* node = cols.Nth(col);
1029
1030 if (!node)
1031 return NULL;
1032
1033 return ((wxQueryCol*)node->Data())->BindVar(var, size);
1034 }
1035
1036 void* wxRecordSet::BindVar(const char* name, void* var, long size) {
1037 wxNode* node = cols.Find(name);
1038
1039 if (!node)
1040 return NULL;
1041
1042 return ((wxQueryCol*)node->Data())->BindVar(var, size);
1043 }
1044
1045 void wxRecordSet::SetType(int typ) {
1046 type = typ;
1047 }
1048
1049 int wxRecordSet::GetType(void) {
1050 return type;
1051 }
1052
1053 void wxRecordSet::SetOptions(int opts) {
1054 options = opts;
1055 }
1056
1057 int wxRecordSet::GetOptions(void) {
1058 return options;
1059 }
1060
1061 bool wxRecordSet::CanAppend(void)
1062 {
1063 return FALSE;
1064 }
1065
1066 bool wxRecordSet::CanRestart(void)
1067 {
1068 return FALSE;
1069 }
1070
1071 bool wxRecordSet::CanScroll(void)
1072 {
1073 return FALSE;
1074 }
1075
1076 bool wxRecordSet::CanTransact(void)
1077 {
1078 return FALSE;
1079 }
1080
1081 bool wxRecordSet::CanUpdate(void)
1082 {
1083 return FALSE;
1084 }
1085
1086 long wxRecordSet::GetCurrentRecord(void)
1087 {
1088 return -1L;
1089 }
1090
1091 bool wxRecordSet::RecordCountFinal(void)
1092 {
1093 return FALSE;
1094 }
1095
1096 char* wxRecordSet::GetTableName(void)
1097 {
1098 return tablename;
1099 }
1100
1101 char *wxRecordSet::GetSQL(void)
1102 {
1103 return NULL;
1104 }
1105
1106 bool wxRecordSet::IsOpen(void)
1107 {
1108 return parentdb->IsOpen();
1109 }
1110
1111 bool wxRecordSet::IsBOF(void)
1112 {
1113 return cursor < 0;
1114 }
1115
1116 bool wxRecordSet::IsEOF(void)
1117 {
1118 return cursor >= nRecords;
1119 }
1120
1121 bool wxRecordSet::IsDeleted(void)
1122 {
1123 return FALSE;
1124 }
1125
1126 // Update operations
1127 void wxRecordSet::AddNew(void)
1128 {
1129 }
1130
1131 bool wxRecordSet::Delete(void)
1132 {
1133 return FALSE;
1134 }
1135
1136 void wxRecordSet::Edit(void)
1137 {
1138 }
1139
1140 bool wxRecordSet::Update(void)
1141 {
1142 return FALSE;
1143 }
1144
1145 // Record navigation
1146 bool wxRecordSet::Move(long rows)
1147 {
1148 if (!nRecords) {
1149 cursor = -1;
1150 return FALSE;
1151 }
1152
1153 switch (type) {
1154 case wxOPEN_TYPE_SNAPSHOT:
1155 cursor += (int)rows;
1156 if (cursor < 0) {
1157 cursor = -1;
1158 return FALSE;
1159 }
1160 if (cursor > nRecords-1) {
1161 cursor = nRecords;
1162 return FALSE;
1163 }
1164 return TRUE;
1165
1166 case wxOPEN_TYPE_DYNASET:
1167 return FALSE;
1168 default:
1169 return FALSE;
1170 }
1171 }
1172
1173 bool wxRecordSet::GoTo(long row)
1174 {
1175 if (!nRecords) {
1176 cursor = -1;
1177 return FALSE;
1178 }
1179
1180 switch (type) {
1181 case wxOPEN_TYPE_SNAPSHOT:
1182 cursor = (int)row;
1183 if (cursor < 0) {
1184 cursor = -1;
1185 return FALSE;
1186 }
1187 if (cursor > nRecords-1) {
1188 cursor = nRecords;
1189 return FALSE;
1190 }
1191 return TRUE;
1192
1193 case wxOPEN_TYPE_DYNASET:
1194 return FALSE;
1195 default:
1196 return FALSE;
1197 }
1198 }
1199
1200 bool wxRecordSet::MoveFirst(void)
1201 {
1202 if (!nRecords) {
1203 cursor = -1;
1204 return FALSE;
1205 }
1206
1207 switch (type) {
1208 case wxOPEN_TYPE_SNAPSHOT:
1209 cursor = 0;
1210 return TRUE;
1211
1212 case wxOPEN_TYPE_DYNASET:
1213 return FALSE;
1214 default:
1215 return FALSE;
1216 }
1217 }
1218
1219 bool wxRecordSet::MoveLast(void)
1220 {
1221 if (!nRecords) {
1222 cursor = -1;
1223 return FALSE;
1224 }
1225
1226 switch (type) {
1227 case wxOPEN_TYPE_SNAPSHOT:
1228 cursor = nRecords-1;
1229 return TRUE;
1230
1231 case wxOPEN_TYPE_DYNASET:
1232 return FALSE;
1233 default:
1234 return FALSE;
1235 }
1236 }
1237
1238 bool wxRecordSet::MoveNext(void)
1239 {
1240 if (!nRecords) {
1241 cursor = -1;
1242 return FALSE;
1243 }
1244
1245 switch (type) {
1246 case wxOPEN_TYPE_SNAPSHOT:
1247 cursor++;
1248 if (cursor >= nRecords) {
1249 cursor = nRecords;
1250 return FALSE;
1251 }
1252 return TRUE;
1253
1254 case wxOPEN_TYPE_DYNASET:
1255 return FALSE;
1256 default:
1257 return FALSE;
1258 }
1259 }
1260
1261 bool wxRecordSet::MovePrev(void)
1262 {
1263 if (!nRecords) {
1264 cursor = -1;
1265 return FALSE;
1266 }
1267
1268 switch (type) {
1269 case wxOPEN_TYPE_SNAPSHOT:
1270 cursor--;
1271 if (cursor < 0) {
1272 cursor = 0;
1273 return FALSE;
1274 }
1275 return TRUE;
1276
1277 case wxOPEN_TYPE_DYNASET:
1278 return FALSE;
1279 default:
1280 return FALSE;
1281 }
1282 }
1283
1284 // Others
1285 void wxRecordSet::Cancel(void)
1286 {
1287 }
1288
1289 bool wxRecordSet::IsFieldDirty(int col)
1290 {
1291 wxNode* node = cols.Nth(col);
1292
1293 if (!node)
1294 return FALSE;
1295
1296 return ((wxQueryCol*)node->Data())->IsFieldDirty(cursor);
1297 }
1298
1299 bool wxRecordSet::IsFieldDirty(const char* name)
1300 {
1301 wxNode* node = cols.Find(name);
1302
1303 if (!node)
1304 return FALSE;
1305
1306 return ((wxQueryCol*)node->Data())->IsFieldDirty(cursor);
1307 }
1308
1309 bool wxRecordSet::IsFieldNull(int col)
1310 {
1311 wxNode* node = cols.Nth(col);
1312
1313 if (!node)
1314 return TRUE;
1315
1316 return NULL != ((wxQueryCol*)node->Data())->GetData(cursor);
1317 }
1318
1319 bool wxRecordSet::IsFieldNull(const char* name)
1320 {
1321 wxNode* node = cols.Find(name);
1322
1323 if (!node)
1324 return TRUE;
1325
1326 return NULL != ((wxQueryCol*)node->Data())->GetData(cursor);
1327 }
1328
1329 bool wxRecordSet::IsColNullable(int col)
1330 {
1331 wxNode* node = cols.Nth(col);
1332
1333 if (!node)
1334 return FALSE;
1335
1336 return ((wxQueryCol*)node->Data())->IsNullable();
1337 }
1338
1339 bool wxRecordSet::IsColNullable(const char* name)
1340 {
1341 wxNode* node = cols.Find(name);
1342
1343 if (!node)
1344 return FALSE;
1345
1346 return ((wxQueryCol*)node->Data())->IsNullable();
1347 }
1348
1349 bool wxRecordSet::Requery(void)
1350 {
1351 return FALSE;
1352 }
1353
1354 void wxRecordSet::SetFieldDirty(int col, bool dirty)
1355 {
1356 wxNode* node = cols.Nth(col);
1357
1358 if (!node)
1359 return;
1360
1361 ((wxQueryCol*)node->Data())->SetFieldDirty(cursor, dirty);
1362 }
1363
1364 void wxRecordSet::SetFieldDirty(const char* name, bool dirty)
1365 {
1366 wxNode* node = cols.Find(name);
1367
1368 if (!node)
1369 return;
1370
1371 ((wxQueryCol*)node->Data())->SetFieldDirty(cursor, dirty);
1372 }
1373
1374 void wxRecordSet::SetFieldNull(void *p, bool isNull)
1375 {
1376 }
1377
1378 // Overridables
1379 char *wxRecordSet::GetDefaultConnect(void)
1380 {
1381 return NULL;
1382 }
1383
1384 char *wxRecordSet::GetDefaultSQL(void)
1385 {
1386 return NULL;
1387 }
1388
1389 void wxRecordSet::SetDefaultSQL(char *s)
1390 {
1391 delete[] defaultSQL;
1392
1393 if (s)
1394 defaultSQL = copystring(s);
1395 else
1396 defaultSQL = NULL;
1397 }
1398
1399 // Build SQL query from column specification
1400 bool wxRecordSet::ConstructDefaultSQL(void)
1401 {
1402 // if (queryCols.Number() == 0)
1403 return FALSE;
1404 }
1405
1406 bool wxRecordSet::ReleaseHandle(void)
1407 {
1408 if (hStmt)
1409 {
1410 retcode = SQLFreeStmt(hStmt, SQL_DROP);
1411 if (retcode == SQL_ERROR)
1412 {
1413 if (parentdb)
1414 parentdb->ErrorSnapshot(hStmt);
1415 return FALSE;
1416 }
1417 hStmt = 0;
1418 }
1419 return TRUE;
1420 }
1421
1422 wxQueryCol::wxQueryCol(void) {
1423 // __type = wxTYPE_QUERYCOL;
1424 name = NULL;
1425 type = SQL_TYPE_NULL;
1426 nullable = FALSE;
1427 var = NULL;
1428 varsize = 0;
1429 }
1430
1431 wxQueryCol::~wxQueryCol(void) {
1432 // delete all data
1433 fields.DeleteContents(TRUE);
1434 fields.Clear();
1435
1436 if (name)
1437 delete[] name;
1438 }
1439
1440 void wxQueryCol::SetName(char* n) {
1441 name = new char[strlen(n)+1];
1442 strcpy(name, n);
1443 }
1444
1445 bool wxQueryCol::SetData(int row, void* buf, long len) {
1446 wxNode* node = fields.Nth(row);
1447
1448 if (!node)
1449 return FALSE;
1450
1451 return ((wxQueryField*)node->Data())->SetData(buf, len);
1452 }
1453
1454 void wxQueryCol::SetFieldDirty(int row, bool dirty) {
1455 wxNode* node = fields.Nth(row);
1456
1457 if (!node)
1458 return;
1459
1460 ((wxQueryField*)node->Data())->SetDirty(dirty);
1461 }
1462
1463 void wxQueryCol::AppendField(void* buf, long len) {
1464 wxNode* node = fields.Append(new wxQueryField);
1465 ((wxQueryField*)node->Data())->SetType(type);
1466 ((wxQueryField*)node->Data())->SetData(buf, len);
1467 }
1468
1469 void wxQueryCol::SetType(short t) {
1470 type = t;
1471 }
1472
1473 void* wxQueryCol::BindVar(void* v, long s) {
1474 void* oldvar = var;
1475
1476 var = v;
1477 varsize = s;
1478
1479 return oldvar;
1480 }
1481
1482 void wxQueryCol::FillVar(int recnum) {
1483 if (!var)
1484 return;
1485
1486 wxNode* node = fields.Nth(recnum);
1487
1488 if (!node)
1489 return;
1490
1491 long actsize = ((wxQueryField*)node->Data())->GetSize();
1492 if (actsize > varsize)
1493 actsize = varsize;
1494
1495 memcpy(var, ((wxQueryField*)node->Data())->GetData(), actsize);
1496 }
1497
1498 void wxQueryCol::SetNullable(bool n) {
1499 nullable = n;
1500 }
1501
1502 char* wxQueryCol::GetName(void) {
1503 return name;
1504 }
1505
1506 short wxQueryCol::GetType(void) {
1507 return type;
1508 }
1509
1510 bool wxQueryCol::IsNullable(void) {
1511 return nullable;
1512 }
1513
1514
1515 bool wxQueryCol::IsFieldDirty(int row) {
1516 wxNode* node = fields.Nth(row);
1517
1518 if (!node)
1519 return FALSE;
1520
1521 return ((wxQueryField*)node->Data())->IsDirty();
1522 }
1523
1524 void* wxQueryCol::GetData(int row) {
1525 wxNode* node = fields.Nth(row);
1526
1527 if (!node)
1528 return NULL;
1529
1530 return ((wxQueryField*)node->Data())->GetData();
1531 }
1532
1533 long wxQueryCol::GetSize(int row) {
1534 wxNode* node = fields.Nth(row);
1535
1536 if (!node)
1537 return NULL;
1538
1539 return ((wxQueryField*)node->Data())->GetSize();
1540 }
1541
1542 wxQueryField::wxQueryField(void) {
1543 // __type = wxTYPE_QUERYROW;
1544 data = NULL;
1545 type = SQL_TYPE_NULL;
1546 size = 0;
1547 dirty = FALSE;
1548 }
1549
1550 wxQueryField::~wxQueryField(void) {
1551 switch (type)
1552 {
1553 case SQL_NUMERIC:
1554 case SQL_DECIMAL:
1555 case SQL_CHAR:
1556 case SQL_VARCHAR:
1557 if (data) // JACS
1558 delete[] (char*)data;
1559 break;
1560 case SQL_INTEGER:
1561 if (data) // JACS
1562 delete (long*)data;
1563 break;
1564 case SQL_SMALLINT:
1565 if (data)
1566 delete (short*)data;
1567 break;
1568 case SQL_FLOAT:
1569 case SQL_DOUBLE:
1570 if (data)
1571 delete (double*)data;
1572 break;
1573 case SQL_REAL:
1574 if (data)
1575 delete (float*)data;
1576 break;
1577 case SQL_TIME:
1578 if (data)
1579 delete (TIME_STRUCT *)data;
1580 break;
1581 case SQL_DATE:
1582 if (data)
1583 delete (DATE_STRUCT *)data;
1584 break;
1585 case SQL_TIMESTAMP:
1586 if (data)
1587 delete (TIMESTAMP_STRUCT *)data;
1588 break;
1589 }
1590 }
1591
1592 bool wxQueryField::AllocData(void) {
1593 switch (type)
1594 {
1595 case SQL_NUMERIC:
1596 case SQL_DECIMAL:
1597 case SQL_CHAR:
1598 case SQL_VARCHAR:
1599 {
1600 if (data) // JACS
1601 delete[] (char*)data;
1602 if (data = new char[size+1])
1603 {
1604 char *str = (char *)data;
1605 int i;
1606 for (i = 0; i < size; i++)
1607 str[i] = 0;
1608 // memset(data, 0, size+1);
1609 }
1610 break;
1611 }
1612 case SQL_INTEGER:
1613 {
1614 if (data) // JACS
1615 delete (long*)data;
1616 if (data = new long)
1617 *(long*)data = 0L;
1618 break;
1619 }
1620 case SQL_SMALLINT:
1621 {
1622 if (data)
1623 delete (short*)data;
1624 if (data = new short)
1625 *(short*)data = 0;
1626 break;
1627 }
1628 case SQL_FLOAT:
1629 case SQL_DOUBLE:
1630 {
1631 if (data)
1632 delete (double*)data;
1633 if (data = new double)
1634 *(double*)data = 0;
1635 break;
1636 }
1637 case SQL_REAL:
1638 {
1639 if (data)
1640 delete (float*)data;
1641 if (data = new float)
1642 *(float*)data = (float)0;
1643 break;
1644 }
1645 case SQL_TIME:
1646 {
1647 if (data)
1648 delete (TIME_STRUCT *)data;
1649 data = new TIME_STRUCT;
1650 memset(data, 0, sizeof(TIME_STRUCT));
1651 break;
1652 }
1653 case SQL_DATE:
1654 {
1655 if (data)
1656 delete (DATE_STRUCT *)data;
1657 data = new DATE_STRUCT;
1658 memset(data, 0, sizeof(DATE_STRUCT));
1659 break;
1660 }
1661 case SQL_TIMESTAMP:
1662 {
1663 if (data)
1664 delete (TIMESTAMP_STRUCT *)data;
1665 data = new TIMESTAMP_STRUCT;
1666 memset(data, 0, sizeof(TIMESTAMP_STRUCT));
1667 break;
1668 }
1669 default:
1670 return FALSE;
1671 }
1672
1673 return TRUE;
1674 }
1675
1676 bool wxQueryField::SetData(void* d, long s) {
1677 size = s;
1678 if (AllocData() && d)
1679 {
1680 // memcpy(data, d, s);
1681 switch (type)
1682 {
1683 case SQL_NUMERIC:
1684 case SQL_DECIMAL:
1685 case SQL_CHAR:
1686 case SQL_VARCHAR:
1687 {
1688 char *str = (char *)data;
1689 int i;
1690 for (i = 0; i < size; i++)
1691 str[i] = 0;
1692
1693 strncpy(str, (char *)d, (int)size);
1694 str[size] = 0;
1695 break;
1696 }
1697 case SQL_INTEGER:
1698 {
1699 *(long*)data = *((long *)d);
1700 break;
1701 }
1702 case SQL_SMALLINT:
1703 {
1704 *(short*)data = *((short*)d);
1705 break;
1706 }
1707 case SQL_FLOAT:
1708 case SQL_DOUBLE:
1709 {
1710 *(double*)data = *((double*)d);
1711 break;
1712 }
1713 case SQL_REAL:
1714 {
1715 *(float*)data = *((float*)d);
1716 break;
1717 }
1718 case SQL_TIME:
1719 {
1720 *(TIME_STRUCT *)data = *((TIME_STRUCT*)d);
1721 break;
1722 }
1723 case SQL_TIMESTAMP:
1724 {
1725 *(TIMESTAMP_STRUCT *)data = *((TIMESTAMP_STRUCT*)d);
1726 break;
1727 }
1728 case SQL_DATE:
1729 {
1730 *(DATE_STRUCT *)data = *((DATE_STRUCT*)d);
1731 break;
1732 }
1733 default:
1734 return FALSE;
1735 }
1736 return TRUE;
1737 }
1738 return FALSE;
1739 }
1740
1741 void wxQueryField::ClearData(void) {
1742 if (data)
1743 {
1744 // memset(data, 0, size);
1745 switch (type)
1746 {
1747 case SQL_NUMERIC:
1748 case SQL_DECIMAL:
1749 case SQL_CHAR:
1750 case SQL_VARCHAR:
1751 {
1752 char *str = (char *)data;
1753 int i;
1754 for (i = 0; i < size; i++)
1755 str[i] = 0;
1756 break;
1757 }
1758 case SQL_INTEGER:
1759 {
1760 *(long*)data = 0L;
1761 break;
1762 }
1763 case SQL_SMALLINT:
1764 {
1765 *(short*)data = 0;
1766 break;
1767 }
1768 case SQL_FLOAT:
1769 case SQL_DOUBLE:
1770 {
1771 *(double*)data = (double)0.0;
1772 break;
1773 }
1774 case SQL_REAL:
1775 {
1776 *(float*)data = (float)0.0;
1777 break;
1778 }
1779 case SQL_TIME:
1780 {
1781 memset(data, 0, sizeof(TIME_STRUCT));
1782 break;
1783 }
1784 case SQL_DATE:
1785 {
1786 memset(data, 0, sizeof(DATE_STRUCT));
1787 break;
1788 }
1789 case SQL_TIMESTAMP:
1790 {
1791 memset(data, 0, sizeof(TIMESTAMP_STRUCT));
1792 break;
1793 }
1794 default:
1795 return;
1796 }
1797 }
1798 }
1799
1800 void wxQueryField::SetDirty(bool d) {
1801 dirty = d;
1802 }
1803
1804 void wxQueryField::SetType(short t) {
1805 type = t;
1806 }
1807
1808 void wxQueryField::SetSize(long s) {
1809 size = s;
1810 AllocData();
1811 }
1812
1813 void* wxQueryField::GetData(void) {
1814 return data;
1815 }
1816
1817 short wxQueryField::GetType(void) {
1818 return type;
1819 }
1820
1821 long wxQueryField::GetSize(void) {
1822 return size;
1823 }
1824
1825 bool wxQueryField::IsDirty(void) {
1826 return dirty;
1827 }
1828
1829 #endif // USE_ODBC