db.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,858 行 · 第 1/5 页
CPP
1,858 行
///////////////////////////////////////////////////////////////////////////////
// Name: db.cpp
// Purpose: Implementation of the wxDb class. The wxDb class represents a connection
// to an ODBC data source. The wxDb class allows operations on the data
// source such as opening and closing the data source.
// Author: Doug Card
// Modified by: George Tasker
// Bart Jourquin
// Mark Johnson, wxWindows@mj10777.de
// Mods: Dec, 1998:
// -Added support for SQL statement logging and database cataloging
// Mods: April, 1999
// -Added QUERY_ONLY mode support to reduce default number of cursors
// -Added additional SQL logging code
// -Added DEBUG-ONLY tracking of wxTable objects to detect orphaned DB connections
// -Set ODBC option to only read committed writes to the DB so all
// databases operate the same in that respect
// Created: 9.96
// RCS-ID: $Id: db.cpp,v 1.125.2.2 2006/01/17 16:51:03 JS Exp $
// Copyright: (c) 1996 Remstar International, Inc.
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
/*
// SYNOPSIS START
// SYNOPSIS STOP
*/
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "db.h"
#endif
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifdef DBDEBUG_CONSOLE
#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"
#include "wx/wxchar.h"
#if wxUSE_ODBC
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include "wx/db.h"
// DLL options compatibility check:
#include "wx/app.h"
WX_CHECK_BUILD_OPTIONS("wxODBC")
WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0;
wxChar const *SQL_LOG_FILENAME = wxT("sqllog.txt");
wxChar const *SQL_CATALOG_FILENAME = wxT("catalog.txt");
#ifdef __WXDEBUG__
extern wxList TablesInUse;
#endif
// SQL Log defaults to be used by GetDbConnection
wxDbSqlLogState SQLLOGstate = sqlLogOFF;
static wxString SQLLOGfn = SQL_LOG_FILENAME;
// The wxDb::errorList is copied to this variable when the wxDb object
// is closed. This way, the error list is still available after the
// database object is closed. This is necessary if the database
// connection fails so the calling application can show the operator
// why the connection failed. Note: as each wxDb object is closed, it
// will overwrite the errors of the previously destroyed wxDb object in
// this variable. NOTE: This occurs during a CLOSE, not a FREEing of the
// connection
wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN+1];
// This type defines the return row-struct form
// SQLTablePrivileges, and is used by wxDB::TablePrivileges.
typedef struct
{
wxChar tableQual[128+1];
wxChar tableOwner[128+1];
wxChar tableName[128+1];
wxChar grantor[128+1];
wxChar grantee[128+1];
wxChar privilege[128+1];
wxChar grantable[3+1];
} wxDbTablePrivilegeInfo;
/********** wxDbConnectInf Constructor - form 1 **********/
wxDbConnectInf::wxDbConnectInf()
{
Henv = 0;
freeHenvOnDestroy = false;
Initialize();
} // Constructor
/********** wxDbConnectInf Constructor - form 2 **********/
wxDbConnectInf::wxDbConnectInf(HENV henv, const wxString &dsn, const wxString &userID,
const wxString &password, const wxString &defaultDir,
const wxString &fileType, const wxString &description)
{
Henv = 0;
freeHenvOnDestroy = false;
Initialize();
if (henv)
SetHenv(henv);
else
AllocHenv();
SetDsn(dsn);
SetUserID(userID);
SetPassword(password);
SetDescription(description);
SetFileType(fileType);
SetDefaultDir(defaultDir);
} // wxDbConnectInf Constructor
wxDbConnectInf::~wxDbConnectInf()
{
if (freeHenvOnDestroy)
{
FreeHenv();
}
} // wxDbConnectInf Destructor
/********** wxDbConnectInf::Initialize() **********/
bool wxDbConnectInf::Initialize()
{
freeHenvOnDestroy = false;
if (freeHenvOnDestroy && Henv)
FreeHenv();
Henv = 0;
Dsn[0] = 0;
Uid[0] = 0;
AuthStr[0] = 0;
ConnectionStr[0] = 0;
Description.Empty();
FileType.Empty();
DefaultDir.Empty();
useConnectionStr = false;
return true;
} // wxDbConnectInf::Initialize()
/********** wxDbConnectInf::AllocHenv() **********/
bool wxDbConnectInf::AllocHenv()
{
// This is here to help trap if you are getting a new henv
// without releasing an existing henv
wxASSERT(!Henv);
// Initialize the ODBC Environment for Database Operations
if (SQLAllocEnv(&Henv) != SQL_SUCCESS)
{
wxLogDebug(wxT("A problem occurred while trying to get a connection to the data source"));
return false;
}
freeHenvOnDestroy = true;
return true;
} // wxDbConnectInf::AllocHenv()
void wxDbConnectInf::FreeHenv()
{
wxASSERT(Henv);
if (Henv)
SQLFreeEnv(Henv);
Henv = 0;
freeHenvOnDestroy = false;
} // wxDbConnectInf::FreeHenv()
void wxDbConnectInf::SetDsn(const wxString &dsn)
{
wxASSERT(dsn.Length() < WXSIZEOF(Dsn));
wxStrncpy(Dsn, dsn, WXSIZEOF(Dsn)-1);
Dsn[WXSIZEOF(Dsn)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetDsn()
void wxDbConnectInf::SetUserID(const wxString &uid)
{
wxASSERT(uid.Length() < WXSIZEOF(Uid));
wxStrncpy(Uid, uid, WXSIZEOF(Uid)-1);
Uid[WXSIZEOF(Uid)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetUserID()
void wxDbConnectInf::SetPassword(const wxString &password)
{
wxASSERT(password.Length() < WXSIZEOF(AuthStr));
wxStrncpy(AuthStr, password, WXSIZEOF(AuthStr)-1);
AuthStr[WXSIZEOF(AuthStr)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetPassword()
void wxDbConnectInf::SetConnectionStr(const wxString &connectStr)
{
wxASSERT(connectStr.Length() < WXSIZEOF(ConnectionStr));
useConnectionStr = wxStrlen(connectStr) > 0;
wxStrncpy(ConnectionStr, connectStr, WXSIZEOF(ConnectionStr)-1);
ConnectionStr[WXSIZEOF(ConnectionStr)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetConnectionStr()
/********** wxDbColFor Constructor **********/
wxDbColFor::wxDbColFor()
{
Initialize();
} // wxDbColFor::wxDbColFor()
/********** wxDbColFor::Initialize() **********/
void wxDbColFor::Initialize()
{
s_Field.Empty();
int i;
for (i=0; i<7; i++)
{
s_Format[i].Empty();
s_Amount[i].Empty();
i_Amount[i] = 0;
}
i_Nation = 0; // 0=EU, 1=UK, 2=International, 3=US
i_dbDataType = 0;
i_sqlDataType = 0;
Format(1,DB_DATA_TYPE_VARCHAR,0,0,0); // the Function that does the work
} // wxDbColFor::Initialize()
/********** wxDbColFor::Format() **********/
int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType,
short columnLength, short decimalDigits)
{
// ----------------------------------------------------------------------------------------
// -- 19991224 : mj10777 : Create
// There is still a lot of work to do here, but it is a start
// It handles all the basic data-types that I have run into up to now
// The main work will have be with Dates and float Formatting
// (US 1,000.00 ; EU 1.000,00)
// There are wxWindow plans for locale support and the new wxDateTime. If
// they define some constants (wxEUROPEAN) that can be gloably used,
// they should be used here.
// ----------------------------------------------------------------------------------------
// There should also be a function to scan in a string to fill the variable
// ----------------------------------------------------------------------------------------
wxString tempStr;
i_Nation = Nation; // 0 = timestamp , 1=EU, 2=UK, 3=International, 4=US
i_dbDataType = dbDataType;
i_sqlDataType = sqlDataType;
s_Field.Printf(wxT("%s%d"),s_Amount[1].c_str(),i_Amount[1]); // OK for VARCHAR, INTEGER and FLOAT
if (i_dbDataType == 0) // Filter unsupported dbDataTypes
{
if ((i_sqlDataType == SQL_VARCHAR)
#if wxUSE_UNICODE
#if defined(SQL_WCHAR)
|| (i_sqlDataType == SQL_WCHAR)
#endif
#if defined(SQL_WVARCHAR)
|| (i_sqlDataType == SQL_WVARCHAR)
#endif
#endif
|| (i_sqlDataType == SQL_LONGVARCHAR))
i_dbDataType = DB_DATA_TYPE_VARCHAR;
if ((i_sqlDataType == SQL_C_DATE) || (i_sqlDataType == SQL_C_TIMESTAMP))
i_dbDataType = DB_DATA_TYPE_DATE;
if (i_sqlDataType == SQL_C_BIT)
i_dbDataType = DB_DATA_TYPE_INTEGER;
if (i_sqlDataType == SQL_NUMERIC)
i_dbDataType = DB_DATA_TYPE_VARCHAR; // glt - ??? is this right?
if (i_sqlDataType == SQL_REAL)
i_dbDataType = DB_DATA_TYPE_FLOAT;
if (i_sqlDataType == SQL_C_BINARY)
i_dbDataType = DB_DATA_TYPE_BLOB;
}
if ((i_dbDataType == DB_DATA_TYPE_INTEGER) && (i_sqlDataType == SQL_C_DOUBLE))
{ // DBASE Numeric
i_dbDataType = DB_DATA_TYPE_FLOAT;
}
switch(i_dbDataType) // TBD: Still a lot of proper formatting to do
{
case DB_DATA_TYPE_VARCHAR:
s_Field = wxT("%s");
break;
case DB_DATA_TYPE_INTEGER:
s_Field = wxT("%d");
break;
case DB_DATA_TYPE_FLOAT:
if (decimalDigits == 0)
decimalDigits = 2;
tempStr.Printf(wxT("%%%d.%d"), columnLength, decimalDigits);
s_Field.Printf(wxT("%sf"), tempStr.c_str());
break;
case DB_DATA_TYPE_DATE:
if (i_Nation == 0) // timestamp YYYY-MM-DD HH:MM:SS.SSS (tested for SYBASE)
{
s_Field = wxT("%04d-%02d-%02d %02d:%02d:%02d.%03d");
}
if (i_Nation == 1) // European DD.MM.YYYY HH:MM:SS.SSS
{
s_Field = wxT("%02d.%02d.%04d %02d:%02d:%02d.%03d");
}
if (i_Nation == 2) // UK DD/MM/YYYY HH:MM:SS.SSS
{
s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
}
if (i_Nation == 3) // International YYYY-MM-DD HH:MM:SS.SSS
{
s_Field = wxT("%04d-%02d-%02d %02d:%02d:%02d.%03d");
}
if (i_Nation == 4) // US MM/DD/YYYY HH:MM:SS.SSS
{
s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
}
break;
case DB_DATA_TYPE_BLOB:
s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"), dbDataType,sqlDataType); //
break;
default:
s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"), dbDataType,sqlDataType); //
break;
};
return TRUE;
} // wxDbColFor::Format()
/********** wxDbColInf Constructor **********/
wxDbColInf::wxDbColInf()
{
Initialize();
} // wxDbColInf::wxDbColInf()
/********** wxDbColInf Destructor ********/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?