[Libreoffice-commits] core.git: Branch 'private/ajrhunt/firebird-improvement' - 2 commits - connectivity/Library_firebird_sdbc.mk connectivity/source

Andrzej Hunt andrzej.hunt at collabora.com
Wed Mar 19 13:35:53 PDT 2014


Rebased ref, commits from common ancestor:
commit d0a9f440e6860a225c5a0ae6222fa96bbc312dbe
Author: Andrzej Hunt <andrzej.hunt at collabora.com>
Date:   Wed Mar 19 20:28:45 2014 +0000

    firebird-sdbc: upgrade Statement to use Sqlda wrapper.
    
    So much cleaner already :).
    
    Change-Id: I8d1709246d4cbcd3113fdd7d14c0885ddca37059

diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx
index d5e1213..3ddf3b5 100644
--- a/connectivity/source/drivers/firebird/PreparedStatement.cxx
+++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx
@@ -56,7 +56,6 @@ OPreparedStatement::OPreparedStatement( Connection* _pConnection,
     :OStatementCommonBase(_pConnection)
     ,m_aTypeInfo(_TypeInfo)
     ,m_sSqlStatement(sql)
-    ,m_pOutSqlda(0)
     ,m_pInSqlda(0)
 {
     SAL_INFO("connectivity.firebird", "OPreparedStatement(). "
@@ -82,8 +81,8 @@ void OPreparedStatement::ensurePrepared()
     }
 
     prepareAndDescribeStatement(m_sSqlStatement,
-                               m_pOutSqlda,
-                               m_pInSqlda);
+                                m_aOutSqlda,
+                                m_pInSqlda);
 
 
     aErr = isc_dsql_describe_bind(m_statusVector,
@@ -152,7 +151,7 @@ Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData()
     ensurePrepared();
 
     if(!m_xMetaData.is())
-        m_xMetaData = new OResultSetMetaData(m_pConnection, m_pOutSqlda);
+        m_xMetaData = new OResultSetMetaData(m_pConnection, &m_aOutSqlda);
 
     return m_xMetaData;
 }
@@ -169,12 +168,6 @@ void SAL_CALL OPreparedStatement::close() throw(SQLException, RuntimeException,
         free(m_pInSqlda);
         m_pInSqlda = 0;
     }
-    if (m_pOutSqlda)
-    {
-        freeSQLVAR(m_pOutSqlda);
-        free(m_pOutSqlda);
-        m_pOutSqlda = 0;
-    }
 }
 
 void SAL_CALL OPreparedStatement::disposing()
@@ -286,7 +279,7 @@ sal_Bool SAL_CALL OPreparedStatement::execute()
                                   m_aMutex,
                                   uno::Reference< XInterface >(*this),
                                   m_aStatementHandle,
-                                  m_pOutSqlda);
+                                  &m_aOutSqlda);
 
     if (getStatementChangeCount() > 0)
         m_pConnection->notifyDatabaseModified();
diff --git a/connectivity/source/drivers/firebird/PreparedStatement.hxx b/connectivity/source/drivers/firebird/PreparedStatement.hxx
index 90e89a8..688063a 100644
--- a/connectivity/source/drivers/firebird/PreparedStatement.hxx
+++ b/connectivity/source/drivers/firebird/PreparedStatement.hxx
@@ -21,6 +21,7 @@
 #define CONNECTIVITY_FIREBIRD_PREPAREDSTATEMENT_HXX
 
 #include "Statement.hxx"
+#include "wrapper/Sqlda.hxx"
 
 #include <cppuhelper/implbase5.hxx>
 
@@ -69,7 +70,7 @@ namespace connectivity
             ::rtl::OUString                                                                 m_sSqlStatement;
             ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData >  m_xMetaData;
 
