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 + -
显示快捷键?