📄 qsql_odbc.cpp
字号:
int idx; if ( (idx = tmp.find( '=' )) != -1 ) connMap[ tmp.left( idx ) ] = tmp.mid( idx + 1 ).simplifyWhiteSpace(); else qWarning( "QODBCDriver::open: Illegal connect option value '%s'", tmp.latin1() ); } if ( connMap.count() ) { QMap<QString, QString>::ConstIterator it; QString opt, val; SQLUINTEGER v = 0; for ( it = connMap.begin(); it != connMap.end(); ++it ) { opt = it.key().upper(); val = it.data().upper(); r = SQL_SUCCESS; if ( opt == "SQL_ATTR_ACCESS_MODE" ) { if ( val == "SQL_MODE_READ_ONLY" ) { v = SQL_MODE_READ_ONLY; } else if ( val == "SQL_MODE_READ_WRITE" ) { v = SQL_MODE_READ_WRITE; } else { qWarning( QString( "QODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); break; } r = SQLSetConnectAttr( hDbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER) v, 0 ); } else if ( opt == "SQL_ATTR_CONNECTION_TIMEOUT" ) { v = val.toUInt(); r = SQLSetConnectAttr( hDbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER) v, 0 ); } else if ( opt == "SQL_ATTR_LOGIN_TIMEOUT" ) { v = val.toUInt(); r = SQLSetConnectAttr( hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) v, 0 ); } else if ( opt == "SQL_ATTR_CURRENT_CATALOG" ) { val.ucs2(); // 0 terminate r = SQLSetConnectAttr( hDbc, SQL_ATTR_CURRENT_CATALOG,#ifdef UNICODE (SQLWCHAR*) val.unicode(),#else (SQLCHAR*) val.latin1(),#endif SQL_NTS ); } else if ( opt == "SQL_ATTR_METADATA_ID" ) { if ( val == "SQL_TRUE" ) { v = SQL_TRUE; } else if ( val == "SQL_FALSE" ) { v = SQL_FALSE; } else { qWarning( QString( "QODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); break; } r = SQLSetConnectAttr( hDbc, SQL_ATTR_METADATA_ID, (SQLPOINTER) v, 0 ); } else if ( opt == "SQL_ATTR_PACKET_SIZE" ) { v = val.toUInt(); r = SQLSetConnectAttr( hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) v, 0 ); } else if ( opt == "SQL_ATTR_TRACEFILE" ) { val.ucs2(); // 0 terminate r = SQLSetConnectAttr( hDbc, SQL_ATTR_TRACEFILE,#ifdef UNICODE (SQLWCHAR*) val.unicode(),#else (SQLCHAR*) val.latin1(),#endif SQL_NTS ); } else if ( opt == "SQL_ATTR_TRACE" ) { if ( val == "SQL_OPT_TRACE_OFF" ) { v = SQL_OPT_TRACE_OFF; } else if ( val == "SQL_OPT_TRACE_ON" ) { v = SQL_OPT_TRACE_ON; } else { qWarning( QString( "QODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); break; } r = SQLSetConnectAttr( hDbc, SQL_ATTR_TRACE, (SQLPOINTER) v, 0 ); }#ifdef QT_CHECK_RANGE else { qWarning( QString("QODBCDriver::open: Unknown connection attribute '%1'").arg( opt ) ); }#endif if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) {#ifdef QT_CHECK_RANGE qSqlWarning( QString("QODBCDriver::open: Unable to set connection attribute '%1'").arg( opt ), this );#endif return FALSE; } } } return TRUE;}void QODBCPrivate::splitTableQualifier(const QString & qualifier, QString &catalog, QString &schema, QString &table){ if (!useSchema) { table = qualifier; return; } QStringList l = QStringList::split( ".", qualifier, TRUE ); if ( l.count() > 3 ) return; // can't possibly be a valid table qualifier int i = 0, n = l.count(); if ( n == 1 ) { table = qualifier; } else { for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { if ( n == 3 ) { if ( i == 0 ) { catalog = *it; } else if ( i == 1 ) { schema = *it; } else if ( i == 2 ) { table = *it; } } else if ( n == 2 ) { if ( i == 0 ) { schema = *it; } else if ( i == 1 ) { table = *it; } } i++; } }}////////////////////////////////////////////////////////////////////////////QODBCResult::QODBCResult( const QODBCDriver * db, QODBCPrivate* p ): QSqlResult(db){ d = new QODBCPrivate(); (*d) = (*p); setExtension( new QODBCPreparedExtension( this ) );}QODBCResult::~QODBCResult(){ if ( d->hStmt && driver()->isOpen() ) { SQLRETURN r = SQLFreeHandle( SQL_HANDLE_STMT, d->hStmt );#ifdef QT_CHECK_RANGE if ( r != SQL_SUCCESS ) qSqlWarning( "QODBCDriver: Unable to free statement handle " + QString::number(r), d );#endif } delete d;}bool QODBCResult::reset ( const QString& query ){ setActive( FALSE ); setAt( QSql::BeforeFirst ); SQLRETURN r; d->rInf.clear(); // Always reallocate the statement handle - the statement attributes // are not reset if SQLFreeStmt() is called which causes some problems. if ( d->hStmt ) { r = SQLFreeHandle( SQL_HANDLE_STMT, d->hStmt ); if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::reset: Unable to free statement handle", d );#endif return FALSE; } } r = SQLAllocHandle( SQL_HANDLE_STMT, d->hDbc, &d->hStmt ); if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::reset: Unable to allocate statement handle", d );#endif return FALSE; } if ( isForwardOnly() ) { r = SQLSetStmtAttr( d->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER ); } else { r = SQLSetStmtAttr( d->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, SQL_IS_UINTEGER ); } if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration", d );#endif return FALSE; }#ifdef UNICODE r = SQLExecDirect( d->hStmt, (SQLWCHAR*) query.unicode(), (SQLINTEGER) query.length() );#else QCString query8 = query.local8Bit(); r = SQLExecDirect( d->hStmt, (SQLCHAR*) query8.data(), (SQLINTEGER) query8.length() );#endif if ( r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO ) { 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 ); return TRUE;}bool QODBCResult::fetch(int i){ if ( isForwardOnly() && i < at() ) return FALSE; if ( i == at() ) return TRUE; fieldCache.clear(); nullCache.clear(); int actualIdx = i + 1; if ( actualIdx <= 0 ) { setAt( QSql::BeforeFirst ); return FALSE; } SQLRETURN r; if ( isForwardOnly() ) { bool ok = TRUE; while ( ok && i > at() ) ok = fetchNext(); return ok; } else { r = SQLFetchScroll( d->hStmt, SQL_FETCH_ABSOLUTE, actualIdx ); } if ( r != SQL_SUCCESS ){ return FALSE; } setAt( i ); return TRUE;}bool QODBCResult::fetchNext(){ SQLRETURN r; fieldCache.clear(); nullCache.clear(); r = SQLFetchScroll( d->hStmt, SQL_FETCH_NEXT, 0 ); if ( r != SQL_SUCCESS ) return FALSE; setAt( at() + 1 ); return TRUE;}bool QODBCResult::fetchFirst(){ if ( isForwardOnly() && at() != QSql::BeforeFirst ) return FALSE; SQLRETURN r; fieldCache.clear(); nullCache.clear(); if ( isForwardOnly() ) { return fetchNext(); } r = SQLFetchScroll( d->hStmt, SQL_FETCH_FIRST, 0 ); if ( r != SQL_SUCCESS ) return FALSE; setAt( 0 ); return TRUE;}bool QODBCResult::fetchPrior(){ if ( isForwardOnly() ) return FALSE; SQLRETURN r; fieldCache.clear(); nullCache.clear(); r = SQLFetchScroll( d->hStmt, SQL_FETCH_PRIOR, 0 ); if ( r != SQL_SUCCESS ) return FALSE; setAt( at() - 1 ); return TRUE;}bool QODBCResult::fetchLast(){ SQLRETURN r; fieldCache.clear(); nullCache.clear(); if ( isForwardOnly() ) { // cannot seek to last row in forwardOnly mode, so we have to use brute force int i = at(); if ( i == QSql::AfterLast ) return FALSE; if ( i == QSql::BeforeFirst ) i = 0; while ( fetchNext() ) ++i; setAt( i ); return TRUE; } r = SQLFetchScroll( d->hStmt, SQL_FETCH_LAST, 0 ); if ( r != SQL_SUCCESS ) { return FALSE; } SQLINTEGER currRow; r = SQLGetStmtAttr( d->hStmt, SQL_ROW_NUMBER, &currRow, SQL_IS_INTEGER, 0 ); if ( r != SQL_SUCCESS ) return FALSE; setAt( currRow-1 ); return TRUE;}QVariant QODBCResult::data( int field ){ if ( field >= (int) d->rInf.count() ) { qWarning( "QODBCResult::data: column %d out of range", field ); return QVariant(); } if ( fieldCache.contains( field ) ) return fieldCache[ field ]; SQLRETURN r(0); SQLINTEGER lengthIndicator = 0; bool isNull = FALSE; int current = fieldCache.count(); for ( ; current < (field + 1); ++current ) { const QSqlFieldInfo info = d->rInf[ current ]; switch ( info.type() ) { case QVariant::LongLong: fieldCache[ current ] = QVariant( (Q_LLONG) qGetBigIntData( d->hStmt, current, isNull ) ); nullCache[ current ] = isNull; break; case QVariant::Int: fieldCache[ current ] = QVariant( qGetIntData( d->hStmt, current, isNull ) ); nullCache[ current ] = isNull; break; case QVariant::Date: DATE_STRUCT dbuf; r = SQLGetData( d->hStmt, current+1, SQL_C_DATE, (SQLPOINTER)&dbuf, 0, &lengthIndicator ); if ( ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != SQL_NULL_DATA ) ) { fieldCache[ current ] = QVariant( QDate( dbuf.year, dbuf.month, dbuf.day ) ); nullCache[ current ] = FALSE; } else { fieldCache[ current ] = QVariant( QDate() ); nullCache[ current ] = TRUE; } break; case QVariant::Time: TIME_STRUCT tbuf; r = SQLGetData( d->hStmt, current+1, SQL_C_TIME, (SQLPOINTER)&tbuf, 0, &lengthIndicator ); if ( ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != SQL_NULL_DATA ) ) { fieldCache[ current ] = QVariant( QTime( tbuf.hour, tbuf.minute, tbuf.second ) ); nullCache[ current ] = FALSE; } else { fieldCache[ current ] = QVariant( QTime() ); nullCache[ current ] = TRUE; } break; case QVariant::DateTime: TIMESTAMP_STRUCT dtbuf; r = SQLGetData( d->hStmt, current+1, SQL_C_TIMESTAMP, (SQLPOINTER)&dtbuf, 0, &lengthIndicator ); if ( ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != SQL_NULL_DATA ) ) { fieldCache[ current ] = QVariant( QDateTime( QDate( dtbuf.year, dtbuf.month, dtbuf.day ), QTime( dtbuf.hour, dtbuf.minute, dtbuf.second ) ) ); nullCache[ current ] = FALSE; } else { fieldCache[ current ] = QVariant( QDateTime() ); nullCache[ current ] = TRUE; } break; case QVariant::ByteArray: { isNull = FALSE; QByteArray val = qGetBinaryData( d->hStmt, current, lengthIndicator, isNull ); fieldCache[ current ] = QVariant( val ); nullCache[ current ] = isNull; break; } case QVariant::String: isNull = FALSE; fieldCache[ current ] = QVariant( qGetStringData( d->hStmt, current, info.length(), isNull, TRUE ) ); nullCache[ current ] = isNull; break; case QVariant::Double: if ( info.typeID() == SQL_DECIMAL || info.typeID() == SQL_NUMERIC ) // bind Double values as string to prevent loss of precision fieldCache[ current ] = QVariant( qGetStringData( d->hStmt, current, info.length() + 1, isNull, FALSE ) ); // length + 1 for the comma else fieldCache[ current ] = QVariant( qGetDoubleData( d->hStmt, current, isNull ) ); nullCache[ current ] = isNull; break; case QVariant::CString: default: isNull = FALSE; fieldCache[ current ] = QVariant( qGetStringData( d->hStmt, current, info.length(), isNull, FALSE ) ); nullCache[ current ] = isNull; break; } } return fieldCache[ --current ];}bool QODBCResult::isNull( int field ){ if ( !fieldCache.contains( field ) ) { // since there is no good way to find out whether the value is NULL // without fetching the field we'll fetch it here. // (data() also sets the NULL flag) data( field ); } return nullCache[ field ];}int QODBCResult::size(){ return -1;}int QODBCResult::numRowsAffected(){ SQLINTEGER affectedRowCount(0); SQLRETURN r = SQLRowCount( d->hStmt, &affectedRowCount ); if ( r == SQL_SUCCESS ) return affectedRowCount;#ifdef QT_CHECK_RANGE else qSqlWarning( "QODBCResult::numRowsAffected: Unable to count affected rows", d );#endif return -1;}bool QODBCResult::prepare( const QString& query ){ setActive( FALSE ); setAt( QSql::BeforeFirst ); SQLRETURN r; d->rInf.clear(); if ( d->hStmt ) { r = SQLFreeHandle( SQL_HANDLE_STMT, d->hStmt ); if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::prepare: Unable to close statement", d );#endif return FALSE; } } r = SQLAllocHandle( SQL_HANDLE_STMT, d->hDbc, &d->hStmt ); if ( r != SQL_SUCCESS ) {#ifdef QT_CHECK_RANGE qSqlWarning( "QODBCResult::prepare: Unable to allocate statement handle", d );#endif return FALSE; } if ( isForwardOnly() ) { r = SQLSetStmtAttr( d->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER ); } else { r = SQLSetStmtAttr( d->hStmt, SQL_ATTR_CURSOR_TYPE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -