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