📄 qsql_odbc.cpp
字号:
(SQLPOINTER)SQL_CURSOR_STATIC, SQL_IS_UINTEGER ); } if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::prepare: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration", d );#endif return FALSE; }#ifdef UNICODE r = SQLPrepare( d->hStmt, (SQLWCHAR*) query.unicode(), (SQLINTEGER) query.length() );#else QCString query8 = query.local8Bit(); r = SQLPrepare( d->hStmt, (SQLCHAR*) query8.data(), (SQLINTEGER) query8.length() );#endif if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::prepare: Unable to prepare statement", d );#endif return FALSE; } return TRUE;}bool QODBCResult::exec(){ SQLRETURN r; QPtrList<QVirtualDestructor> tmpStorage; // holds temporary ptrs. which will be deleted on fu exit tmpStorage.setAutoDelete( TRUE ); setActive( FALSE ); setAt( QSql::BeforeFirst ); d->rInf.clear(); if ( !d->hStmt ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::exec: No statement handle available", d );#endif return FALSE; } else { r = SQLFreeStmt( d->hStmt, SQL_CLOSE ); if ( r != SQL_SUCCESS ) { qSqlWarning( "QODBCResult::exec: Unable to close statement handle", d ); return FALSE; } } // bind parameters - only positional binding allowed if ( extension()->index.count() > 0 ) { QMap<int, QString>::Iterator it; int para = 1; QVariant val; for ( it = extension()->index.begin(); it != extension()->index.end(); ++it ) { val = extension()->values[ it.data() ].value; SQLINTEGER * ind = new SQLINTEGER( SQL_NTS ); tmpStorage.append( qAutoDeleter(ind) ); if ( val.isNull() ) { *ind = SQL_NULL_DATA; } switch ( val.type() ) { case QVariant::Date: { DATE_STRUCT * dt = new DATE_STRUCT; tmpStorage.append( qAutoDeleter(dt) ); QDate qdt = val.toDate(); dt->year = qdt.year(); dt->month = qdt.month(); dt->day = qdt.day(); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_DATE, SQL_DATE, 0, 0, (void *) dt, 0, *ind == SQL_NULL_DATA ? ind : NULL ); break; } case QVariant::Time: { TIME_STRUCT * dt = new TIME_STRUCT; tmpStorage.append( qAutoDeleter(dt) ); QTime qdt = val.toTime(); dt->hour = qdt.hour(); dt->minute = qdt.minute(); dt->second = qdt.second(); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_TIME, SQL_TIME, 0, 0, (void *) dt, 0, *ind == SQL_NULL_DATA ? ind : NULL ); break; } case QVariant::DateTime: { TIMESTAMP_STRUCT * dt = new TIMESTAMP_STRUCT; tmpStorage.append( qAutoDeleter(dt) ); QDateTime qdt = val.toDateTime(); dt->year = qdt.date().year(); dt->month = qdt.date().month(); dt->day = qdt.date().day(); dt->hour = qdt.time().hour(); dt->minute = qdt.time().minute(); dt->second = qdt.time().second(); dt->fraction = 0; r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, (void *) dt, 0, *ind == SQL_NULL_DATA ? ind : NULL ); break; } case QVariant::Int: { int * v = new int( val.toInt() ); tmpStorage.append( qAutoDeleter(v) ); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_SLONG, SQL_INTEGER, 0, 0, (void *) v, 0, *ind == SQL_NULL_DATA ? ind : NULL ); break; } case QVariant::Double: { double * v = new double( val.toDouble() ); tmpStorage.append( qAutoDeleter(v) ); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, (void *) v, 0, *ind == SQL_NULL_DATA ? ind : NULL ); break; } case QVariant::ByteArray: { if ( *ind != SQL_NULL_DATA ) { *ind = val.asByteArray().size(); } r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_BINARY, SQL_LONGVARBINARY, val.asByteArray().size(), 0, (void *) val.asByteArray().data(), val.asByteArray().size(), ind ); break; }#ifndef Q_ODBC_VERSION_2 case QVariant::String: if ( d->unicode ) { QString * str = new QString( val.asString() ); str->ucs2(); int len = str->length()*2; tmpStorage.append( qAutoDeleter(str) ); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_WCHAR, SQL_WVARCHAR, 0, // god knows... don't change this! 0, (void *) str->unicode(), len, ind ); break; }#endif // fall through default: { QCString * str = new QCString( val.asString().local8Bit() ); tmpStorage.append( qAutoDeleter(str) ); r = SQLBindParameter( d->hStmt, para, qParamType[ (int)extension()->values[ it.data() ].typ ], SQL_C_CHAR, SQL_VARCHAR, str->length() + 1, 0, (void *) str->data(), str->length() + 1, ind ); break; } } para++; if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qWarning( "QODBCResult::exec: unable to bind variable: %s", qODBCWarn( d ).local8Bit().data() );#endif setLastError( qMakeError( "Unable to bind variable", QSqlError::Statement, d ) ); return FALSE; } } } r = SQLExecute( d->hStmt ); if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) {#ifdef QT_CHECK_RANGE qWarning( "QODBCResult::exec: Unable to execute statement: %s", qODBCWarn( d ).local8Bit().data() );#endif setLastError( qMakeError( "Unable to execute statement", QSqlError::Statement, d ) ); return FALSE; } SQLSMALLINT count; r = SQLNumResultCols( d->hStmt, &count ); if ( count ) { setSelect( TRUE ); for ( int i = 0; i < count; ++i ) { d->rInf.append( qMakeFieldInfo( d, i ) ); } } else { setSelect( FALSE ); } setActive( TRUE ); //get out parameters if ( extension()->index.count() > 0 ) { QMap<int, QString>::Iterator it; for ( it = extension()->index.begin(); it != extension()->index.end(); ++it ) { SQLINTEGER* indPtr = qAutoDeleterData( (QAutoDeleter<SQLINTEGER>*)tmpStorage.getFirst() ); if ( !indPtr ) return FALSE; bool isNull = (*indPtr == SQL_NULL_DATA); tmpStorage.removeFirst(); QVariant::Type type = extension()->values[ it.data() ].value.type(); if ( isNull ) { QVariant v; v.cast(type); extension()->values[ it.data() ].value = v; if (type != QVariant::ByteArray) tmpStorage.removeFirst(); continue; } switch (type) { case QVariant::Date: { DATE_STRUCT * ds = qAutoDeleterData( (QAutoDeleter<DATE_STRUCT>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( QDate( ds->year, ds->month, ds->day ) ); break; } case QVariant::Time: { TIME_STRUCT * dt = qAutoDeleterData( (QAutoDeleter<TIME_STRUCT>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( QTime( dt->hour, dt->minute, dt->second ) ); break; } case QVariant::DateTime: { TIMESTAMP_STRUCT * dt = qAutoDeleterData( (QAutoDeleter<TIMESTAMP_STRUCT>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( QDateTime( QDate( dt->year, dt->month, dt->day ), QTime( dt->hour, dt->minute, dt->second ) ) ); break; } case QVariant::Int: { int * v = qAutoDeleterData( (QAutoDeleter<int>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( *v ); break; } case QVariant::Double: { double * v = qAutoDeleterData( (QAutoDeleter<double>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( *v ); break; } case QVariant::ByteArray: break; case QVariant::String: if ( d->unicode ) { QString * str = qAutoDeleterData( (QAutoDeleter<QString>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( *str ); break; } // fall through default: { QCString * str = qAutoDeleterData( (QAutoDeleter<QCString>*)tmpStorage.getFirst() ); extension()->values[ it.data() ].value = QVariant( *str ); break; } } if (type != QVariant::ByteArray) tmpStorage.removeFirst(); } } return TRUE;}////////////////////////////////////////QODBCDriver::QODBCDriver( QObject * parent, const char * name ) : QSqlDriver(parent,name ? name : "QODBC"){ init();}QODBCDriver::QODBCDriver( SQLHANDLE env, SQLHANDLE con, QObject * parent, const char * name ) : QSqlDriver(parent,name ? name : "QODBC"){ init(); d->hEnv = env; d->hDbc = con; if ( env && con ) { setOpen( TRUE ); setOpenError( FALSE ); }}void QODBCDriver::init(){ qSqlOpenExtDict()->insert( this, new QODBCOpenExtension(this) ); d = new QODBCPrivate();}QODBCDriver::~QODBCDriver(){ cleanup(); delete d; if ( !qSqlOpenExtDict()->isEmpty() ) { QSqlOpenExtension *ext = qSqlOpenExtDict()->take( this ); delete ext; }}bool QODBCDriver::hasFeature( DriverFeature f ) const{ switch ( f ) { case Transactions: { if ( !d->hDbc ) return FALSE; SQLUSMALLINT txn; SQLSMALLINT t; int r = SQLGetInfo( d->hDbc, (SQLUSMALLINT)SQL_TXN_CAPABLE, &txn, sizeof(txn), &t); if ( r != SQL_SUCCESS || txn == SQL_TC_NONE ) return FALSE; else return TRUE; } case QuerySize: return FALSE; case BLOB: return TRUE; case Unicode: return d->unicode; case PreparedQueries: return TRUE; case PositionalPlaceholders: return TRUE; default: return FALSE; }}bool QODBCDriver::open( const QString&, const QString&, const QString&, const QString&, int ){ qWarning("QODBCDriver::open(): This version of open() is no longer supported." ); return FALSE;}bool QODBCDriver::open( const QString & db, const QString & user, const QString & password, const QString &, int, const QString& connOpts ){ if ( isOpen() ) close(); SQLRETURN r; r = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &d->hEnv); if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCDriver::open: Unable to allocate environment", d );#endif setOpenError( TRUE ); return FALSE; } r = SQLSetEnvAttr( d->hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, SQL_IS_UINTEGER ); r = SQLAllocHandle( SQL_HANDLE_DBC, d->hEnv, &d->hDbc); if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCDriver::open: Unable to allocate connection", d );#endif setOpenError( TRUE ); return FALSE; } if ( !d->setConnectionOptions( connOpts ) ) return FALSE; // Create the connection string QString connQStr; // support the "DRIVER={SQL SERVER};SERVER=blah" syntax if ( db.contains(".dsn") ) connQStr = "FILEDSN=" + db; else if ( db.contains( "DRIVER" ) || db.contains( "SERVER" ) ) connQStr = db; else connQStr = "DSN=" + db; connQStr += ";UID=" + user + ";PWD=" + password; SQLSMALLINT cb; SQLTCHAR connOut[1024]; r = SQLDriverConnect( d->hDbc, NULL,#ifdef UNICODE (SQLWCHAR*)connQStr.unicode(),#else (SQLCHAR*)connQStr.latin1(),#endif (SQLSMALLINT)connQStr.length(), connOut, 1024, &cb, SQL_DRIVER_NOPROMPT ); if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) { setLastError( qMakeError( "Unable to connect", QSqlError::Connection, d ) ); setOpenError( TRUE ); return FALSE; } if ( !d->checkDriver() ) { setLastError( qMakeError( "Unable to connect - Driver doesn't support all needed functionality", QSqlError::Connection, d ) ); setOpenError( TRUE ); return FALSE; } d->checkUnicode(); d->checkSchemaUsage(); setOpen( TRUE ); setOpenError( FALSE ); return TRUE;}void QODBCDriver::close(){ cleanup(); setOpen( FALSE ); setOpenError( FALSE );}void QODBCDriver::cleanup(){ SQLRETURN r; if ( !d ) return; if( d->hDbc ) { // Open statements/descriptors handles are automatically cleaned up by SQLDisconnect if ( isOpen() ) { r = SQLDisconnect( d->hDbc );#ifdef QT_CHECK_RANGE if ( r != SQL_SUCCESS ) qSqlWarning( "QODBCDriver::disconnect: Unable to disconnect datasource", d );#endif } r = SQLFreeHandle( SQL_HANDLE_DBC, d->hDbc );#ifdef QT_CHECK_RANGE if ( r != SQL_SUCCESS ) qSqlWarning( "QODBCDriver::cleanup: Unable to free connection handle", d );#endif d->hDbc = 0; } if ( d->hEnv ) { r = SQLFreeHandle( SQL_HANDLE_ENV, d->hEnv );#ifdef QT_CHECK_RANGE if ( r != SQL_SUCCESS ) qSqlWarning( "QODBCDriver::cleanup: Unable to free environment handle", d );#endif d->hEnv = 0; }}// checks whether the server can return char, varchar and longvarchar// as two byte unicode charactersvoid QODBCPrivate::checkUnicode()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -