List:Commits« Previous MessageNext Message »
From:pharvey Date:July 10 2006 8:05pm
Subject:Connector/ODBC 5 commit: r436 - in trunk/MYSQLPlus: MYSQLPlusLib include
View as plain text  
Modified:
   trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp
   trunk/MYSQLPlus/MYSQLPlusLib/MCommand.h
   trunk/MYSQLPlus/MYSQLPlusLib/MYSQLPlusLib.vpj
   trunk/MYSQLPlus/include/MStatement.h
Log:
more fleshing out MCommand

Modified: trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp	2006-07-10 16:02:49 UTC (rev 435)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MCommand.cpp	2006-07-10 20:05:53 UTC (rev 436)
@@ -16,6 +16,8 @@
     this->pConnection = pConnection;
     pStatement = NULL;
 
+    nCommandType = COMMAND_TYPE_NULL;
+
     MYODBCDbgReturn2();
 }
 
@@ -27,41 +29,99 @@
     this->pStatement = pStatement;
     pConnection = pStatement->getConnection();
 
+    nCommandType = COMMAND_TYPE_NULL;
+
     MYODBCDbgReturn2();
 }
 
 /*!
     \brief      Causes the given command to be prepared.
 
-                We separate the commands by ';' and create an MCommand for each. 
+                Here we prepare the command so as to;
 
-                The MCommand will do the remaining processing.
+                - translate any ODBC specific syntax into syntax supported by the server
(ie "{d <dateval>}" )
+                - process escape sequences as needed
+                - provide parameter marker information
+                - provide feature information (ie is command viable for a transaction)
 
     \return     SQLRETURN
+
+    \retval     SQL_SUCCESS             Success.
+    \retval     SQL_SUCCESS_WITH_INFO   Warning(s) have been put into diagnostic. We can
continue.
+    \retval     SQL_ERROR               Error(s) have been put into diagnostic. We can
not continue.
 */
-SQLRETURN MCommands::setCommand( const QString &stringCommands )
+SQLRETURN MCommand::setCommand( const QString &stringCommand )
 {
     MYODBCDbgEnter();
 
-    QChar   cQuote;
-    QChar   cMarker( '?' );
-    QChar   cBraceOpen( '{' );
-    QChar   cBraceClose( '}' );
-    int     nBraceNest = 0;
-    BOOLEAN bBraceCheck = true;
-    QString stringQuotes = "\"'";
-    QString stringStatementSegment;
+    /*!
+        \internal
+        \note
 
-    for ( int nChar = 0; nChar < stringStatement.length(); nChar++ )
+        At the moment - we are just doing the following in here;
+
+        - strip off any curly braces used on entire command ie "{ CALL sp() }" becomes "
CALL sp() " 
+        - get index pos for each parameter marker (without removing marker)
+        - get command type based upon first keyword
+
+        As a side affect we are usually (but not always) going to catch;
+
+        - mismatched quotes
+        - mismatched braces
+
+        \todo
+
+        - translate ODBC specific syntax to server friendly
+        - handle escape sequences as needed
+        - get details about commands within store procedures so we can report command
features etc (probably not practical to do this)
+    */
+    SQLRETURN   nReturn = SQL_SUCCESS;
+    QChar       cQuote;
+    QChar       cMarker( '?' );
+    QChar       cBraceOpen( '{' );
+    QChar       cBraceClose( '}' );
+    int         nBraceNest      = 0;
+    BOOLEAN     bBraceCheck     = true;
+    QString     stringQuotes    = "\"'";
+
+    /* clear any existing processing */
+    nCommandType = COMMAND_TYPE_NULL;
+    listParameterMarkers.clear();
+    stringCommand.clear();
+    stringCommandNative.clear();
+
+    /* for each char in stringCommand */
+    for ( int nChar = 0, int nCharsSkipped = 0; nChar < stringCommand.length();
nChar++ )
     {
-        QChar cChar = stringStatement.at( nChar );
+        QChar   cChar       = stringCommand.at( nChar );
+        BOOLEAN bLastChar   = ( nChar == (stringCommand.length() - 1) );
 
+        /* catch some last char problems */
+        if ( bLastChar )
+        {
+            /* mismatched quote */
+            if ( ( !cQuote.isNull() && cChar != cQuote ) ||                 /*
last char is not going to close our quote            */
+                 ( cQuote.isNull() && stringQuotes.contains( cChar ) )  )   /*
last char is going to open a quote                   */
+                MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
QString( tr("mismatched quote near: ") ).arg( stringCommand ) ) );
+
+            /* mismatched brace */
+            if ( bBraceCheck &&
+                 (nBraceNest && cChar != cBraceClose) ||
+                 (nBraceNest == 0 && cChar == cBraceOpen || cChar == cBraceClose)
||
+                 nBraceNest > 1 ||
+                 nBraceNest < 0 )
+                MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
QString( tr("mismatched brace near: ") ).arg( stringCommand ) ) );
+        }
+
         /* brace opening (not in quotes) */
         if ( bBraceCheck && cQuote.isNull() && cChar == cBraceOpen )
         {
             nBraceNest++;
             if ( nBraceNest == 1 )
+            {
+                nCharsSkipped++;
                 continue;
+            }
         }
 
         /* brace closing (not in quotes) */
