]>
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 exclusive
, bool readOnly
, char *username
, char *password
)
139 SetUsername(username
);
140 SetPassword(password
);
141 SetDataSource(thedatasource
);
146 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
147 if (retcode
!= SQL_SUCCESS
) {
152 retcode
= SQLConnect(hDBC
, (UCHAR FAR
*)thedatasource
, strlen(thedatasource
), (UCHAR FAR
*)username
, strlen(username
),
153 (UCHAR FAR
*)password
, strlen(password
));
155 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
165 bool wxDatabase::Close(void)
167 // JACS: make sure the record set statements are all released.
173 retcode
= SQLDisconnect(hDBC
);
175 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
180 retcode
= SQLFreeConnect(hDBC
);
191 // Database attributes
192 char *wxDatabase::GetDatabaseName(void)
201 retcode
= SQLGetInfo(hDBC
, SQL_DATABASE_NAME
, nameBuf
, sizeof(nameBuf
), (short *)&nameSize
);
203 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
)
211 dbname
= copystring(nameBuf
);
218 bool wxDatabase::CanUpdate(void)
223 bool wxDatabase::CanTransact(void)
228 bool wxDatabase::InWaitForDataSource(void)
233 void wxDatabase::SetLoginTimeout(long seconds
)
237 void wxDatabase::SetQueryTimeout(long seconds
)
241 void wxDatabase::SetSynchronousMode(bool synchronous
)
245 // Database operations
246 bool wxDatabase::BeginTrans(void)
251 bool wxDatabase::CommitTrans(void)
256 bool wxDatabase::RollbackTrans(void)
261 void wxDatabase::Cancel(void)
266 void wxDatabase::OnSetOptions(wxRecordSet
*recordSet
)
270 void wxDatabase::OnWaitForDataSource(bool stillExecuting
)
274 void wxDatabase::SetPassword(char *s
)
280 password
= copystring(s
);
286 void wxDatabase::SetUsername(char *s
)
291 username
= copystring(s
);
296 void wxDatabase::SetDataSource(char *s
)
301 datasource
= copystring(s
);
310 void wxDatabase::DeleteRecordSets(void)
312 wxNode
*node
= recordSets
.First();
315 wxNode
*next
= node
->Next();
316 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
318 // The node is implicitly deleted by ~wxRecordSet
323 void wxDatabase::ResetRecordSets(void)
325 wxNode
*node
= recordSets
.First();
328 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
329 rec
->ReleaseHandle();
335 bool wxDatabase::GetInfo(long infoType
, long *buf
)
338 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (char *)buf
, sizeof(buf
), &sz
);
340 if (retcode
!= SQL_ERROR
)
346 bool wxDatabase::GetInfo(long infoType
, char *buf
, int bufSize
)
349 bufSize
= sizeof(buf
);
352 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, buf
, bufSize
, &sz
);
354 if (retcode
!= SQL_ERROR
)
360 wxString
wxDatabase::GetODBCVersionString(bool implementation
)
365 #ifdef SQL_SPEC_MAJOR
366 sprintf(buf
, "%d%d.%d", (int)(SQL_SPEC_MAJOR
/10), (int)(SQL_SPEC_MAJOR
- (((int)(SQL_SPEC_MAJOR
/10))*10)),
368 return wxString(buf
);
370 return wxString("00.00");
378 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
379 if (retcode
!= SQL_SUCCESS
)
382 return wxString("00.00");
386 int bufSize
= sizeof(buf
);
389 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, buf
, bufSize
, &sz
);
391 if (hDBC
!= 0 && noDBC
)
393 retcode
= SQLFreeConnect(hDBC
);
397 if (retcode
== SQL_ERROR
)
400 return wxString(buf
);
403 float wxDatabase::GetODBCVersionFloat(bool implementation
)
407 #ifdef SQL_SPEC_MAJOR
408 return (float)(SQL_SPEC_MAJOR
+ (SQL_SPEC_MINOR
/100.0));
418 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
419 if (retcode
!= SQL_SUCCESS
)
427 int bufSize
= sizeof(buf
);
430 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, buf
, bufSize
, &sz
);
432 if (hDBC
!= 0 && noDBC
)
434 retcode
= SQLFreeConnect(hDBC
);
438 if (retcode
== SQL_ERROR
)
448 wxRecordSet::wxRecordSet(wxDatabase
*db
, int typ
, int opt
):
468 parentdb
->GetRecordSets().Append(this);
471 wxRecordSet::~wxRecordSet(void)
477 parentdb
->GetRecordSets().DeleteObject(this);
480 delete[] recordFilter
;
487 // If SQL is non-NULL, table and columns can be NULL.
488 bool wxRecordSet::BeginQuery(int openType
, char *sql
, int options
)
490 // Needs to construct an appropriate SQL statement. By default
491 // (i.e. if table and columns are provided) then
492 // SELECT <columns> FROM <table>
496 if (!parentdb
->GetHDBC())
501 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
502 if (retcode
== SQL_ERROR
)
504 parentdb
->ErrorSnapshot(hStmt
);
510 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
511 if (retcode
!= SQL_SUCCESS
)
517 bool wxRecordSet::Query(char *columns
, char *table
, char *filter
)
519 // Needs to construct an appropriate SQL statement. By default
520 // (i.e. if table and columns are provided) then
521 // SELECT <columns> FROM <table>
524 char* thetable
= table
? table
: tablename
;
542 retcode
= SQLPrepare(hStmt
, (UCHAR FAR
*)query
.GetData(), strlen(query
.GetData()));
543 if (retcode
!= SQL_SUCCESS
) {
544 parentdb
->ErrorSnapshot(hStmt
);
548 retcode
= SQLExecute(hStmt
);
550 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
551 parentdb
->ErrorSnapshot(hStmt
);
558 bool wxRecordSet::EndQuery(void)
563 void wxRecordSet::FillVars(int recnum
) {
564 wxNode
* node
= cols
.First();
567 ((wxQueryCol
*)node
->Data())->FillVar(recnum
);
568 } while (node
= node
->Next());
571 bool wxRecordSet::GetResultSet(void)
573 // long trash = SQL_NULL_DATA; // value added by JACS
575 // contains the number of bytes transferred by SQLFetch()
577 wxNode
*currow
, *fetch
, *curcol
;
579 retcode
= SQLNumResultCols(hStmt
, &nCols
);
584 // delete old data first
585 cols
.DeleteContents(TRUE
);
587 fetchbuf
.DeleteContents(TRUE
);
594 for (i
=0; i
<nCols
; i
++) {
596 short type
, scale
, nullable
, namelen
;
599 retcode
= SQLDescribeCol(hStmt
, i
+1, (unsigned char *)name
, 511, &namelen
, &type
, &len
, &scale
, &nullable
);
600 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
601 parentdb
->ErrorSnapshot(hStmt
);
605 wxQueryCol
*col1
= new wxQueryCol
;
606 curcol
= cols
.Append(name
, col1
);
609 col1
->SetNullable(nullable
);
611 wxQueryField
*field1
= new wxQueryField
;
612 fetch
= fetchbuf
.Append(field1
);
613 field1
->SetType(type
);
614 field1
->SetSize(len
);
616 SQLBindCol(hStmt
, i
+1, SQL_C_BINARY
, field1
->GetData(), field1
->GetSize(), &trash
);
620 case wxOPEN_TYPE_SNAPSHOT
:
622 // After we've done an SQLFetch, copy the data in the fetch buffer into
623 // new fields, for each column.
624 while (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || SQL_SUCCESS_WITH_INFO
== retcode
) {
627 curcol
= cols
.First();
628 fetch
= fetchbuf
.First();
629 for (i
=0; i
<nCols
; i
++) {
631 wxQueryField
*fetchField
= (wxQueryField
*)fetch
->Data();
632 wxQueryCol
*col
= (wxQueryCol
*)curcol
->Data();
633 wxQueryField
*field
= new wxQueryField
;
635 currow
= col
->fields
.Append(field
);
637 field
->SetType(fetchField
->GetType());
638 field
->SetData(fetchField
->GetData(), fetchField
->GetSize());
639 curcol
= curcol
->Next();
640 fetchField
->ClearData(); // Runs ok if this commented out and SetData commented out
641 fetch
= fetch
->Next();
644 // while loop should only be left, when no more data was found;
645 // otherwise it seems, that there was an error
646 if (SQL_NO_DATA_FOUND
!= retcode
) {
647 parentdb
->ErrorSnapshot(hStmt
);
651 case wxOPEN_TYPE_DYNASET
:
652 // get first record only
653 if (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || retcode
== SQL_SUCCESS_WITH_INFO
) {
654 nRecords
= 1; // TO DO! # of records in the ODBC result set should be set here.
656 curcol
= cols
.First();
657 fetch
= fetchbuf
.First();
658 for (i
=0; i
<nCols
; i
++) {
659 currow
= ((wxQueryCol
*)curcol
->Data())->fields
.Append(new wxQueryField
);
661 ((wxQueryField
*)currow
->Data())->SetType(((wxQueryField
*)fetch
->Data())->GetType());
662 ((wxQueryField
*)currow
->Data())->SetData(((wxQueryField
*)fetch
->Data())->GetData(), ((wxQueryField
*)fetch
->Data())->GetSize());
663 curcol
= curcol
->Next();
664 ((wxQueryField
*)fetch
->Data())->ClearData();
665 fetch
= fetch
->Next();
668 if (SQL_NO_DATA_FOUND
!= retcode
) {
669 parentdb
->ErrorSnapshot(hStmt
);
682 bool wxRecordSet::ExecuteSQL(char *sql
)
686 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
687 if (retcode
== SQL_ERROR
)
689 parentdb
->ErrorSnapshot(hStmt
);
695 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
697 if (SQL_SUCCESS
!= retcode
) {
698 parentdb
->ErrorSnapshot(hStmt
);
702 retcode
= SQLExecDirect(hStmt
, (UCHAR FAR
*)sql
, SQL_NTS
);
704 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
705 parentdb
->ErrorSnapshot(hStmt
);
709 return GetResultSet();
712 bool wxRecordSet::GetDataSources(void) {
714 char *dsname
= "Name", *dsdesc
= "Description";
717 short namelen
, desclen
;
721 // delete old data first
722 cols
.DeleteContents(TRUE
);
726 // JACS This is a snapshot, not a dynaset.
727 type
= wxOPEN_TYPE_SNAPSHOT
;
729 wxNode
*namecol
, *desccol
;
731 namecol
= cols
.Append(dsname
, new wxQueryCol
);
732 ((wxQueryCol
*)namecol
->Data())->SetName(dsname
);
733 ((wxQueryCol
*)namecol
->Data())->SetType(SQL_CHAR
);
734 desccol
= cols
.Append(dsdesc
, new wxQueryCol
);
735 ((wxQueryCol
*)desccol
->Data())->SetName(dsdesc
);
736 ((wxQueryCol
*)desccol
->Data())->SetType(SQL_CHAR
);
738 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_FIRST
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
739 while (SQL_SUCCESS
== retcode
|| SQL_SUCCESS_WITH_INFO
== retcode
) {
741 ((wxQueryCol
*)namecol
->Data())->AppendField(namebuf
, namelen
);
742 ((wxQueryCol
*)desccol
->Data())->AppendField(descbuf
, desclen
);
743 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_NEXT
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
746 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
&& SQL_NO_DATA_FOUND
!= retcode
) {
747 parentdb
->ErrorSnapshot();
757 void wxRecordSet::SetTableName(char* name
) {
762 tablename
= copystring(name
);
765 bool wxRecordSet::GetTables(void)
769 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
770 if (retcode
== SQL_ERROR
)
772 parentdb
->ErrorSnapshot(hStmt
);
779 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
781 if (SQL_SUCCESS
!= retcode
) {
782 parentdb
->ErrorSnapshot();
786 retcode
= SQLTables(hStmt
, NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0);
788 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
789 parentdb
->ErrorSnapshot(hStmt
);
793 return GetResultSet();
796 bool wxRecordSet::GetColumns(char* table
)
799 char* wildcard
= "%";
801 name
= table
? table
: tablename
;
808 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
809 if (retcode
== SQL_ERROR
)
811 parentdb
->ErrorSnapshot(hStmt
);
817 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
819 if (SQL_SUCCESS
!= retcode
) {
820 parentdb
->ErrorSnapshot();
824 //retcode = SQLColumns(hstmt, (unsigned char*)parentdb->GetDataSource(), strlen(parentdb->GetDataSource()), wildcard, 1, name, strlen(name), wildcard, 1);
825 retcode
= SQLColumns(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, strlen(name
), NULL
, 0);
827 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
828 parentdb
->ErrorSnapshot(hStmt
);
832 return GetResultSet();
835 // It is derived from previous GetColumns
836 bool wxRecordSet::GetPrimaryKeys(char* table
)
839 char* wildcard
= "%";
841 name
= table
? table
: tablename
;
848 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
849 if (retcode
== SQL_ERROR
)
851 parentdb
->ErrorSnapshot(hStmt
);
857 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
859 if (SQL_SUCCESS
!= retcode
) {
860 parentdb
->ErrorSnapshot();
864 retcode
= SQLPrimaryKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, SQL_NTS
);
866 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
867 parentdb
->ErrorSnapshot(hStmt
);
871 return GetResultSet();
874 bool wxRecordSet::GetForeignKeys(char* PkTableName
, char * FkTableName
)
878 char* wildcard
= "%";
880 // Try to disable situation: both PkTableName and FkTableName are NULL
881 // set Pkname from tablename
882 if( !PkTableName
&& !FkTableName
) {
883 Pkname
= PkTableName
? PkTableName
: tablename
;
884 Fkname
= FkTableName
;
888 Pkname
= PkTableName
;
889 Fkname
= FkTableName
;
894 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
895 if (retcode
== SQL_ERROR
)
897 parentdb
->ErrorSnapshot(hStmt
);
903 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
905 if (SQL_SUCCESS
!= retcode
) {
906 parentdb
->ErrorSnapshot();
910 retcode
= SQLForeignKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)Pkname
,
911 (Pkname
? SQL_NTS
: 0), NULL
, 0, NULL
, 0, (unsigned char *)Fkname
,(Fkname
?SQL_NTS
: 0) );
913 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
914 parentdb
->ErrorSnapshot(hStmt
);
918 return GetResultSet();
921 long wxRecordSet::GetNumberRecords(void)
926 long wxRecordSet::GetNumberCols(void)
931 char* wxRecordSet::GetColName(int col
)
933 wxNode
* node
= cols
.Nth(col
);
938 return ((wxQueryCol
*)node
->Data())->GetName();
941 short wxRecordSet::GetColType(int col
)
943 wxNode
* node
= cols
.Nth(col
);
946 return SQL_TYPE_NULL
;
948 return ((wxQueryCol
*)node
->Data())->GetType();
951 short wxRecordSet::GetColType(const char *col
)
953 wxNode
* node
= cols
.Find(col
);
956 return SQL_TYPE_NULL
;
958 return ((wxQueryCol
*)node
->Data())->GetType();
961 bool wxRecordSet::GetFieldData(int col
, int type
, void* data
)
963 wxNode
* node
= cols
.Nth(col
);
968 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
971 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
976 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
981 bool wxRecordSet::GetFieldData(const char* name
, int type
, void *data
)
983 wxNode
* node
= cols
.Find(name
);
988 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
991 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
996 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
1001 void* wxRecordSet::GetFieldDataPtr(int col
, int type
)
1003 wxNode
* node
= cols
.Nth(col
);
1008 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1011 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1014 void* wxRecordSet::GetFieldDataPtr(const char* name
, int type
)
1016 wxNode
* node
= cols
.Find(name
);
1021 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1024 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1027 void* wxRecordSet::BindVar(int col
, void* var
, long size
) {
1028 wxNode
* node
= cols
.Nth(col
);
1033 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1036 void* wxRecordSet::BindVar(const char* name
, void* var
, long size
) {
1037 wxNode
* node
= cols
.Find(name
);
1042 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1045 void wxRecordSet::SetType(int typ
) {
1049 int wxRecordSet::GetType(void) {
1053 void wxRecordSet::SetOptions(int opts
) {
1057 int wxRecordSet::GetOptions(void) {
1061 bool wxRecordSet::CanAppend(void)
1066 bool wxRecordSet::CanRestart(void)
1071 bool wxRecordSet::CanScroll(void)
1076 bool wxRecordSet::CanTransact(void)
1081 bool wxRecordSet::CanUpdate(void)
1086 long wxRecordSet::GetCurrentRecord(void)
1091 bool wxRecordSet::RecordCountFinal(void)
1096 char* wxRecordSet::GetTableName(void)
1101 char *wxRecordSet::GetSQL(void)
1106 bool wxRecordSet::IsOpen(void)
1108 return parentdb
->IsOpen();
1111 bool wxRecordSet::IsBOF(void)
1116 bool wxRecordSet::IsEOF(void)
1118 return cursor
>= nRecords
;
1121 bool wxRecordSet::IsDeleted(void)
1126 // Update operations
1127 void wxRecordSet::AddNew(void)
1131 bool wxRecordSet::Delete(void)
1136 void wxRecordSet::Edit(void)
1140 bool wxRecordSet::Update(void)
1145 // Record navigation
1146 bool wxRecordSet::Move(long rows
)
1154 case wxOPEN_TYPE_SNAPSHOT
:
1155 cursor
+= (int)rows
;
1160 if (cursor
> nRecords
-1) {
1166 case wxOPEN_TYPE_DYNASET
:
1173 bool wxRecordSet::GoTo(long row
)
1181 case wxOPEN_TYPE_SNAPSHOT
:
1187 if (cursor
> nRecords
-1) {
1193 case wxOPEN_TYPE_DYNASET
:
1200 bool wxRecordSet::MoveFirst(void)
1208 case wxOPEN_TYPE_SNAPSHOT
:
1212 case wxOPEN_TYPE_DYNASET
:
1219 bool wxRecordSet::MoveLast(void)
1227 case wxOPEN_TYPE_SNAPSHOT
:
1228 cursor
= nRecords
-1;
1231 case wxOPEN_TYPE_DYNASET
:
1238 bool wxRecordSet::MoveNext(void)
1246 case wxOPEN_TYPE_SNAPSHOT
:
1248 if (cursor
>= nRecords
) {
1254 case wxOPEN_TYPE_DYNASET
:
1261 bool wxRecordSet::MovePrev(void)
1269 case wxOPEN_TYPE_SNAPSHOT
:
1277 case wxOPEN_TYPE_DYNASET
:
1285 void wxRecordSet::Cancel(void)
1289 bool wxRecordSet::IsFieldDirty(int col
)
1291 wxNode
* node
= cols
.Nth(col
);
1296 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1299 bool wxRecordSet::IsFieldDirty(const char* name
)
1301 wxNode
* node
= cols
.Find(name
);
1306 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1309 bool wxRecordSet::IsFieldNull(int col
)
1311 wxNode
* node
= cols
.Nth(col
);
1316 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1319 bool wxRecordSet::IsFieldNull(const char* name
)
1321 wxNode
* node
= cols
.Find(name
);
1326 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1329 bool wxRecordSet::IsColNullable(int col
)
1331 wxNode
* node
= cols
.Nth(col
);
1336 return ((wxQueryCol
*)node
->Data())->IsNullable();
1339 bool wxRecordSet::IsColNullable(const char* name
)
1341 wxNode
* node
= cols
.Find(name
);
1346 return ((wxQueryCol
*)node
->Data())->IsNullable();
1349 bool wxRecordSet::Requery(void)
1354 void wxRecordSet::SetFieldDirty(int col
, bool dirty
)
1356 wxNode
* node
= cols
.Nth(col
);
1361 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1364 void wxRecordSet::SetFieldDirty(const char* name
, bool dirty
)
1366 wxNode
* node
= cols
.Find(name
);
1371 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1374 void wxRecordSet::SetFieldNull(void *p
, bool isNull
)
1379 char *wxRecordSet::GetDefaultConnect(void)
1384 char *wxRecordSet::GetDefaultSQL(void)
1389 void wxRecordSet::SetDefaultSQL(char *s
)
1391 delete[] defaultSQL
;
1394 defaultSQL
= copystring(s
);
1399 // Build SQL query from column specification
1400 bool wxRecordSet::ConstructDefaultSQL(void)
1402 // if (queryCols.Number() == 0)
1406 bool wxRecordSet::ReleaseHandle(void)
1410 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
1411 if (retcode
== SQL_ERROR
)
1414 parentdb
->ErrorSnapshot(hStmt
);
1422 wxQueryCol::wxQueryCol(void) {
1423 // __type = wxTYPE_QUERYCOL;
1425 type
= SQL_TYPE_NULL
;
1431 wxQueryCol::~wxQueryCol(void) {
1433 fields
.DeleteContents(TRUE
);
1440 void wxQueryCol::SetName(char* n
) {
1441 name
= new char[strlen(n
)+1];
1445 bool wxQueryCol::SetData(int row
, void* buf
, long len
) {
1446 wxNode
* node
= fields
.Nth(row
);
1451 return ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1454 void wxQueryCol::SetFieldDirty(int row
, bool dirty
) {
1455 wxNode
* node
= fields
.Nth(row
);
1460 ((wxQueryField
*)node
->Data())->SetDirty(dirty
);
1463 void wxQueryCol::AppendField(void* buf
, long len
) {
1464 wxNode
* node
= fields
.Append(new wxQueryField
);
1465 ((wxQueryField
*)node
->Data())->SetType(type
);
1466 ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1469 void wxQueryCol::SetType(short t
) {
1473 void* wxQueryCol::BindVar(void* v
, long s
) {
1482 void wxQueryCol::FillVar(int recnum
) {
1486 wxNode
* node
= fields
.Nth(recnum
);
1491 long actsize
= ((wxQueryField
*)node
->Data())->GetSize();
1492 if (actsize
> varsize
)
1495 memcpy(var
, ((wxQueryField
*)node
->Data())->GetData(), actsize
);
1498 void wxQueryCol::SetNullable(bool n
) {
1502 char* wxQueryCol::GetName(void) {
1506 short wxQueryCol::GetType(void) {
1510 bool wxQueryCol::IsNullable(void) {
1515 bool wxQueryCol::IsFieldDirty(int row
) {
1516 wxNode
* node
= fields
.Nth(row
);
1521 return ((wxQueryField
*)node
->Data())->IsDirty();
1524 void* wxQueryCol::GetData(int row
) {
1525 wxNode
* node
= fields
.Nth(row
);
1530 return ((wxQueryField
*)node
->Data())->GetData();
1533 long wxQueryCol::GetSize(int row
) {
1534 wxNode
* node
= fields
.Nth(row
);
1539 return ((wxQueryField
*)node
->Data())->GetSize();
1542 wxQueryField::wxQueryField(void) {
1543 // __type = wxTYPE_QUERYROW;
1545 type
= SQL_TYPE_NULL
;
1550 wxQueryField::~wxQueryField(void) {
1558 delete[] (char*)data
;
1566 delete (short*)data
;
1571 delete (double*)data
;
1575 delete (float*)data
;
1579 delete (TIME_STRUCT
*)data
;
1583 delete (DATE_STRUCT
*)data
;
1587 delete (TIMESTAMP_STRUCT
*)data
;
1592 bool wxQueryField::AllocData(void) {
1601 delete[] (char*)data
;
1602 if (data
= new char[size
+1])
1604 char *str
= (char *)data
;
1606 for (i
= 0; i
< size
; i
++)
1608 // memset(data, 0, size+1);
1616 if (data
= new long)
1623 delete (short*)data
;
1624 if (data
= new short)
1632 delete (double*)data
;
1633 if (data
= new double)
1640 delete (float*)data
;
1641 if (data
= new float)
1642 *(float*)data
= (float)0;
1648 delete (TIME_STRUCT
*)data
;
1649 data
= new TIME_STRUCT
;
1650 memset(data
, 0, sizeof(TIME_STRUCT
));
1656 delete (DATE_STRUCT
*)data
;
1657 data
= new DATE_STRUCT
;
1658 memset(data
, 0, sizeof(DATE_STRUCT
));
1664 delete (TIMESTAMP_STRUCT
*)data
;
1665 data
= new TIMESTAMP_STRUCT
;
1666 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1676 bool wxQueryField::SetData(void* d
, long s
) {
1678 if (AllocData() && d
)
1680 // memcpy(data, d, s);
1688 char *str
= (char *)data
;
1690 for (i
= 0; i
< size
; i
++)
1693 strncpy(str
, (char *)d
, (int)size
);
1699 *(long*)data
= *((long *)d
);
1704 *(short*)data
= *((short*)d
);
1710 *(double*)data
= *((double*)d
);
1715 *(float*)data
= *((float*)d
);
1720 *(TIME_STRUCT
*)data
= *((TIME_STRUCT
*)d
);
1725 *(TIMESTAMP_STRUCT
*)data
= *((TIMESTAMP_STRUCT
*)d
);
1730 *(DATE_STRUCT
*)data
= *((DATE_STRUCT
*)d
);
1741 void wxQueryField::ClearData(void) {
1744 // memset(data, 0, size);
1752 char *str
= (char *)data
;
1754 for (i
= 0; i
< size
; i
++)
1771 *(double*)data
= (double)0.0;
1776 *(float*)data
= (float)0.0;
1781 memset(data
, 0, sizeof(TIME_STRUCT
));
1786 memset(data
, 0, sizeof(DATE_STRUCT
));
1791 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1800 void wxQueryField::SetDirty(bool d
) {
1804 void wxQueryField::SetType(short t
) {
1808 void wxQueryField::SetSize(long s
) {
1813 void* wxQueryField::GetData(void) {
1817 short wxQueryField::GetType(void) {
1821 long wxQueryField::GetSize(void) {
1825 bool wxQueryField::IsDirty(void) {