Modified:
trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp
trunk/MYSQLPlus/MYSQLPlusLib/MStatement.cpp
Log:
more work on SQLMoreResults
Modified: trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp 2006-07-29 05:37:54 UTC (rev 463)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp 2006-07-29 18:20:02 UTC (rev 464)
@@ -399,7 +399,9 @@
/*!
\internal MYSQL RULE
- We support transactions on DML commands (not on DDL).
+ We support transactions on DML commands (not on DDL). But note that caller can
get this
+ from MConnection::getInfoTxnCapable() and MCommand::isDataManipulationLanguage()
instead
+ of using this method.
*/
if ( isDataManipulationLanguage() )
MYODBCDbgReturn3( "%d", true );
Modified: trunk/MYSQLPlus/MYSQLPlusLib/MStatement.cpp
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MStatement.cpp 2006-07-29 05:37:54 UTC (rev 463)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MStatement.cpp 2006-07-29 18:20:02 UTC (rev 464)
@@ -2747,6 +2747,9 @@
{
MYODBCDbgEnter();
+ SQLRETURN nReturnPrepare;
+ SQLRETURN nReturnExecute;
+
/*!
\internal ODBC RULE
@@ -2758,6 +2761,10 @@
\internal ODBC RULE (DM)
The StatementHandle was not prepared.
+
+ \internal MYODBC RULE
+
+ Seems to make more sense that we must be executed - not just prepared.
*/
if ( !isExecuted() )
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY010 ) );
@@ -2790,6 +2797,14 @@
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY010 ) );
/*!
+ \internal
+
+ We have already iterated over all commands.
+ */
+ if ( pCommands->getPos() < 0 )
+ MYODBCDbgReturn( SQL_NO_DATA );
+
+ /*!
\internal ODBC RULE
It is driver-specific whether the entire batch statement is executed before any
results are
@@ -2813,20 +2828,20 @@
* PREPARE
*/
- /* rollback to prepared state */
- doStateRollBack( STATE_S3 );
-
/* advance to next command */
if ( pCommands->doNext() )
{
- delete pResult;
+ MResult *pResultOriginal = pResult;
pResult = NULL;
- nReturn = doPrepare( pCommands->getCommand() );
- if ( !SQL_SUCCEEDED( nReturn ) )
+ nReturnPrepare = doPrepare( pCommands->getCommand() );
+ if ( !SQL_SUCCEEDED( nReturnPrepare ) )
{
- MYODBCDbgReturn( nReturn );
+ pResult = pResultOriginal;
+ doStateRollBack( STATE_S1 );
+ MYODBCDbgReturn( nReturnPrepare );
}
+ delete pResultOriginal;
}
else
{
@@ -2834,12 +2849,49 @@
MYODBCDbgReturn( SQL_NO_DATA );
}
+ doStateRollBack( STATE_S1 );
+
/*
* EXECUTE
*/
- pResult->doExecute();
+ nReturnExecute = pResult->doExecute();
+ if ( !SQL_SUCCEEDED( nReturnExecute ) )
+ {
+ /*!
+ \internal ODBC RULE
+ \todo
+ If SQLExecute executes a searched update or delete statement that does
+ not affect any rows at the data source, the call to SQLExecute returns
+ SQL_NO_DATA.
+ */
+ /*!
+ \internal ODBC RULE
+ \todo
+
+ If SQLExecute encounters a data-at-execution parameter, it returns
+ SQL_NEED_DATA. The application sends the data using SQLParamData and
+ SQLPutData.
+ */
+ MYODBCDbgReturn( nReturnExecute );
+ }
+
+ /*!
+ \internal ODBC RULE
+
+ No columns then no resultset - set state accordingly. Being in state S5 does
+ not imply that we have data/rows in the resultset - just that we have a
+ resultset.
+ */
+ if ( getImpRowDesc()->getCount() )
+ setState( STATE_S5 );
+ else
+ setState( STATE_S4 );
+
+ if ( nReturnPrepare == SQL_SUCCESS_WITH_INFO || nReturnExecute ==
SQL_SUCCESS_WITH_INFO )
+ MYODBCDbgReturn( SQL_SUCCESS_WITH_INFO );
+
MYODBCDbgReturn( SQL_SUCCESS );
}
@@ -3127,6 +3179,18 @@
goto doPrepareExit2;
}
+ /*!
+ \internal
+ \todo
+
+ Set SQL_DIAG_DYNAMIC_FUNCTION and SQL_DIAG_DYNAMIC_FUNCTION_CODE diagnostic
header fields and possibly use them instead
+ of statement type.
+ */
+ if ( pCommands->getCommand().isResultSetPossible() )
+ setState( STATE_S3 );
+ else
+ setState( STATE_S2 );
+
MYODBCDbgReturn( nReturn );
doPrepareExit2:
@@ -5204,6 +5268,31 @@
MYODBCDbgReturn3( "%d", nUseBookmarks );
}
+/*!
+ \brief Roll back the state.
+
+ This will roll back the state - ensuring that things get cleaned up along
+ the way.
+
+ This is *the* method for rolling back state - other nethods should always
+ use this to roll back a state. However; there are some exceptional
circumstances
+ such as \sa doMoreResults which needs to partially roll back to a STATE_S1
from
+ an executed state.
+
+ \param nState The desired state. This must be greater than the current state. The
actual
+ state set may differ. For example; request STATE_S3 from an executed
state
+ may result in STATE_S2 depending upon the current command.
+
+ \return SQLRETURN
+
+ \retval SUCCESS
+ \retval WARNING
+ \retval ERROR
+
+ \sa getState
+ setState
+ doMoreResults
+*/
SQLRETURN MStatement::doStateRollBack( STATE nState )
{
MYODBCDbgEnter();
@@ -5258,6 +5347,15 @@
nState = STATE_S3; // we will have a resultset
else
{
+ /*!
+ \note
+
+ Once we have iterated over all the results with doMoreResults we
end up with a kind of EOF pos. In
+ this case doMoreResults will only return SQL_NO_DATA. doExecute
can be used to go back to the first
+ command, execute it, and allow doMoreResults to execute next
command (if any).
+ */
+ pCommands->doFirst();
+
if ( pCommands->getCommand().isResultSetPossible() )
nState = STATE_S3; // we will have a resultset
}
@@ -5307,6 +5405,19 @@
The idea here is that this can be called from \sa doPrepare() and \sa
doMoreResults().
+ pResult needs to be NULL coming into here. The state should be STATE_S1 or an
executed
+ state.
+
+ \return SQLRETURN
+
+ \retval SUCCESS Called succeeded;
+ - state unchanged (caller should adjust)
+ - pResult will be viable
+
+ \retval ERROR Call failed;
+ - state unchanged
+ - pResult unchanged
+
\sa doPrepare
doMoreResults
*/
@@ -5330,8 +5441,6 @@
- server feature support
- SQL statement
- resultset characteristics expected (if possible)
-
- Our bias is toward using server-side prepared.
*/
if ( nStatementType == MConnection::STATEMENT_DYNAMIC )
{
@@ -5344,7 +5453,7 @@
/* if app wants server-side prepare but we can not use it then we fall back to
client-side and throw a warning */
if ( nStatementType == MConnection::STATEMENT_STMT &&
!command.isServerSidePreparePossible() )
{
- getDiagnostic()->doAppend( MDiagnostic::DIA_01000, 0, tr("STATEMENT_STMT will
not support command - will use STATEMENT_RES instead") );
+ getDiagnostic()->doAppend( MDiagnostic::DIA_01000, 0, tr("Server-side prepare
not possible for this command - using client-side.") );
nStatementType = MConnection::STATEMENT_RES;
}
@@ -5361,13 +5470,16 @@
break;
default:
- nReturn = getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0, QString(
tr("Unknown statement type %1") ).arg( nStatementType ) );
- goto doPrepareExit1;
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
QString( tr("Unknown statement type %1") ).arg( nStatementType ) ) );
}
SQLRETURN nReturn = pResult->doPrepare( command );
if ( !SQL_SUCCEEDED( nReturn ) )
+ {
+ delete pResult;
+ pResult = NULL;
MYODBCDbgReturn( nReturn );
+ }
/*!
\internal
@@ -5376,7 +5488,7 @@
We silently start a transaction as needed. We do not rely upon the server doing
this for us but perhaps we should - will see.
*/
- MConnection * pConnection = getConnection();
+ MConnection *pConnection = getConnection();
if ( pConnection->isTransaction() == false )
{
@@ -5395,22 +5507,12 @@
case SQL_TC_ALL:
nReturn = pConnection->doTransactionStart();
default:
+ delete pResult;
+ pResult = NULL;
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
tr("Unknown value from getInfoTxnCapable()") ) );
}
}
- /*!
- \internal
- \todo
-
- Set SQL_DIAG_DYNAMIC_FUNCTION and SQL_DIAG_DYNAMIC_FUNCTION_CODE diagnostic
header fields and possibly use them instead
- of statement type.
- */
- if ( command.isResultSetPossible() )
- setState( STATE_S3 );
- else
- setState( STATE_S2 );
-
MYODBCDbgReturn( nReturn );
}
| Thread |
|---|
| • Connector/ODBC 5 commit: r464 - trunk/MYSQLPlus/MYSQLPlusLib | pharvey | 29 Jul |