⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsql_odbc.cpp

📁 这个是Linux的qt源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************** Implementation of ODBC driver classes**** Created : 001103**** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.**** This file is part of the sql module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition licenses may use this** file in accordance with the Qt Commercial License Agreement provided** with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for**   information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qsql_odbc.h"#include <qsqlrecord.h>#if defined (Q_OS_WIN32)#include <qt_windows.h>#include <qapplication.h>#endif#include <qdatetime.h>#include <private/qsqlextension_p.h>#include <private/qinternal_p.h>#include <stdlib.h>// undefine this to prevent initial check of the ODBC driver#define ODBC_CHECK_DRIVER#if defined(Q_ODBC_VERSION_2)//crude hack to get non-unicode capable driver managers to work# undef UNICODE# define SQLTCHAR SQLCHAR# define SQL_C_WCHAR SQL_C_CHAR#endifstatic const int COLNAMESIZE = 255;//Map Qt parameter types to ODBC typesstatic const SQLSMALLINT qParamType[ 4 ] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };class QODBCPrivate{public:    QODBCPrivate()    : hEnv(0), hDbc(0), hStmt(0), useSchema(FALSE)    {	sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::CString;	unicode = FALSE;    }    SQLHANDLE hEnv;    SQLHANDLE hDbc;    SQLHANDLE hStmt;    bool unicode;    bool useSchema;    QVariant::Type sql_char_type;    QVariant::Type sql_varchar_type;    QVariant::Type sql_longvarchar_type;    QSqlRecordInfo rInf;    bool checkDriver() const;    void checkUnicode();    void checkSchemaUsage();    bool setConnectionOptions( const QString& connOpts );    void splitTableQualifier(const QString &qualifier, QString &catalog,			     QString &schema, QString &table);};class QODBCPreparedExtension : public QSqlExtension{public:    QODBCPreparedExtension( QODBCResult * r )	: result( r ) {}    bool prepare( const QString& query )    {	return result->prepare( query );    }    bool exec()    {	return result->exec();    }    QODBCResult * result;};QPtrDict<QSqlOpenExtension> *qSqlOpenExtDict();class QODBCOpenExtension : public QSqlOpenExtension{public:    QODBCOpenExtension( QODBCDriver *dri )	: QSqlOpenExtension(), driver(dri) {}    ~QODBCOpenExtension() {}    bool open( const QString& db,	       const QString& user,	       const QString& password,	       const QString& host,	       int port,	       const QString& connOpts );private:    QODBCDriver *driver;};bool QODBCOpenExtension::open( const QString& db,			       const QString& user,			       const QString& password,			       const QString& host,			       int port,			       const QString& connOpts ){    return driver->open( db, user, password, host, port, connOpts );}static QString qWarnODBCHandle(int handleType, SQLHANDLE handle){    SQLINTEGER nativeCode_;    SQLSMALLINT msgLen;    SQLRETURN r = SQL_ERROR;    SQLTCHAR state_[SQL_SQLSTATE_SIZE+1];    SQLTCHAR description_[SQL_MAX_MESSAGE_LENGTH];    r = SQLGetDiagRec( handleType,			 handle,			 1,			 (SQLTCHAR*)state_,			 &nativeCode_,			 (SQLTCHAR*)description_,			 SQL_MAX_MESSAGE_LENGTH-1, /* in bytes, not in characters */			 &msgLen);    if ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO )#ifdef UNICODE	return QString( (const QChar*)description_, (uint)msgLen );#else	return QString::fromLocal8Bit( (const char*)description_ );#endif    return QString::null;}static QString qODBCWarn( const QODBCPrivate* odbc){    return ( qWarnODBCHandle( SQL_HANDLE_ENV, odbc->hEnv ) + " "	     + qWarnODBCHandle( SQL_HANDLE_DBC, odbc->hDbc ) + " "	     + qWarnODBCHandle( SQL_HANDLE_STMT, odbc->hStmt ) );}static void qSqlWarning( const QString& message, const QODBCPrivate* odbc ){#ifdef QT_CHECK_RANGE    qWarning( "%s\tError: %s", message.local8Bit().data(), qODBCWarn( odbc ).local8Bit().data() );#endif}static QSqlError qMakeError( const QString& err, int type, const QODBCPrivate* p ){    return QSqlError( "QODBC3: " + err, qODBCWarn(p), type );}static QVariant::Type qDecodeODBCType( SQLSMALLINT sqltype, const QODBCPrivate* p ){    QVariant::Type type = QVariant::Invalid;    switch ( sqltype ) {    case SQL_DECIMAL:    case SQL_NUMERIC:    case SQL_REAL:    case SQL_FLOAT:    case SQL_DOUBLE:	type = QVariant::Double;	break;    case SQL_SMALLINT:    case SQL_INTEGER:    case SQL_BIT:    case SQL_TINYINT:	type = QVariant::Int;	break;    case SQL_BIGINT:	type = QVariant::LongLong;	break;    case SQL_BINARY:    case SQL_VARBINARY:    case SQL_LONGVARBINARY:	type = QVariant::ByteArray;	break;    case SQL_DATE:    case SQL_TYPE_DATE:	type = QVariant::Date;	break;    case SQL_TIME:    case SQL_TYPE_TIME:	type = QVariant::Time;	break;    case SQL_TIMESTAMP:    case SQL_TYPE_TIMESTAMP:	type = QVariant::DateTime;	break;#ifndef Q_ODBC_VERSION_2    case SQL_WCHAR:    case SQL_WVARCHAR:    case SQL_WLONGVARCHAR:	type = QVariant::String;	break;#endif    case SQL_CHAR:	type = p->sql_char_type;	break;    case SQL_VARCHAR:	type = p->sql_varchar_type;	break;    case SQL_LONGVARCHAR:	type = p->sql_longvarchar_type;	break;    default:	type = QVariant::CString;	break;    }    return type;}static QString qGetStringData( SQLHANDLE hStmt, int column, int colSize, bool& isNull, bool unicode = FALSE ){    QString     fieldVal;    SQLRETURN   r = SQL_ERROR;    SQLINTEGER  lengthIndicator = 0;    if ( colSize <= 0 ) {	colSize = 255;    } else if ( colSize > 65536 ) { // limit buffer size to 64 KB	colSize = 65536;    } else {	colSize++; // make sure there is room for more than the 0 termination	if ( unicode ) {	    colSize *= 2; // a tiny bit faster, since it saves a SQLGetData() call	}    }    char* buf = new char[ colSize ];    while ( TRUE ) {	r = SQLGetData( hStmt,			column+1,			unicode ? SQL_C_WCHAR : SQL_C_CHAR,			(SQLPOINTER)buf,			colSize,			&lengthIndicator );	if ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) {	    if ( lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL ) {		fieldVal = QString::null;		isNull = TRUE;		break;	    }	    // if SQL_SUCCESS_WITH_INFO is returned, indicating that	    // more data can be fetched, the length indicator does NOT	    // contain the number of bytes returned - it contains the	    // total number of bytes that CAN be fetched	    // colSize-1: remove 0 termination when there is more data to fetch	    int rSize = (r == SQL_SUCCESS_WITH_INFO) ? (unicode ? colSize-2 : colSize-1) : lengthIndicator;	    if ( unicode ) {		fieldVal += QString( (QChar*) buf, rSize / 2 );	    } else {		buf[ rSize ] = 0;		fieldVal += buf;	    }	    if ( lengthIndicator < colSize ) {		// workaround for Drivermanagers that don't return SQL_NO_DATA		break;	    }	} else if ( r == SQL_NO_DATA ) {	    break;	} else {#ifdef QT_CHECK_RANGE	    qWarning( "qGetStringData: Error while fetching data (%d)", r );#endif	    fieldVal = QString::null;	    break;	}    }    delete[] buf;    return fieldVal;}static QByteArray qGetBinaryData( SQLHANDLE hStmt, int column, SQLINTEGER& lengthIndicator, bool& isNull ){    QByteArray fieldVal;    SQLSMALLINT colNameLen;    SQLSMALLINT colType;    SQLUINTEGER colSize;    SQLSMALLINT colScale;    SQLSMALLINT nullable;    SQLRETURN r = SQL_ERROR;    SQLTCHAR colName[COLNAMESIZE];    r = SQLDescribeCol( hStmt,			column+1,			colName,			COLNAMESIZE,			&colNameLen,			&colType,			&colSize,			&colScale,			&nullable );#ifdef QT_CHECK_RANGE    if ( r != SQL_SUCCESS )	qWarning( "qGetBinaryData: Unable to describe column %d", column );#endif    // SQLDescribeCol may return 0 if size cannot be determined    if (!colSize) {	colSize = 255;    }    if ( colSize > 65536 ) { // read the field in 64 KB chunks	colSize = 65536;    }    char * buf = new char[ colSize ];    while ( TRUE ) {	r = SQLGetData( hStmt,			column+1,			SQL_C_BINARY,			(SQLPOINTER) buf,			colSize,			&lengthIndicator );	if ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) {	    if ( lengthIndicator == SQL_NULL_DATA ) { 		isNull = TRUE;		break;	    } else {		int rSize;		r == SQL_SUCCESS ? rSize = lengthIndicator : rSize = colSize;		if ( lengthIndicator == SQL_NO_TOTAL ) { // size cannot be determined		    rSize = colSize;		}		// NB! This is not a memleak - the mem will be deleted by QByteArray when		// no longer ref'd		char * tmp = (char *) malloc( rSize + fieldVal.size() );		if ( fieldVal.size() ) {		    memcpy( tmp, fieldVal.data(), fieldVal.size() );		}		memcpy( tmp + fieldVal.size(), buf, rSize );		fieldVal = fieldVal.assign( tmp, fieldVal.size() + rSize );		if ( r == SQL_SUCCESS ) { // the whole field was read in one chunk		    break;		}	    }	} else {	    break;	}    }    delete [] buf;    return fieldVal;}static int qGetIntData( SQLHANDLE hStmt, int column, bool& isNull  ){    SQLINTEGER intbuf = 0;    isNull = FALSE;    SQLINTEGER lengthIndicator = 0;    SQLRETURN r = SQLGetData( hStmt,			      column+1,			      SQL_C_SLONG,			      (SQLPOINTER)&intbuf,			      0,			      &lengthIndicator );    if ( ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) || lengthIndicator == SQL_NULL_DATA ) {	isNull = TRUE;	return 0;    }    return (int)intbuf;}static double qGetDoubleData( SQLHANDLE hStmt, int column, bool& isNull ){    SQLDOUBLE dblbuf;    SQLINTEGER lengthIndicator = 0;    isNull = FALSE;    SQLRETURN r = SQLGetData( hStmt,			      column+1,			      SQL_C_DOUBLE,			      (SQLPOINTER)&dblbuf,			      0,			      &lengthIndicator );    if ( ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) || lengthIndicator == SQL_NULL_DATA ) {	isNull = TRUE;	return 0.0;    }    return (double) dblbuf;}static SQLBIGINT qGetBigIntData( SQLHANDLE hStmt, int column, bool& isNull ){    SQLBIGINT lngbuf = Q_INT64_C( 0 );    isNull = FALSE;    SQLINTEGER lengthIndicator = 0;    SQLRETURN r = SQLGetData( hStmt,			      column+1,			      SQL_C_SBIGINT,			      (SQLPOINTER) &lngbuf,			      0,			      &lengthIndicator );    if ( ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) || lengthIndicator == SQL_NULL_DATA )	isNull = TRUE;    return lngbuf;}// creates a QSqlFieldInfo from a valid hStmt generated// by SQLColumns. The hStmt has to point to a valid position.static QSqlFieldInfo qMakeFieldInfo( const SQLHANDLE hStmt, const QODBCPrivate* p ){    bool isNull;    QString fname = qGetStringData( hStmt, 3, -1, isNull, p->unicode );    int type = qGetIntData( hStmt, 4, isNull ); // column type    int required = qGetIntData( hStmt, 10, isNull ); // nullable-flag    // required can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN    if ( required == SQL_NO_NULLS ) {	required = 1;    } else if ( required == SQL_NULLABLE ) {	required = 0;    } else {	required = -1;    }    int size = qGetIntData( hStmt, 6, isNull ); // column size    int prec = qGetIntData( hStmt, 8, isNull ); // precision    return QSqlFieldInfo( fname, qDecodeODBCType( type, p ), required, size, prec, QVariant(), type );}static QSqlFieldInfo qMakeFieldInfo( const QODBCPrivate* p, int i  ){    SQLSMALLINT colNameLen;    SQLSMALLINT colType;    SQLUINTEGER colSize;    SQLSMALLINT colScale;    SQLSMALLINT nullable;    SQLRETURN r = SQL_ERROR;    SQLTCHAR colName[ COLNAMESIZE ];    r = SQLDescribeCol( p->hStmt,			i+1,			colName,			(SQLSMALLINT)COLNAMESIZE,			&colNameLen,			&colType,			&colSize,			&colScale,			&nullable);    if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE	qSqlWarning( QString("qMakeField: Unable to describe column %1").arg(i), p );#endif	return QSqlFieldInfo();    }#ifdef UNICODE    QString qColName( (const QChar*)colName, (uint)colNameLen );#else    QString qColName = QString::fromLocal8Bit( (const char*)colName );#endif    // nullable can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN    int required = -1;    if ( nullable == SQL_NO_NULLS ) {	required = 1;    } else if ( nullable == SQL_NULLABLE ) {	required = 0;    }    QVariant::Type type = qDecodeODBCType( colType, p );    return QSqlFieldInfo( qColName,    			  type,    			  required,    			  (int)colSize == 0 ? -1 : (int)colSize,    			  (int)colScale == 0 ? -1 : (int)colScale,    			  QVariant(),    			  (int)colType );}bool QODBCPrivate::setConnectionOptions( const QString& connOpts ){    // Set any connection attributes    QStringList raw = QStringList::split( ';', connOpts );    QStringList opts;    SQLRETURN r = SQL_SUCCESS;    QMap<QString, QString> connMap;    for ( QStringList::ConstIterator it = raw.begin(); it != raw.end(); ++it ) {	QString tmp( *it );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -