[Libreoffice-commits] core.git: connectivity/source

Tamas Bunth tamas.bunth at collabora.co.uk
Thu Dec 28 09:40:12 UTC 2017


 connectivity/source/drivers/firebird/DatabaseMetaData.cxx  |   86 +++---
 connectivity/source/drivers/firebird/ResultSetMetaData.cxx |   58 +++-
 connectivity/source/drivers/firebird/ResultSetMetaData.hxx |    1 
 connectivity/source/drivers/firebird/Tables.cxx            |   15 +
 connectivity/source/drivers/firebird/Util.cxx              |  185 ++++++-------
 connectivity/source/drivers/firebird/Util.hxx              |   39 ++
 6 files changed, 245 insertions(+), 139 deletions(-)

New commits:
commit bf662904c4b60e93c6b86e06288d41996eed12a2
Author: Tamas Bunth <tamas.bunth at collabora.co.uk>
Date:   Sat Dec 16 12:57:43 2017 +0100

    tdf#104734 Firebird: Add Binary (fix) type
    
    There is no explicit binary type in Firebird. It can be accomplished
    using the CHAR type with a special character set, which tells the
    database that it is binary data and there is no collation. (called
    OCTETS).
    
    Because of that, we also need the character set to decide the exact
    column type.
    
    And also refactor some parts of the driver:
    - Create class to determine internal type from firebird type, subtype,
    scale and character set.
    - Use internal type (DataType::XXX) in XDatabaseMetaData::getTypeInfo()
    indirectly. (We want to return a Firebird type for each internal type,
    not in the opposite direction.
    
    Change-Id: Ica56a84d89253e11936e7012086fe1d9f61a65f0
    Reviewed-on: https://gerrit.libreoffice.org/47091
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tamás Bunth <btomi96 at gmail.com>

diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
index 92e46c8ba95d..dcb617363692 100644
--- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
+++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
@@ -827,9 +827,9 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aRow[17] = new ORowSetValueDecorator();             // Unused
         aRow[18] = new ORowSetValueDecorator(sal_Int16(10));// Radix
 
-        // SQL_TEXT
+        // Char
         aRow[1] = new ORowSetValueDecorator(OUString("CHAR"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::CHAR);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -839,9 +839,9 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale
         aResults.push_back(aRow);
 
-        // SQL_VARYING
+        // Varchar
         aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -851,6 +851,18 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale
         aResults.push_back(aRow);
 
+        // Binary (CHAR)
+        // It is distinguished from Text type by its character set
+        aRow[1] = new ORowSetValueDecorator(OUString("CHAR"));
+        aRow[2] = new ORowSetValueDecorator(DataType::BINARY);
+        aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length
+        aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
+        aRow[9] = new ORowSetValueDecorator(
+                sal_Int16(ColumnSearch::NONE)); // Searchable
+        aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale
+        aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale
+        aResults.push_back(aRow);
+
         // Integer Types common
         {
             aRow[6] = new ORowSetValueDecorator(); // Create Params
@@ -860,19 +872,19 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
             aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale
             aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale
         }
-        // SQL_SHORT
+        // Smallint (SQL_SHORT)
         aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::SMALLINT);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision
         aResults.push_back(aRow);
-        // SQL_LONG
+        // Integer (SQL_LONG)
         aRow[1] = new ORowSetValueDecorator(OUString("INTEGER"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_LONG, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::INTEGER);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision
         aResults.push_back(aRow);
-        // SQL_INT64
+        // Bigint (SQL_INT64)
         aRow[1] = new ORowSetValueDecorator(OUString("BIGINT"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_INT64, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::BIGINT);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision
         aResults.push_back(aRow);
 
@@ -884,14 +896,14 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         }
 
         aRow[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params
-        // NUMERIC
+        // Numeric
         aRow[1] = new ORowSetValueDecorator(OUString("NUMERIC"));
         aRow[2] = new ORowSetValueDecorator(DataType::NUMERIC);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
         aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
         aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale
         aResults.push_back(aRow);
-        // DECIMAL
+        // Decimal
         aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL"));
         aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
@@ -900,34 +912,26 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aResults.push_back(aRow);
 
         aRow[6] = new ORowSetValueDecorator(); // Create Params
-        // SQL_FLOAT
+        // Float (SQL_FLOAT)
         aRow[1] = new ORowSetValueDecorator(OUString("FLOAT"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::FLOAT);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(7)); // Precision
         aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
         aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale
         aResults.push_back(aRow);
-        // SQL_DOUBLE
+        // Double (SQL_DOUBLE)
         aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_DOUBLE, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE);
         aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
         aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
         aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale
         aResults.push_back(aRow);
 
-//         // SQL_D_FLOAT
-//         aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0, 0));
-//         aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 0, 0));
-//         aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
-//         aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
-//         aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale
-//         aResults.push_back(aRow);
         // TODO: no idea whether D_FLOAT corresponds to an sql type
 
         // SQL_TIMESTAMP
-        // TODO: precision?
         aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TIMESTAMP, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP);
         aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -938,9 +942,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aResults.push_back(aRow);
 
         // SQL_TYPE_TIME
-        // TODO: precision?
         aRow[1] = new ORowSetValueDecorator(OUString("TIME"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_TIME, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::TIME);
         aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -951,9 +954,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aResults.push_back(aRow);
 
         // SQL_TYPE_DATE
-        // TODO: precision?
         aRow[1] = new ORowSetValueDecorator(OUString("DATE"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_DATE, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::DATE);
         aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -964,9 +966,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aResults.push_back(aRow);
 
         // SQL_BLOB
-        // TODO: precision?
         aRow[1] = new ORowSetValueDecorator(OUString("BLOB"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BLOB, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::BLOB);
         aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -977,9 +978,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aResults.push_back(aRow);
 
         // SQL_BOOLEAN
-        // TODO FIXME precision
         aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN"));
-        aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BOOLEAN, 0, 0));
+        aRow[2] = new ORowSetValueDecorator(DataType::BOOLEAN);
         aRow[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length
         aRow[6] = new ORowSetValueDecorator(); // Create Params
         aRow[9] = new ORowSetValueDecorator(
@@ -989,10 +989,6 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
         aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale
         aResults.push_back(aRow);
 
-        // TODO: complete
-//     case SQL_ARRAY:
-//     case SQL_NULL:
-//     case SQL_QUAD:      // Is a "Blob ID" according to the docs
     }
     pResultSet->setRows(aResults);
     return xResultSet;
@@ -1099,10 +1095,13 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
         // this is also the one we manually fiddle when changin NULL/NOT NULL
         // (see Table.cxx)
         "relfields.RDB$NULL_FLAG, "      // 11
-        "fields.RDB$CHARACTER_LENGTH "   // 12
+        "fields.RDB$CHARACTER_LENGTH, "   // 12
+        "charset.RDB$CHARACTER_SET_NAME " // 13
         "FROM RDB$RELATION_FIELDS relfields "
         "JOIN RDB$FIELDS fields "
         "on (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) "
+        "LEFT JOIN RDB$CHARACTER_SETS charset "
+        "on (fields.RDB$CHARACTER_SET_ID = charset.RDB$CHARACTER_SET_ID) "
         "WHERE (1 = 1) ");
 
     if (!tableNamePattern.isEmpty())
@@ -1152,11 +1151,16 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
         aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2)));
         // 5. Datatype
         short aType = getFBTypeFromBlrType(xRow->getShort(6));
-        short aSubType = xRow->getShort(7);
         short aScale = xRow->getShort(10);
-        aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType, aSubType, aScale));
+        OUString sCharsetName = xRow->getString(13);
+        // result field may be filled with spaces
+        sCharsetName = sCharsetName.trim();
+        ColumnTypeInfo aInfo(aType, xRow->getShort(7), aScale,
+                xRow->getString(13));
+
+        aCurrentRow[5] = new ORowSetValueDecorator(aInfo.getSdbcType());
         // 6. Typename (SQL_*)
-        aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType, aScale));
+        aCurrentRow[6] = new ORowSetValueDecorator(aInfo.getColumnTypeName());
 
         // 7. Column Sizes
         {
diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
index e5ba68a3bd72..725ed288d00a 100644
--- a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
+++ b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
@@ -39,6 +39,39 @@ OResultSetMetaData::~OResultSetMetaData()
 {
 }
 
+OUString OResultSetMetaData::getCharacterSet( sal_Int32 nIndex )
+{
+    OUString sTable = getTableName( nIndex );
+    if( !sTable.isEmpty() )
+    {
+        OUString sColumnName = getColumnName( nIndex );
+
+        OUString sSql = "SELECT charset.RDB$CHARACTER_SET_NAME "
+                        "FROM RDB$CHARACTER_SETS charset "
+                        "JOIN RDB$FIELDS fields "
+                        "ON (fields.RDB$CHARACTER_SET_ID = charset.RDB$CHARACTER_SET_ID) "
+                        "JOIN RDB$RELATION_FIELDS relfields "
+                        "ON (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) "
+                        "WHERE relfields.RDB$RELATION_NAME = '"
+                   + escapeWith(sTable, '\'', '\'') + "' AND "
+                   "relfields.RDB$FIELD_NAME = '"+ escapeWith(sColumnName, '\'', '\'') +"'";
+
+        Reference<XStatement> xStmt= m_pConnection->createStatement();
+
+        Reference<XResultSet> xRes =
+                xStmt->executeQuery(sSql);
+        Reference<XRow> xRow ( xRes, UNO_QUERY);
+        if(xRes->next())
+        {
+            OUString sCharset = xRow->getString(1).trim();
+            return sCharset;
+        }
+    }
+    return OUString();
+
+
+}
+
 void OResultSetMetaData::verifyValidColumn(sal_Int32 column)
 {
     if (column>getColumnCount() || column < 1)
@@ -60,11 +93,20 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column)
 {
     verifyValidColumn(column);
 
-    short aType = m_pSqlda->sqlvar[column-1].sqltype;
-    short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype;
-    short aScale = m_pSqlda->sqlvar[column-1].sqlscale;
+    short aType = m_pSqlda->sqlvar[column-1].sqltype & ~1;
+    OUString sCharset;
+
+    if(aType == SQL_TEXT)
+    {
+        sCharset = getCharacterSet(column);
+    }
+
+    ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype,
+            m_pSqlda->sqlvar[column-1].sqlsubtype,
+            m_pSqlda->sqlvar[column-1].sqlscale,
+            sCharset );
 
-    return getColumnTypeFromFBType(aType, aSubType, aScale);
+    return aInfo.getSdbcType();
 }
 
 sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32)
