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