List:Commits« Previous MessageNext Message »
From:jbalint Date:March 30 2007 2:42am
Subject: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...
View as plain text  
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...jbalint30 Mar