@@ -109,11 +151,11 @@ OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column)
 {
     verifyValidColumn(column);
 
-    short aType = m_pSqlda->sqlvar[column-1].sqltype;
-    short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype;
-    short aScale = m_pSqlda->sqlvar[column-1].sqlscale;
+    ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype,
+            m_pSqlda->sqlvar[column-1].sqlsubtype,
+            m_pSqlda->sqlvar[column-1].sqlscale );
 
-    return getColumnTypeNameFromFBType(aType, aSubType, aScale);
+    return aInfo.getColumnTypeName();
 }
 
 OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column)
diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.hxx b/connectivity/source/drivers/firebird/ResultSetMetaData.hxx
index d6dffe0cd708..1b134a0628fd 100644
--- a/connectivity/source/drivers/firebird/ResultSetMetaData.hxx
+++ b/connectivity/source/drivers/firebird/ResultSetMetaData.hxx
@@ -45,6 +45,7 @@ namespace connectivity
 
             /// @throws css::sdbc::SQLException
             void verifyValidColumn(sal_Int32 column);
+            OUString getCharacterSet(sal_Int32 nIndex);
         public:
             // a constructor, which is required for returning objects:
             OResultSetMetaData(Connection* pConnection,
diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx
index f1423763ab16..afc68fca93f5 100644
--- a/connectivity/source/drivers/firebird/Tables.cxx
+++ b/connectivity/source/drivers/firebird/Tables.cxx
@@ -92,6 +92,21 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP
 
     aSql.append(dbtools::createStandardTypePart(xColProp, _xConnection));
 
+    // Add character set for BINARY (fix) type:
+    // BINARY is distinguished from other CHAR types by its character set.
+    // Octets is a special character set for binary data.
+    if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(
+                    PROPERTY_ID_TYPE)) )
+    {
+        sal_Int32 aType = 0;
+        xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE))
+            >>= aType;
+        if(aType == DataType::BINARY)
+        {
+            aSql.append(" ");
+            aSql.append("CHARACTER SET OCTETS");
+        }
+    }
 
     if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty())
     {
diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx
index e30a7a9b41f8..20587e5172ba 100644
--- a/connectivity/source/drivers/firebird/Util.cxx
+++ b/connectivity/source/drivers/firebird/Util.cxx
@@ -17,6 +17,8 @@ using namespace ::com::sun::star;
 using namespace ::com::sun::star::sdbc;
 using namespace ::com::sun::star::uno;
 
+using namespace firebird;
+
 OUString firebird::sanitizeIdentifier(const OUString& rIdentifier)
 {
     OUString sRet = rIdentifier.trim();
@@ -64,41 +66,76 @@ void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY& rStatusVector,
     }
 }
 
-sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short aScale)
+sal_Int32 lcl_getNumberType( short aType, NumberSubType aSubType )
+{
+    switch(aSubType)
+    {
+        case NumberSubType::Numeric:
+            return DataType::NUMERIC;
+        case NumberSubType::Decimal:
+            return DataType::DECIMAL;
+        default:
+            switch(aType)
+            {
+                case SQL_SHORT:
+                    return DataType::SMALLINT;
+                case SQL_LONG:
+                    return DataType::INTEGER;
+                case SQL_DOUBLE:
+                    return DataType::DOUBLE;
+                case SQL_INT64:
+                    return DataType::BIGINT;
+                default:
+                    assert(false); // not a number
+                    return 0;
+            }
+    }
+}
+sal_Int32 lcl_getCharColumnType( short aType, const OUString& sCharset )
+{
+    switch(aType)
+    {
+        case SQL_TEXT:
+            if( sCharset == "OCTETS")
+                return DataType::BINARY;
+            else
+                return DataType::CHAR;
+        case SQL_VARYING: // TODO VARBINARY
+            return DataType::VARCHAR;
+        default:
+            assert(false);
+            return 0;
+    }
+}
+
+sal_Int32 firebird::ColumnTypeInfo::getSdbcType() const
 {
-    aType &= ~1; // Remove last bit -- it is used to denote whether column
+    short aType = m_aType & ~1; // Remove last bit -- it is used to denote whether column
                  // can store Null, not needed for type determination
+    short aSubType = m_aSubType;
+    if( m_nScale > 0 )
+    {
+        // scale makes sense only for decimal and numeric types
+        assert(aType == SQL_SHORT || aType == SQL_LONG || aType == SQL_DOUBLE
+                || aType == SQL_INT64);
 
-    // if scale is set without subtype then imply numeric
-    if(aSubType == 0 && aScale < 0)
-        aSubType = 1;
+        // if scale is set without subtype then imply numeric
+        if( static_cast<NumberSubType>(aSubType) == NumberSubType::Other )
+            aSubType = static_cast<short>(NumberSubType::Numeric);
+    }
 
     switch (aType)
     {
     case SQL_TEXT:
-        return DataType::CHAR;
     case SQL_VARYING:
-        return DataType::VARCHAR;
+        return lcl_getCharColumnType(aType, m_sCharsetName);
     case SQL_SHORT:
-        if(aSubType == 1)
-            return DataType::NUMERIC;
-        if(aSubType == 2)
-            return DataType::DECIMAL;
-        return DataType::SMALLINT;
     case SQL_LONG:
-        if(aSubType == 1)
-            return DataType::NUMERIC;
-        if(aSubType == 2)
-            return DataType::DECIMAL;
-        return DataType::INTEGER;
+    case SQL_DOUBLE:
+    case SQL_INT64:
+        return lcl_getNumberType(aType, static_cast<NumberSubType>(aSubType) );
     case SQL_FLOAT:
         return DataType::FLOAT;
-    case SQL_DOUBLE:
-        if(aSubType == 1)
-            return DataType::NUMERIC;
-        if(aSubType == 2)
-            return DataType::DECIMAL;
-        return DataType::DOUBLE;
     case SQL_D_FLOAT:
         return DataType::DOUBLE;
     case SQL_TIMESTAMP:
@@ -121,12 +158,6 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short a
         return DataType::TIME;
     case SQL_TYPE_DATE:
         return DataType::DATE;
-    case SQL_INT64:
-        if(aSubType == 1)
-            return DataType::NUMERIC;
-        if(aSubType == 2)
-            return DataType::DECIMAL;
-        return DataType::BIGINT;
     case SQL_NULL:
         return DataType::SQLNULL;
     case SQL_QUAD:      // Is a "Blob ID" according to the docs
@@ -139,68 +170,48 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short a
     }
 }
 
