Modified:
trunk/Driver/Driver/Library/MYODBCDriverMain.cpp
trunk/Driver/Driver/Library/SQLAllocHandle.cpp
trunk/Driver/Driver/Library/SQLFreeHandle.cpp
trunk/SDK/C/Library/MYODBCC.cpp
trunk/SDK/C/include/MYODBCC.h
trunk/SDK/MYSQLPlus/Library/MConnection.cpp
trunk/SDK/MYSQLPlus/Library/MConnection_props.cpp
trunk/SDK/MYSQLPlus/Library/MDescriptor.cpp
trunk/SDK/MYSQLPlus/Library/MDiagnostic.cpp
trunk/SDK/MYSQLPlus/Library/MDiagnostic.h
trunk/SDK/MYSQLPlus/Library/MEnvironment.cpp
trunk/SDK/MYSQLPlus/Library/MStatement.cpp
trunk/SDK/MYSQLPlus/Library/MStatement_props.cpp
trunk/SDK/MYSQLPlus/Tests/MYSQLPlusTest.cpp
trunk/SDK/MYSQLPlus/include/MConnection.h
trunk/SDK/MYSQLPlus/include/MDescriptor.h
trunk/SDK/MYSQLPlus/include/MEnvironment.h
trunk/SDK/MYSQLPlus/include/MStatement.h
Log:
removed qt-based hierarchy management of main classes
cleaned up state-management after tx-completion
moved "parent" check out of MDiagnostic for stmt-specific diag fields
Modified: trunk/Driver/Driver/Library/MYODBCDriverMain.cpp
===================================================================
--- trunk/Driver/Driver/Library/MYODBCDriverMain.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/Driver/Driver/Library/MYODBCDriverMain.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -41,13 +41,6 @@
void libdeinit() __attribute__((destructor));
#endif
-/* TODO put this elsewhere */
-#ifdef UNICODE
-# define TEXT(x) L##x
-#else
-# define TEXT(x) (x)
-#endif
-
int gnMYODBCDrvProcesses = 0;
int gnMYODBCDrvThreads = 0;
QFile gMYODBCTraceFile;
@@ -204,4 +197,3 @@
}
#endif
-
Modified: trunk/Driver/Driver/Library/SQLAllocHandle.cpp
===================================================================
--- trunk/Driver/Driver/Library/SQLAllocHandle.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/Driver/Driver/Library/SQLAllocHandle.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -107,7 +107,12 @@
break;
}
#endif
- *phOutputHandle = (SQLHANDLE)(new MConnection( (MEnvironment*)hInputHandle
));
+ {
+ MEnvironment *menv = (MEnvironment *)hInputHandle;
+ MConnection *mconn = new MConnection( menv );
+ menv->doAddConnection( mconn );
+ *phOutputHandle = (SQLHANDLE)mconn;
+ }
break;
case SQL_HANDLE_STMT:
@@ -119,7 +124,12 @@
break;
}
#endif
- *phOutputHandle = (SQLHANDLE)(new MStatement( (MConnection*)hInputHandle ));
+ {
+ MConnection *mconn = (MConnection *)hInputHandle;
+ MStatement *mstmt = new MStatement( mconn );
+ mconn->doAddStatement( mstmt );
+ *phOutputHandle = (SQLHANDLE)mstmt;
+ }
break;
case SQL_HANDLE_DESC:
@@ -131,7 +141,8 @@
break;
}
#endif
- nReturn = ((MConnection*)hInputHandle)->doAllocDescriptor(phOutputHandle);
+ *phOutputHandle = (SQLHANDLE)
+ ((MConnection*)hInputHandle)->doCreateDescriptor();
break;
}
Modified: trunk/Driver/Driver/Library/SQLFreeHandle.cpp
===================================================================
--- trunk/Driver/Driver/Library/SQLFreeHandle.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/Driver/Driver/Library/SQLFreeHandle.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -98,4 +98,3 @@
MYODBCDbgReturn( SQL_SUCCESS );
}
-
Modified: trunk/SDK/C/Library/MYODBCC.cpp
===================================================================
--- trunk/SDK/C/Library/MYODBCC.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/C/Library/MYODBCC.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -2496,30 +2496,6 @@
return SQL_C_CHAR;
}
-/* this is a temp solution to the sudden realization that findChildren() returns all
objects - probably because we do not use Q_OBJECT */
-QList<QObject*> MYODBCC::getChildren( const QObject *pObject, const QString
&stringObjectName, bool bStartsWith )
-{
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)pObject->children() );
-
- while ( i.hasNext() )
- {
- QObject *pObject = i.next();
- if ( bStartsWith )
- {
- if ( pObject->objectName().startsWith( stringObjectName ) )
- listObjects.append( pObject );
- }
- else
- {
- if ( pObject->objectName() == stringObjectName )
- listObjects.append( pObject );
- }
- }
-
- return listObjects;
-}
-
/*!
\brief Map an ODBC V2 statement option to ODBC V3 statement attribute.
*/
Modified: trunk/SDK/C/include/MYODBCC.h
===================================================================
--- trunk/SDK/C/include/MYODBCC.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/C/include/MYODBCC.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -563,8 +563,6 @@
static SQLSMALLINT getCDefault( SQLINTEGER nODBCVersion, SQLSMALLINT nSQLType,
SQLSMALLINT nUnsigned = SQL_FALSE );
- static QList<QObject*> getChildren( const QObject *pObject, const QString
&stringObjectName, bool bStartsWith = false );
-
static SQLINTEGER getStmtAttrFromOption( SQLUSMALLINT nOption );
static void * doMemCpy( void *pDest, const void *pSrc, size_t nBytes );
Modified: trunk/SDK/MYSQLPlus/Library/MConnection.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MConnection.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MConnection.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -7,38 +7,17 @@
typedef BOOL (*MYODBCInsDriverConnectFunc)( SQLHWND, MYODBCInsDriverConnect * );
/*!
- \brief Construct a MConnection.
-
- This is the constructor for MConnection. It must have a viable MEnvironment
to be used
- as a parent object.
-
- MConnection may have the following child objects;
-
- - MStatement (0-n)
- - MDiagnostic (1)
- - MDescriptor (0-n)
- - MCommands (0-n)
-
- \note
-
- Indicate our className without using Q_OBJECT/className(). We can do this
- because we do not need objectName for anything else.
-
- Avoiding className() does, however, limit our options for filtering object
child
- lists - [sigh].
-
- \sa objectName()
+ \brief Construct an MConnection.
*/
MConnection::MConnection( MEnvironment *pEnvironment )
- : QObject( pEnvironment )
{
MYODBCDbgEnter();
Q_ASSERT( pEnvironment );
- setObjectName( "MConnection" ); // we avoid Q_OBJECT by avoiding className
pEnvironment->pDiagnostic->doClear();
+ environment = pEnvironment;
nState = STATE_C2_ALLOC;
pDiagnostic = new MDiagnostic( this,
pEnvironment->getDiagnostic()->getODBCVersion() );
pDiagnosticCaller = NULL;
@@ -107,8 +86,16 @@
MYODBCDbgInfo( QString( "this=%1" ).arg( (qulonglong)this ) );
#endif
- /* QObject will delete our children */
+ getEnvironment()->doRemoveConnection( this );
+ /* Clean up statements and user-allocated descriptors,
+ * both will remove themselves from the list */
+ while ( statements.size() )
+ delete statements.last();
+
+ while ( descriptors.size() )
+ delete descriptors.last();
+
MYODBCDbgReturn2();
}
@@ -119,12 +106,12 @@
/* Its possible our state has changed but we do not know it yet so... */
if ( nState == STATE_C4_CONN )
{
- if ( !MYODBCC::getChildren( this, "MStatement" ).isEmpty() )
+ if ( statements.size() )
setState( STATE_C5_STMT );
}
else if ( nState == STATE_C5_STMT )
{
- if ( MYODBCC::getChildren( this, "MStatement" ).isEmpty() )
+ if ( !statements.size() )
setState( STATE_C4_CONN );
}
@@ -158,7 +145,7 @@
if ( getState() >= STATE_C4_CONN )
{
if ( getInfoTxnCapable() == SQL_TC_NONE )
- MYODBCDbgReturn( getDiagnostic()->doAppend(
MDiagnostic::STATE_HYC00, 0, tr("Server does not support transactions.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend(
MDiagnostic::STATE_HYC00, 0, QObject::tr("Server does not support transactions.") ) );
if ( !SQL_SUCCEEDED( doSubmitCommand( "SET AUTOCOMMIT=1" ) ) )
MYODBCDbgReturn( getDiagnostic()->doAppend(
MDiagnostic::STATE_HY000 ) );
@@ -187,7 +174,7 @@
MYODBCDbgEnter();
if ( getInfoTxnCapable() == SQL_TC_NONE )
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HYC00, 0,
tr("Server does not support transactions.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HYC00, 0,
QObject::tr("Server does not support transactions.") ) );
/*!
\internal ODBC RULE
@@ -251,7 +238,7 @@
getDiagnostic()->doAppend( MDiagnostic::STATE_01000, nReturn,
"CR_SERVER_LOST" );
break;
default:
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
nReturn, tr("Unhandled return code from mysql_ping()") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
nReturn, QObject::tr("Unhandled return code from mysql_ping()") ) );
}
}
@@ -355,7 +342,7 @@
MYODBCDbgEnter();
// if ( stringCurrentCatalog.isEmpty() )
-// MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY090, 0,
tr("Missing database name.") ) );
+// MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY090, 0,
QObject::tr("Missing database name.") ) );
/* are we connected? */
if ( isConnected() )
@@ -432,7 +419,7 @@
of this.
*/
if ( !psOutConnectionString )
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
tr("Invalid buffer.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
QObject::tr("Invalid buffer.") ) );
/*!
\internal MYODBC RULE
@@ -505,7 +492,7 @@
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_IM011 ) );
}
else
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
tr("DSN or DRIVER attribute must be supplied.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
QObject::tr("DSN or DRIVER attribute must be supplied.") ) );
/*!
\internal ODBC RULE
@@ -522,25 +509,25 @@
{
/* getDiagnostic()->doAppend( MDiagnostic::STATE_01S00 ); */
/* nReturn = SQL_NEED_DATA; */
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
tr("Failed to validate the attributes.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
QObject::tr("Failed to validate the attributes.") ) );
}
/* do we have a SERVER attribute? */
if ( !hashKeywordValues.contains( "SERVER" ) )
- stringConnectionMissing = "SERVER:" + tr("Server") + "=?";
+ stringConnectionMissing = "SERVER:" + QObject::tr("Server") + "=?";
/* do we have a UID attribute? */
if ( !hashKeywordValues.contains( "UID" ) )
{
if ( !stringConnectionMissing.isEmpty() )
stringConnectionMissing += ";";
- stringConnectionMissing = "UID:" + tr("User ID") + "=?";
+ stringConnectionMissing = "UID:" + QObject::tr("User ID") + "=?";
}
/* do we have a PWD attribute? */
if ( !hashKeywordValues.contains( "PWD" ) )
{
if ( !stringConnectionMissing.isEmpty() )
stringConnectionMissing += ";";
- stringConnectionMissing = "PWD:" + tr("Password") + "=?";
+ stringConnectionMissing = "PWD:" + QObject::tr("Password") + "=?";
}
/* do we have a DATABASE attribute? */
if ( !hashKeywordValues.contains( "DATABASE" ) )
@@ -556,7 +543,7 @@
For example; "DATABASE:Database={mysql,test}"
*/
- stringConnectionMissing = "DATABASE:" + tr("Database") + "=?";
+ stringConnectionMissing = "DATABASE:" + QObject::tr("Database") + "=?";
}
/* are we missing mandatory attributes? */
@@ -595,7 +582,7 @@
{
if ( !pnStringLength2Ptr )
{
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
0, tr("Output buffer too small and length indicator buffer not provided.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
0, QObject::tr("Output buffer too small and length indicator buffer not provided.") ) );
}
else
nReturn = SQL_SUCCESS_WITH_INFO;
@@ -848,35 +835,15 @@
disconnects from the data source, frees those statements and all
descriptors that have been explicitly allocated on the connection.
*/
- /*!
- \internal
- \note
- Originally used findChildren() but it was returning all objects :( Possibly
because
- we are avoiding Q_OBJECT based meta data and hence no className(). Not sure.
-
- Originally used QMutableListIterator on children() but that causes segfault.
- */
-
/* delete statements */
- {
- QListIterator<QObject*> i( (QList<QObject*>)children() );
- while ( i.hasNext() )
- {
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
- {
- delete pObject;
- }
- }
- }
+ while ( statements.count() )
+ delete statements.takeLast();
/* delete, explicitly allocated, descriptors */
- for( QListIterator<MDescriptor *> i( descriptors ); i.hasNext(); )
- delete i.next();
+ while ( descriptors.count() )
+ delete descriptors.takeLast();
- descriptors.clear();
-
/* close and free mysql handle */
mysql_close( (MYSQL*)pMySQL );
pMySQL = NULL;
@@ -1239,22 +1206,52 @@
if ( !isTransaction() )
MYODBCDbgReturn( SQL_SUCCESS );
- /* do it */
+ SQLRETURN rc;
+ SQLUSMALLINT behavior;
+
+ /*!
+ \internal
+ \note
+
+ We could use mysql_commit() but we do not want to deal with the
+ possibility that our connection could be closed (see C API doc)
+ so we use an SQL statement.
+
+ \sa mysql_commit
+ */
switch ( nCompletionType )
{
case SQL_COMMIT:
- MYODBCDbgReturn( doTransactionCommit() );
+ behavior = getInfoCursorCommitBehavior();
+ rc = doSubmitCommand( "COMMIT" );
+ break;
case SQL_ROLLBACK:
- MYODBCDbgReturn( doTransactionRollback() );
+ behavior = getInfoCursorRollbackBehavior();
+ rc = doSubmitCommand( "ROLLBACK" );
+ break;
+
+ default:
+ /*!
+ \internal ODBC RULE (DM)
+
+ The value specified for the argument CompletionType was neither
SQL_COMMIT nor SQL_ROLLBACK.
+ */
+ MYODBCDbgReturn( getDiagnostic()->
+ doAppend( MDiagnostic::STATE_HY012 ) );
}
- /*!
- \internal ODBC RULE (DM)
+ if ( !SQL_SUCCEEDED( rc ) )
+ /*!
+ \internal ODBC RULE
- The value specified for the argument CompletionType was neither SQL_COMMIT nor
SQL_ROLLBACK.
- */
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY012 ) );
+ The HandleType was SQL_HANDLE_DBC, and the connection associated with the
Handle failed during the execution of the
+ function, and it cannot be determined whether the requested COMMIT or
ROLLBACK occurred before the failure.
+ */
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_08007 ) );
+
+ /* perform after-tx cleanup */
+ MYODBCDbgReturn( doPostTxCleanup( behavior ) );
}
/*!
@@ -1305,32 +1302,74 @@
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_08003 ) );
/* Use same code as we normally use so we get same translation... */
- MStatement statement( this );
+ MStatement *statement = new MStatement( this );
+ doAddStatement( statement );
/* redirect diagnostic to us... */
- statement.setDiagnostic( getDiagnostic() );
+ statement->setDiagnostic( getDiagnostic() );
- SQLRETURN nReturn = statement.doNativeSql( psInStatementText, nTextLength1,
psOutStatementText, nBufferLength, pnTextLength2 );
+ SQLRETURN nReturn = statement->doNativeSql( psInStatementText, nTextLength1,
psOutStatementText, nBufferLength, pnTextLength2 );
+ delete statement;
+
MYODBCDbgReturn( nReturn );
}
/*!
- Allocate a new descriptor handle for the application. Add to internal list
- for later clean up.
+ Create a new descriptor handle for the application.
*/
-SQLRETURN MConnection::doAllocDescriptor(SQLHANDLE *desc)
+MDescriptor *MConnection::doCreateDescriptor()
{
MYODBCDbgEnter();
MDescriptor *mdesc = new MDescriptor( getEnvironment()->getODBCVersion(),
SQL_DESC_ALLOC_USER );
- descriptors.append(mdesc);
- *desc = (SQLHANDLE)mdesc;
+ descriptors.append( mdesc );
+ mdesc->setConnection( this );
- MYODBCDbgReturn( SQL_SUCCESS );
+ MYODBCDbgReturn3( "%p", mdesc );
}
+/*!
+ Add new statement to this environment.
+*/
+void MConnection::doAddStatement( MStatement *stmt )
+{
+ MYODBCDbgEnter();
+
+ statements.append( stmt );
+
+ MYODBCDbgReturn2();
+}
+
+/*!
+ Remove an application-allocated descriptor.
+*/
+void MConnection::doRemoveDescriptor(MDescriptor *desc)
+{
+ MYODBCDbgEnter();
+
+ int idx = descriptors.indexOf( desc );
+ Q_ASSERT( idx != -1 );
+ descriptors.removeAt( idx );
+
+ MYODBCDbgReturn2();
+}
+
+/*!
+ Remove a statement associated with this environment.
+*/
+void MConnection::doRemoveStatement(MStatement *stmt)
+{
+ MYODBCDbgEnter();
+
+ int idx = statements.indexOf( stmt );
+ Q_ASSERT( idx != -1 );
+ statements.removeAt( idx );
+
+ MYODBCDbgReturn2();
+}
+
SQLRETURN MConnection::doConnectInternal( MYODBCInsDataSource *pDataSource )
{
MYODBCDbgEnter();
@@ -1534,7 +1573,7 @@
MYODBCDbgEnter();
if ( !SQL_SUCCEEDED( doSubmitCommand( "START TRANSACTION" ) ) )
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
tr("Failed to start transaction.") ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000, 0,
QObject::tr("Failed to start transaction.") ) );
setState( STATE_C6_TRXN );
@@ -1542,193 +1581,55 @@
}
/*!
- \brief Commits a transaction.
+ \brief Rollback the connection state after transaction completion.
- This is a convenience function which is used to request that the server
- commit a transaction.
-
- This will adjust the state (away from STATE_C6_TRXN) if success.
-
- \note The caller must ensure that this request fits in with the state, config
options
- and features available. This just sends the request to the server.
-
- \sa doTransactionStart
- doTransactionRollback
+ This will adjust the state (away from STATE_C6_TRXN).
*/
-SQLRETURN MConnection::doTransactionCommit()
+SQLRETURN MConnection::doPostTxCleanup( SQLUSMALLINT behavior )
{
MYODBCDbgEnter();
/*!
- \internal
- \note
-
- We could use mysql_commit() but we do not want to deal with the
- possibility that our connection could be closed (see C API doc)
- so we use an SQL statement.
-
- \sa mysql_commit
- */
- if ( !SQL_SUCCEEDED( doSubmitCommand( "COMMIT" ) ) )
- /*!
- \internal ODBC RULE
-
- The HandleType was SQL_HANDLE_DBC, and the connection associated with the
Handle failed during the execution of the
- function, and it cannot be determined whether the requested COMMIT or
ROLLBACK occurred before the failure.
- */
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_08007 ) );
-
- /*!
\internal ODBC RULE
- If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_DELETE, SQLEndTran
- closes and deletes all open cursors on all statements associated with the
connection
- and discards all pending results. SQLEndTran leaves any statement present in an
allocated (unprepared)
- state; the application can reuse them for subsequent SQL requests or can call
SQLFreeStmt or
- SQLFreeHandle with a HandleType of SQL_HANDLE_STMT to deallocate them.
- */
- if ( getInfoCursorCommitBehavior() == SQL_CB_DELETE )
- {
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
- while ( i.hasNext() )
- {
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
- {
- MStatement *pStatement = (MStatement*)pObject;
- pStatement->doStateRollBack( MStatement::STATE_S1 );
- }
- }
- }
-
- /*!
- \internal ODBC RULE
-
- If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_CLOSE, SQLEndTran
- closes all open cursors on all statements associated with the connection.
SQLEndTran leaves any statement
- present in a prepared state; the application can call SQLExecute for a statement
associated with the
- connection without first calling SQLPrepare.
- */
- if ( getInfoCursorCommitBehavior() == SQL_CB_CLOSE )
- {
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
- while ( i.hasNext() )
- {
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
- {
- MStatement *pStatement = (MStatement*)pObject;
- if ( pStatement->isImplicitPrepare() )
- pStatement->doStateRollBack( MStatement::STATE_S1 );
- else
- pStatement->doStateRollBack( MStatement::STATE_S3 );
- }
- }
- }
-
- /*!
- \internal ODBC RULE
-
If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_PRESERVE, SQLEndTran
does not affect open cursors associated with the connection. Cursors remain at
the row they pointed to
prior to the call to SQLEndTran.
*/
- if ( getInfoCursorCommitBehavior() == SQL_CB_PRESERVE )
+ if ( behavior == SQL_CB_PRESERVE )
{
/* do nothing special */
}
-
- /* we no longer have a transaction in play so... */
- setState( STATE_C5_STMT );
-
- MYODBCDbgReturn( SQL_SUCCESS );
-}
-
-/*!
- \brief Commits a transaction.
-
- This is a convenience function which is used to request that the server
- rollback a transaction.
-
- This will adjust the state (away from STATE_C6_TRXN) if success.
-
- \note The caller must ensure that this request fits in with the state, config
options
- and features available. This just sends the request to the server.
-
- \sa doTransactionStart
- doTransactionCommit
-*/
-SQLRETURN MConnection::doTransactionRollback()
-{
- MYODBCDbgEnter();
-
- /*!
- \internal
- \note
-
- We could use mysql_rollback() but we do not want to deal with the
- possibility that our connection could be closed (see C API doc) so
- we use an SQL statement.
-
- \sa mysql_rollback
- */
- if ( !SQL_SUCCEEDED( doSubmitCommand( "ROLLBACK" ) ) )
- /*!
- \internal ODBC RULE
-
- The HandleType was SQL_HANDLE_DBC, and the connection associated with the
Handle failed during the execution of the
- function, and it cannot be determined whether the requested COMMIT or
ROLLBACK occurred before the failure.
- */
- MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_08007 ) );
-
- /*!
- \internal ODBC RULE
-
- If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_DELETE, SQLEndTran
- closes and deletes all open cursors on all statements associated with the
connection
- and discards all pending results. SQLEndTran leaves any statement present in an
allocated (unprepared)
- state; the application can reuse them for subsequent SQL requests or can call
SQLFreeStmt or
- SQLFreeHandle with a HandleType of SQL_HANDLE_STMT to deallocate them.
- */
- if ( getInfoCursorRollbackBehavior() == SQL_CB_DELETE )
+ else
{
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
+ QListIterator<MStatement *> i( statements );
while ( i.hasNext() )
{
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
+ MStatement *pStatement = i.next();
+
+ /*!
+ \internal ODBC RULE
+
+ If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value
equals SQL_CB_DELETE, SQLEndTran
+ closes and deletes all open cursors on all statements associated with the
connection
+ and discards all pending results. SQLEndTran leaves any statement present
in an allocated (unprepared)
+ state; the application can reuse them for subsequent SQL requests or can
call SQLFreeStmt or
+ SQLFreeHandle with a HandleType of SQL_HANDLE_STMT to deallocate them.
+ */
+ if ( behavior == SQL_CB_DELETE )
{
- MStatement *pStatement = (MStatement*)pObject;
pStatement->doStateRollBack( MStatement::STATE_S1 );
}
- }
- }
+ /*!
+ \internal ODBC RULE
- /*!
- \internal ODBC RULE
-
- If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_CLOSE, SQLEndTran
- closes all open cursors on all statements associated with the connection.
SQLEndTran leaves any statement
- present in a prepared state; the application can call SQLExecute for a statement
associated with the
- connection without first calling SQLPrepare.
- */
- if ( getInfoCursorRollbackBehavior() == SQL_CB_CLOSE )
- {
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
- while ( i.hasNext() )
- {
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
+ If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value
equals SQL_CB_CLOSE, SQLEndTran
+ closes all open cursors on all statements associated with the connection.
SQLEndTran leaves any statement
+ present in a prepared state; the application can call SQLExecute for a
statement associated with the
+ connection without first calling SQLPrepare.
+ */
+ else if ( behavior == SQL_CB_CLOSE )
{
- MStatement *pStatement = (MStatement*)pObject;
if ( pStatement->isImplicitPrepare() )
pStatement->doStateRollBack( MStatement::STATE_S1 );
else
@@ -1737,20 +1638,9 @@
}
}
- /*!
- \internal ODBC RULE
-
- If the SQL_CURSOR_ROLLBACK_BEHAVIOR or SQL_CURSOR_COMMIT_BEHAVIOR value equals
SQL_CB_PRESERVE, SQLEndTran
- does not affect open cursors associated with the connection. Cursors remain at
the row they pointed to
- prior to the call to SQLEndTran.
- */
- if ( getInfoCursorRollbackBehavior() == SQL_CB_PRESERVE )
- {
- /* do nothing special */
- }
-
/* we no longer have a transaction in play so... */
setState( STATE_C5_STMT );
MYODBCDbgReturn( SQL_SUCCESS );
}
+
Modified: trunk/SDK/MYSQLPlus/Library/MConnection_props.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MConnection_props.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MConnection_props.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -78,7 +78,7 @@
- the downside of separating the two for connection pooling (hopefully
that is all that is happening) is
very minimal
*/
- /* MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
0, tr("Driver does NOT behave differently if the application is ANSI.") ) ); */
+ /* MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::STATE_HY000,
0, QObject::tr("Driver does NOT behave differently if the application is ANSI.") ) ); */
break;
case SQL_ATTR_ASYNC_ENABLE:
@@ -440,7 +440,8 @@
SQLRETURN MConnection::getDiagField( SQLSMALLINT nRecNumber, SQLSMALLINT nDiagIdentifier,
SQLPOINTER pDiagInfo, SQLSMALLINT nBufferLength, SQLSMALLINT *pnStringLength )
{
MYODBCDbgEnter();
- MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
pDiagInfo, nBufferLength, pnStringLength ) );
+ MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
+ pDiagInfo, nBufferLength, pnStringLength, 0 ) );
}
SQLRETURN MConnection::getDiagRec( SQLSMALLINT nRecNumber, SQLWCHAR *psSQLState,
SQLINTEGER *pnNativeError, SQLWCHAR *psMessageText, SQLSMALLINT nBufferLength,
SQLSMALLINT *pnTextLength )
@@ -1252,7 +1253,7 @@
if ( dummy != 0xcdcdcdcd )
MYODBCDbgReturn( getDiagnostic()->doAppend(
MDiagnostic::STATE_HY000, 0,
- tr("buffer, to return value, must be provided") ) );
+ QObject::tr("buffer, to return value, must be provided") ) );
MYODBCDbgReturn( SQL_SUCCESS );
}
@@ -1311,18 +1312,11 @@
{
MYODBCDbgEnter();
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
- while ( i.hasNext() )
+ for ( QListIterator<MStatement *> i( statements ); i.hasNext(); )
{
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
- {
- MStatement *pStatement = (MStatement*)pObject;
- if ( pStatement->getCursorName() == stringCursorName )
- MYODBCDbgReturn3( "%p", pStatement );
- }
+ MStatement *pStatement = i.next();
+ if ( pStatement->getCursorName() == stringCursorName )
+ MYODBCDbgReturn3( "%p", pStatement );
}
MYODBCDbgReturn3( "%p", NULL );
@@ -1486,23 +1480,14 @@
bWarning = true;
/* for each statement set value, any MStatement errors get downgraded to generic
warnings in MConnection */
+ for ( QListIterator<MStatement *> i( statements ); i.hasNext(); )
{
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
-
- while ( i.hasNext() )
+ MStatement *pStatement = i.next();
+ nReturn = pStatement->setStmtAttr( nAttribute, pValue, nStringLength );
+ if ( !SQL_SUCCEEDED( nReturn ) )
{
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MStatement" )
- {
- MStatement *pStatement = (MStatement*)pObject;
- nReturn = pStatement->setStmtAttr( nAttribute, pValue, nStringLength
);
- if ( !SQL_SUCCEEDED( nReturn ) )
- {
- bWarning = true;
- getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, tr("Failed
to set a statement attribute.") );
- }
- }
+ bWarning = true;
+ getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0,
QObject::tr("Failed to set a statement attribute.") );
}
}
@@ -1773,7 +1758,7 @@
{
MYODBCDbgEnter();
- MYODBCDbgReturn3( "%p", ((MEnvironment*)parent()) );
+ MYODBCDbgReturn3( "%p", environment );
}
MDiagnostic *MConnection::getDiagnostic()
@@ -1999,7 +1984,7 @@
Warn if bookmarks are meaningless to us.
*/
// if ( getInfoBookmarkPersistence() == 0 )
-// getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, tr("Bookmarks not
supported.") );
+// getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0,
QObject::tr("Bookmarks not supported.") );
MYODBCDbgReturn3( "%d", nUseBookmarks );
}
@@ -3809,12 +3794,12 @@
*/
if ( !pMySQL )
{
- getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, tr("No mysql handle
yet so we are going to guess that we do have support.") );
+ getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, QObject::tr("No mysql
handle yet so we are going to guess that we do have support.") );
MYODBCDbgReturn3( "%d", SQL_TC_DDL_COMMIT );
}
if ( !isConnected() )
{
- getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, tr("No connection yet
so we are going to guess that we do have support.") );
+ getDiagnostic()->doAppend( MDiagnostic::STATE_01000, 0, QObject::tr("No
connection yet so we are going to guess that we do have support.") );
MYODBCDbgReturn3( "%d", SQL_TC_DDL_COMMIT );
}
@@ -3927,11 +3912,10 @@
{
MYODBCDbgEnter();
- QList<QObject*> listStatements = MYODBCC::getChildren( this,
"MStatement" ); // findChildren<MStatement*>();
- QListIterator<QObject*> i( listStatements );
+ QListIterator<MStatement *> i( statements );
while ( i.hasNext() )
{
- if ( ((MStatement*)i.next())->isAsyncInProgress() )
+ if ( i.next()->isAsyncInProgress() )
MYODBCDbgReturn3( "%d", true );
}
@@ -3942,11 +3926,10 @@
{
MYODBCDbgEnter();
- QList<QObject*> listStatements = MYODBCC::getChildren( this,
"MStatement" ); // findChildren<MStatement*>();
- QListIterator<QObject*> i( listStatements );
+ QListIterator<MStatement *> i( statements );
while ( i.hasNext() )
{
- if ( ((MStatement*)i.next())->getState() > MStatement::STATE_S1 )
+ if ( i.next()->getState() > MStatement::STATE_S1 )
MYODBCDbgReturn3( "%d", true );
}
@@ -3957,11 +3940,10 @@
{
MYODBCDbgEnter();
- QList<QObject*> listStatements = MYODBCC::getChildren( this,
"MStatement" ); // findChildren<MStatement*>();
- QListIterator<QObject*> i( listStatements );
+ QListIterator<MStatement *> i( statements );
while ( i.hasNext() )
{
- if ( ((MStatement*)i.next())->isDataNeeded() )
+ if ( i.next()->isDataNeeded() )
MYODBCDbgReturn3( "%d", true );
}
Modified: trunk/SDK/MYSQLPlus/Library/MDescriptor.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MDescriptor.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MDescriptor.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -12,12 +12,10 @@
MStatement::setStmtAttr
*/
MDescriptor::MDescriptor( SQLSMALLINT odbcVersion, SQLSMALLINT allocType )
- : QObject( NULL )
{
MYODBCDbgEnter();
- setObjectName( "MDescriptor" ); // we avoid Q_OBJECT by avoiding className
-
+ connection = NULL;
pDiagnostic = new MDiagnostic( NULL, odbcVersion );
nAllocType = allocType;
doInit();
@@ -63,6 +61,13 @@
delete pDiagnostic;
+ /* Remove descriptor from connection if its explicitly allocated */
+ if ( nAllocType == SQL_DESC_ALLOC_USER )
+ {
+ Q_ASSERT( connection );
+ connection->doRemoveDescriptor( this );
+ }
+
MYODBCDbgReturn2();
}
@@ -113,6 +118,14 @@
MYODBCDbgReturn( getRecord( nRecNumber )->setDescRec( nType, nSubType, nLength,
nPrecision, nScale, pDataPtr, pnStringLengthPtr, pnIndicatorPtr ) );
}
+/*!
+ Specify a connection to act as the parent of this descriptor.
+*/
+void MDescriptor::setConnection( MConnection *conn )
+{
+ connection = conn;
+}
+
SQLRETURN MDescriptor::getDescField( SQLSMALLINT nRecNumber, SQLSMALLINT
nFieldIdentifier, SQLPOINTER pValuePtr, SQLINTEGER nBufferLength, SQLINTEGER
*pnStringLengthPtr )
{
MYODBCDbgEnter();
@@ -208,7 +221,8 @@
SQLRETURN MDescriptor::getDiagField( SQLSMALLINT nRecNumber, SQLSMALLINT nDiagIdentifier,
SQLPOINTER pDiagInfo, SQLSMALLINT nBufferLength, SQLSMALLINT *pnStringLength )
{
MYODBCDbgEnter();
- MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
pDiagInfo, nBufferLength, pnStringLength ) )
+ MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
+ pDiagInfo, nBufferLength, pnStringLength, 0 ) )
}
SQLRETURN MDescriptor::getDiagRec( SQLSMALLINT nRecNumber, SQLWCHAR *psSQLState,
SQLINTEGER *pnNativeError, SQLWCHAR *psMessageText, SQLSMALLINT nBufferLength,
SQLSMALLINT *pnTextLength )
Modified: trunk/SDK/MYSQLPlus/Library/MDiagnostic.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MDiagnostic.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MDiagnostic.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -156,7 +156,7 @@
*/
if ( psSqlstate )
{
- nReturn = getDiagField( nRecNumber, SQL_DIAG_SQLSTATE, psSqlstate, 5, NULL );
+ nReturn = getDiagField( nRecNumber, SQL_DIAG_SQLSTATE, psSqlstate, 5, NULL, 0 );
if ( nReturn == SQL_SUCCESS_WITH_INFO )
nReturnHolistic = SQL_SUCCESS_WITH_INFO;
if ( !SQL_SUCCEEDED( nReturn ) )
@@ -165,7 +165,7 @@
if ( pnNativeError )
{
- nReturn = getDiagField( nRecNumber, SQL_DIAG_NATIVE, pnNativeError,
SQL_IS_INTEGER, NULL );
+ nReturn = getDiagField( nRecNumber, SQL_DIAG_NATIVE, pnNativeError,
SQL_IS_INTEGER, NULL, 0 );
if ( nReturn == SQL_SUCCESS_WITH_INFO )
nReturnHolistic = SQL_SUCCESS_WITH_INFO;
if ( !SQL_SUCCEEDED( nReturn ) )
@@ -173,7 +173,7 @@
}
nReturn = getDiagField( nRecNumber, SQL_DIAG_MESSAGE_TEXT,
- pszMessageText, nBufferCharLength, pnTextByteLength );
+ pszMessageText, nBufferCharLength, pnTextByteLength, 0 );
/* we need char length for getDiagRec,
* not byte length which is what getDiagField returns */
@@ -198,6 +198,7 @@
\param pBuffer Place to return the value.
\param nBufferLength The size of pBuffer.
\param pnStrLenPtr Length of string data available.
+ \param isStmtDiag Whether this is a statement diagnostic
\return SQLRETURN
@@ -206,7 +207,7 @@
\retval SQL_ERROR General error.
\retval SQL_NO_DATA No data to return (ie requested record does not
exist).
*/
-SQLRETURN MDiagnostic::getDiagField( SQLSMALLINT nRecNumber, SQLSMALLINT nDiagIdentifier,
SQLPOINTER pDiagInfoPtr, SQLSMALLINT nBufferLength, SQLSMALLINT *pnStringLengthPtr )
+SQLRETURN MDiagnostic::getDiagField( SQLSMALLINT nRecNumber, SQLSMALLINT nDiagIdentifier,
SQLPOINTER pDiagInfoPtr, SQLSMALLINT nBufferLength, SQLSMALLINT *pnStringLengthPtr, bool
isStmtDiag )
{
SQLSMALLINT nStringLength;
@@ -237,6 +238,21 @@
break;
}
+ /*
+ Make sure statement-mode are only accessed when allowed.
+ */
+ if ( !isStmtDiag )
+ {
+ switch ( nDiagIdentifier )
+ {
+ case SQL_DIAG_CURSOR_ROW_COUNT:
+ case SQL_DIAG_ROW_COUNT:
+ case SQL_DIAG_DYNAMIC_FUNCTION:
+ case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
+ MYODBCDbgReturn( SQL_ERROR );
+ }
+ }
+
/*
These are the fields we know about listed by category
(header/record) and in _alpha_ order.
@@ -244,32 +260,10 @@
switch ( nDiagIdentifier )
{
case SQL_DIAG_CURSOR_ROW_COUNT:
- /*!
- \internal ODBC RULE
-
- An application can call SQLGetDiagField to return any diagnostic field at
any time, with the exception of SQL_DIAG_CURSOR_ROW_COUNT or
- SQL_DIAG_ROW_COUNT, which will return SQL_ERROR if Handle is not a
statement handle. If any other diagnostic field is undefined, the
- call to SQLGetDiagField will return SQL_SUCCESS (provided no other
diagnostic is encountered) and an undefined value is returned for
- the field.
- */
- if ( parent() && parent()->objectName() != "MStatement" )
- MYODBCDbgReturn( SQL_ERROR );
-
*(SQLINTEGER*)pDiagInfoPtr = getCursorRowCount();
break;
case SQL_DIAG_DYNAMIC_FUNCTION:
- /*!
- \internal ODBC RULE
-
- The contents of this field are defined only for statement handles and
only after a call to SQLExecute, SQLExecDirect, or SQLMoreResults.
- Calling SQLGetDiagField with a DiagIdentifier of
SQL_DIAG_DYNAMIC_FUNCTION_CODE on other than a statement handle will return SQL_ERROR.
- */
- if ( parent() && parent()->objectName() != "MStatement" )
- MYODBCDbgReturn( SQL_ERROR );
- if ( ((MStatement*)parent())->getState() < MStatement::STATE_S4 )
- MYODBCDbgReturn( SQL_ERROR );
-
{
QString stringDynamicFunction = getDynamicFunction();
if ( stringDynamicFunction.isNull() )
@@ -285,17 +279,6 @@
break;
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
- /*!
- \internal ODBC RULE
-
- The contents of this field are defined only for statement handles and
only after a call to SQLExecute, SQLExecDirect, or SQLMoreResults.
- Calling SQLGetDiagField with a DiagIdentifier of
SQL_DIAG_DYNAMIC_FUNCTION_CODE on other than a statement handle will return SQL_ERROR.
- */
- if ( parent() && parent()->objectName() != "MStatement" )
- MYODBCDbgReturn( SQL_ERROR );
- if ( ((MStatement*)parent())->getState() < MStatement::STATE_S4 )
- MYODBCDbgReturn( SQL_ERROR );
-
*(SQLINTEGER*)pDiagInfoPtr = getDynamicFunctionCode();
break;
@@ -308,17 +291,6 @@
break;
case SQL_DIAG_ROW_COUNT:
- /*!
- \internal ODBC RULE
-
- An application can call SQLGetDiagField to return any diagnostic field at
any time, with the exception of SQL_DIAG_CURSOR_ROW_COUNT or
- SQL_DIAG_ROW_COUNT, which will return SQL_ERROR if Handle is not a
statement handle. If any other diagnostic field is undefined, the
- call to SQLGetDiagField will return SQL_SUCCESS (provided no other
diagnostic is encountered) and an undefined value is returned for
- the field.
- */
- if ( parent() && parent()->objectName() != "MStatement" )
- MYODBCDbgReturn( SQL_ERROR );
-
*(SQLINTEGER*)pDiagInfoPtr = getRowCount();
break;
Modified: trunk/SDK/MYSQLPlus/Library/MDiagnostic.h
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MDiagnostic.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MDiagnostic.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -204,7 +204,7 @@
/* getters */
SQLRETURN getDiagRec( SQLSMALLINT nRecNumber /* 1-based */, SQLWCHAR
*psSqlstate, SQLINTEGER *pnNativeErrorPtr, SQLWCHAR *psMessageText, SQLSMALLINT
nBufferLength, SQLSMALLINT *pnTextLengthPtr );
- SQLRETURN getDiagField( SQLSMALLINT nRecNumber /* 1-based */, SQLSMALLINT
nDiagIdentifier, SQLPOINTER pDiagInfoPtr, SQLSMALLINT nBufferLength, SQLSMALLINT
*pnStringLengthPtr );
+ SQLRETURN getDiagField( SQLSMALLINT nRecNumber /* 1-based */, SQLSMALLINT
nDiagIdentifier, SQLPOINTER pDiagInfoPtr, SQLSMALLINT nBufferLength, SQLSMALLINT
*pnStringLengthPtr, bool isStmtDiag );
QStringList getDiagnostics();
SQLSMALLINT getODBCVersion();
Modified: trunk/SDK/MYSQLPlus/Library/MEnvironment.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MEnvironment.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MEnvironment.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -31,27 +31,9 @@
#include <QTextCodec>
/*!
- \brief Construct a MEnvironment.
-
- This is the constructor for MEnvironment.
-
- MEnvironment may have the following child objects;
-
- - MConnection (0-n)
- - MDiagnostic (1)
-
- \note
-
- Indicate our className without using Q_OBJECT/className(). We can do this
- because we do not need objectName for anything else.
-
- Avoiding className() does, however, limit our options for filtering object
child
- lists - [sigh].
-
- \sa objectName()
+ \brief Construct an MEnvironment.
*/
-MEnvironment::MEnvironment( QObject *pObjectParent )
- : QObject( pObjectParent )
+MEnvironment::MEnvironment( )
{
MYODBCDbgEnter();
@@ -60,7 +42,6 @@
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
- setObjectName( "MEnvironment" ); // we avoid Q_OBJECT by avoiding className
pDiagnostic = new MDiagnostic( this );
nConnectionPooling = SQL_CP_DEFAULT;
@@ -79,7 +60,9 @@
MYODBCDbgInfo( QString( "this=%1" ).arg( (qulonglong)this ) );
#endif
- /* QObject will delete our children */
+ /* clean up connections, they remove themselves */
+ while ( connections.count() )
+ delete connections.last();
MYODBCDbgReturn2();
}
@@ -175,7 +158,8 @@
SQLRETURN MEnvironment::getDiagField( SQLSMALLINT nRecNumber, SQLSMALLINT
nDiagIdentifier, SQLPOINTER pDiagInfo, SQLSMALLINT nBufferLength, SQLSMALLINT
*pnStringLength )
{
MYODBCDbgEnter();
- MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
pDiagInfo, nBufferLength, pnStringLength ) );
+ MYODBCDbgReturn( pDiagnostic->getDiagField( nRecNumber, nDiagIdentifier,
+ pDiagInfo, nBufferLength, pnStringLength, 0 ) );
}
/*!
@@ -318,6 +302,8 @@
{
MYODBCDbgEnter();
+ SQLRETURN nReturn;
+
/*!
\internal ODBC RULE
@@ -325,53 +311,64 @@
*/
pDiagnostic->doClear();
- QList<QObject*> listObjects;
- QListIterator<QObject*> i( (QList<QObject*>)children() );
- SQLRETURN nReturn = SQL_SUCCESS;
-
- while ( i.hasNext() )
+ for( QListIterator<MConnection *> i( connections ); i.hasNext(); )
{
- QObject *pObject = i.next();
- if ( pObject->objectName() == "MConnection" )
- {
- MConnection *pConnection = (MConnection*)pObject;
+ MConnection *pConnection = i.next();
- /*!
- \internal MYODBC RULE
+ /*!
+ \internal MYODBC RULE
- We avoid 'not connected' error from connection.
- */
- if ( !pConnection->isConnected() )
- continue;
+ We avoid 'not connected' error from connection.
+ */
+ if ( !pConnection->isConnected() )
+ continue;
- /*!
- \internal MYODBC RULE
+ /*!
+ \internal MYODBC RULE
- We redirect connection diagnostic information to our diagnostic. We
ensure
- that it is reset to default when we are done.
- */
- pConnection->setDiagnostic( getDiagnostic() );
+ We redirect connection diagnostic information to our diagnostic. We ensure
+ that it is reset to default when we are done.
+ */
+ pConnection->setDiagnostic( getDiagnostic() );
- SQLRETURN n = pConnection->doEndTran( nCompletionType );
- switch ( n )
- {
- case SQL_SUCCESS:
- break;
- case SQL_SUCCESS_WITH_INFO:
- nReturn = n;
- break;
- default:
- pConnection->setDiagnostic( NULL );
- MYODBCDbgReturn( n );
- }
- pConnection->setDiagnostic( NULL );
- }
+ nReturn = pConnection->doEndTran( nCompletionType );
+
+ pConnection->setDiagnostic( NULL );
+
+ if ( nReturn != SQL_SUCCESS && nReturn != SQL_SUCCESS_WITH_INFO )
+ break;
}
MYODBCDbgReturn( nReturn );
}
/*!
+ Add a new connection.
+*/
+void MEnvironment::doAddConnection( MConnection *conn )
+{
+ MYODBCDbgEnter();
+
+ connections.append(conn);
+
+ MYODBCDbgReturn2();
+}
+
+/*!
+ Remove a connection.
+*/
+void MEnvironment::doRemoveConnection( MConnection *conn )
+{
+ MYODBCDbgEnter();
+
+ int idx = connections.indexOf( conn );
+ Q_ASSERT( idx != -1 );
+ connections.removeAt( idx );
+
+ MYODBCDbgReturn2();
+}
+
+/*!
\brief Sets an environment attribute.
This attribute corresponds to the SQL_ATTR_CONNECTION_POOLING field.
@@ -651,7 +648,7 @@
{
MYODBCDbgEnter();
- if ( MYODBCC::getChildren( this, "MConnection" ).isEmpty() )
+ if ( !connections.size() )
MYODBCDbgReturn3( "%d", STATE_E1 );
MYODBCDbgReturn3( "%d", STATE_E2 );
Modified: trunk/SDK/MYSQLPlus/Library/MStatement.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MStatement.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MStatement.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -31,15 +31,15 @@
\sa objectName()
*/
MStatement::MStatement( MConnection *pConnection )
- : QObject( pConnection )
{
MYODBCDbgEnter();
Q_ASSERT( pConnection );
+ connection = pConnection;
+
SQLSMALLINT odbcVersion = pConnection->getEnvironment()->getODBCVersion();
- setObjectName( "MStatement" ); // we avoid Q_OBJECT by avoiding className
pConnection->pDiagnostic->doClear();
nState = STATE_S1;
@@ -55,6 +55,11 @@
pImpParamDesc = new MDescriptorIPD( odbcVersion );
pImpRowDesc = new MDescriptorIRD( odbcVersion );
+ descriptors.append( pAppParamDesc );
+ descriptors.append( pAppRowDesc );
+ descriptors.append( pImpParamDesc );
+ descriptors.append( pImpRowDesc );
+
/* attributes */
bImplicitPrepare = false;
nCursorScrollable = SQL_NONSCROLLABLE;
@@ -110,8 +115,12 @@
doStateRollBack( STATE_S0 );
- /* QObject will delete our children */
+ connection->doRemoveStatement( this );
+ /* clean up descriptors, they wont remove themselves (so takeLast) */
+ while ( descriptors.size() )
+ delete descriptors.takeLast();
+
MYODBCDbgReturn2();
}
Modified: trunk/SDK/MYSQLPlus/Library/MStatement_props.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Library/MStatement_props.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Library/MStatement_props.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -352,7 +352,18 @@
MYODBCDbgInfo( QString( "nDiagIdentifier=%1=%2" ).arg( nDiagIdentifier ).arg(
MYODBCC::getDiagFieldString( nDiagIdentifier ) ) );
#endif
- MYODBCDbgReturn( getDiagnostic()->getDiagField( nRecNumber, nDiagIdentifier,
pDiagInfo, nBufferLength, pnStringLength ) );
+ /* specific state is required */
+ switch ( nDiagIdentifier )
+ {
+ case SQL_DIAG_DYNAMIC_FUNCTION:
+ case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
+ if ( getState() < MStatement::STATE_S4 )
+ MYODBCDbgReturn( SQL_ERROR );
+ }
+
+ MYODBCDbgReturn( getDiagnostic()->getDiagField( nRecNumber,
+ nDiagIdentifier, pDiagInfo, nBufferLength,
+ pnStringLength, 1 ) );
}
SQLRETURN MStatement::getDiagRec( SQLSMALLINT nRecNumber, SQLWCHAR *psSQLState,
SQLINTEGER *pnNativeError, SQLWCHAR *psMessageText, SQLSMALLINT nBufferLength,
SQLSMALLINT *pnTextLength )
@@ -426,7 +437,7 @@
MYODBCCSet( pnStringLength, 0 );
}
#if MYODBC_DBG > 1
- MYODBCDbgInfo( QString( "SQL_ATTR_APP_PARAM_DESC=%1 and is a %2" ).arg(
(qulonglong)pAppParamDesc ).arg( pAppParamDesc->objectName() ) );
+ MYODBCDbgInfo( QString( "SQL_ATTR_APP_PARAM_DESC=%1" ).arg(
(qulonglong)pAppParamDesc ) );
if ( pnStringLength )
MYODBCDbgInfo( QString( "pnStringLength=%1" ).arg( *pnStringLength )
);
#endif
@@ -449,7 +460,7 @@
MYODBCCSet( pnStringLength, 0 );
}
#if MYODBC_DBG > 1
- MYODBCDbgInfo( QString( "SQL_ATTR_APP_ROW_DESC=%1 and is a %2" ).arg(
(qulonglong)pAppRowDesc ).arg( pAppParamDesc->objectName() ) );
+ MYODBCDbgInfo( QString( "SQL_ATTR_APP_ROW_DESC=%1" ).arg(
(qulonglong)pAppRowDesc ) );
if ( pnStringLength )
MYODBCDbgInfo( QString( "pnStringLength=%1" ).arg( *pnStringLength )
);
#endif
@@ -501,7 +512,7 @@
MYODBCCSet( pnStringLength, 0 );
}
#if MYODBC_DBG > 1
- MYODBCDbgInfo( QString( "SQL_ATTR_IMP_PARAM_DESC=%1 and is a %2" ).arg(
(qulonglong)pImpParamDesc ).arg( pAppParamDesc->objectName() ) );
+ MYODBCDbgInfo( QString( "SQL_ATTR_IMP_PARAM_DESC=%1" ).arg(
(qulonglong)pImpParamDesc ) );
if ( pnStringLength )
MYODBCDbgInfo( QString( "pnStringLength=%1" ).arg( *pnStringLength )
);
#endif
@@ -522,7 +533,7 @@
MYODBCCSet( pnStringLength, 0 );
}
#if MYODBC_DBG > 1
- MYODBCDbgInfo( QString( "SQL_ATTR_IMP_ROW_DESC=%1 and is a %2" ).arg(
(qulonglong)pImpRowDesc ).arg( pAppParamDesc->objectName() ) );
+ MYODBCDbgInfo( QString( "SQL_ATTR_IMP_ROW_DESC=%1" ).arg(
(qulonglong)pImpRowDesc ) );
if ( pnStringLength )
MYODBCDbgInfo( QString( "pnStringLength=%1" ).arg( *pnStringLength )
);
#endif
@@ -1394,7 +1405,7 @@
{
MYODBCDbgEnter();
- MYODBCDbgReturn3( "%p", (MConnection*)parent() );
+ MYODBCDbgReturn3( "%p", connection );
}
QString MStatement::getCursorName()
Modified: trunk/SDK/MYSQLPlus/Tests/MYSQLPlusTest.cpp
===================================================================
--- trunk/SDK/MYSQLPlus/Tests/MYSQLPlusTest.cpp 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/Tests/MYSQLPlusTest.cpp 2007-03-30 00:42:18 UTC (rev 822)
@@ -86,7 +86,7 @@
MYODBCDbgFini();
fileDebugOut.close();
- /* MEnvironment cleans up its child objects (MConnection(s) for example)
automagically. */
+ /* MEnvironment cleans up its child objects (MConnection(s) for example)
automatically. */
}
/*!
@@ -97,7 +97,8 @@
void MYSQLPlusTest::doDriverConnect()
{
MEnvironment * pEnvironment = new MEnvironment();
- MConnection * pConnection = new MConnection( &environment );
+ MConnection * pConnection = new MConnection( pEnvironment );
+ pEnvironment->doAddConnection( pConnection );
SQLWCHAR * pszConnectStringIn = L"DRIVER=MySQL Connector/ODBC
v5;UID=myodbctest;PWD=myodbctest;DATABASE=Northwind";
SQLWCHAR szConnectStringOut[1024];
SQLSMALLINT nLength;
@@ -124,7 +125,8 @@
void MYSQLPlusTest::doConnectDirect()
{
MEnvironment * pEnvironment = new MEnvironment();
- MConnection * pConnection = new MConnection( &environment );
+ MConnection * pConnection = new MConnection( pEnvironment );
+ pEnvironment->doAddConnection( pConnection );
MYODBCInsDataSource datasource;
datasource.setSERVER( "localhost" );
@@ -153,6 +155,7 @@
void MYSQLPlusTest::doConnect()
{
pConnection = new MConnection( &environment );
+ environment.doAddConnection( pConnection );
SQLRETURN nReturn = pConnection->doConnect( L"myodbctest", SQL_NTS, L"myodbctest",
SQL_NTS, L"myodbctest", SQL_NTS );
if ( nReturn != SQL_SUCCESS )
@@ -174,6 +177,8 @@
SQLWCHAR * psSQL = L"DROP TABLE IF EXISTS tbMyODBCTest";
MStatement statement( pConnection );
+ pConnection->doAddStatement( &statement );
+
SQLRETURN nReturn = statement.doExecDirect( psSQL, SQL_NTS );
if ( nReturn != SQL_SUCCESS )
@@ -193,6 +198,8 @@
SQLWCHAR * psSQL = L"CREATE TABLE tbMyODBCTest ( nUserID INT NOT NULL
AUTO_INCREMENT, vcName VARCHAR(60) NOT NULL, dCreated TIMESTAMP NULL, nFlag INT, PRIMARY
KEY ( nUserID ), KEY ( vcName ) )";
MStatement statement( pConnection );
+ pConnection->doAddStatement( &statement );
+
SQLRETURN nReturn = statement.doExecDirect( psSQL, SQL_NTS );
if ( nReturn != SQL_SUCCESS )
*gpMYODBCDbg << statement.getDiagnostics().join( "\n" );
@@ -216,6 +223,8 @@
SQLRETURN nReturn;
SQLINTEGER nRows = 0;
+ pConnection->doAddStatement( &statement );
+
nReturn = statement.doExecDirect( L"INSERT INTO tbMyODBCTest ( vcName ) VALUES (
'name1' )", SQL_NTS );
if ( nReturn != SQL_SUCCESS )
textstreamStdOut << endl << endl <<
statement.getDiagnostics().join( "\n" ) << endl << endl;
@@ -279,6 +288,8 @@
SQLWCHAR szNameWide[100];
SQLINTEGER nStrLenOrInd;
+ pConnection->doAddStatement( &statement );
+
/* this *should* error out so we do not show diag message - diagnostics will be
cleared by next call */
nReturn = statement.doNumResultCols( &nCols );
QCOMPARE( nReturn, (SQLRETURN)SQL_ERROR );
@@ -372,6 +383,8 @@
SQLINTEGER nFlag = 5;
SQLINTEGER nRowCount = 0;
+ pConnection->doAddStatement( &statement );
+
nReturn = statement.doBindParameter( 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 100,
0, szCreated, 0, &nStrLenOrIndCreated );
if ( nReturn != SQL_SUCCESS )
textstreamStdOut << endl << endl <<
statement.getDiagnostics().join( "\n" ) << endl << endl;
@@ -428,6 +441,8 @@
SQLCHAR szCreated[100];
SQLINTEGER nStrLenOrInd;
+ pConnection->doAddStatement( &statement );
+
nReturn = statement.doExecDirect( L"SELECT * FROM tbMyODBCTest", SQL_NTS );
if ( nReturn != SQL_SUCCESS )
textstreamStdOut << endl << endl <<
statement.getDiagnostics().join( "\n" ) << endl << endl;
@@ -487,6 +502,8 @@
SQLINTEGER nStrLenOrIndName = SQL_NTS;
SQLINTEGER nStrLenOrIndCreated = SQL_NTS;
+ pConnection->doAddStatement( &statement );
+
/* vcName for WHERE in 1st SELECT */
nReturn = statement.doBindParameter( 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 100,
0, szName, sizeof(szName), &nStrLenOrIndName );
if ( nReturn != SQL_SUCCESS )
Modified: trunk/SDK/MYSQLPlus/include/MConnection.h
===================================================================
--- trunk/SDK/MYSQLPlus/include/MConnection.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/include/MConnection.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -83,7 +83,10 @@
SQLRETURN doEndTran( SQLSMALLINT nCompletionType );
SQLRETURN doNativeSql( SQLWCHAR *psInStatementText, SQLINTEGER nTextLength1, SQLWCHAR
*psOutStatementText, SQLINTEGER nBufferLength, SQLINTEGER *pnTextLength2 );
- SQLRETURN doAllocDescriptor(SQLHANDLE *desc);
+ MDescriptor *doCreateDescriptor();
+ void doAddStatement(MStatement *stmt);
+ void doRemoveDescriptor(MDescriptor *desc);
+ void doRemoveStatement(MStatement *stmt);
protected:
@@ -391,8 +394,7 @@
SQLRETURN doSubmitCommandForResult( const QString cmd, QString &result );
BOOL doServerAliveSanityCheck();
SQLRETURN doTransactionStart();
- SQLRETURN doTransactionCommit();
- SQLRETURN doTransactionRollback();
+ SQLRETURN doPostTxCleanup( SQLUSMALLINT behavior );
/* iser */
BOOL isConnected();
@@ -410,7 +412,9 @@
BUFFERED_TYPE nBufferedType; /*!< whether or not we are going to buffer
results - greatly affects result-set handling */
QString stringDataSourceName;
QString stringUserIdentifier;
+ MEnvironment * environment;
QList<MDescriptor *> descriptors; /*!< User-allocated descriptors on this
connection */
+ QList<MStatement *> statements;
/*!
\internal
Modified: trunk/SDK/MYSQLPlus/include/MDescriptor.h
===================================================================
--- trunk/SDK/MYSQLPlus/include/MDescriptor.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/include/MDescriptor.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -50,7 +50,7 @@
class MDescriptorRecordIPD;
class MDescriptorRecordIRD;
-class MDescriptor : public QObject
+class MDescriptor
{
friend class MResult;
#ifdef RESULTPLUS
@@ -86,6 +86,7 @@
/* setters */
virtual SQLRETURN setDescField( SQLSMALLINT nRecNumber, SQLSMALLINT nFieldIdentifier,
SQLPOINTER pValuePtr, SQLINTEGER nBufferLength );
virtual SQLRETURN setDescRec( SQLSMALLINT nRecNumber, SQLSMALLINT nType, SQLSMALLINT
nSubType, SQLLEN nLength, SQLSMALLINT nPrecision, SQLSMALLINT nScale, SQLPOINTER
pDataPtr, SQLLEN *pnStringLengthPtr, SQLLEN *pnIndicatorPtr );
+ virtual void setConnection( MConnection *conn );
/* getters */
virtual SQLRETURN getDescField( SQLSMALLINT nRecNumber, SQLSMALLINT nFieldIdentifier,
SQLPOINTER pValuePtr, SQLINTEGER nBufferLength, SQLINTEGER *pnStringLengthPtr );
@@ -134,6 +135,7 @@
private:
MDiagnostic * pDiagnostic; /*!< our diagnostic information
*/
MDiagnostic * pDiagnosticCaller; /*!< our callers diagnostic information
(send diag here if !NULL) */
+ MConnection * connection; /*!< optional connection "parent", for explicitly
alloc'd descriptors */
SQLSMALLINT nAllocType; /*!< SQL_DESC_ALLOC_TYPE */
SQLUINTEGER nArraySize; /*!< SQL_DESC_ARRAY_SIZE */
Modified: trunk/SDK/MYSQLPlus/include/MEnvironment.h
===================================================================
--- trunk/SDK/MYSQLPlus/include/MEnvironment.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/include/MEnvironment.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -38,7 +38,7 @@
The Environment is typically the first class to be instantiated. An
application
creates an instance of MEnvironment and then one or more MConnection's.
*/
-class MEnvironment : public QObject
+class MEnvironment : QObject
{
friend class MConnection;
friend class MStatement;
@@ -49,7 +49,7 @@
friend class MResultPlus;
#endif
public:
- MEnvironment( QObject *pObjectParent = NULL );
+ MEnvironment();
~MEnvironment();
enum STATE
@@ -71,6 +71,8 @@
/* doers */
SQLRETURN doEndTran( SQLSMALLINT nCompletionType );
+ void doAddConnection( MConnection *conn );
+ void doRemoveConnection( MConnection *conn );
protected:
/* setters */
@@ -94,6 +96,7 @@
SQLUINTEGER nCPMatch; /*!< SQL_ATTR_CP_MATCH (DM)
*/
SQLINTEGER nODBCVersion; /*!< SQL_ATTR_ODBC_VERSION
*/
SQLINTEGER bOutputNTS; /*!< SQL_ATTR_OUTPUT_NTS
*/
+ QList<MConnection *> connections;
};
#endif
Modified: trunk/SDK/MYSQLPlus/include/MStatement.h
===================================================================
--- trunk/SDK/MYSQLPlus/include/MStatement.h 2007-03-29 15:15:27 UTC (rev 821)
+++ trunk/SDK/MYSQLPlus/include/MStatement.h 2007-03-30 00:42:18 UTC (rev 822)
@@ -198,6 +198,8 @@
MDiagnostic * pDiagnosticCaller; /*!< our callers diagnostic information
(send diag here if !NULL) */
BOOL bImplicitPrepare; /*!< true if prepare done implicitly ie
doExecDirect or doTables etc*/
STATE nState; /*!< our current state
*/
+ MConnection * connection;
+ QList<MDescriptor *> descriptors; /*!< Auto-allocated descriptors */
MDescriptor * pAppParamDesc; /*!< SQL_ATTR_APP_PARAM_DESC */
MDescriptor * pAppRowDesc; /*!< SQL_ATTR_APP_ROW_DESC */
| Thread |
|---|
| • Connector/ODBC 5 commit: r822 - in trunk: Driver/Driver/Library SDK/C/Library SDK/C/include SDK/MYSQLPlus/Library SDK/MYSQLPlus/Tests SDK/MYSQLPlus/in... | jbalint | 30 Mar |