-            XSQLDA*         m_pOutSqlda;
+            wrapper::Sqlda  m_aOutSqlda;
             XSQLDA*         m_pInSqlda;
             void checkParameterIndex(sal_Int32 nParameterIndex)
                 throw(::com::sun::star::sdbc::SQLException,
diff --git a/connectivity/source/drivers/firebird/Statement.cxx b/connectivity/source/drivers/firebird/Statement.cxx
index 94b9474..eb185a4 100644
--- a/connectivity/source/drivers/firebird/Statement.cxx
+++ b/connectivity/source/drivers/firebird/Statement.cxx
@@ -34,6 +34,7 @@
 #include <com/sun/star/sdbc/FetchDirection.hpp>
 
 using namespace connectivity::firebird;
+using namespace connectivity::firebird::wrapper;
 
 using namespace com::sun::star;
 using namespace com::sun::star::uno;
@@ -84,13 +85,6 @@ void OStatement::disposeResultSet()
     checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
 
     OStatementCommonBase::disposeResultSet();
-
-    if (m_pSqlda)
-    {
-        freeSQLVAR(m_pSqlda);
-        free(m_pSqlda);
-        m_pSqlda = 0;
-    }
 }
 
 // ---- XStatement -----------------------------------------------------------
@@ -115,7 +109,7 @@ uno::Reference< XResultSet > SAL_CALL OStatement::executeQuery(const OUString& s
     disposeResultSet();
 
     prepareAndDescribeStatement(sql,
-                                m_pSqlda);
+                                m_aSqlda);
 
     aErr = isc_dsql_execute(m_statusVector,
                             &m_pConnection->getTransaction(),
@@ -129,7 +123,7 @@ uno::Reference< XResultSet > SAL_CALL OStatement::executeQuery(const OUString& s
                                   m_aMutex,
                                   uno::Reference< XInterface >(*this),
                                   m_aStatementHandle,
-                                  m_pSqlda);
+                                  &m_aSqlda);
 
     // TODO: deal with cleanup
 
diff --git a/connectivity/source/drivers/firebird/Statement.hxx b/connectivity/source/drivers/firebird/Statement.hxx
index 15b81f2..ed18376 100644
--- a/connectivity/source/drivers/firebird/Statement.hxx
+++ b/connectivity/source/drivers/firebird/Statement.hxx
@@ -21,6 +21,7 @@
 #define CONNECTIVITY_FIREBIRD_STATEMENT_HXX
 
 #include "StatementCommonBase.hxx"
+#include "wrapper/Sqlda.hxx"
 
 #include <cppuhelper/implbase1.hxx>
 
@@ -40,13 +41,12 @@ namespace connectivity
         protected:
             virtual ~OStatement(){}
 
-            XSQLDA* m_pSqlda;
+            wrapper::Sqlda m_aSqlda;
 
         public:
             // a constructor, which is required for returning objects:
             OStatement( Connection* _pConnection)
-                : OStatementCommonBase( _pConnection),
-                  m_pSqlda(0)
+                : OStatementCommonBase( _pConnection)
             {}
 
             virtual void disposeResultSet();
diff --git a/connectivity/source/drivers/firebird/StatementCommonBase.cxx b/connectivity/source/drivers/firebird/StatementCommonBase.cxx
index 93770c2..8a12fa9 100644
--- a/connectivity/source/drivers/firebird/StatementCommonBase.cxx
+++ b/connectivity/source/drivers/firebird/StatementCommonBase.cxx
@@ -28,6 +28,7 @@
 #include <TConnection.hxx>
 
 using namespace ::connectivity::firebird;
+using namespace ::connectivity::firebird::wrapper;
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -123,35 +124,22 @@ void SAL_CALL OStatementCommonBase::close()
 }
 
 void OStatementCommonBase::prepareAndDescribeStatement(const OUString& sql,
-                                                      XSQLDA*& pOutSqlda,
-                                                      XSQLDA* pInSqlda)
+                                                       Sqlda& rOutSqlda,
+                                                       XSQLDA* pInSqlda)
     throw (SQLException)
 {
     MutexGuard aGuard(m_aMutex);
 
     freeStatementHandle();
 
-    if (!pOutSqlda)
-    {
-        pOutSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(10));
-        pOutSqlda->version = SQLDA_VERSION1;
-        pOutSqlda->sqln = 10;
-    }
-
     ISC_STATUS aErr = 0;
 