-OUString firebird::getColumnTypeNameFromFBType(short aType, short aSubType, short aScale)
+OUString firebird::ColumnTypeInfo::getColumnTypeName() const
 {
-    aType &= ~1; // Remove last bit -- it is used to denote whether column
+    short aType = m_aType & ~1; // Remove last bit -- it is used to denote whether column
                 // can store Null, not needed for type determination
 
-    // if scale is set without subtype than imply numeric
-    if(aSubType == 0 && aScale < 0)
-        aSubType = 1;
-
-   switch (aType)
+    switch (aType)
     {
-    case SQL_TEXT:
-        return OUString("SQL_TEXT");
-    case SQL_VARYING:
-        return OUString("SQL_VARYING");
-    case SQL_SHORT:
-        if(aSubType == 1)
-            return OUString("SQL_NUMERIC");
-        if(aSubType == 2)
-            return OUString("SQL_DECIMAL");
-        return OUString("SQL_SHORT");
-    case SQL_LONG:
-        if(aSubType == 1)
-            return OUString("SQL_NUMERIC");
-        if(aSubType == 2)
-            return OUString("SQL_DECIMAL");
-        return OUString("SQL_LONG");
-    case SQL_FLOAT:
-        return OUString("SQL_FLOAT");
-    case SQL_DOUBLE:
-        if(aSubType == 1)
-            return OUString("SQL_NUMERIC");
-        if(aSubType == 2)
-            return OUString("SQL_DECIMAL");
-        return OUString("SQL_DOUBLE");
-    case SQL_D_FLOAT:
-        return OUString("SQL_D_FLOAT");
-    case SQL_TIMESTAMP:
-        return OUString("SQL_TIMESTAMP");
-    case SQL_BLOB:
-        return OUString("SQL_BLOB");
-    case SQL_ARRAY:
-        return OUString("SQL_ARRAY");
-    case SQL_TYPE_TIME:
-        return OUString("SQL_TYPE_TIME");
-    case SQL_TYPE_DATE:
-        return OUString("SQL_TYPE_DATE");
-    case SQL_INT64:
-        if(aSubType == 1)
-            return OUString("SQL_NUMERIC");
-        if(aSubType == 2)
-            return OUString("SQL_DECIMAL");
-        return OUString("SQL_INT64");
-    case SQL_NULL:
-        return OUString("SQL_NULL");
-    case SQL_QUAD:
-        return OUString("SQL_QUAD");
-    case SQL_BOOLEAN:
-        return OUString("SQL_BOOLEAN");
-    default:
-        assert(false); // Should never happen
-        return OUString();
+     case SQL_TEXT:
+         return OUString("SQL_TEXT");
+     case SQL_VARYING:
+         return OUString("SQL_VARYING");
+     case SQL_SHORT:
+         return OUString("SQL_SHORT");
+     case SQL_LONG:
+         return OUString("SQL_LONG");
+     case SQL_FLOAT:
+         return OUString("SQL_FLOAT");
+     case SQL_DOUBLE:
+         return OUString("SQL_DOUBLE");
+     case SQL_D_FLOAT:
+         return OUString("SQL_D_FLOAT");
+     case SQL_TIMESTAMP:
+         return OUString("SQL_TIMESTAMP");
+     case SQL_BLOB:
+         return OUString("SQL_BLOB");
+     case SQL_ARRAY:
+         return OUString("SQL_ARRAY");
+     case SQL_TYPE_TIME:
+         return OUString("SQL_TYPE_TIME");
+     case SQL_TYPE_DATE:
+         return OUString("SQL_TYPE_DATE");
+     case SQL_INT64:
+         return OUString("SQL_INT64");
+     case SQL_NULL:
+         return OUString("SQL_NULL");
+     case SQL_QUAD:
+         return OUString("SQL_QUAD");
+     case SQL_BOOLEAN:
+         return OUString("SQL_BOOLEAN");
+     default:
+         assert(false); // Should never happen
+         return OUString();
     }
 }
 
