List:Commits« Previous MessageNext Message »
From:pharvey Date:August 11 2006 11:31am
Subject:Connector/ODBC 5 commit: r485 - trunk/MYSQLPlus/MYSQLPlusLib
View as plain text  
Modified:
   trunk/MYSQLPlus/MYSQLPlusLib/MConnection.cpp
Log:
- added support for SQLBrowseConnect (still needs post-build tests)

Modified: trunk/MYSQLPlus/MYSQLPlusLib/MConnection.cpp
===================================================================
--- trunk/MYSQLPlus/MYSQLPlusLib/MConnection.cpp	2006-08-11 04:12:32 UTC (rev 484)
+++ trunk/MYSQLPlus/MYSQLPlusLib/MConnection.cpp	2006-08-11 09:31:11 UTC (rev 485)
@@ -1385,7 +1385,6 @@
     */
     pDiagnostic->doClear();
 
-
     /*!
         \internal ODBC RULE (DM)
 
@@ -1400,7 +1399,7 @@
 
         The value specified for argument StringLength1 was less than 0 and was not equal
to SQL_NTS.
     */
-    if ( nStringLength1 < 0 && nStringLength1 != SQL_NTS) )
+    if ( nStringLength1 < 0 && nStringLength1 != SQL_NTS )
         MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY090 ) );
 
     /*! 
@@ -1414,106 +1413,203 @@
     /*!
         \internal MYODBC RULE
 
-        In this context - we need the following information to connect;
+        Its implied (by nBufferLength > 0) that we have a viable buffer to return
stuff in but we make sure
+        of this.
+    */
+    if ( !psOutConnectionString )
+        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
tr("Invalid buffer.") ) );
 
-            - server
-            - database
-            - userid
-            - password
+    /*!
+        \internal MYODBC RULE
 
+        In this context - we need the following attributes to connect;
+
+            - DSN || DRIVER
+            - SERVER
+            - UID
+            - PWD
+            - DATABASE
+
         These are not strictly required but we ask for them all - favouring the idea of
discovering most common
-        connection information.
+        connection information. The caller still has the option of providing the
attribute with no value. If the 
+        value is required - the connect will fail.
     */
 
-    /* */
-    QString stringInConnection;
-    QString stringOutConnection;
+    /* we will work with a MYODBCInsDataSource (even as we abuse the DRIVER attribute
within) because its so near perfect for this purpose */
+    MYODBCInsDataSource datasource;
 
-    if ( psInConnectionString )
-        stringInConnection.setUtf16( psInConnectionString, ( nNameLength1 == SQL_NTS ?
wcslen( psInConnectionString ) : nNameLength1 ) );
+    datasource.setMode( MYODBCInsDataSource::DATASOURCE_MODE_DSN_VIEW );
+    datasource.setScope( MYODBCInsDataSource::DATASOURCE_SCOPE_BOTH );
 
+    /* parse incoming attributes */
+    QString stringConnection;
+    QString stringConnectionMissing;
+
+    stringConnection.setUtf16( psInConnectionString, ( nStringLength1 == SQL_NTS ?
wcslen( psInConnectionString ) : nStringLength1 ) );
+
     QHash<QString,QString> hashKeywordValues;
-    if ( !MYODBCIns::getKeywordValues( &hashKeywordValues, stringInConnection,
MYODBCIns::DELIM_SEMI ) )
-        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
stringInConnection ) );
+    if ( !MYODBCIns::getKeywordValues( &hashKeywordValues, stringConnection,
MYODBCIns::DELIM_SEMI ) )
+        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
stringConnection ) );
 
+    /*!
+        \internal ODBC RULE
 
-    /* if we have a DSN then look it up... */
-    MYODBCInsDataSource datasource;
+        When SQLBrowseConnect is called for the first time on a connection, the browse
request connection string 
+        must contain the DSN keyword or the DRIVER keyword.
+    */
+    if ( hashKeywordValues.contains( "DSN" ) )
+    {
+        /*!
+            \internal ODBC RULE (DM)
 
-    datasource.setMode( MYODBCInsDataSource::DATASOURCE_MODE_DSN_VIEW );
-    datasource.setScope( MYODBCInsDataSource::DATASOURCE_SCOPE_BOTH );
+            The attribute value for the DSN keyword was longer than SQL_MAX_DSN_LENGTH
characters.
+        */
+        if ( hashKeywordValues.value( "DSN" ).length() > SQL_MAX_DSN_LENGTH )
+            MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_IM010 ) );
 
-    if ( !hashKeywordValues.contains( "DSN" ) )
+        /*!
+            \internal ODBC RULE (me thinks)
+
+            We use any DSN attributes we can find in the system information - but the
ones provided in hashKeywordValues
+            will take precedence.
+
+            \note
+
+            We ignore any error in loading the DSN - it does not make sense to return
DIA_IM002 in this context as we are
+            driver to be used.
+        */
+        datasource.doRead( hashKeywordValues.value( "DSN" ) );
+    }
+    else if ( hashKeywordValues.contains( "DRIVER" ) )
     {
-        if ( !datasource.doRead( hashKeywordValues.value( "DSN" ) ) )
-            MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_IM002 ) );
+        /*!
+            \internal ODBC RULE (DM)
+
+            The attribute value for the DRIVER keyword was longer than 255 characters.
+        */
+        if ( hashKeywordValues.value( "DRIVER" ).length() > 255 )
+            MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_IM011 ) );
     }
+    else
+        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0, tr("DSN
or DRIVER attribute must be supplied.") ) );
 
-    if ( !hashKeywordValues.contains( "DSN" ) )
+    /*!
+        \internal ODBC RULE
+
+        An invalid attribute keyword was specified in the browse request connection
string 
+        (InConnectionString). (Function returns SQL_NEED_DATA.)
+
+        \note
+
+        The concern here is that the caller will not take steps to handle this case and
end up
+        looping on SQL_NEED_DATA.
+    */
+    if ( !datasource.setAttributes( hashKeywordValues, true, false ) )
     {
-        if ( !datasource.doRead( hashKeywordValues.value( "DSN" ) ) )
-            MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_IM002 ) );
+        /* getDiagnostic()->doAppend( MDiagnostic::DIA_01S00 ); */
+        /* nReturn = SQL_NEED_DATA;                             */
+        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
tr("Failed to validate the attributes.") ) );
     }
 
     /* do we have a SERVER attribute? */
     if ( !hashKeywordValues.contains( "SERVER" ) )
-        stringOutConnection = "SERVER:" + tr("Server") + "=?";
+        stringConnectionMissing = "SERVER:" + tr("Server") + "=?";
     /* do we have a UID attribute? */
     if ( !hashKeywordValues.contains( "UID" ) )
     {
-        if ( !stringOutConnection.isEmpty() )
-            stringOutConnection += ";";
-        stringOutConnection = "UID:" + tr("User ID") + "=?";
+        if ( !stringConnectionMissing.isEmpty() )
+            stringConnectionMissing += ";";
+        stringConnectionMissing = "UID:" + tr("User ID") + "=?";
     }
     /* do we have a PWD attribute? */
     if ( !hashKeywordValues.contains( "PWD" ) )
     {
-        if ( !stringOutConnection.isEmpty() )
-            stringOutConnection += ";";
-        stringOutConnection = "PWD:" + tr("Password") + "=?";
+        if ( !stringConnectionMissing.isEmpty() )
+            stringConnectionMissing += ";";
+        stringConnectionMissing = "PWD:" + tr("Password") + "=?";
     }
     /* do we have a DATABASE attribute? */
     if ( !hashKeywordValues.contains( "DATABASE" ) )
     {
-        if ( !stringOutConnection.isEmpty() )
-            stringOutConnection += ";";
+        if ( !stringConnectionMissing.isEmpty() )
+            stringConnectionMissing += ";";
         /*!
             \internal
             \todo
 
             We should connect with SERVER+UID+PWD and get list of databases. In which
case we should use a list
             of databases surrounded by curly braces - instead of ?.
+
+            For example; "DATABASE:Database={mysql,test}"
         */
-        stringOutConnection = "DATABASE:" + tr("Database") + "=?";
+        stringConnectionMissing = "DATABASE:" + tr("Database") + "=?";
     }
 