-    aErr = isc_dsql_allocate_statement(m_statusVector,
-                                       &m_pConnection->getDBHandle(),
-                                       &m_aStatementHandle);
-
-    if (aErr)
-    {
-        free(pOutSqlda);
-        pOutSqlda = 0;
+    if (isc_dsql_allocate_statement(m_statusVector,
+                                    &m_pConnection->getDBHandle(),
+                                    &m_aStatementHandle))
         evaluateStatusVector(m_statusVector,
                              "isc_dsql_allocate_statement",
                              *this);
-    }
 
     aErr = isc_dsql_prepare(m_statusVector,
                             &m_pConnection->getTransaction(),
@@ -164,49 +152,12 @@ void OStatementCommonBase::prepareAndDescribeStatement(const OUString& sql,
     if (aErr)
     {
         // TODO: free statement handle?
-        free(pOutSqlda);
-        pOutSqlda = 0;
         evaluateStatusVector(m_statusVector,
                              "isc_dsql_prepare",
                              *this);
     }
 
-    aErr = isc_dsql_describe(m_statusVector,
-                             &m_aStatementHandle,
-                             1,
-                             pOutSqlda);
-
-
-    if (aErr)
-    {
-        // TODO: free statement handle, etc.?
-        free(pOutSqlda);
-        pOutSqlda = 0;
-        evaluateStatusVector(m_statusVector,
-                             "isc_dsql_describe",
-                             *this);
-    }
-
-    // Ensure we have enough space in pOutSqlda
-    if (pOutSqlda->sqld > pOutSqlda->sqln)
-    {
-        int n = pOutSqlda->sqld;
-        free(pOutSqlda);
-        pOutSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(n));
-        pOutSqlda->version = SQLDA_VERSION1;
-        aErr = isc_dsql_describe(m_statusVector,
-                                 &m_aStatementHandle,
-                                 1,
-                                 pOutSqlda);
-    }
-
-    // Process each XSQLVAR parameter structure in the output XSQLDA
-    if (aErr)
-        evaluateStatusVector(m_statusVector,
-                             "isc_dsql_describe",
-                             *this);
-
-    mallocSQLVAR(pOutSqlda);
+    rOutSqlda.describeStatement(m_aStatementHandle);
 }
 
 // ---- XMultipleResults - UNSUPPORTED ----------------------------------------
diff --git a/connectivity/source/drivers/firebird/StatementCommonBase.hxx b/connectivity/source/drivers/firebird/StatementCommonBase.hxx
index b1e0411..edd2016 100644
--- a/connectivity/source/drivers/firebird/StatementCommonBase.hxx
+++ b/connectivity/source/drivers/firebird/StatementCommonBase.hxx
@@ -21,6 +21,7 @@
 #define CONNECTIVITY_FIREBIRD_STATEMENT_BASE_HXX
 
 #include "Connection.hxx"
+#include "wrapper/Sqlda.hxx"
 
 #include <ibase.h>
 
@@ -90,7 +91,7 @@ namespace connectivity
             virtual ~OStatementCommonBase();
 
             void prepareAndDescribeStatement(const OUString& sqlIn,
-                                             XSQLDA*& pOutSqlda,
+                                             wrapper::Sqlda& aOutSqlda,
                                              XSQLDA* pInSqlda=0)
                 throw (::com::sun::star::sdbc::SQLException);
 
commit c9eeb8b93f06d890c363f6f264d19b4fcdcd67dc
Author: Andrzej Hunt <andrzej.hunt at collabora.com>
Date:   Wed Mar 19 20:15:11 2014 +0000

    firebird-sdbc: Implement XSQLDA wrapper.
    
    Should hopefully help cleanup some of the madness when dealing
    with XSQLDAs manually.
    
    Change-Id: Ia8a477c08fc8d3b66cae11766551d396b881e4bf