diff --git a/connectivity/source/drivers/firebird/Util.hxx b/connectivity/source/drivers/firebird/Util.hxx
index 1900ed4b87d1..2bf242ff441b 100644
--- a/connectivity/source/drivers/firebird/Util.hxx
+++ b/connectivity/source/drivers/firebird/Util.hxx
@@ -33,6 +33,42 @@ namespace connectivity
             Clob = 1
         };
 
+        // Numeric and decimal types can be identified by their subtype
+        // 1 for NUMERIC, 2 for DECIMAL
+        enum class NumberSubType {
+            Other = 0,
+            Numeric = 1,
+            Decimal = 2
+        };
+
+        class ColumnTypeInfo {
+private:
+            short m_aType;
+            short m_aSubType;
+            short m_nScale;
+            OUString m_sCharsetName;
+public:
+            explicit ColumnTypeInfo( short aType, short aSubType = 0,
+                    short nScale = 0, const OUString& sCharset = OUString() )
+                : m_aType(aType)
+                , m_aSubType(aSubType)
+                , m_nScale(nScale)
+                , m_sCharsetName(sCharset) {}
+            explicit ColumnTypeInfo( short aType, const OUString& sCharset )
+                : m_aType(aType)
+                , m_aSubType(0)
+                , m_nScale(0)
+                , m_sCharsetName(sCharset) {}
+            short getType() const { return m_aType; }
+            short getSubType() const { return m_aSubType; }
+            short getScale() const { return m_nScale; }
+            OUString getCharacterSet() const { return m_sCharsetName; }
+
+            sal_Int32 getSdbcType() const;
+            ::rtl::OUString getColumnTypeName() const;
+
+        };
+
         /**
          * Make sure an identifier is safe to use within the database. Currently
          * firebird seems to return identifiers with 93 character (instead of
@@ -62,9 +98,6 @@ namespace connectivity
                                   const ::rtl::OUString& aCause,
                                   const css::uno::Reference< css::uno::XInterface >& _rxContext);
 
-        sal_Int32 getColumnTypeFromFBType(short aType, short aSubType, short aScale);
-        ::rtl::OUString getColumnTypeNameFromFBType(short aType, short aSubType, short aScale);
-
         /**
          * Internally (i.e. in RDB$FIELD_TYPE) firebird stores the data type
          * for a column as defined in blr_*, however in the firebird


More information about the Libreoffice-commits mailing list