]>
git.saurik.com Git - wxWidgets.git/blob - src/common/odbc.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: ODBC implementation
4 // Author: Julian Smart, Olaf Klein (oklein@smallo.ruhr.de),
5 // Patrick Halke (patrick@zaphod.ruhr.de)
9 // Copyright: (c) Julian Smart and Markus Holzem
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "odbc.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
30 #include "wx/dialog.h"
33 #include "wx/string.h"
39 #if defined(__WXMSW__) && !defined(__WIN32__)
43 HENV
wxDatabase::hEnv
= 0;
44 int wxDatabase::refCount
= 0;
46 #if !USE_SHARED_LIBRARY
47 IMPLEMENT_DYNAMIC_CLASS(wxDatabase
, wxObject
)
48 IMPLEMENT_DYNAMIC_CLASS(wxQueryCol
, wxObject
)
49 IMPLEMENT_DYNAMIC_CLASS(wxQueryField
, wxObject
)
50 IMPLEMENT_DYNAMIC_CLASS(wxRecordSet
, wxObject
)
53 wxDatabase::wxDatabase(void)
68 memset(sqlstate
, 0, sizeof sqlstate
);
69 memset(errmsg
, 0, sizeof errmsg
);
73 retcode
= SQLAllocEnv(&hEnv
);
75 if (retcode
!= SQL_SUCCESS
)
80 wxDatabase::~wxDatabase(void)
83 DeleteRecordSets(); // Added JACS
86 delete[] connectstring
;
97 if (!refCount
&& hEnv
)
99 retcode
= SQLFreeEnv(hEnv
);
100 hEnv
= 0; // JACS 17/6
104 void wxDatabase::ErrorSnapshot(HSTMT hstmt
)
106 SWORD len
= 0; // JACS: sometimes doesn't get filled in by SQLError.
109 SQLError(hEnv
, hDBC
, hstmt
, (unsigned char *)sqlstate
, &nat_err
, (unsigned char *)errmsg
, SQL_MAX_MESSAGE_LENGTH
-1, &len
);
113 bool wxDatabase::ErrorOccured(void)
118 char* wxDatabase::GetErrorMessage(void)
123 long wxDatabase::GetErrorNumber(void)
128 char* wxDatabase::GetErrorClass(void) {
132 bool wxDatabase::Open(char *thedatasource
, bool WXUNUSED(exclusive
),
133 bool WXUNUSED(readOnly
), char *username
, char *password
)
140 SetUsername(username
);
141 SetPassword(password
);
142 SetDataSource(thedatasource
);
147 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
148 if (retcode
!= SQL_SUCCESS
) {
153 retcode
= SQLConnect(hDBC
, (UCHAR FAR
*)thedatasource
, strlen(thedatasource
), (UCHAR FAR
*)username
, strlen(username
),
154 (UCHAR FAR
*)password
, strlen(password
));
156 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
166 bool wxDatabase::Close(void)
168 // JACS: make sure the record set statements are all released.
174 retcode
= SQLDisconnect(hDBC
);
176 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
181 retcode
= SQLFreeConnect(hDBC
);
192 // Database attributes
193 char *wxDatabase::GetDatabaseName(void)
202 retcode
= SQLGetInfo(hDBC
, SQL_DATABASE_NAME
, (unsigned char*)nameBuf
, sizeof(nameBuf
), (short *)&nameSize
);
204 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
)
212 dbname
= copystring(nameBuf
);
219 bool wxDatabase::CanUpdate(void)
224 bool wxDatabase::CanTransact(void)
229 bool wxDatabase::InWaitForDataSource(void)
234 void wxDatabase::SetLoginTimeout(long WXUNUSED(seconds
))
238 void wxDatabase::SetQueryTimeout(long WXUNUSED(seconds
))
242 void wxDatabase::SetSynchronousMode(bool WXUNUSED(synchronous
))
246 // Database operations
247 bool wxDatabase::BeginTrans(void)
252 bool wxDatabase::CommitTrans(void)
257 bool wxDatabase::RollbackTrans(void)
262 void wxDatabase::Cancel(void)
267 void wxDatabase::OnSetOptions(wxRecordSet
*WXUNUSED(recordSet
))
271 void wxDatabase::OnWaitForDataSource(bool WXUNUSED(stillExecuting
))
275 void wxDatabase::SetPassword(char *s
)
281 password
= copystring(s
);
287 void wxDatabase::SetUsername(char *s
)
292 username
= copystring(s
);
297 void wxDatabase::SetDataSource(char *s
)
302 datasource
= copystring(s
);
311 void wxDatabase::DeleteRecordSets(void)
313 wxNode
*node
= recordSets
.First();
316 wxNode
*next
= node
->Next();
317 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
319 // The node is implicitly deleted by ~wxRecordSet
324 void wxDatabase::ResetRecordSets(void)
326 wxNode
*node
= recordSets
.First();
329 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
330 rec
->ReleaseHandle();
336 bool wxDatabase::GetInfo(long infoType
, long *buf
)
339 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, sizeof(buf
), &sz
);
341 if (retcode
!= SQL_ERROR
)
347 bool wxDatabase::GetInfo(long infoType
, char *buf
, int bufSize
)
350 bufSize
= sizeof(buf
);
353 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, bufSize
, &sz
);
355 if (retcode
!= SQL_ERROR
)
361 wxString
wxDatabase::GetODBCVersionString(bool implementation
)
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)),
369 return wxString(buf
);
371 return wxString("00.00");
379 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
380 if (retcode
!= SQL_SUCCESS
)
383 return wxString("00.00");
387 int bufSize
= sizeof(buf
);
390 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
392 if (hDBC
!= 0 && noDBC
)
394 retcode
= SQLFreeConnect(hDBC
);
398 if (retcode
== SQL_ERROR
)
401 return wxString(buf
);
404 float wxDatabase::GetODBCVersionFloat(bool implementation
)
408 #ifdef SQL_SPEC_MAJOR
409 return (float)(SQL_SPEC_MAJOR
+ (SQL_SPEC_MINOR
/100.0));
419 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
420 if (retcode
!= SQL_SUCCESS
)
428 int bufSize
= sizeof(buf
);
431 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
433 if (hDBC
!= 0 && noDBC
)
435 retcode
= SQLFreeConnect(hDBC
);
439 if (retcode
== SQL_ERROR
)
449 wxRecordSet::wxRecordSet(wxDatabase
*db
, int typ
, int opt
):
469 parentdb
->GetRecordSets().Append(this);
472 wxRecordSet::~wxRecordSet(void)
478 parentdb
->GetRecordSets().DeleteObject(this);
481 delete[] recordFilter
;
488 // If SQL is non-NULL, table and columns can be NULL.
489 bool wxRecordSet::BeginQuery(int WXUNUSED(openType
), char *WXUNUSED(sql
), int WXUNUSED(options
))
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>
497 if (!parentdb
->GetHDBC())
502 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
503 if (retcode
== SQL_ERROR
)
505 parentdb
->ErrorSnapshot(hStmt
);
511 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
512 if (retcode
!= SQL_SUCCESS
)
518 bool wxRecordSet::Query(char *columns
, char *table
, char *filter
)
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>
525 char* thetable
= table
? table
: tablename
;
543 retcode
= SQLPrepare(hStmt
, (UCHAR FAR
*)query
.GetData(), strlen(query
.GetData()));
544 if (retcode
!= SQL_SUCCESS
) {
545 parentdb
->ErrorSnapshot(hStmt
);
549 retcode
= SQLExecute(hStmt
);
551 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
552 parentdb
->ErrorSnapshot(hStmt
);
559 bool wxRecordSet::EndQuery(void)
564 void wxRecordSet::FillVars(int recnum
) {
565 wxNode
* node
= cols
.First();
568 ((wxQueryCol
*)node
->Data())->FillVar(recnum
);
569 } while ((node
= node
->Next()));
572 bool wxRecordSet::GetResultSet(void)
574 // long trash = SQL_NULL_DATA; // value added by JACS
576 // contains the number of bytes transferred by SQLFetch()
578 wxNode
*currow
, *fetch
, *curcol
;
580 retcode
= SQLNumResultCols(hStmt
, &nCols
);
585 // delete old data first
586 cols
.DeleteContents(TRUE
);
588 fetchbuf
.DeleteContents(TRUE
);
595 for (i
=0; i
<nCols
; i
++) {
597 short type
, scale
, nullable
, namelen
;
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
);
606 wxQueryCol
*col1
= new wxQueryCol
;
607 curcol
= cols
.Append(name
, col1
);
610 col1
->SetNullable((nullable
!= 0));
612 wxQueryField
*field1
= new wxQueryField
;
613 fetch
= fetchbuf
.Append(field1
);
614 field1
->SetType(type
);
615 field1
->SetSize(len
);
617 SQLBindCol(hStmt
, i
+1, SQL_C_BINARY
, field1
->GetData(), field1
->GetSize(), &trash
);
621 case wxOPEN_TYPE_SNAPSHOT
:
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
) {
628 curcol
= cols
.First();
629 fetch
= fetchbuf
.First();
630 for (i
=0; i
<nCols
; i
++) {
632 wxQueryField
*fetchField
= (wxQueryField
*)fetch
->Data();
633 wxQueryCol
*col
= (wxQueryCol
*)curcol
->Data();
634 wxQueryField
*field
= new wxQueryField
;
636 currow
= col
->fields
.Append(field
);
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();
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
);
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.
657 curcol
= cols
.First();
658 fetch
= fetchbuf
.First();
659 for (i
=0; i
<nCols
; i
++) {
660 currow
= ((wxQueryCol
*)curcol
->Data())->fields
.Append(new wxQueryField
);
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();
669 if (SQL_NO_DATA_FOUND
!= retcode
) {
670 parentdb
->ErrorSnapshot(hStmt
);
683 bool wxRecordSet::ExecuteSQL(char *sql
)
687 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
688 if (retcode
== SQL_ERROR
)
690 parentdb
->ErrorSnapshot(hStmt
);
696 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
698 if (SQL_SUCCESS
!= retcode
) {
699 parentdb
->ErrorSnapshot(hStmt
);
703 retcode
= SQLExecDirect(hStmt
, (UCHAR FAR
*)sql
, SQL_NTS
);
705 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
706 parentdb
->ErrorSnapshot(hStmt
);
710 return GetResultSet();
713 bool wxRecordSet::GetDataSources(void) {
715 char *dsname
= "Name", *dsdesc
= "Description";
718 short namelen
, desclen
;
722 // delete old data first
723 cols
.DeleteContents(TRUE
);
727 // JACS This is a snapshot, not a dynaset.
728 type
= wxOPEN_TYPE_SNAPSHOT
;
730 wxNode
*namecol
, *desccol
;
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
);
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
) {
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
);
747 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
&& SQL_NO_DATA_FOUND
!= retcode
) {
748 parentdb
->ErrorSnapshot();
758 void wxRecordSet::SetTableName(char* name
) {
763 tablename
= copystring(name
);
766 bool wxRecordSet::GetTables(void)
770 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
771 if (retcode
== SQL_ERROR
)
773 parentdb
->ErrorSnapshot(hStmt
);
780 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
782 if (SQL_SUCCESS
!= retcode
) {
783 parentdb
->ErrorSnapshot();
787 retcode
= SQLTables(hStmt
, NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0);
789 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
790 parentdb
->ErrorSnapshot(hStmt
);
794 return GetResultSet();
797 bool wxRecordSet::GetColumns(char* table
)
800 // char* wildcard = "%";
802 name
= table
? table
: tablename
;
809 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
810 if (retcode
== SQL_ERROR
)
812 parentdb
->ErrorSnapshot(hStmt
);
818 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
820 if (SQL_SUCCESS
!= retcode
) {
821 parentdb
->ErrorSnapshot();
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);
828 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
829 parentdb
->ErrorSnapshot(hStmt
);
833 return GetResultSet();
836 // It is derived from previous GetColumns
837 bool wxRecordSet::GetPrimaryKeys(char* table
)
840 // char* wildcard = "%";
842 name
= table
? table
: tablename
;
849 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
850 if (retcode
== SQL_ERROR
)
852 parentdb
->ErrorSnapshot(hStmt
);
858 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
860 if (SQL_SUCCESS
!= retcode
) {
861 parentdb
->ErrorSnapshot();
865 retcode
= SQLPrimaryKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, SQL_NTS
);
867 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
868 parentdb
->ErrorSnapshot(hStmt
);
872 return GetResultSet();
875 bool wxRecordSet::GetForeignKeys(char* PkTableName
, char * FkTableName
)
879 // char* wildcard = "%";
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
;
889 Pkname
= PkTableName
;
890 Fkname
= FkTableName
;
895 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
896 if (retcode
== SQL_ERROR
)
898 parentdb
->ErrorSnapshot(hStmt
);
904 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
906 if (SQL_SUCCESS
!= retcode
) {
907 parentdb
->ErrorSnapshot();
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) );
914 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
915 parentdb
->ErrorSnapshot(hStmt
);
919 return GetResultSet();
922 long wxRecordSet::GetNumberRecords(void)
927 long wxRecordSet::GetNumberCols(void)
932 char* wxRecordSet::GetColName(int col
)
934 wxNode
* node
= cols
.Nth(col
);
939 return ((wxQueryCol
*)node
->Data())->GetName();
942 short wxRecordSet::GetColType(int col
)
944 wxNode
* node
= cols
.Nth(col
);
947 return SQL_TYPE_NULL
;
949 return ((wxQueryCol
*)node
->Data())->GetType();
952 short wxRecordSet::GetColType(const char *col
)
954 wxNode
* node
= cols
.Find(col
);
957 return SQL_TYPE_NULL
;
959 return ((wxQueryCol
*)node
->Data())->GetType();
962 bool wxRecordSet::GetFieldData(int col
, int type
, void* data
)
964 wxNode
* node
= cols
.Nth(col
);
969 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
972 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
977 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
982 bool wxRecordSet::GetFieldData(const char* name
, int type
, void *data
)
984 wxNode
* node
= cols
.Find(name
);
989 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
992 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
997 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
1002 void* wxRecordSet::GetFieldDataPtr(int col
, int type
)
1004 wxNode
* node
= cols
.Nth(col
);
1009 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1012 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1015 void* wxRecordSet::GetFieldDataPtr(const char* name
, int type
)
1017 wxNode
* node
= cols
.Find(name
);
1022 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1025 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1028 void* wxRecordSet::BindVar(int col
, void* var
, long size
) {
1029 wxNode
* node
= cols
.Nth(col
);
1034 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1037 void* wxRecordSet::BindVar(const char* name
, void* var
, long size
) {
1038 wxNode
* node
= cols
.Find(name
);
1043 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1046 void wxRecordSet::SetType(int typ
) {
1050 int wxRecordSet::GetType(void) {
1054 void wxRecordSet::SetOptions(int opts
) {
1058 int wxRecordSet::GetOptions(void) {
1062 bool wxRecordSet::CanAppend(void)
1067 bool wxRecordSet::CanRestart(void)
1072 bool wxRecordSet::CanScroll(void)
1077 bool wxRecordSet::CanTransact(void)
1082 bool wxRecordSet::CanUpdate(void)
1087 long wxRecordSet::GetCurrentRecord(void)
1092 bool wxRecordSet::RecordCountFinal(void)
1097 char* wxRecordSet::GetTableName(void)
1102 char *wxRecordSet::GetSQL(void)
1107 bool wxRecordSet::IsOpen(void)
1109 return parentdb
->IsOpen();
1112 bool wxRecordSet::IsBOF(void)
1117 bool wxRecordSet::IsEOF(void)
1119 return cursor
>= nRecords
;
1122 bool wxRecordSet::IsDeleted(void)
1127 // Update operations
1128 void wxRecordSet::AddNew(void)
1132 bool wxRecordSet::Delete(void)
1137 void wxRecordSet::Edit(void)
1141 bool wxRecordSet::Update(void)
1146 // Record navigation
1147 bool wxRecordSet::Move(long rows
)
1155 case wxOPEN_TYPE_SNAPSHOT
:
1156 cursor
+= (int)rows
;
1161 if (cursor
> nRecords
-1) {
1167 case wxOPEN_TYPE_DYNASET
:
1174 bool wxRecordSet::GoTo(long row
)
1182 case wxOPEN_TYPE_SNAPSHOT
:
1188 if (cursor
> nRecords
-1) {
1194 case wxOPEN_TYPE_DYNASET
:
1201 bool wxRecordSet::MoveFirst(void)
1209 case wxOPEN_TYPE_SNAPSHOT
:
1213 case wxOPEN_TYPE_DYNASET
:
1220 bool wxRecordSet::MoveLast(void)
1228 case wxOPEN_TYPE_SNAPSHOT
:
1229 cursor
= nRecords
-1;
1232 case wxOPEN_TYPE_DYNASET
:
1239 bool wxRecordSet::MoveNext(void)
1247 case wxOPEN_TYPE_SNAPSHOT
:
1249 if (cursor
>= nRecords
) {
1255 case wxOPEN_TYPE_DYNASET
:
1262 bool wxRecordSet::MovePrev(void)
1270 case wxOPEN_TYPE_SNAPSHOT
:
1278 case wxOPEN_TYPE_DYNASET
:
1286 void wxRecordSet::Cancel(void)
1290 bool wxRecordSet::IsFieldDirty(int col
)
1292 wxNode
* node
= cols
.Nth(col
);
1297 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1300 bool wxRecordSet::IsFieldDirty(const char* name
)
1302 wxNode
* node
= cols
.Find(name
);
1307 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1310 bool wxRecordSet::IsFieldNull(int col
)
1312 wxNode
* node
= cols
.Nth(col
);
1317 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1320 bool wxRecordSet::IsFieldNull(const char* name
)
1322 wxNode
* node
= cols
.Find(name
);
1327 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1330 bool wxRecordSet::IsColNullable(int col
)
1332 wxNode
* node
= cols
.Nth(col
);
1337 return ((wxQueryCol
*)node
->Data())->IsNullable();
1340 bool wxRecordSet::IsColNullable(const char* name
)
1342 wxNode
* node
= cols
.Find(name
);
1347 return ((wxQueryCol
*)node
->Data())->IsNullable();
1350 bool wxRecordSet::Requery(void)
1355 void wxRecordSet::SetFieldDirty(int col
, bool dirty
)
1357 wxNode
* node
= cols
.Nth(col
);
1362 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1365 void wxRecordSet::SetFieldDirty(const char* name
, bool dirty
)
1367 wxNode
* node
= cols
.Find(name
);
1372 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1375 void wxRecordSet::SetFieldNull(void *WXUNUSED(p
), bool WXUNUSED(isNull
))
1380 char *wxRecordSet::GetDefaultConnect(void)
1385 char *wxRecordSet::GetDefaultSQL(void)
1390 void wxRecordSet::SetDefaultSQL(char *s
)
1392 delete[] defaultSQL
;
1395 defaultSQL
= copystring(s
);
1400 // Build SQL query from column specification
1401 bool wxRecordSet::ConstructDefaultSQL(void)
1403 // if (queryCols.Number() == 0)
1407 bool wxRecordSet::ReleaseHandle(void)
1411 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
1412 if (retcode
== SQL_ERROR
)
1415 parentdb
->ErrorSnapshot(hStmt
);
1423 wxQueryCol::wxQueryCol(void) {
1424 // __type = wxTYPE_QUERYCOL;
1426 type
= SQL_TYPE_NULL
;
1432 wxQueryCol::~wxQueryCol(void) {
1434 fields
.DeleteContents(TRUE
);
1441 void wxQueryCol::SetName(char* n
) {
1442 name
= new char[strlen(n
)+1];
1446 bool wxQueryCol::SetData(int row
, void* buf
, long len
) {
1447 wxNode
* node
= fields
.Nth(row
);
1452 return ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1455 void wxQueryCol::SetFieldDirty(int row
, bool dirty
) {
1456 wxNode
* node
= fields
.Nth(row
);
1461 ((wxQueryField
*)node
->Data())->SetDirty(dirty
);
1464 void wxQueryCol::AppendField(void* buf
, long len
) {
1465 wxNode
* node
= fields
.Append(new wxQueryField
);
1466 ((wxQueryField
*)node
->Data())->SetType(type
);
1467 ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1470 void wxQueryCol::SetType(short t
) {
1474 void* wxQueryCol::BindVar(void* v
, long s
) {
1483 void wxQueryCol::FillVar(int recnum
) {
1487 wxNode
* node
= fields
.Nth(recnum
);
1492 long actsize
= ((wxQueryField
*)node
->Data())->GetSize();
1493 if (actsize
> varsize
)
1496 memcpy(var
, ((wxQueryField
*)node
->Data())->GetData(), actsize
);
1499 void wxQueryCol::SetNullable(bool n
) {
1503 char* wxQueryCol::GetName(void) {
1507 short wxQueryCol::GetType(void) {
1511 bool wxQueryCol::IsNullable(void) {
1516 bool wxQueryCol::IsFieldDirty(int row
) {
1517 wxNode
* node
= fields
.Nth(row
);
1522 return ((wxQueryField
*)node
->Data())->IsDirty();
1525 void* wxQueryCol::GetData(int row
) {
1526 wxNode
* node
= fields
.Nth(row
);
1531 return ((wxQueryField
*)node
->Data())->GetData();
1534 long wxQueryCol::GetSize(int row
) {
1535 wxNode
* node
= fields
.Nth(row
);
1540 return ((wxQueryField
*)node
->Data())->GetSize();
1543 wxQueryField::wxQueryField(void) {
1544 // __type = wxTYPE_QUERYROW;
1546 type
= SQL_TYPE_NULL
;
1551 wxQueryField::~wxQueryField(void) {
1559 delete[] (char*)data
;
1567 delete (short*)data
;
1572 delete (double*)data
;
1576 delete (float*)data
;
1580 delete (TIME_STRUCT
*)data
;
1584 delete (DATE_STRUCT
*)data
;
1588 delete (TIMESTAMP_STRUCT
*)data
;
1593 bool wxQueryField::AllocData(void) {
1602 delete[] (char*)data
;
1603 if ((data
= new char[size
+1]))
1605 char *str
= (char *)data
;
1607 for (i
= 0; i
< size
; i
++)
1609 // memset(data, 0, size+1);
1617 if ((data
= new long))
1624 delete (short*)data
;
1625 if ((data
= new short))
1633 delete (double*)data
;
1634 if ((data
= new double))
1641 delete (float*)data
;
1642 if ((data
= new float))
1643 *(float*)data
= (float)0;
1649 delete (TIME_STRUCT
*)data
;
1650 data
= new TIME_STRUCT
;
1651 memset(data
, 0, sizeof(TIME_STRUCT
));
1657 delete (DATE_STRUCT
*)data
;
1658 data
= new DATE_STRUCT
;
1659 memset(data
, 0, sizeof(DATE_STRUCT
));
1665 delete (TIMESTAMP_STRUCT
*)data
;
1666 data
= new TIMESTAMP_STRUCT
;
1667 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1677 bool wxQueryField::SetData(void* d
, long s
) {
1679 if (AllocData() && d
)
1681 // memcpy(data, d, s);
1689 char *str
= (char *)data
;
1691 for (i
= 0; i
< size
; i
++)
1694 strncpy(str
, (char *)d
, (int)size
);
1700 *(long*)data
= *((long *)d
);
1705 *(short*)data
= *((short*)d
);
1711 *(double*)data
= *((double*)d
);
1716 *(float*)data
= *((float*)d
);
1721 *(TIME_STRUCT
*)data
= *((TIME_STRUCT
*)d
);
1726 *(TIMESTAMP_STRUCT
*)data
= *((TIMESTAMP_STRUCT
*)d
);
1731 *(DATE_STRUCT
*)data
= *((DATE_STRUCT
*)d
);
1742 void wxQueryField::ClearData(void) {
1745 // memset(data, 0, size);
1753 char *str
= (char *)data
;
1755 for (i
= 0; i
< size
; i
++)
1772 *(double*)data
= (double)0.0;
1777 *(float*)data
= (float)0.0;
1782 memset(data
, 0, sizeof(TIME_STRUCT
));
1787 memset(data
, 0, sizeof(DATE_STRUCT
));
1792 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1801 void wxQueryField::SetDirty(bool d
) {
1805 void wxQueryField::SetType(short t
) {
1809 void wxQueryField::SetSize(long s
) {
1814 void* wxQueryField::GetData(void) {
1818 short wxQueryField::GetType(void) {
1822 long wxQueryField::GetSize(void) {
1826 bool wxQueryField::IsDirty(void) {