diff --git a/connectivity/Library_firebird_sdbc.mk b/connectivity/Library_firebird_sdbc.mk
index 3f46e6e..0ad7611 100644
--- a/connectivity/Library_firebird_sdbc.mk
+++ b/connectivity/Library_firebird_sdbc.mk
@@ -18,6 +18,7 @@ $(eval $(call gb_Library_use_externals,firebird_sdbc,\
 
 $(eval $(call gb_Library_set_include,firebird_sdbc,\
 	-I$(SRCDIR)/connectivity/source/inc \
+	-I$(SRCDIR)/connectivity/source/drivers/firebird \
 	$$(INCLUDE) \
 	-I$(WORKDIR)/YaccTarget/connectivity/source/parse \
 ))
@@ -57,6 +58,7 @@ $(eval $(call gb_Library_add_exception_objects,firebird_sdbc,\
     connectivity/source/drivers/firebird/User \
     connectivity/source/drivers/firebird/Users \
     connectivity/source/drivers/firebird/Util \
+    connectivity/source/drivers/firebird/wrapper/Sqlda \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/connectivity/source/drivers/firebird/wrapper/Sqlda.cxx b/connectivity/source/drivers/firebird/wrapper/Sqlda.cxx
new file mode 100644
index 0000000..9cca23d
--- /dev/null
+++ b/connectivity/source/drivers/firebird/wrapper/Sqlda.cxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "Sqlda.hxx"
+#include "Driver.hxx"
+#include "Util.hxx"
+
+#include <assert.h>
+#include <cstdlib>
+
+#include <sal/log.hxx>
+
+using namespace ::connectivity::firebird;
+using namespace ::connectivity::firebird::wrapper;
+
+XSQLDA* lcl_allocateSqlda(unsigned int nLength)
+{
+    // We specifically calloc so that all the sqlvar->sqldata pointers are null
+    // allowing us to easily track whether they have been allocated or not.
+    XSQLDA* pSqlda = (XSQLDA*) calloc(1, XSQLDA_LENGTH(nLength));
+    pSqlda->version = SQLDA_VERSION1;
+    pSqlda->sqln = nLength;
+    return pSqlda;
+}
+
+void lcl_allocateSQLVAR(XSQLDA* pSqlda)
+{
+    XSQLVAR* pVar = pSqlda->sqlvar;
+    for (int i=0; i < pSqlda->sqld; i++, pVar++)
+    {
+        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
+        switch(dtype) {
+        case SQL_TEXT:
+            pVar->sqldata = (char*) malloc(sizeof(char)*pVar->sqllen);
+            break;
+        case SQL_VARYING:
+            // First two bytes define the length of string actually present,
+            // then we can have up to sqllen bytes of text.
+            pVar->sqldata = (char*) malloc(sizeof(char)*pVar->sqllen + 2);
+            break;
+        case SQL_SHORT:
+            pVar->sqldata = (char*) malloc(sizeof(sal_Int16));
+            break;
+        case SQL_LONG:
+            pVar->sqldata = (char*) malloc(sizeof(sal_Int32));
+            break;
+        case SQL_FLOAT:
+            pVar->sqldata = (char*) malloc(sizeof(float));
+            break;
+        case SQL_DOUBLE:
+            pVar->sqldata = (char*) malloc(sizeof(double));
+            break;
+        case SQL_D_FLOAT:
+            pVar->sqldata = (char*) malloc(sizeof(double));
+            break;
+        case SQL_TIMESTAMP:
+            pVar->sqldata = (char*) malloc(sizeof(ISC_TIMESTAMP));
+            break;
+        case SQL_BLOB:
+            pVar->sqldata = (char*) malloc(sizeof(ISC_QUAD));
+            break;
+        case SQL_ARRAY:
+            assert(false); // TODO: implement
+            break;
+        case SQL_TYPE_TIME:
+            pVar->sqldata = (char*) malloc(sizeof(ISC_TIME));
+            break;
+        case SQL_TYPE_DATE:
+            pVar->sqldata = (char*) malloc(sizeof(ISC_DATE));
+            break;
+        case SQL_INT64:
+            pVar->sqldata = (char *)malloc(sizeof(sal_Int64));
+            break;
+        case SQL_NULL:
+            assert(false); // TODO: implement
+            break;
+        case SQL_QUAD:
+            assert(false); // TODO: implement
+            break;
+        default:
+            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
+            assert(false);
+            break;
+        }
+        if (pVar->sqltype & 1)
+        {
+            /* allocate variable to hold NULL status */
+            pVar->sqlind = (short*) malloc(sizeof(short));
+        }
+    }
+}
+void lcl_freeSQLVAR(XSQLDA* pSqlda)
+{
+    XSQLVAR* pVar = pSqlda->sqlvar;
+    for (int i=0; i < pSqlda->sqld; i++, pVar++)
+    {
+        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
+        switch(dtype) {
+        case SQL_TEXT:
+        case SQL_VARYING:
+        case SQL_SHORT:
+        case SQL_LONG:
+        case SQL_FLOAT:
+        case SQL_DOUBLE:
+        case SQL_D_FLOAT:
+        case SQL_TIMESTAMP:
+        case SQL_BLOB:
+        case SQL_INT64:
+        case SQL_TYPE_TIME:
+        case SQL_TYPE_DATE:
+            free(pVar->sqldata);
+            break;
+        case SQL_ARRAY:
+            assert(false); // TODO: implement
+            break;
+        case SQL_NULL:
+            assert(false); // TODO: implement
+            break;
+        case SQL_QUAD:
+            assert(false); // TODO: implement
+            break;
+        default:
+            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
+            assert(false);
+            break;
+        }
+
+        if (pVar->sqltype & 1)
+        {
+            free(pVar->sqlind);
+        }
+    }
+}
+
+Sqlda::Sqlda()
+    : mpSqlda(0)
+{
+}
+
+Sqlda::~Sqlda()
+{
+    if (mpSqlda)
+    {
+        lcl_freeSQLVAR(mpSqlda);
+        free(mpSqlda);
+    }
+}
+
+void Sqlda::describeStatement(isc_stmt_handle& aStatementHandle)
+{
+    if (!mpSqlda)
+    {
+        mpSqlda = lcl_allocateSqlda(DEFAULT_SQLDA_SIZE);
+    }
+    else
+    {
+        // types might change, hence we need to completely wipe the
+        // sqldatas.
+        lcl_freeSQLVAR(mpSqlda);
+    }
+
+    try
+    {
+        ISC_STATUS_ARRAY aStatusVector;
+
+        if (isc_dsql_describe(aStatusVector,
+                              &aStatementHandle,
+                              FIREBIRD_SQL_DIALECT,
+                              mpSqlda))
+            evaluateStatusVector(aStatusVector, "isc_dsql_describe", 0);
+
+        // We cannot know how much space we need until after the first call of
+        // isc_dsql_describe -- hence we need to check we have enough space
+        // afterwards, and reallocate as necessary.
+        if (mpSqlda->sqld > mpSqlda->sqln)
+        {
+            free(mpSqlda);
+            mpSqlda = lcl_allocateSqlda(mpSqlda->sqld);
+        }
+
+        if (isc_dsql_describe(aStatusVector,
+                              &aStatementHandle,
+                              FIREBIRD_SQL_DIALECT,
+                              mpSqlda))
+            evaluateStatusVector(aStatusVector, "isc_dsql_describe", 0);
+
+        lcl_allocateSQLVAR(mpSqlda);
+    }
+    catch (::com::sun::star::sdbc::SQLException e)
+    {
+        // We specifically free the sqlda since we are at an incomplete state
+        // where the sqlda might be partially populated, and the sqlvar's
+        // may or may not be allocated -- it is simplest to ensure consistency
+        // by freeing the sqlda unless we have successfully described it
+        // and allocated all sqlvars in it.
+        free(mpSqlda);
+        mpSqlda = 0;
+        throw e;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/connectivity/source/drivers/firebird/wrapper/Sqlda.hxx b/connectivity/source/drivers/firebird/wrapper/Sqlda.hxx
new file mode 100644
index 0000000..0c395db
--- /dev/null
+++ b/connectivity/source/drivers/firebird/wrapper/Sqlda.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef CONNECTIVITY_FIREBIRD_WRAPPER_SQLDA_HXX
+#define CONNECTIVITY_FIREBIRD_WRAPPER_SQLDA_HXX
+
+#include <ibase.h>
+
+namespace connectivity
+{
+    namespace firebird
+    {
+        namespace wrapper
+        {
+           /*
+            * Default sqlvar length that we allocate.
+            */
+            static const unsigned int DEFAULT_SQLDA_SIZE = 10;
+
+            class Sqlda
+            {
+            private:
+                XSQLDA* mpSqlda;
+
+            public:
+                Sqlda();
+                ~Sqlda();
+                XSQLDA* operator&() { return mpSqlda; };
+
+                /**
+                 * Set up the Sqlda for a given statement, is equivalent to
+                 * using isc_dsql_describe, but with all the details handled
+                 * within.
+                 */
+                void describeStatement(isc_stmt_handle& aStatementHandle);
+            };
+        }
+    }
+}
+
+#endif // CONNECTIVITY_FIREBIRD_WRAPPER_SQLDA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file


More information about the Libreoffice-commits mailing list