]> git.saurik.com Git - wxWidgets.git/blame - src/common/odbc.cpp
Added #include to get FIONBIO on Solaris 2.6
[wxWidgets.git] / src / common / odbc.cpp
CommitLineData
c801d85f
KB
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
2049ba38 39#if defined(__WXMSW__) && !defined(__WIN32__)
c801d85f
KB
40#include <print.h>
41#endif
42
43HENV wxDatabase::hEnv = 0;
44int wxDatabase::refCount = 0;
45
46#if !USE_SHARED_LIBRARY
47IMPLEMENT_DYNAMIC_CLASS(wxDatabase, wxObject)
48IMPLEMENT_DYNAMIC_CLASS(wxQueryCol, wxObject)
49IMPLEMENT_DYNAMIC_CLASS(wxQueryField, wxObject)
50IMPLEMENT_DYNAMIC_CLASS(wxRecordSet, wxObject)
51#endif
52
53wxDatabase::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
80wxDatabase::~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
104void 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
113bool wxDatabase::ErrorOccured(void)
114{
115 return err_occured;
116}
117
118char* wxDatabase::GetErrorMessage(void)
119{
120 return errmsg;
121}
122
123long wxDatabase::GetErrorNumber(void)
124{
125 return nat_err;
126}
127
128char* wxDatabase::GetErrorClass(void) {
129 return sqlstate;
130}
131
46dc76ba
RR
132bool wxDatabase::Open(char *thedatasource, bool WXUNUSED(exclusive),
133 bool WXUNUSED(readOnly), char *username, char *password)
c801d85f
KB
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
166bool 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
193char *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
46dc76ba 202 retcode = SQLGetInfo(hDBC, SQL_DATABASE_NAME, (unsigned char*)nameBuf, sizeof(nameBuf), (short *)&nameSize);
c801d85f
KB
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
219bool wxDatabase::CanUpdate(void)
220{
221 return FALSE;
222}
223
224bool wxDatabase::CanTransact(void)
225{
226 return FALSE;
227}
228
229bool wxDatabase::InWaitForDataSource(void)
230{
231 return FALSE;
232}
233
46dc76ba 234void wxDatabase::SetLoginTimeout(long WXUNUSED(seconds))
c801d85f
KB
235{
236}
237
46dc76ba 238void wxDatabase::SetQueryTimeout(long WXUNUSED(seconds))
c801d85f
KB
239{
240}
241
46dc76ba 242void wxDatabase::SetSynchronousMode(bool WXUNUSED(synchronous))
c801d85f
KB
243{
244}
245
246// Database operations
247bool wxDatabase::BeginTrans(void)
248{
249 return FALSE;
250}
251
252bool wxDatabase::CommitTrans(void)
253{
254 return FALSE;
255}
256
257bool wxDatabase::RollbackTrans(void)
258{
259 return FALSE;
260}
261
262void wxDatabase::Cancel(void)
263{
264}
265
266// Overridables
46dc76ba 267void wxDatabase::OnSetOptions(wxRecordSet *WXUNUSED(recordSet))
c801d85f
KB
268{
269}
270
46dc76ba 271void wxDatabase::OnWaitForDataSource(bool WXUNUSED(stillExecuting))
c801d85f
KB
272{
273}
274
275void 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
287void wxDatabase::SetUsername(char *s)
288{
289 delete[] username;
290
291 if (s)
292 username = copystring(s);
293 else
294 username = NULL;
295}
296
297void 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
311void 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
324void 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
336bool wxDatabase::GetInfo(long infoType, long *buf)
337{
338 short sz = 0;
46dc76ba 339 retcode = SQLGetInfo(hDBC, (UWORD)infoType, (unsigned char*)buf, sizeof(buf), &sz);
c801d85f
KB
340
341 if (retcode != SQL_ERROR)
342 return TRUE;
343 else
344 return FALSE;
345}
346
347bool wxDatabase::GetInfo(long infoType, char *buf, int bufSize)
348{
349 if (bufSize == -1)
350 bufSize = sizeof(buf);
351
352 short sz = 0;
46dc76ba 353 retcode = SQLGetInfo(hDBC, (UWORD)infoType, (unsigned char*)buf, bufSize, &sz);
c801d85f
KB
354
355 if (retcode != SQL_ERROR)
356 return TRUE;
357 else
358 return FALSE;
359}
360
361wxString 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;
46dc76ba 390 retcode = SQLGetInfo(hDBC, (UWORD)SQL_ODBC_VER, (unsigned char*)buf, bufSize, &sz);
c801d85f
KB
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
404float 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;
46dc76ba 431 retcode = SQLGetInfo(hDBC, (UWORD)SQL_ODBC_VER, (unsigned char*)buf, bufSize, &sz);
c801d85f
KB
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
449wxRecordSet::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
472wxRecordSet::~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.
46dc76ba 489bool wxRecordSet::BeginQuery(int WXUNUSED(openType), char *WXUNUSED(sql), int WXUNUSED(options))
c801d85f
KB
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
518bool 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
559bool wxRecordSet::EndQuery(void)
560{
561 return TRUE;
562}
563
564void wxRecordSet::FillVars(int recnum) {
565 wxNode* node = cols.First();
566
567 do {
568 ((wxQueryCol*)node->Data())->FillVar(recnum);
46dc76ba 569 } while ((node = node->Next()));
c801d85f
KB
570}
571
572bool 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);
4d0c0756 610 col1->SetNullable((nullable != 0));
c801d85f
KB
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
683bool 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
713bool 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
758void wxRecordSet::SetTableName(char* name) {
759 delete[] tablename;
760 tablename = NULL;
761
762 if (name)
763 tablename = copystring(name);
764}
765
766bool 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
797bool wxRecordSet::GetColumns(char* table)
798{
799 char* name=NULL;
46dc76ba 800// char* wildcard = "%";
c801d85f
KB
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
837bool wxRecordSet::GetPrimaryKeys(char* table)
838{
839 char* name=NULL;
46dc76ba 840// char* wildcard = "%";
c801d85f
KB
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
875bool wxRecordSet::GetForeignKeys(char* PkTableName, char * FkTableName)
876{
877 char* Pkname=NULL;
878 char* Fkname=NULL;
46dc76ba 879// char* wildcard = "%";
c801d85f
KB
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
922long wxRecordSet::GetNumberRecords(void)
923{
924 return nRecords;
925}
926
927long wxRecordSet::GetNumberCols(void)
928{
929 return nCols;
930}
931
932char* 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
942short 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
952short 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
962bool 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
982bool 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
1002void* 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
1015void* 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
1028void* 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
1037void* 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
1046void wxRecordSet::SetType(int typ) {
1047 type = typ;
1048}
1049
1050int wxRecordSet::GetType(void) {
1051 return type;
1052}
1053
1054void wxRecordSet::SetOptions(int opts) {
1055 options = opts;
1056}
1057
1058int wxRecordSet::GetOptions(void) {
1059 return options;
1060}
1061
1062bool wxRecordSet::CanAppend(void)
1063{
1064 return FALSE;
1065}
1066
1067bool wxRecordSet::CanRestart(void)
1068{
1069 return FALSE;
1070}
1071
1072bool wxRecordSet::CanScroll(void)
1073{
1074 return FALSE;
1075}
1076
1077bool wxRecordSet::CanTransact(void)
1078{
1079 return FALSE;
1080}
1081
1082bool wxRecordSet::CanUpdate(void)
1083{
1084 return FALSE;
1085}
1086
1087long wxRecordSet::GetCurrentRecord(void)
1088{
1089 return -1L;
1090}
1091
1092bool wxRecordSet::RecordCountFinal(void)
1093{
1094 return FALSE;
1095}
1096
1097char* wxRecordSet::GetTableName(void)
1098{
1099 return tablename;
1100}
1101
1102char *wxRecordSet::GetSQL(void)
1103{
1104 return NULL;
1105}
1106
1107bool wxRecordSet::IsOpen(void)
1108{
1109 return parentdb->IsOpen();
1110}
1111
1112bool wxRecordSet::IsBOF(void)
1113{
1114 return cursor < 0;
1115}
1116
1117bool wxRecordSet::IsEOF(void)
1118{
1119 return cursor >= nRecords;
1120}
1121
1122bool wxRecordSet::IsDeleted(void)
1123{
1124 return FALSE;
1125}
1126
1127// Update operations
1128void wxRecordSet::AddNew(void)
1129{
1130}
1131
1132bool wxRecordSet::Delete(void)
1133{
1134 return FALSE;
1135}
1136
1137void wxRecordSet::Edit(void)
1138{
1139}
1140
1141bool wxRecordSet::Update(void)
1142{
1143 return FALSE;
1144}
1145
1146// Record navigation
1147bool 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
1174bool 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
1201bool 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
1220bool 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
1239bool 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
1262bool 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
1286void wxRecordSet::Cancel(void)
1287{
1288}
1289
1290bool 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
1300bool 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
1310bool 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
1320bool 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
1330bool 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
1340bool 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
1350bool wxRecordSet::Requery(void)
1351{
1352 return FALSE;
1353}
1354
1355void 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
1365void 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
46dc76ba 1375void wxRecordSet::SetFieldNull(void *WXUNUSED(p), bool WXUNUSED(isNull))
c801d85f
KB
1376{
1377}
1378
1379// Overridables
1380char *wxRecordSet::GetDefaultConnect(void)
1381{
1382 return NULL;
1383}
1384
1385char *wxRecordSet::GetDefaultSQL(void)
1386{
1387 return NULL;
1388}
1389
1390void 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
1401bool wxRecordSet::ConstructDefaultSQL(void)
1402{
1403// if (queryCols.Number() == 0)
1404 return FALSE;
1405}
1406
1407bool 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
1423wxQueryCol::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
1432wxQueryCol::~wxQueryCol(void) {
1433 // delete all data
1434 fields.DeleteContents(TRUE);
1435 fields.Clear();
1436
1437 if (name)
1438 delete[] name;
1439}
1440
1441void wxQueryCol::SetName(char* n) {
1442 name = new char[strlen(n)+1];
1443 strcpy(name, n);
1444}
1445
1446bool 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
1455void 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
1464void 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
1470void wxQueryCol::SetType(short t) {
1471 type = t;
1472}
1473
1474void* wxQueryCol::BindVar(void* v, long s) {
1475 void* oldvar = var;
1476
1477 var = v;
1478 varsize = s;
1479
1480 return oldvar;
1481}
1482
1483void 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
1499void wxQueryCol::SetNullable(bool n) {
1500 nullable = n;
1501}
1502
1503char* wxQueryCol::GetName(void) {
1504 return name;
1505}
1506
1507short wxQueryCol::GetType(void) {
1508 return type;
1509}
1510
1511bool wxQueryCol::IsNullable(void) {
1512 return nullable;
1513}
1514
1515
1516bool 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
1525void* 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
1534long wxQueryCol::GetSize(int row) {
1535 wxNode* node = fields.Nth(row);
1536
1537 if (!node)
46dc76ba 1538 return 0;
c801d85f
KB
1539
1540 return ((wxQueryField*)node->Data())->GetSize();
1541}
1542
1543wxQueryField::wxQueryField(void) {
1544// __type = wxTYPE_QUERYROW;
1545 data = NULL;
1546 type = SQL_TYPE_NULL;
1547 size = 0;
1548 dirty = FALSE;
1549}
1550
1551wxQueryField::~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
1593bool 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;
46dc76ba 1603 if ((data = new char[size+1]))
c801d85f
KB
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;
46dc76ba 1617 if ((data = new long))
c801d85f
KB
1618 *(long*)data = 0L;
1619 break;
1620 }
1621 case SQL_SMALLINT:
1622 {
1623 if (data)
1624 delete (short*)data;
46dc76ba 1625 if ((data = new short))
c801d85f
KB
1626 *(short*)data = 0;
1627 break;
1628 }
1629 case SQL_FLOAT:
1630 case SQL_DOUBLE:
1631 {
1632 if (data)
1633 delete (double*)data;
46dc76ba 1634 if ((data = new double))
c801d85f
KB
1635 *(double*)data = 0;
1636 break;
1637 }
1638 case SQL_REAL:
1639 {
1640 if (data)
1641 delete (float*)data;
46dc76ba 1642 if ((data = new float))
c801d85f
KB
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
1677bool 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
1742void 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
1801void wxQueryField::SetDirty(bool d) {
1802 dirty = d;
1803}
1804
1805void wxQueryField::SetType(short t) {
1806 type = t;
1807}
1808
1809void wxQueryField::SetSize(long s) {
1810 size = s;
1811 AllocData();
1812}
1813
1814void* wxQueryField::GetData(void) {
1815 return data;
1816}
1817
1818short wxQueryField::GetType(void) {
1819 return type;
1820}
1821
1822long wxQueryField::GetSize(void) {
1823 return size;
1824}
1825
1826bool wxQueryField::IsDirty(void) {
1827 return dirty;
1828}
1829
1830#endif // USE_ODBC