@@ -71,6 +131,7 @@
             if ( nBraceNest == 0 )
             {
                 bBraceCheck = false;
+                nCharsSkipped++;
                 continue;
             }
         }
@@ -81,13 +142,7 @@
 
         /* parameter marker */
         if ( cQuote.isNull() && cChar == cMarker )
-        {
-            if ( !stringStatementSegment.isNull() )
-                stringlistStatement += stringStatementSegment;
-            stringlistStatement += QString( cMarker );
-            stringStatementSegment.clear();
-            continue;
-        }
+            listParameterMarkers.append( nChar - nCharsSkipped );
 
         /* quote opening */
         if ( cQuote.isNull() && stringQuotes.contains( cChar ) )
@@ -96,13 +151,42 @@
         else if ( !cQuote.isNull() && cQuote == cChar )
             cQuote = '\0';
 
-        stringStatementSegment += cChar;
+        this->stringCommand += cChar;
     }
-    if ( !stringStatementSegment.isNull() )
-        stringlistStatement += stringStatementSegment;
 
-    this->stringCommand = stringCommand;
+    this->stringCommand = this->stringCommand.trimmed();
 
+    /*!
+        \internal
+
+        determine command type 
+
+        \todo
+
+        - detect SELECT INTO
+        - support for more keywords/types
+    */
+    if ( this->stringCommand.startWith( "SELECT " ) )
+        nCommandType = COMMAND_TYPE_SELECT;
+    else if ( this->stringCommand.startWith( "SHOW " ) )
+        nCommandType = COMMAND_TYPE_SHOW;
+    else if ( this->stringCommand.startWith( "UPDATE " ) )
+        nCommandType = COMMAND_TYPE_UPDATE;
+    else if ( this->stringCommand.startWith( "DELETE " ) )
+        nCommandType = COMMAND_TYPE_DELETE;
+    else if ( this->stringCommand.startWith( "INSERT " ) )
+        nCommandType = COMMAND_TYPE_INSERT;
+    else if ( this->stringCommand.startWith( "CALL " ) )
+        nCommandType = COMMAND_TYPE_CALL;
+    else if ( this->stringCommand.startWith( "CREATE " ) )
+        nCommandType = COMMAND_TYPE_CREATE;
+    else if ( this->stringCommand.startWith( "GRANT " ) )
+        nCommandType = COMMAND_TYPE_GRANT;
+    else if ( this->stringCommand.startWith( "SET " ) )
+        nCommandType = COMMAND_TYPE_SET;
+    else
+        nCommandType = COMMAND_TYPE_UNKNOWN;
+
     MYODBCDbgReturn( nReturn );
 }
 
@@ -111,7 +195,7 @@
 
     \return     QString
 */