+    /* are we missing mandatory attributes? */
+    if ( !stringConnectionMissing.isEmpty() )
+    {
+        /*!
+            \internal ODBC RULE
 
+            Each call to SQLBrowseConnect() returns only the information required to
satisfy the next level of 
+            the connection process. DB2 CLI associates state information with the
connection handle so that the 
+            context can always be determined on each call.
+        */
+        /*!
+            \internal ODBC RULE
 
-+++++++++
-    SQLRETURN nReturn = SQL_SUCCESS;
+            The buffer *OutConnectionString was not large enough to return the entire
browse result 
+            connection string, so the string was truncated. The buffer *StringLength2Ptr
contains 
+            the length of the untruncated browse result connection string. (Function
returns 
+            SQL_SUCCESS_WITH_INFO.)
 
-    if ( !stringOutConnection.isEmpty() )
-    {
+            \note
+
+            The caller must NOT assume that SQL_SUCCESS_WITH_INFO means we can proceed.
In this case we will
+            return SQL_SUCCESS_WITH_INFO and the caller must check that the length in
pnStringLength2Ptr is
+            not larger than nBufferLength.
+
+            \internal MYODBC RULE
+
+            We will return an error if pnStringLength2Ptr is not provided and we get a
truncation as it is
+            likely that the caller will catch the truncation (it would have to get our
state info to see
+            that we are, in fact, still wanting more data - STATE_C3).
+        */
+        SQLRETURN nReturn = SQL_NEED_DATA;
+
+        if ( !MYODBCC::doStringCopyOut( psOutConnectionString, nBufferLength /
sizeof(SQLWCHAR), (SQLWCHAR*)stringConnectionMissing.utf16(),
(SQLINTEGER*)pnStringLength2Ptr ) )
+        {
+            if ( !pnStringLength2Ptr )
+            {
+                MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_HY000, 0,
tr("Output buffer too small and length indicator buffer not provided.") ) );
+            }
+            else
+                nReturn = SQL_SUCCESS_WITH_INFO;
+        }
+
+        /* we want more data - regardless of the return value */
         setState( STATE_C3 );
-        nReturn = SQL_NEED_DATA;
+        MYODBCDbgReturn( nReturn );
     }
-    else
-    {
-    }
 
     /*!
+        \internal
+        \note
+
+        We want to be able to return SQL_SUCCESS_WITH_INFO without indicating a
truncation.
+    */
+    if ( pnStringLength2Ptr )
+        *pnStringLength2Ptr = 0;
+
+    /*!
         \internal ODBC RULE
 
-        The buffer *OutConnectionString was not large enough to return the entire browse
result 
-        connection string, so the string was truncated. The buffer *StringLength2Ptr
contains 
-        the length of the untruncated browse result connection string. (Function returns 
-        SQL_SUCCESS_WITH_INFO.)
+        The driver was unable to establish a connection with the data source.
     */
-    psOutConnectionString;
-    nBufferLength;
-    pnStringLength2Ptr;
+    if ( doConnectInternal( &datasource ) != SQL_SUCCESS )
+        MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_08001 ) );
 
-    MYODBCDbgReturn( nReturn );
+    MYODBCDbgReturn( SQL_SUCCESS );
 }
 
 SQLRETURN MConnection::doConnect( SQLWCHAR *psServerName, SQLSMALLINT nNameLength1,
SQLWCHAR *psUserName, SQLSMALLINT nNameLength2, SQLWCHAR *psAuthentication, SQLSMALLINT
nNameLength3 )

Thread
Connector/ODBC 5 commit: r485 - trunk/MYSQLPlus/MYSQLPlusLibpharvey11 Aug