dbtable.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,992 行 · 第 1/5 页
CPP
1,992 行
///////////////////////////////////////////////////////////////////////////////
// Name: dbtable.cpp
// Purpose: Implementation of the wxDbTable class.
// Author: Doug Card
// Modified by: George Tasker
// Bart Jourquin
// Mark Johnson
// Created: 9.96
// RCS-ID: $Id: dbtable.cpp,v 1.105 2005/09/16 11:03:53 JS Exp $
// Copyright: (c) 1996 Remstar International, Inc.
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
/*
// SYNOPSIS START
// SYNOPSIS STOP
*/
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "dbtable.h"
#endif
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifdef DBDEBUG_CONSOLE
#if wxUSE_IOSTREAMH
#include <iostream.h>
#else
#include <iostream>
#endif
#include "wx/ioswrap.h"
#endif
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/object.h"
#include "wx/list.h"
#include "wx/utils.h"
#include "wx/log.h"
#endif
#include "wx/filefn.h"
#if wxUSE_ODBC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wx/dbtable.h"
#ifdef __UNIX__
// The HPUX preprocessor lines below were commented out on 8/20/97
// because macros.h currently redefines DEBUG and is unneeded.
// # ifdef HPUX
// # include <macros.h>
// # endif
# ifdef LINUX
# include <sys/minmax.h>
# endif
#endif
ULONG lastTableID = 0;
#ifdef __WXDEBUG__
wxList TablesInUse;
#endif
void csstrncpyt(wxChar *target, const wxChar *source, int n)
{
while ( (*target++ = *source++) != '\0' && --n )
;
*target = '\0';
}
/********** wxDbColDef::wxDbColDef() Constructor **********/
wxDbColDef::wxDbColDef()
{
Initialize();
} // Constructor
bool wxDbColDef::Initialize()
{
ColName[0] = 0;
DbDataType = DB_DATA_TYPE_INTEGER;
SqlCtype = SQL_C_LONG;
PtrDataObj = NULL;
SzDataObj = 0;
KeyField = false;
Updateable = false;
InsertAllowed = false;
DerivedCol = false;
CbValue = 0;
Null = false;
return true;
} // wxDbColDef::Initialize()
/********** wxDbTable::wxDbTable() Constructor **********/
wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns,
const wxString &qryTblName, bool qryOnly, const wxString &tblPath)
{
if (!initialize(pwxDb, tblName, numColumns, qryTblName, qryOnly, tblPath))
cleanup();
} // wxDbTable::wxDbTable()
/***** DEPRECATED: use wxDbTable::wxDbTable() format above *****/
#if WXWIN_COMPATIBILITY_2_4
wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns,
const wxChar *qryTblName, bool qryOnly, const wxString &tblPath)
{
wxString tempQryTblName;
tempQryTblName = qryTblName;
if (!initialize(pwxDb, tblName, numColumns, tempQryTblName, qryOnly, tblPath))
cleanup();
} // wxDbTable::wxDbTable()
#endif // WXWIN_COMPATIBILITY_2_4
/********** wxDbTable::~wxDbTable() **********/
wxDbTable::~wxDbTable()
{
this->cleanup();
} // wxDbTable::~wxDbTable()
bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns,
const wxString &qryTblName, bool qryOnly, const wxString &tblPath)
{
// Initializing member variables
pDb = pwxDb; // Pointer to the wxDb object
henv = 0;
hdbc = 0;
hstmt = 0;
m_hstmtGridQuery = 0;
hstmtDefault = 0; // Initialized below
hstmtCount = 0; // Initialized first time it is needed
hstmtInsert = 0;
hstmtDelete = 0;
hstmtUpdate = 0;
hstmtInternal = 0;
colDefs = 0;
tableID = 0;
m_numCols = numColumns; // Number of columns in the table
where.Empty(); // Where clause
orderBy.Empty(); // Order By clause
from.Empty(); // From clause
selectForUpdate = false; // SELECT ... FOR UPDATE; Indicates whether to include the FOR UPDATE phrase
queryOnly = qryOnly;
insertable = true;
tablePath.Empty();
tableName.Empty();
queryTableName.Empty();
wxASSERT(tblName.Length());
wxASSERT(pDb);
if (!pDb)
return false;
tableName = tblName; // Table Name
if ((pDb->Dbms() == dbmsORACLE) ||
(pDb->Dbms() == dbmsFIREBIRD) ||
(pDb->Dbms() == dbmsINTERBASE))
tableName = tableName.Upper();
if (tblPath.Length())
tablePath = tblPath; // Table Path - used for dBase files
else
tablePath.Empty();
if (qryTblName.Length()) // Name of the table/view to query
queryTableName = qryTblName;
else
queryTableName = tblName;
if ((pDb->Dbms() == dbmsORACLE) ||
(pDb->Dbms() == dbmsFIREBIRD) ||
(pDb->Dbms() == dbmsINTERBASE))
queryTableName = queryTableName.Upper();
pDb->incrementTableCount();
wxString s;
tableID = ++lastTableID;
s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), tblName.c_str(), tableID, pDb);
#ifdef __WXDEBUG__
wxTablesInUse *tableInUse;
tableInUse = new wxTablesInUse();
tableInUse->tableName = tblName;
tableInUse->tableID = tableID;
tableInUse->pDb = pDb;
TablesInUse.Append(tableInUse);
#endif
pDb->WriteSqlLog(s);
// Grab the HENV and HDBC from the wxDb object
henv = pDb->GetHENV();
hdbc = pDb->GetHDBC();
// Allocate space for column definitions
if (m_numCols)
colDefs = new wxDbColDef[m_numCols]; // Points to the first column definition
// Allocate statement handles for the table
if (!queryOnly)
{
// Allocate a separate statement handle for performing inserts
if (SQLAllocStmt(hdbc, &hstmtInsert) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
// Allocate a separate statement handle for performing deletes
if (SQLAllocStmt(hdbc, &hstmtDelete) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
// Allocate a separate statement handle for performing updates
if (SQLAllocStmt(hdbc, &hstmtUpdate) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
}
// Allocate a separate statement handle for internal use
if (SQLAllocStmt(hdbc, &hstmtInternal) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
// Set the cursor type for the statement handles
cursorType = SQL_CURSOR_STATIC;
if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS)
{
// Check to see if cursor type is supported
pDb->GetNextError(henv, hdbc, hstmtInternal);
if (! wxStrcmp(pDb->sqlState, wxT("01S02"))) // Option Value Changed
{
// Datasource does not support static cursors. Driver
// will substitute a cursor type. Call SQLGetStmtOption()
// to determine which cursor type was selected.
if (SQLGetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, &cursorType) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc, hstmtInternal);
#ifdef DBDEBUG_CONSOLE
cout << wxT("Static cursor changed to: ");
switch(cursorType)
{
case SQL_CURSOR_FORWARD_ONLY:
cout << wxT("Forward Only");
break;
case SQL_CURSOR_STATIC:
cout << wxT("Static");
break;
case SQL_CURSOR_KEYSET_DRIVEN:
cout << wxT("Keyset Driven");
break;
case SQL_CURSOR_DYNAMIC:
cout << wxT("Dynamic");
break;
}
cout << endl << endl;
#endif
// BJO20000425
if (pDb->FwdOnlyCursors() && cursorType != SQL_CURSOR_FORWARD_ONLY)
{
// Force the use of a forward only cursor...
cursorType = SQL_CURSOR_FORWARD_ONLY;
if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS)
{
// Should never happen
pDb->GetNextError(henv, hdbc, hstmtInternal);
return false;
}
}
}
else
{
pDb->DispNextError();
pDb->DispAllErrors(henv, hdbc, hstmtInternal);
}
}
#ifdef DBDEBUG_CONSOLE
else
cout << wxT("Cursor Type set to STATIC") << endl << endl;
#endif
if (!queryOnly)
{
// Set the cursor type for the INSERT statement handle
if (SQLSetStmtOption(hstmtInsert, SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc, hstmtInsert);
// Set the cursor type for the DELETE statement handle
if (SQLSetStmtOption(hstmtDelete, SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc, hstmtDelete);
// Set the cursor type for the UPDATE statement handle
if (SQLSetStmtOption(hstmtUpdate, SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc, hstmtUpdate);
}
// Make the default cursor the active cursor
hstmtDefault = GetNewCursor(false,false);
wxASSERT(hstmtDefault);
hstmt = *hstmtDefault;
return true;
} // wxDbTable::initialize()
void wxDbTable::cleanup()
{
wxString s;
if (pDb)
{
s.Printf(wxT("wxDbTable destructor (%-20s) tableID:[%6lu] pDb:[%p]"), tableName.c_str(), tableID, pDb);
pDb->WriteSqlLog(s);
}
#ifdef __WXDEBUG__
if (tableID)
{
bool found = false;
wxList::compatibility_iterator pNode;
pNode = TablesInUse.GetFirst();
while (pNode && !found)
{
if (((wxTablesInUse *)pNode->GetData())->tableID == tableID)
{
found = true;
delete (wxTablesInUse *)pNode->GetData();
TablesInUse.Erase(pNode);
}
else
pNode = pNode->GetNext();
}
if (!found)
{
wxString msg;
msg.Printf(wxT("Unable to find the tableID in the linked\nlist of tables in use.\n\n%s"),s.c_str());
wxLogDebug (msg,wxT("NOTICE..."));
}
}
#endif
// Decrement the wxDb table count
if (pDb)
pDb->decrementTableCount();
// Delete memory allocated for column definitions
if (colDefs)
delete [] colDefs;
// Free statement handles
if (!queryOnly)
{
if (hstmtInsert)
{
/*
ODBC 3.0 says to use this form
if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
*/
if (SQLFreeStmt(hstmtInsert, SQL_DROP) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
}
if (hstmtDelete)
{
/*
ODBC 3.0 says to use this form
if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
*/
if (SQLFreeStmt(hstmtDelete, SQL_DROP) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
}
if (hstmtUpdate)
{
/*
ODBC 3.0 says to use this form
if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
*/
if (SQLFreeStmt(hstmtUpdate, SQL_DROP) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
}
}
if (hstmtInternal)
{
if (SQLFreeStmt(hstmtInternal, SQL_DROP) != SQL_SUCCESS)
pDb->DispAllErrors(henv, hdbc);
}
// Delete dynamically allocated cursors
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?