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