-QString MCommands::getCommand()
+QString MCommand::getCommand()
 {
     MYODBCDbgEnter();
 
@@ -127,7 +211,7 @@
 
     \return QString
 */
-QString MCommands::getCommandNative()
+QString MCommand::getCommandNative()
 {
     MYODBCDbgEnter();
 
@@ -142,28 +226,99 @@
 
     \return QList<int>
 */
-QList<int> MCommands::getParameterMarkers()
+QList<int> MCommand::getParameterMarkers()
 {
     MYODBCDbgEnter();
 
     MYODBCDbgReturn3( "%p", listParameterMarkers );
 }
 
+BOOLEAN MCommand::isDataManipulationLanguage()
+{
+    MYODBCDbgEnter();
+
+    /*!
+        \note
+
+        We classify CALL as both DML and DDL. At some point this code will need to know
for certian.
+    */
+    switch ( nCommandType )
+    {
+        case COMMAND_TYPE_SELECT:
+        case COMMAND_TYPE_SELECT_INTO:
+        case COMMAND_TYPE_SHOW:
+        case COMMAND_TYPE_UPDATE:
+        case COMMAND_TYPE_DELETE:
+        case COMMAND_TYPE_INSERT:
+        case COMMAND_TYPE_CALL:
+        case COMMAND_TYPE_SET:
+            MYODBCDbgReturn3( "%d", true );
+        case COMMAND_TYPE_CREATE:
+        case COMMAND_TYPE_GRANT:
+        case COMMAND_TYPE_NULL:
+        case COMMAND_TYPE_UNKNOWN:
+    }
+
+    MYODBCDbgReturn3( "%d", false );
+}
+
+BOOLEAN MCommand::isDataDefinitionLanguage()
+{
+    MYODBCDbgEnter();
+
+    /*!
+        \note
+
+        We classify CALL as both DML and DDL. At some point this code will need to know
for certian.
+    */
+    switch ( nCommandType )
+    {
+        case COMMAND_TYPE_CALL:
+        case COMMAND_TYPE_CREATE:
+        case COMMAND_TYPE_GRANT:
+            MYODBCDbgReturn3( "%d", true );
+        case COMMAND_TYPE_SELECT:
+        case COMMAND_TYPE_SELECT_INTO:
+        case COMMAND_TYPE_SHOW:
+        case COMMAND_TYPE_UPDATE:
+        case COMMAND_TYPE_DELETE:
+        case COMMAND_TYPE_INSERT:
+        case COMMAND_TYPE_SET:
+        case COMMAND_TYPE_NULL:
+        case COMMAND_TYPE_UNKNOWN:
+    }
+
+    MYODBCDbgReturn3( "%d", false );
+}
+
 /*!
     \brief  Used to determine if command is going to honour any transaction it may be a
party to.
 
             This may be used to enforce ODBC rules during a prepare.
 
+    \note   This does NOT factor in;
+
+            - whether or not the server supports transactions
+            - whether or not the driver has been told to use transactions
+            - whether or not database objects (tables) referenced support transactions 
+
     \return BOOLEAN
 
     \retval true    If command will honour a transaction.
     \retval false   If command will not honour a transaction.
 */
-BOOLEAN MCommands::isTransactionPossible()
+BOOLEAN MCommand::isTransactionPossible()
 {
     MYODBCDbgEnter();
 
+    /*!
+        \internal MYSQL RULE
 
+        We support transactions on DML commands (not on DDL).
+    */
+    if ( isDataManipulationLanguage() )
+        MYODBCDbgReturn3( "%d", true );
+
     MYODBCDbgReturn3( "%d", false );
 }
 
@@ -181,10 +336,32 @@
     \retval true    If command will create a result-set.
     \retval false   If command will not create a result-set.
 */
-BOOLEAN MCommands::isResultSetPossible()
+BOOLEAN MCommand::isResultSetPossible()
 {
     MYODBCDbgEnter();
 
+    /*!
+        \note
+
+        We assume CALL produces a result-set. At some point this code will need to know
for certian.
+    */
+    switch ( nCommandType )
+    {
+        case COMMAND_TYPE_CALL:
+        case COMMAND_TYPE_SELECT:
+        case COMMAND_TYPE_SHOW:
+            MYODBCDbgReturn3( "%d", true );
+        case COMMAND_TYPE_CREATE:
+        case COMMAND_TYPE_GRANT:
+        case COMMAND_TYPE_SELECT_INTO:
+        case COMMAND_TYPE_UPDATE:
+        case COMMAND_TYPE_DELETE:
+        case COMMAND_TYPE_INSERT:
+        case COMMAND_TYPE_SET:
+        case COMMAND_TYPE_NULL:
+        case COMMAND_TYPE_UNKNOWN:
+    }
+
     MYODBCDbgReturn3( "%d", false );
 }
 
@@ -200,14 +377,36 @@
     \retval true    If command may modify data.
     \retval false   If command will not modify data.
 */
-BOOLEAN MCommands::isDataModificationPossible()
+BOOLEAN MCommand::isDataModificationPossible()
 {
     MYODBCDbgEnter();
 
+    /*!
+        \note
+
+        We assume CALL may modify data. At some point this code will need to know for
certian.
+    */
+    switch ( nCommandType )
+    {
+        case COMMAND_TYPE_CALL:
+        case COMMAND_TYPE_CREATE:
+        case COMMAND_TYPE_GRANT:
+        case COMMAND_TYPE_SELECT_INTO:
+        case COMMAND_TYPE_UPDATE:
+        case COMMAND_TYPE_DELETE:
+        case COMMAND_TYPE_INSERT:
+        case COMMAND_TYPE_SET:
+            MYODBCDbgReturn3( "%d", true );
+        case COMMAND_TYPE_SELECT:
+        case COMMAND_TYPE_SHOW:
+        case COMMAND_TYPE_NULL:
+        case COMMAND_TYPE_UNKNOWN:
+    }
+
     MYODBCDbgReturn3( "%d", false );
 }
 
-MDiagnostic *MCommands::getDiagnostic()
+MDiagnostic *MCommand::getDiagnostic()
 {
     if ( pStatement )
         pStatement->getDiagnostic();

Modified: trunk/MYSQLPlus/MYSQLPlusLib/MCommand.h
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MCommand.h	2006-07-10 16:02:49 UTC (rev 435)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MCommand.h	2006-07-10 20:05:53 UTC (rev 436)
@@ -35,17 +35,18 @@
 public:
     enum COMMAND_TYPE
     {
-        COMMAND_TYPE_NULL,          /*!< we do not have a statement                   
         */
-        COMMAND_TYPE_SELECT,        /*!< SELECT statement has been prepared           
         */
-        COMMAND_TYPE_SELECT_INTO,   /*!< SELECT INTO statement has been prepared      
         */
-        COMMAND_TYPE_SHOW,          /*!< SHOW statement has been prepared             
         */
-        COMMAND_TYPE_UPDATE,        /*!< UPDATE statement has been prepared           
         */
-        COMMAND_TYPE_DELETE,        /*!< DELETE statement has been prepared           
         */
-        COMMAND_TYPE_INSERT,        /*!< INSERT statement has been prepared           
         */
-        COMMAND_TYPE_CALL,          /*!< CALL statement has been prepared             
         */
-        COMMAND_TYPE_CREATE,        /*!< CREATE statement has been prepared           
         */
-        COMMAND_TYPE_GRANT,         /*!< GRANT statement has been prepared            
         */
-        COMMAND_TYPE_SET            /*!< SET statement has been prepared              
         */
+        COMMAND_TYPE_NULL,          /*!< we do not have a command                     
         */
+        COMMAND_TYPE_SELECT,        /*!< SELECT command has been prepared             
         */
+        COMMAND_TYPE_SELECT_INTO,   /*!< SELECT INTO command has been prepared        
         */
+        COMMAND_TYPE_SHOW,          /*!< SHOW command has been prepared               
         */
+        COMMAND_TYPE_UPDATE,        /*!< UPDATE command has been prepared             
         */
+        COMMAND_TYPE_DELETE,        /*!< DELETE command has been prepared             
         */
+        COMMAND_TYPE_INSERT,        /*!< INSERT command has been prepared             
         */
+        COMMAND_TYPE_CALL,          /*!< CALL command has been prepared               
         */
+        COMMAND_TYPE_CREATE,        /*!< CREATE command has been prepared             
         */
+        COMMAND_TYPE_GRANT,         /*!< GRANT command has been prepared              
         */
+        COMMAND_TYPE_SET,           /*!< SET command has been prepared                
         */
+        COMMAND_TYPE_UNKNOWN        /*!< command starts with unknown keyword          
         */
     };
 
     MCommand( MConnection *pConnection );

Modified: trunk/MYSQLPlus/MYSQLPlusLib/MYSQLPlusLib.vpj
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MYSQLPlusLib.vpj	2006-07-10 16:02:49 UTC (rev 435)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MYSQLPlusLib.vpj	2006-07-10 20:05:53 UTC (rev 436)
@@ -52,6 +52,7 @@
 		<Folder
 			Name="Source Files"
 			Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl">
+			<F N="MCommand.cpp"/>
 			<F N="MCommands.cpp"/>
 			<F N="MConnection.cpp"/>
 			<F N="MDescriptor.cpp"/>

Modified: trunk/MYSQLPlus/include/MStatement.h
===================================================================
--- trunk/MYSQLPlus/include/MStatement.h	2006-07-10 16:02:49 UTC (rev 435)
+++ trunk/MYSQLPlus/include/MStatement.h	2006-07-10 20:05:53 UTC (rev 436)
@@ -5,6 +5,8 @@
 
 class MStatement : public QObject
 {
+    friend class MCommands;
+    friend class MCommand;
     friend class MStatement;
     friend class MConnection;
     friend class MResult;

Thread
Connector/ODBC 5 commit: r436 - in trunk/MYSQLPlus: MYSQLPlusLib includepharvey10 Jul