]>
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"
29 #pragma warning(disable:4706) // assignment within conditional expression
34 #include "wx/dialog.h"
37 #include "wx/string.h"
43 #if defined(__WXMSW__) && !defined(__WIN32__)
47 HENV
wxDatabase::hEnv
= 0;
48 int wxDatabase::refCount
= 0;
50 #if !USE_SHARED_LIBRARY
51 IMPLEMENT_DYNAMIC_CLASS(wxDatabase
, wxObject
)
52 IMPLEMENT_DYNAMIC_CLASS(wxQueryCol
, wxObject
)
53 IMPLEMENT_DYNAMIC_CLASS(wxQueryField
, wxObject
)
54 IMPLEMENT_DYNAMIC_CLASS(wxRecordSet
, wxObject
)
57 wxDatabase::wxDatabase(void)
72 memset(sqlstate
, 0, sizeof sqlstate
);
73 memset(errmsg
, 0, sizeof errmsg
);
77 retcode
= SQLAllocEnv(&hEnv
);
79 if (retcode
!= SQL_SUCCESS
)
84 wxDatabase::~wxDatabase(void)
87 DeleteRecordSets(); // Added JACS
90 delete[] connectstring
;
101 if (!refCount
&& hEnv
)
103 retcode
= SQLFreeEnv(hEnv
);
104 hEnv
= 0; // JACS 17/6
108 void wxDatabase::ErrorSnapshot(HSTMT hstmt
)
110 SWORD len
= 0; // JACS: sometimes doesn't get filled in by SQLError.
113 SQLError(hEnv
, hDBC
, hstmt
, (unsigned char *)sqlstate
, &nat_err
, (unsigned char *)errmsg
, SQL_MAX_MESSAGE_LENGTH
-1, &len
);
117 bool wxDatabase::ErrorOccured(void)
122 char* wxDatabase::GetErrorMessage(void)
127 long wxDatabase::GetErrorNumber(void)
132 char* wxDatabase::GetErrorClass(void) {
136 bool wxDatabase::Open(char *thedatasource
, bool WXUNUSED(exclusive
),
137 bool WXUNUSED(readOnly
), char *username
, char *password
)
144 SetUsername(username
);
145 SetPassword(password
);
146 SetDataSource(thedatasource
);
151 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
152 if (retcode
!= SQL_SUCCESS
) {
157 retcode
= SQLConnect(hDBC
, (UCHAR FAR
*)thedatasource
, strlen(thedatasource
), (UCHAR FAR
*)username
, strlen(username
),
158 (UCHAR FAR
*)password
, strlen(password
));
160 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
170 bool wxDatabase::Close(void)
172 // JACS: make sure the record set statements are all released.
178 retcode
= SQLDisconnect(hDBC
);
180 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
185 retcode
= SQLFreeConnect(hDBC
);
196 // Database attributes
197 char *wxDatabase::GetDatabaseName(void)
206 retcode
= SQLGetInfo(hDBC
, SQL_DATABASE_NAME
, (unsigned char*)nameBuf
, sizeof(nameBuf
), (short *)&nameSize
);
208 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
)
216 dbname
= copystring(nameBuf
);
223 bool wxDatabase::CanUpdate(void)
228 bool wxDatabase::CanTransact(void)
233 bool wxDatabase::InWaitForDataSource(void)
238 void wxDatabase::SetLoginTimeout(long WXUNUSED(seconds
))
242 void wxDatabase::SetQueryTimeout(long WXUNUSED(seconds
))
246 void wxDatabase::SetSynchronousMode(bool WXUNUSED(synchronous
))
250 // Database operations
251 bool wxDatabase::BeginTrans(void)
256 bool wxDatabase::CommitTrans(void)
261 bool wxDatabase::RollbackTrans(void)
266 void wxDatabase::Cancel(void)
271 void wxDatabase::OnSetOptions(wxRecordSet
*WXUNUSED(recordSet
))
275 void wxDatabase::OnWaitForDataSource(bool WXUNUSED(stillExecuting
))
279 void wxDatabase::SetPassword(char *s
)
285 password
= copystring(s
);
291 void wxDatabase::SetUsername(char *s
)
296 username
= copystring(s
);
301 void wxDatabase::SetDataSource(char *s
)
306 datasource
= copystring(s
);
315 void wxDatabase::DeleteRecordSets(void)
317 wxNode
*node
= recordSets
.First();
320 wxNode
*next
= node
->Next();
321 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
323 // The node is implicitly deleted by ~wxRecordSet
328 void wxDatabase::ResetRecordSets(void)
330 wxNode
*node
= recordSets
.First();
333 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
334 rec
->ReleaseHandle();
340 bool wxDatabase::GetInfo(long infoType
, long *buf
)
343 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, sizeof(buf
), &sz
);
345 if (retcode
!= SQL_ERROR
)
351 bool wxDatabase::GetInfo(long infoType
, char *buf
, int bufSize
)
354 bufSize
= sizeof(buf
);
357 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, bufSize
, &sz
);
359 if (retcode
!= SQL_ERROR
)
365 wxString
wxDatabase::GetODBCVersionString(bool implementation
)
370 #ifdef SQL_SPEC_MAJOR
371 sprintf(buf
, "%d%d.%d", (int)(SQL_SPEC_MAJOR
/10), (int)(SQL_SPEC_MAJOR
- (((int)(SQL_SPEC_MAJOR
/10))*10)),
373 return wxString(buf
);
375 return wxString("00.00");
383 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
384 if (retcode
!= SQL_SUCCESS
)
387 return wxString("00.00");
391 int bufSize
= sizeof(buf
);
394 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
396 if (hDBC
!= 0 && noDBC
)
398 retcode
= SQLFreeConnect(hDBC
);
402 if (retcode
== SQL_ERROR
)
405 return wxString(buf
);
408 float wxDatabase::GetODBCVersionFloat(bool implementation
)
412 #ifdef SQL_SPEC_MAJOR
413 return (float)(SQL_SPEC_MAJOR
+ (SQL_SPEC_MINOR
/100.0));
423 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
424 if (retcode
!= SQL_SUCCESS
)
432 int bufSize
= sizeof(buf
);
435 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
437 if (hDBC
!= 0 && noDBC
)
439 retcode
= SQLFreeConnect(hDBC
);
443 if (retcode
== SQL_ERROR
)
446 return (float)atof(buf
);
453 wxRecordSet::wxRecordSet(wxDatabase
*db
, int typ
, int opt
):
473 parentdb
->GetRecordSets().Append(this);
476 wxRecordSet::~wxRecordSet(void)
482 parentdb
->GetRecordSets().DeleteObject(this);
485 delete[] recordFilter
;
492 // If SQL is non-NULL, table and columns can be NULL.
493 bool wxRecordSet::BeginQuery(int WXUNUSED(openType
), char *WXUNUSED(sql
), int WXUNUSED(options
))
495 // Needs to construct an appropriate SQL statement. By default
496 // (i.e. if table and columns are provided) then
497 // SELECT <columns> FROM <table>
501 if (!parentdb
->GetHDBC())
506 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
507 if (retcode
== SQL_ERROR
)
509 parentdb
->ErrorSnapshot(hStmt
);
515 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
516 if (retcode
!= SQL_SUCCESS
)
522 bool wxRecordSet::Query(char *columns
, char *table
, char *filter
)
524 // Needs to construct an appropriate SQL statement. By default
525 // (i.e. if table and columns are provided) then
526 // SELECT <columns> FROM <table>
529 char* thetable
= table
? table
: tablename
;
547 retcode
= SQLPrepare(hStmt
, (UCHAR FAR
*)query
.GetData(), strlen(query
.GetData()));
548 if (retcode
!= SQL_SUCCESS
) {
549 parentdb
->ErrorSnapshot(hStmt
);
553 retcode
= SQLExecute(hStmt
);
555 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
556 parentdb
->ErrorSnapshot(hStmt
);
563 bool wxRecordSet::EndQuery(void)
568 void wxRecordSet::FillVars(int recnum
) {
569 wxNode
* node
= cols
.First();
572 ((wxQueryCol
*)node
->Data())->FillVar(recnum
);
573 } while ((node
= node
->Next()));
576 bool wxRecordSet::GetResultSet(void)
578 // long trash = SQL_NULL_DATA; // value added by JACS
580 // contains the number of bytes transferred by SQLFetch()
582 wxNode
*currow
, *fetch
, *curcol
;
584 retcode
= SQLNumResultCols(hStmt
, &nCols
);
589 // delete old data first
590 cols
.DeleteContents(TRUE
);
592 fetchbuf
.DeleteContents(TRUE
);
599 for (i
=0; i
<nCols
; i
++) {
601 short type
, scale
, nullable
, namelen
;
604 retcode
= SQLDescribeCol(hStmt
, i
+1, (unsigned char *)name
, 511, &namelen
, &type
, &len
, &scale
, &nullable
);
605 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
606 parentdb
->ErrorSnapshot(hStmt
);
610 wxQueryCol
*col1
= new wxQueryCol
;
611 curcol
= cols
.Append(name
, col1
);
614 col1
->SetNullable((nullable
!= 0));
616 wxQueryField
*field1
= new wxQueryField
;
617 fetch
= fetchbuf
.Append(field1
);
618 field1
->SetType(type
);
619 field1
->SetSize(len
);
621 SQLBindCol(hStmt
, i
+1, SQL_C_BINARY
, (unsigned char*)field1
->GetData(), field1
->GetSize(), &trash
);
625 case wxOPEN_TYPE_SNAPSHOT
:
627 // After we've done an SQLFetch, copy the data in the fetch buffer into
628 // new fields, for each column.
629 while (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || SQL_SUCCESS_WITH_INFO
== retcode
) {
632 curcol
= cols
.First();
633 fetch
= fetchbuf
.First();
634 for (i
=0; i
<nCols
; i
++) {
636 wxQueryField
*fetchField
= (wxQueryField
*)fetch
->Data();
637 wxQueryCol
*col
= (wxQueryCol
*)curcol
->Data();
638 wxQueryField
*field
= new wxQueryField
;
640 currow
= col
->fields
.Append(field
);
642 field
->SetType(fetchField
->GetType());
643 field
->SetData(fetchField
->GetData(), fetchField
->GetSize());
644 curcol
= curcol
->Next();
645 fetchField
->ClearData(); // Runs ok if this commented out and SetData commented out
646 fetch
= fetch
->Next();
649 // while loop should only be left, when no more data was found;
650 // otherwise it seems, that there was an error
651 if (SQL_NO_DATA_FOUND
!= retcode
) {
652 parentdb
->ErrorSnapshot(hStmt
);
656 case wxOPEN_TYPE_DYNASET
:
657 // get first record only
658 if (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || retcode
== SQL_SUCCESS_WITH_INFO
) {
659 nRecords
= 1; // TO DO! # of records in the ODBC result set should be set here.
661 curcol
= cols
.First();
662 fetch
= fetchbuf
.First();
663 for (i
=0; i
<nCols
; i
++) {
664 currow
= ((wxQueryCol
*)curcol
->Data())->fields
.Append(new wxQueryField
);
666 ((wxQueryField
*)currow
->Data())->SetType(((wxQueryField
*)fetch
->Data())->GetType());
667 ((wxQueryField
*)currow
->Data())->SetData(((wxQueryField
*)fetch
->Data())->GetData(), ((wxQueryField
*)fetch
->Data())->GetSize());
668 curcol
= curcol
->Next();
669 ((wxQueryField
*)fetch
->Data())->ClearData();
670 fetch
= fetch
->Next();
673 if (SQL_NO_DATA_FOUND
!= retcode
) {
674 parentdb
->ErrorSnapshot(hStmt
);
687 bool wxRecordSet::ExecuteSQL(char *sql
)
691 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
692 if (retcode
== SQL_ERROR
)
694 parentdb
->ErrorSnapshot(hStmt
);
700 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
702 if (SQL_SUCCESS
!= retcode
) {
703 parentdb
->ErrorSnapshot(hStmt
);
707 retcode
= SQLExecDirect(hStmt
, (UCHAR FAR
*)sql
, SQL_NTS
);
709 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
710 parentdb
->ErrorSnapshot(hStmt
);
714 return GetResultSet();
717 bool wxRecordSet::GetDataSources(void) {
719 char *dsname
= "Name", *dsdesc
= "Description";
722 short namelen
, desclen
;
726 // delete old data first
727 cols
.DeleteContents(TRUE
);
731 // JACS This is a snapshot, not a dynaset.
732 type
= wxOPEN_TYPE_SNAPSHOT
;
734 wxNode
*namecol
, *desccol
;
736 namecol
= cols
.Append(dsname
, new wxQueryCol
);
737 ((wxQueryCol
*)namecol
->Data())->SetName(dsname
);
738 ((wxQueryCol
*)namecol
->Data())->SetType(SQL_CHAR
);
739 desccol
= cols
.Append(dsdesc
, new wxQueryCol
);
740 ((wxQueryCol
*)desccol
->Data())->SetName(dsdesc
);
741 ((wxQueryCol
*)desccol
->Data())->SetType(SQL_CHAR
);
743 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_FIRST
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
744 while (SQL_SUCCESS
== retcode
|| SQL_SUCCESS_WITH_INFO
== retcode
) {
746 ((wxQueryCol
*)namecol
->Data())->AppendField(namebuf
, namelen
);
747 ((wxQueryCol
*)desccol
->Data())->AppendField(descbuf
, desclen
);
748 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_NEXT
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
751 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
&& SQL_NO_DATA_FOUND
!= retcode
) {
752 parentdb
->ErrorSnapshot();
762 void wxRecordSet::SetTableName(char* name
) {
767 tablename
= copystring(name
);
770 bool wxRecordSet::GetTables(void)
774 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
775 if (retcode
== SQL_ERROR
)
777 parentdb
->ErrorSnapshot(hStmt
);
784 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
786 if (SQL_SUCCESS
!= retcode
) {
787 parentdb
->ErrorSnapshot();
791 retcode
= SQLTables(hStmt
, NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0);
793 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
794 parentdb
->ErrorSnapshot(hStmt
);
798 return GetResultSet();
801 bool wxRecordSet::GetColumns(char* table
)
804 // char* wildcard = "%";
806 name
= table
? table
: tablename
;
813 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
814 if (retcode
== SQL_ERROR
)
816 parentdb
->ErrorSnapshot(hStmt
);
822 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
824 if (SQL_SUCCESS
!= retcode
) {
825 parentdb
->ErrorSnapshot();
829 //retcode = SQLColumns(hstmt, (unsigned char*)parentdb->GetDataSource(), strlen(parentdb->GetDataSource()), wildcard, 1, name, strlen(name), wildcard, 1);
830 retcode
= SQLColumns(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, strlen(name
), NULL
, 0);
832 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
833 parentdb
->ErrorSnapshot(hStmt
);
837 return GetResultSet();
840 // It is derived from previous GetColumns
841 bool wxRecordSet::GetPrimaryKeys(char* table
)
844 // char* wildcard = "%";
846 name
= table
? table
: tablename
;
853 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
854 if (retcode
== SQL_ERROR
)
856 parentdb
->ErrorSnapshot(hStmt
);
862 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
864 if (SQL_SUCCESS
!= retcode
) {
865 parentdb
->ErrorSnapshot();
869 retcode
= SQLPrimaryKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, SQL_NTS
);
871 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
872 parentdb
->ErrorSnapshot(hStmt
);
876 return GetResultSet();
879 bool wxRecordSet::GetForeignKeys(char* PkTableName
, char * FkTableName
)
883 // char* wildcard = "%";
885 // Try to disable situation: both PkTableName and FkTableName are NULL
886 // set Pkname from tablename
887 if( !PkTableName
&& !FkTableName
) {
888 Pkname
= PkTableName
? PkTableName
: tablename
;
889 Fkname
= FkTableName
;
893 Pkname
= PkTableName
;
894 Fkname
= FkTableName
;
899 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
900 if (retcode
== SQL_ERROR
)
902 parentdb
->ErrorSnapshot(hStmt
);
908 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
910 if (SQL_SUCCESS
!= retcode
) {
911 parentdb
->ErrorSnapshot();
915 retcode
= SQLForeignKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)Pkname
,
916 (Pkname
? SQL_NTS
: 0), NULL
, 0, NULL
, 0, (unsigned char *)Fkname
,(Fkname
?SQL_NTS
: 0) );
918 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
919 parentdb
->ErrorSnapshot(hStmt
);
923 return GetResultSet();
926 long wxRecordSet::GetNumberRecords(void)
931 long wxRecordSet::GetNumberCols(void)
936 char* wxRecordSet::GetColName(int col
)
938 wxNode
* node
= cols
.Nth(col
);
943 return ((wxQueryCol
*)node
->Data())->GetName();
946 short wxRecordSet::GetColType(int col
)
948 wxNode
* node
= cols
.Nth(col
);
951 return SQL_TYPE_NULL
;
953 return ((wxQueryCol
*)node
->Data())->GetType();
956 short wxRecordSet::GetColType(const char *col
)
958 wxNode
* node
= cols
.Find(col
);
961 return SQL_TYPE_NULL
;
963 return ((wxQueryCol
*)node
->Data())->GetType();
966 bool wxRecordSet::GetFieldData(int col
, int type
, void* data
)
968 wxNode
* node
= cols
.Nth(col
);
973 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
976 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
981 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
986 bool wxRecordSet::GetFieldData(const char* name
, int type
, void *data
)
988 wxNode
* node
= cols
.Find(name
);
993 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
996 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1001 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
1006 void* wxRecordSet::GetFieldDataPtr(int col
, int type
)
1008 wxNode
* node
= cols
.Nth(col
);
1013 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1016 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1019 void* wxRecordSet::GetFieldDataPtr(const char* name
, int type
)
1021 wxNode
* node
= cols
.Find(name
);
1026 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1029 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1032 void* wxRecordSet::BindVar(int col
, void* var
, long size
) {
1033 wxNode
* node
= cols
.Nth(col
);
1038 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1041 void* wxRecordSet::BindVar(const char* name
, void* var
, long size
) {
1042 wxNode
* node
= cols
.Find(name
);
1047 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1050 void wxRecordSet::SetType(int typ
) {
1054 int wxRecordSet::GetType(void) {
1058 void wxRecordSet::SetOptions(int opts
) {
1062 int wxRecordSet::GetOptions(void) {
1066 bool wxRecordSet::CanAppend(void)
1071 bool wxRecordSet::CanRestart(void)
1076 bool wxRecordSet::CanScroll(void)
1081 bool wxRecordSet::CanTransact(void)
1086 bool wxRecordSet::CanUpdate(void)
1091 long wxRecordSet::GetCurrentRecord(void)
1096 bool wxRecordSet::RecordCountFinal(void)
1101 char* wxRecordSet::GetTableName(void)
1106 char *wxRecordSet::GetSQL(void)
1111 bool wxRecordSet::IsOpen(void)
1113 return parentdb
->IsOpen();
1116 bool wxRecordSet::IsBOF(void)
1121 bool wxRecordSet::IsEOF(void)
1123 return cursor
>= nRecords
;
1126 bool wxRecordSet::IsDeleted(void)
1131 // Update operations
1132 void wxRecordSet::AddNew(void)
1136 bool wxRecordSet::Delete(void)
1141 void wxRecordSet::Edit(void)
1145 bool wxRecordSet::Update(void)
1150 // Record navigation
1151 bool wxRecordSet::Move(long rows
)
1159 case wxOPEN_TYPE_SNAPSHOT
:
1160 cursor
+= (int)rows
;
1165 if (cursor
> nRecords
-1) {
1171 case wxOPEN_TYPE_DYNASET
:
1178 bool wxRecordSet::GoTo(long row
)
1186 case wxOPEN_TYPE_SNAPSHOT
:
1192 if (cursor
> nRecords
-1) {
1198 case wxOPEN_TYPE_DYNASET
:
1205 bool wxRecordSet::MoveFirst(void)
1213 case wxOPEN_TYPE_SNAPSHOT
:
1217 case wxOPEN_TYPE_DYNASET
:
1224 bool wxRecordSet::MoveLast(void)
1232 case wxOPEN_TYPE_SNAPSHOT
:
1233 cursor
= nRecords
-1;
1236 case wxOPEN_TYPE_DYNASET
:
1243 bool wxRecordSet::MoveNext(void)
1251 case wxOPEN_TYPE_SNAPSHOT
:
1253 if (cursor
>= nRecords
) {
1259 case wxOPEN_TYPE_DYNASET
:
1266 bool wxRecordSet::MovePrev(void)
1274 case wxOPEN_TYPE_SNAPSHOT
:
1282 case wxOPEN_TYPE_DYNASET
:
1290 void wxRecordSet::Cancel(void)
1294 bool wxRecordSet::IsFieldDirty(int col
)
1296 wxNode
* node
= cols
.Nth(col
);
1301 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1304 bool wxRecordSet::IsFieldDirty(const char* name
)
1306 wxNode
* node
= cols
.Find(name
);
1311 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1314 bool wxRecordSet::IsFieldNull(int col
)
1316 wxNode
* node
= cols
.Nth(col
);
1321 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1324 bool wxRecordSet::IsFieldNull(const char* name
)
1326 wxNode
* node
= cols
.Find(name
);
1331 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1334 bool wxRecordSet::IsColNullable(int col
)
1336 wxNode
* node
= cols
.Nth(col
);
1341 return ((wxQueryCol
*)node
->Data())->IsNullable();
1344 bool wxRecordSet::IsColNullable(const char* name
)
1346 wxNode
* node
= cols
.Find(name
);
1351 return ((wxQueryCol
*)node
->Data())->IsNullable();
1354 bool wxRecordSet::Requery(void)
1359 void wxRecordSet::SetFieldDirty(int col
, bool dirty
)
1361 wxNode
* node
= cols
.Nth(col
);
1366 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1369 void wxRecordSet::SetFieldDirty(const char* name
, bool dirty
)
1371 wxNode
* node
= cols
.Find(name
);
1376 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1379 void wxRecordSet::SetFieldNull(void *WXUNUSED(p
), bool WXUNUSED(isNull
))
1384 char *wxRecordSet::GetDefaultConnect(void)
1389 char *wxRecordSet::GetDefaultSQL(void)
1394 void wxRecordSet::SetDefaultSQL(char *s
)
1396 delete[] defaultSQL
;
1399 defaultSQL
= copystring(s
);
1404 // Build SQL query from column specification
1405 bool wxRecordSet::ConstructDefaultSQL(void)
1407 // if (queryCols.Number() == 0)
1411 bool wxRecordSet::ReleaseHandle(void)
1415 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
1416 if (retcode
== SQL_ERROR
)
1419 parentdb
->ErrorSnapshot(hStmt
);
1427 wxQueryCol::wxQueryCol(void) {
1428 // __type = wxTYPE_QUERYCOL;
1430 type
= SQL_TYPE_NULL
;
1436 wxQueryCol::~wxQueryCol(void) {
1438 fields
.DeleteContents(TRUE
);
1445 void wxQueryCol::SetName(char* n
) {
1446 name
= new char[strlen(n
)+1];
1450 bool wxQueryCol::SetData(int row
, void* buf
, long len
) {
1451 wxNode
* node
= fields
.Nth(row
);
1456 return ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1459 void wxQueryCol::SetFieldDirty(int row
, bool dirty
) {
1460 wxNode
* node
= fields
.Nth(row
);
1465 ((wxQueryField
*)node
->Data())->SetDirty(dirty
);
1468 void wxQueryCol::AppendField(void* buf
, long len
) {
1469 wxNode
* node
= fields
.Append(new wxQueryField
);
1470 ((wxQueryField
*)node
->Data())->SetType(type
);
1471 ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1474 void wxQueryCol::SetType(short t
) {
1478 void* wxQueryCol::BindVar(void* v
, long s
) {
1487 void wxQueryCol::FillVar(int recnum
) {
1491 wxNode
* node
= fields
.Nth(recnum
);
1496 long actsize
= ((wxQueryField
*)node
->Data())->GetSize();
1497 if (actsize
> varsize
)
1500 memcpy(var
, ((wxQueryField
*)node
->Data())->GetData(), actsize
);
1503 void wxQueryCol::SetNullable(bool n
) {
1507 char* wxQueryCol::GetName(void) {
1511 short wxQueryCol::GetType(void) {
1515 bool wxQueryCol::IsNullable(void) {
1520 bool wxQueryCol::IsFieldDirty(int row
) {
1521 wxNode
* node
= fields
.Nth(row
);
1526 return ((wxQueryField
*)node
->Data())->IsDirty();
1529 void* wxQueryCol::GetData(int row
) {
1530 wxNode
* node
= fields
.Nth(row
);
1535 return ((wxQueryField
*)node
->Data())->GetData();
1538 long wxQueryCol::GetSize(int row
) {
1539 wxNode
* node
= fields
.Nth(row
);
1544 return ((wxQueryField
*)node
->Data())->GetSize();
1547 wxQueryField::wxQueryField(void) {
1548 // __type = wxTYPE_QUERYROW;
1550 type
= SQL_TYPE_NULL
;
1555 wxQueryField::~wxQueryField(void) {
1563 delete[] (char*)data
;
1571 delete (short*)data
;
1576 delete (double*)data
;
1580 delete (float*)data
;
1584 delete (TIME_STRUCT
*)data
;
1588 delete (DATE_STRUCT
*)data
;
1592 delete (TIMESTAMP_STRUCT
*)data
;
1597 bool wxQueryField::AllocData(void) {
1606 delete[] (char*)data
;
1607 if ((data
= new char[size
+1]))
1609 char *str
= (char *)data
;
1611 for (i
= 0; i
< size
; i
++)
1613 // memset(data, 0, size+1);
1621 if ((data
= new long))
1628 delete (short*)data
;
1629 if ((data
= new short))
1637 delete (double*)data
;
1638 if ((data
= new double))
1645 delete (float*)data
;
1646 if ((data
= new float))
1647 *(float*)data
= (float)0;
1653 delete (TIME_STRUCT
*)data
;
1654 data
= new TIME_STRUCT
;
1655 memset(data
, 0, sizeof(TIME_STRUCT
));
1661 delete (DATE_STRUCT
*)data
;
1662 data
= new DATE_STRUCT
;
1663 memset(data
, 0, sizeof(DATE_STRUCT
));
1669 delete (TIMESTAMP_STRUCT
*)data
;
1670 data
= new TIMESTAMP_STRUCT
;
1671 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1681 bool wxQueryField::SetData(void* d
, long s
) {
1683 if (AllocData() && d
)
1685 // memcpy(data, d, s);
1693 char *str
= (char *)data
;
1695 for (i
= 0; i
< size
; i
++)
1698 strncpy(str
, (char *)d
, (int)size
);
1704 *(long*)data
= *((long *)d
);
1709 *(short*)data
= *((short*)d
);
1715 *(double*)data
= *((double*)d
);
1720 *(float*)data
= *((float*)d
);
1725 *(TIME_STRUCT
*)data
= *((TIME_STRUCT
*)d
);
1730 *(TIMESTAMP_STRUCT
*)data
= *((TIMESTAMP_STRUCT
*)d
);
1735 *(DATE_STRUCT
*)data
= *((DATE_STRUCT
*)d
);
1746 void wxQueryField::ClearData(void) {
1749 // memset(data, 0, size);
1757 char *str
= (char *)data
;
1759 for (i
= 0; i
< size
; i
++)
1776 *(double*)data
= (double)0.0;
1781 *(float*)data
= (float)0.0;
1786 memset(data
, 0, sizeof(TIME_STRUCT
));
1791 memset(data
, 0, sizeof(DATE_STRUCT
));
1796 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1805 void wxQueryField::SetDirty(bool d
) {
1809 void wxQueryField::SetType(short t
) {
1813 void wxQueryField::SetSize(long s
) {
1818 void* wxQueryField::GetData(void) {
1822 short wxQueryField::GetType(void) {
1826 long wxQueryField::GetSize(void) {
1830 bool wxQueryField::IsDirty(void) {
1835 #pragma warning(default:4706) // assignment within conditional expression
1838 #endif // wxUSE_ODBC