]>
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"
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
33 #pragma warning(disable:4706) // assignment within conditional expression
38 #include "wx/dialog.h"
41 #include "wx/string.h"
47 #if defined(__WXMSW__) && !defined(__WIN32__)
51 HENV
wxDatabase::hEnv
= 0;
52 int wxDatabase::refCount
= 0;
54 IMPLEMENT_DYNAMIC_CLASS(wxDatabase
, wxObject
)
55 IMPLEMENT_DYNAMIC_CLASS(wxQueryCol
, wxObject
)
56 IMPLEMENT_DYNAMIC_CLASS(wxQueryField
, wxObject
)
57 IMPLEMENT_DYNAMIC_CLASS(wxRecordSet
, wxObject
)
59 wxDatabase::wxDatabase(void)
74 memset(sqlstate
, 0, sizeof sqlstate
);
75 memset(errmsg
, 0, sizeof errmsg
);
79 retcode
= SQLAllocEnv(&hEnv
);
81 if (retcode
!= SQL_SUCCESS
)
86 wxDatabase::~wxDatabase(void)
89 DeleteRecordSets(); // Added JACS
92 delete[] connectstring
;
103 if (!refCount
&& hEnv
)
105 retcode
= SQLFreeEnv(hEnv
);
106 hEnv
= 0; // JACS 17/6
110 void wxDatabase::ErrorSnapshot(HSTMT hstmt
)
112 SWORD len
= 0; // JACS: sometimes doesn't get filled in by SQLError.
115 SQLError(hEnv
, hDBC
, hstmt
, (unsigned char *)sqlstate
, &nat_err
, (unsigned char *)errmsg
, SQL_MAX_MESSAGE_LENGTH
-1, &len
);
119 bool wxDatabase::ErrorOccured(void)
124 char* wxDatabase::GetErrorMessage(void)
129 long wxDatabase::GetErrorNumber(void)
134 char* wxDatabase::GetErrorClass(void) {
138 bool wxDatabase::Open(char *thedatasource
, bool WXUNUSED(exclusive
),
139 bool WXUNUSED(readOnly
), char *username
, char *password
)
146 SetUsername(username
);
147 SetPassword(password
);
148 SetDataSource(thedatasource
);
153 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
154 if (retcode
!= SQL_SUCCESS
) {
159 retcode
= SQLConnect(hDBC
, (UCHAR FAR
*)thedatasource
, strlen(thedatasource
), (UCHAR FAR
*)username
, strlen(username
),
160 (UCHAR FAR
*)password
, strlen(password
));
162 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
172 bool wxDatabase::Close(void)
174 // JACS: make sure the record set statements are all released.
180 retcode
= SQLDisconnect(hDBC
);
182 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
187 retcode
= SQLFreeConnect(hDBC
);
198 // Database attributes
199 char *wxDatabase::GetDatabaseName(void)
208 retcode
= SQLGetInfo(hDBC
, SQL_DATABASE_NAME
, (unsigned char*)nameBuf
, sizeof(nameBuf
), (short *)&nameSize
);
210 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
)
218 dbname
= copystring(nameBuf
);
225 bool wxDatabase::CanUpdate(void)
230 bool wxDatabase::CanTransact(void)
235 bool wxDatabase::InWaitForDataSource(void)
240 void wxDatabase::SetLoginTimeout(long WXUNUSED(seconds
))
244 void wxDatabase::SetQueryTimeout(long WXUNUSED(seconds
))
248 void wxDatabase::SetSynchronousMode(bool WXUNUSED(synchronous
))
252 // Database operations
253 bool wxDatabase::BeginTrans(void)
258 bool wxDatabase::CommitTrans(void)
263 bool wxDatabase::RollbackTrans(void)
268 void wxDatabase::Cancel(void)
273 void wxDatabase::OnSetOptions(wxRecordSet
*WXUNUSED(recordSet
))
277 void wxDatabase::OnWaitForDataSource(bool WXUNUSED(stillExecuting
))
281 void wxDatabase::SetPassword(char *s
)
287 password
= copystring(s
);
293 void wxDatabase::SetUsername(char *s
)
298 username
= copystring(s
);
303 void wxDatabase::SetDataSource(char *s
)
308 datasource
= copystring(s
);
317 void wxDatabase::DeleteRecordSets(void)
319 wxNode
*node
= recordSets
.First();
322 wxNode
*next
= node
->Next();
323 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
325 // The node is implicitly deleted by ~wxRecordSet
330 void wxDatabase::ResetRecordSets(void)
332 wxNode
*node
= recordSets
.First();
335 wxRecordSet
*rec
= (wxRecordSet
*)node
->Data();
336 rec
->ReleaseHandle();
342 bool wxDatabase::GetInfo(long infoType
, long *buf
)
345 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, sizeof(buf
), &sz
);
347 if (retcode
!= SQL_ERROR
)
353 bool wxDatabase::GetInfo(long infoType
, char *buf
, int bufSize
)
356 bufSize
= sizeof(buf
);
359 retcode
= SQLGetInfo(hDBC
, (UWORD
)infoType
, (unsigned char*)buf
, bufSize
, &sz
);
361 if (retcode
!= SQL_ERROR
)
367 wxString
wxDatabase::GetODBCVersionString(bool implementation
)
372 #ifdef SQL_SPEC_MAJOR
373 sprintf(buf
, "%d%d.%d", (int)(SQL_SPEC_MAJOR
/10), (int)(SQL_SPEC_MAJOR
- (((int)(SQL_SPEC_MAJOR
/10))*10)),
375 return wxString(buf
);
377 return wxString("00.00");
385 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
386 if (retcode
!= SQL_SUCCESS
)
389 return wxString("00.00");
393 int bufSize
= sizeof(buf
);
396 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
398 if (hDBC
!= 0 && noDBC
)
400 retcode
= SQLFreeConnect(hDBC
);
404 if (retcode
== SQL_ERROR
)
407 return wxString(buf
);
410 float wxDatabase::GetODBCVersionFloat(bool implementation
)
414 #ifdef SQL_SPEC_MAJOR
415 return (float)(SQL_SPEC_MAJOR
+ (SQL_SPEC_MINOR
/100.0));
425 retcode
= SQLAllocConnect(hEnv
, &hDBC
);
426 if (retcode
!= SQL_SUCCESS
)
434 int bufSize
= sizeof(buf
);
437 retcode
= SQLGetInfo(hDBC
, (UWORD
)SQL_ODBC_VER
, (unsigned char*)buf
, bufSize
, &sz
);
439 if (hDBC
!= 0 && noDBC
)
441 retcode
= SQLFreeConnect(hDBC
);
445 if (retcode
== SQL_ERROR
)
448 return (float)atof(buf
);
455 wxRecordSet::wxRecordSet(wxDatabase
*db
, int typ
, int opt
):
475 parentdb
->GetRecordSets().Append(this);
478 wxRecordSet::~wxRecordSet(void)
484 parentdb
->GetRecordSets().DeleteObject(this);
487 delete[] recordFilter
;
494 // If SQL is non-NULL, table and columns can be NULL.
495 bool wxRecordSet::BeginQuery(int WXUNUSED(openType
), char *WXUNUSED(sql
), int WXUNUSED(options
))
497 // Needs to construct an appropriate SQL statement. By default
498 // (i.e. if table and columns are provided) then
499 // SELECT <columns> FROM <table>
503 if (!parentdb
->GetHDBC())
508 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
509 if (retcode
== SQL_ERROR
)
511 parentdb
->ErrorSnapshot(hStmt
);
517 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
518 if (retcode
!= SQL_SUCCESS
)
524 bool wxRecordSet::Query(char *columns
, char *table
, char *filter
)
526 // Needs to construct an appropriate SQL statement. By default
527 // (i.e. if table and columns are provided) then
528 // SELECT <columns> FROM <table>
531 char* thetable
= table
? table
: tablename
;
549 retcode
= SQLPrepare(hStmt
, (UCHAR FAR
*)query
.GetData(), strlen(query
.GetData()));
550 if (retcode
!= SQL_SUCCESS
) {
551 parentdb
->ErrorSnapshot(hStmt
);
555 retcode
= SQLExecute(hStmt
);
557 if (retcode
!= SQL_SUCCESS
&& retcode
!= SQL_SUCCESS_WITH_INFO
) {
558 parentdb
->ErrorSnapshot(hStmt
);
565 bool wxRecordSet::EndQuery(void)
570 void wxRecordSet::FillVars(int recnum
) {
571 wxNode
* node
= cols
.First();
574 ((wxQueryCol
*)node
->Data())->FillVar(recnum
);
575 } while ((node
= node
->Next()));
578 bool wxRecordSet::GetResultSet(void)
580 // long trash = SQL_NULL_DATA; // value added by JACS
582 // contains the number of bytes transferred by SQLFetch()
584 wxNode
*currow
, *fetch
, *curcol
;
586 retcode
= SQLNumResultCols(hStmt
, &nCols
);
591 // delete old data first
592 cols
.DeleteContents(TRUE
);
594 fetchbuf
.DeleteContents(TRUE
);
601 for (i
=0; i
<nCols
; i
++) {
603 short type
, scale
, nullable
, namelen
;
606 retcode
= SQLDescribeCol(hStmt
, i
+1, (unsigned char *)name
, 511, &namelen
, &type
, &len
, &scale
, &nullable
);
607 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
608 parentdb
->ErrorSnapshot(hStmt
);
612 wxQueryCol
*col1
= new wxQueryCol
;
613 curcol
= cols
.Append(name
, col1
);
616 col1
->SetNullable((nullable
!= 0));
618 wxQueryField
*field1
= new wxQueryField
;
619 fetch
= fetchbuf
.Append(field1
);
620 field1
->SetType(type
);
621 field1
->SetSize(len
);
623 SQLBindCol(hStmt
, i
+1, SQL_C_BINARY
, (unsigned char*)field1
->GetData(), field1
->GetSize(), &trash
);
627 case wxOPEN_TYPE_SNAPSHOT
:
629 // After we've done an SQLFetch, copy the data in the fetch buffer into
630 // new fields, for each column.
631 while (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || SQL_SUCCESS_WITH_INFO
== retcode
) {
634 curcol
= cols
.First();
635 fetch
= fetchbuf
.First();
636 for (i
=0; i
<nCols
; i
++) {
638 wxQueryField
*fetchField
= (wxQueryField
*)fetch
->Data();
639 wxQueryCol
*col
= (wxQueryCol
*)curcol
->Data();
640 wxQueryField
*field
= new wxQueryField
;
642 currow
= col
->fields
.Append(field
);
644 field
->SetType(fetchField
->GetType());
645 field
->SetData(fetchField
->GetData(), fetchField
->GetSize());
646 curcol
= curcol
->Next();
647 fetchField
->ClearData(); // Runs ok if this commented out and SetData commented out
648 fetch
= fetch
->Next();
651 // while loop should only be left, when no more data was found;
652 // otherwise it seems, that there was an error
653 if (SQL_NO_DATA_FOUND
!= retcode
) {
654 parentdb
->ErrorSnapshot(hStmt
);
658 case wxOPEN_TYPE_DYNASET
:
659 // get first record only
660 if (SQL_SUCCESS
== (retcode
= SQLFetch(hStmt
)) || retcode
== SQL_SUCCESS_WITH_INFO
) {
661 nRecords
= 1; // TO DO! # of records in the ODBC result set should be set here.
663 curcol
= cols
.First();
664 fetch
= fetchbuf
.First();
665 for (i
=0; i
<nCols
; i
++) {
666 currow
= ((wxQueryCol
*)curcol
->Data())->fields
.Append(new wxQueryField
);
668 ((wxQueryField
*)currow
->Data())->SetType(((wxQueryField
*)fetch
->Data())->GetType());
669 ((wxQueryField
*)currow
->Data())->SetData(((wxQueryField
*)fetch
->Data())->GetData(), ((wxQueryField
*)fetch
->Data())->GetSize());
670 curcol
= curcol
->Next();
671 ((wxQueryField
*)fetch
->Data())->ClearData();
672 fetch
= fetch
->Next();
675 if (SQL_NO_DATA_FOUND
!= retcode
) {
676 parentdb
->ErrorSnapshot(hStmt
);
689 bool wxRecordSet::ExecuteSQL(char *sql
)
693 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
694 if (retcode
== SQL_ERROR
)
696 parentdb
->ErrorSnapshot(hStmt
);
702 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
704 if (SQL_SUCCESS
!= retcode
) {
705 parentdb
->ErrorSnapshot(hStmt
);
709 retcode
= SQLExecDirect(hStmt
, (UCHAR FAR
*)sql
, SQL_NTS
);
711 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
712 parentdb
->ErrorSnapshot(hStmt
);
716 return GetResultSet();
719 bool wxRecordSet::GetDataSources(void) {
721 char *dsname
= "Name", *dsdesc
= "Description";
724 short namelen
, desclen
;
728 // delete old data first
729 cols
.DeleteContents(TRUE
);
733 // JACS This is a snapshot, not a dynaset.
734 type
= wxOPEN_TYPE_SNAPSHOT
;
736 wxNode
*namecol
, *desccol
;
738 namecol
= cols
.Append(dsname
, new wxQueryCol
);
739 ((wxQueryCol
*)namecol
->Data())->SetName(dsname
);
740 ((wxQueryCol
*)namecol
->Data())->SetType(SQL_CHAR
);
741 desccol
= cols
.Append(dsdesc
, new wxQueryCol
);
742 ((wxQueryCol
*)desccol
->Data())->SetName(dsdesc
);
743 ((wxQueryCol
*)desccol
->Data())->SetType(SQL_CHAR
);
745 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_FIRST
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
746 while (SQL_SUCCESS
== retcode
|| SQL_SUCCESS_WITH_INFO
== retcode
) {
748 ((wxQueryCol
*)namecol
->Data())->AppendField(namebuf
, namelen
);
749 ((wxQueryCol
*)desccol
->Data())->AppendField(descbuf
, desclen
);
750 retcode
= SQLDataSources(parentdb
->GetHENV(), SQL_FETCH_NEXT
, (unsigned char *)namebuf
, 63, &namelen
, (unsigned char *)descbuf
, 511, &desclen
);
753 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
&& SQL_NO_DATA_FOUND
!= retcode
) {
754 parentdb
->ErrorSnapshot();
764 void wxRecordSet::SetTableName(char* name
) {
769 tablename
= copystring(name
);
772 bool wxRecordSet::GetTables(void)
776 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
777 if (retcode
== SQL_ERROR
)
779 parentdb
->ErrorSnapshot(hStmt
);
786 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
788 if (SQL_SUCCESS
!= retcode
) {
789 parentdb
->ErrorSnapshot();
793 retcode
= SQLTables(hStmt
, NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0);
795 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
796 parentdb
->ErrorSnapshot(hStmt
);
800 return GetResultSet();
803 bool wxRecordSet::GetColumns(char* table
)
806 // char* wildcard = "%";
808 name
= table
? table
: tablename
;
815 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
816 if (retcode
== SQL_ERROR
)
818 parentdb
->ErrorSnapshot(hStmt
);
824 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
826 if (SQL_SUCCESS
!= retcode
) {
827 parentdb
->ErrorSnapshot();
831 //retcode = SQLColumns(hstmt, (unsigned char*)parentdb->GetDataSource(), strlen(parentdb->GetDataSource()), wildcard, 1, name, strlen(name), wildcard, 1);
832 retcode
= SQLColumns(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, strlen(name
), NULL
, 0);
834 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
835 parentdb
->ErrorSnapshot(hStmt
);
839 return GetResultSet();
842 // It is derived from previous GetColumns
843 bool wxRecordSet::GetPrimaryKeys(char* table
)
846 // char* wildcard = "%";
848 name
= table
? table
: tablename
;
855 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
856 if (retcode
== SQL_ERROR
)
858 parentdb
->ErrorSnapshot(hStmt
);
864 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
866 if (SQL_SUCCESS
!= retcode
) {
867 parentdb
->ErrorSnapshot();
871 retcode
= SQLPrimaryKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)name
, SQL_NTS
);
873 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
874 parentdb
->ErrorSnapshot(hStmt
);
878 return GetResultSet();
881 bool wxRecordSet::GetForeignKeys(char* PkTableName
, char * FkTableName
)
885 // char* wildcard = "%";
887 // Try to disable situation: both PkTableName and FkTableName are NULL
888 // set Pkname from tablename
889 if( !PkTableName
&& !FkTableName
) {
890 Pkname
= PkTableName
? PkTableName
: tablename
;
891 Fkname
= FkTableName
;
895 Pkname
= PkTableName
;
896 Fkname
= FkTableName
;
901 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
902 if (retcode
== SQL_ERROR
)
904 parentdb
->ErrorSnapshot(hStmt
);
910 retcode
= SQLAllocStmt(parentdb
->GetHDBC(), &hStmt
);
912 if (SQL_SUCCESS
!= retcode
) {
913 parentdb
->ErrorSnapshot();
917 retcode
= SQLForeignKeys(hStmt
, NULL
, 0, NULL
, 0, (unsigned char *)Pkname
,
918 (Pkname
? SQL_NTS
: 0), NULL
, 0, NULL
, 0, (unsigned char *)Fkname
,(Fkname
?SQL_NTS
: 0) );
920 if (SQL_SUCCESS
!= retcode
&& SQL_SUCCESS_WITH_INFO
!= retcode
) {
921 parentdb
->ErrorSnapshot(hStmt
);
925 return GetResultSet();
928 long wxRecordSet::GetNumberRecords(void)
933 long wxRecordSet::GetNumberCols(void)
938 char* wxRecordSet::GetColName(int col
)
940 wxNode
* node
= cols
.Nth(col
);
945 return ((wxQueryCol
*)node
->Data())->GetName();
948 short wxRecordSet::GetColType(int col
)
950 wxNode
* node
= cols
.Nth(col
);
953 return SQL_TYPE_NULL
;
955 return ((wxQueryCol
*)node
->Data())->GetType();
958 short wxRecordSet::GetColType(const char *col
)
960 wxNode
* node
= cols
.Find(col
);
963 return SQL_TYPE_NULL
;
965 return ((wxQueryCol
*)node
->Data())->GetType();
968 bool wxRecordSet::GetFieldData(int col
, int type
, void* data
)
970 wxNode
* node
= cols
.Nth(col
);
975 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
978 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
983 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
988 bool wxRecordSet::GetFieldData(const char* name
, int type
, void *data
)
990 wxNode
* node
= cols
.Find(name
);
995 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
998 void* src
= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1003 memcpy(data
, src
, ((wxQueryCol
*)node
->Data())->GetSize(cursor
));
1008 void* wxRecordSet::GetFieldDataPtr(int col
, int type
)
1010 wxNode
* node
= cols
.Nth(col
);
1015 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1018 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1021 void* wxRecordSet::GetFieldDataPtr(const char* name
, int type
)
1023 wxNode
* node
= cols
.Find(name
);
1028 if (((wxQueryCol
*)node
->Data())->GetType() != type
)
1031 return ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1034 void* wxRecordSet::BindVar(int col
, void* var
, long size
) {
1035 wxNode
* node
= cols
.Nth(col
);
1040 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1043 void* wxRecordSet::BindVar(const char* name
, void* var
, long size
) {
1044 wxNode
* node
= cols
.Find(name
);
1049 return ((wxQueryCol
*)node
->Data())->BindVar(var
, size
);
1052 void wxRecordSet::SetType(int typ
) {
1056 int wxRecordSet::GetType(void) {
1060 void wxRecordSet::SetOptions(int opts
) {
1064 int wxRecordSet::GetOptions(void) {
1068 bool wxRecordSet::CanAppend(void)
1073 bool wxRecordSet::CanRestart(void)
1078 bool wxRecordSet::CanScroll(void)
1083 bool wxRecordSet::CanTransact(void)
1088 bool wxRecordSet::CanUpdate(void)
1093 long wxRecordSet::GetCurrentRecord(void)
1098 bool wxRecordSet::RecordCountFinal(void)
1103 char* wxRecordSet::GetTableName(void)
1108 char *wxRecordSet::GetSQL(void)
1113 bool wxRecordSet::IsOpen(void)
1115 return parentdb
->IsOpen();
1118 bool wxRecordSet::IsBOF(void)
1123 bool wxRecordSet::IsEOF(void)
1125 return cursor
>= nRecords
;
1128 bool wxRecordSet::IsDeleted(void)
1133 // Update operations
1134 void wxRecordSet::AddNew(void)
1138 bool wxRecordSet::Delete(void)
1143 void wxRecordSet::Edit(void)
1147 bool wxRecordSet::Update(void)
1152 // Record navigation
1153 bool wxRecordSet::Move(long rows
)
1161 case wxOPEN_TYPE_SNAPSHOT
:
1162 cursor
+= (int)rows
;
1167 if (cursor
> nRecords
-1) {
1173 case wxOPEN_TYPE_DYNASET
:
1180 bool wxRecordSet::GoTo(long row
)
1188 case wxOPEN_TYPE_SNAPSHOT
:
1194 if (cursor
> nRecords
-1) {
1200 case wxOPEN_TYPE_DYNASET
:
1207 bool wxRecordSet::MoveFirst(void)
1215 case wxOPEN_TYPE_SNAPSHOT
:
1219 case wxOPEN_TYPE_DYNASET
:
1226 bool wxRecordSet::MoveLast(void)
1234 case wxOPEN_TYPE_SNAPSHOT
:
1235 cursor
= nRecords
-1;
1238 case wxOPEN_TYPE_DYNASET
:
1245 bool wxRecordSet::MoveNext(void)
1253 case wxOPEN_TYPE_SNAPSHOT
:
1255 if (cursor
>= nRecords
) {
1261 case wxOPEN_TYPE_DYNASET
:
1268 bool wxRecordSet::MovePrev(void)
1276 case wxOPEN_TYPE_SNAPSHOT
:
1284 case wxOPEN_TYPE_DYNASET
:
1292 void wxRecordSet::Cancel(void)
1296 bool wxRecordSet::IsFieldDirty(int col
)
1298 wxNode
* node
= cols
.Nth(col
);
1303 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1306 bool wxRecordSet::IsFieldDirty(const char* name
)
1308 wxNode
* node
= cols
.Find(name
);
1313 return ((wxQueryCol
*)node
->Data())->IsFieldDirty(cursor
);
1316 bool wxRecordSet::IsFieldNull(int col
)
1318 wxNode
* node
= cols
.Nth(col
);
1323 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1326 bool wxRecordSet::IsFieldNull(const char* name
)
1328 wxNode
* node
= cols
.Find(name
);
1333 return NULL
!= ((wxQueryCol
*)node
->Data())->GetData(cursor
);
1336 bool wxRecordSet::IsColNullable(int col
)
1338 wxNode
* node
= cols
.Nth(col
);
1343 return ((wxQueryCol
*)node
->Data())->IsNullable();
1346 bool wxRecordSet::IsColNullable(const char* name
)
1348 wxNode
* node
= cols
.Find(name
);
1353 return ((wxQueryCol
*)node
->Data())->IsNullable();
1356 bool wxRecordSet::Requery(void)
1361 void wxRecordSet::SetFieldDirty(int col
, bool dirty
)
1363 wxNode
* node
= cols
.Nth(col
);
1368 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1371 void wxRecordSet::SetFieldDirty(const char* name
, bool dirty
)
1373 wxNode
* node
= cols
.Find(name
);
1378 ((wxQueryCol
*)node
->Data())->SetFieldDirty(cursor
, dirty
);
1381 void wxRecordSet::SetFieldNull(void *WXUNUSED(p
), bool WXUNUSED(isNull
))
1386 char *wxRecordSet::GetDefaultConnect(void)
1391 char *wxRecordSet::GetDefaultSQL(void)
1396 void wxRecordSet::SetDefaultSQL(char *s
)
1398 delete[] defaultSQL
;
1401 defaultSQL
= copystring(s
);
1406 // Build SQL query from column specification
1407 bool wxRecordSet::ConstructDefaultSQL(void)
1409 // if (queryCols.Number() == 0)
1413 bool wxRecordSet::ReleaseHandle(void)
1417 retcode
= SQLFreeStmt(hStmt
, SQL_DROP
);
1418 if (retcode
== SQL_ERROR
)
1421 parentdb
->ErrorSnapshot(hStmt
);
1429 wxQueryCol::wxQueryCol(void) {
1430 // __type = wxTYPE_QUERYCOL;
1432 type
= SQL_TYPE_NULL
;
1438 wxQueryCol::~wxQueryCol(void) {
1440 fields
.DeleteContents(TRUE
);
1447 void wxQueryCol::SetName(char* n
) {
1448 name
= new char[strlen(n
)+1];
1452 bool wxQueryCol::SetData(int row
, void* buf
, long len
) {
1453 wxNode
* node
= fields
.Nth(row
);
1458 return ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1461 void wxQueryCol::SetFieldDirty(int row
, bool dirty
) {
1462 wxNode
* node
= fields
.Nth(row
);
1467 ((wxQueryField
*)node
->Data())->SetDirty(dirty
);
1470 void wxQueryCol::AppendField(void* buf
, long len
) {
1471 wxNode
* node
= fields
.Append(new wxQueryField
);
1472 ((wxQueryField
*)node
->Data())->SetType(type
);
1473 ((wxQueryField
*)node
->Data())->SetData(buf
, len
);
1476 void wxQueryCol::SetType(short t
) {
1480 void* wxQueryCol::BindVar(void* v
, long s
) {
1489 void wxQueryCol::FillVar(int recnum
) {
1493 wxNode
* node
= fields
.Nth(recnum
);
1498 long actsize
= ((wxQueryField
*)node
->Data())->GetSize();
1499 if (actsize
> varsize
)
1502 memcpy(var
, ((wxQueryField
*)node
->Data())->GetData(), actsize
);
1505 void wxQueryCol::SetNullable(bool n
) {
1509 char* wxQueryCol::GetName(void) {
1513 short wxQueryCol::GetType(void) {
1517 bool wxQueryCol::IsNullable(void) {
1522 bool wxQueryCol::IsFieldDirty(int row
) {
1523 wxNode
* node
= fields
.Nth(row
);
1528 return ((wxQueryField
*)node
->Data())->IsDirty();
1531 void* wxQueryCol::GetData(int row
) {
1532 wxNode
* node
= fields
.Nth(row
);
1537 return ((wxQueryField
*)node
->Data())->GetData();
1540 long wxQueryCol::GetSize(int row
) {
1541 wxNode
* node
= fields
.Nth(row
);
1546 return ((wxQueryField
*)node
->Data())->GetSize();
1549 wxQueryField::wxQueryField(void) {
1550 // __type = wxTYPE_QUERYROW;
1552 type
= SQL_TYPE_NULL
;
1557 wxQueryField::~wxQueryField(void) {
1565 delete[] (char*)data
;
1573 delete (short*)data
;
1578 delete (double*)data
;
1582 delete (float*)data
;
1586 delete (TIME_STRUCT
*)data
;
1590 delete (DATE_STRUCT
*)data
;
1594 delete (TIMESTAMP_STRUCT
*)data
;
1599 bool wxQueryField::AllocData(void) {
1608 delete[] (char*)data
;
1609 if ((data
= new char[size
+1]))
1611 char *str
= (char *)data
;
1613 for (i
= 0; i
< size
; i
++)
1615 // memset(data, 0, size+1);
1623 if ((data
= new long))
1630 delete (short*)data
;
1631 if ((data
= new short))
1639 delete (double*)data
;
1640 if ((data
= new double))
1647 delete (float*)data
;
1648 if ((data
= new float))
1649 *(float*)data
= (float)0;
1655 delete (TIME_STRUCT
*)data
;
1656 data
= new TIME_STRUCT
;
1657 memset(data
, 0, sizeof(TIME_STRUCT
));
1663 delete (DATE_STRUCT
*)data
;
1664 data
= new DATE_STRUCT
;
1665 memset(data
, 0, sizeof(DATE_STRUCT
));
1671 delete (TIMESTAMP_STRUCT
*)data
;
1672 data
= new TIMESTAMP_STRUCT
;
1673 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1683 bool wxQueryField::SetData(void* d
, long s
) {
1685 if (AllocData() && d
)
1687 // memcpy(data, d, s);
1695 char *str
= (char *)data
;
1697 for (i
= 0; i
< size
; i
++)
1700 strncpy(str
, (char *)d
, (int)size
);
1706 *(long*)data
= *((long *)d
);
1711 *(short*)data
= *((short*)d
);
1717 *(double*)data
= *((double*)d
);
1722 *(float*)data
= *((float*)d
);
1727 *(TIME_STRUCT
*)data
= *((TIME_STRUCT
*)d
);
1732 *(TIMESTAMP_STRUCT
*)data
= *((TIMESTAMP_STRUCT
*)d
);
1737 *(DATE_STRUCT
*)data
= *((DATE_STRUCT
*)d
);
1748 void wxQueryField::ClearData(void) {
1751 // memset(data, 0, size);
1759 char *str
= (char *)data
;
1761 for (i
= 0; i
< size
; i
++)
1778 *(double*)data
= (double)0.0;
1783 *(float*)data
= (float)0.0;
1788 memset(data
, 0, sizeof(TIME_STRUCT
));
1793 memset(data
, 0, sizeof(DATE_STRUCT
));
1798 memset(data
, 0, sizeof(TIMESTAMP_STRUCT
));
1807 void wxQueryField::SetDirty(bool d
) {
1811 void wxQueryField::SetType(short t
) {
1815 void wxQueryField::SetSize(long s
) {
1820 void* wxQueryField::GetData(void) {
1824 short wxQueryField::GetType(void) {
1828 long wxQueryField::GetSize(void) {
1832 bool wxQueryField::IsDirty(void) {
1837 #pragma warning(default:4706) // assignment within conditional expression
1840 #endif // wxUSE_OLD_ODBC