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