diff options
author | Tamás Bunth <btomi96@gmail.com> | 2017-01-29 14:26:16 +0100 |
---|---|---|
committer | Tamás Bunth <btomi96@gmail.com> | 2017-01-30 14:57:40 +0000 |
commit | 4a193d39fb785c75668c977cf6b40d11b0ef4afe (patch) | |
tree | 626c25dc18f925d948b67c2e9eedf392837cd057 /connectivity | |
parent | e7606f1f19b2970f0160075f56d4d97029f1e47a (diff) |
tdf#105101 check scale to determine subtype
For computed decimal/numeric values firebird's subtype remains 0. In
this case we check for the scale of column. If it is not 0 (negative),
than imply numeric.
Change-Id: Ie5a023d165852fe402b3b4cac817b0bbef58e7cd
Reviewed-on: https://gerrit.libreoffice.org/33660
Reviewed-by: Lionel Elie Mamane <lionel@mamane.lu>
Tested-by: Tamás Bunth <btomi96@gmail.com>
Diffstat (limited to 'connectivity')
5 files changed, 49 insertions, 27 deletions
diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index 66d9783ba9cd..e773e09b41eb 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -857,7 +857,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_TEXT aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -869,7 +869,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_VARYING aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -890,17 +890,17 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() } // SQL_SHORT aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision aResults.push_back(aRow); // SQL_LONG aRow[1] = new ORowSetValueDecorator(OUString("INTEGER")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_LONG, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_LONG, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision aResults.push_back(aRow); // SQL_INT64 aRow[1] = new ORowSetValueDecorator(OUString("BIGINT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_INT64, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_INT64, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision aResults.push_back(aRow); @@ -930,22 +930,22 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[6] = new ORowSetValueDecorator(); // Create Params // SQL_FLOAT aRow[1] = new ORowSetValueDecorator(OUString("FLOAT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT, 0, 0)); 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 aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_DOUBLE, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_DOUBLE, 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); // // SQL_D_FLOAT -// aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0)); -// aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 0)); +// 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 @@ -955,7 +955,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_TIMESTAMP // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TIMESTAMP, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TIMESTAMP, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -968,7 +968,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_TYPE_TIME // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("TIME")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_TIME, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_TIME, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -981,7 +981,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_TYPE_DATE // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("DATE")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_DATE, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_DATE, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -994,7 +994,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_BLOB // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BLOB, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BLOB, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -1007,7 +1007,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // SQL_BOOLEAN // TODO FIXME precision aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BOOLEAN, 0)); + aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BOOLEAN, 0, 0)); aRow[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -1180,9 +1180,10 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( // 5. Datatype short aType = getFBTypeFromBlrType(xRow->getShort(6)); short aSubType = xRow->getShort(7); - aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType, aSubType)); + short aScale = xRow->getShort(10); + aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType, aSubType, aScale)); // 6. Typename (SQL_*) - aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType)); + aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType, aScale)); // 7. Column Sizes { @@ -1216,7 +1217,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( // 9. Decimal digits (scale) // fb stores a negative number - aCurrentRow[9] = new ORowSetValueDecorator( (sal_Int16) -(xRow->getShort(10)) ); + aCurrentRow[9] = new ORowSetValueDecorator( (sal_Int16) -(aScale) ); // 11. Nullable if (xRow->getShort(11)) diff --git a/connectivity/source/drivers/firebird/ResultSet.cxx b/connectivity/source/drivers/firebird/ResultSet.cxx index 4aebf25e810a..fb3e72675fab 100644 --- a/connectivity/source/drivers/firebird/ResultSet.cxx +++ b/connectivity/source/drivers/firebird/ResultSet.cxx @@ -447,6 +447,13 @@ ORowSetValue OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_S // Basically we just have to map to the correct direct request and // ORowSetValue does the rest for us here. int nSqlSubType = m_pSqlda->sqlvar[nColumnIndex-1].sqlsubtype; + + // TODO Firebird 3.0 does not set subtype (i.e. set to 0) for computed numeric/decimal value. + // It may change in the future. + // Imply numeric data type when subtype is 0 and scale is negative + if( nSqlSubType == 0 && m_pSqlda->sqlvar[nColumnIndex-1].sqlscale < 0 ) + nSqlSubType = 1; + switch (m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) { case SQL_TEXT: @@ -577,9 +584,11 @@ OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT aLength, RTL_TEXTENCODING_UTF8); } - else if ((aSqlType == SQL_SHORT || aSqlType == SQL_LONG - || aSqlType == SQL_DOUBLE || aSqlType == SQL_INT64) - && (aSqlSubType == 1 || aSqlSubType == 2)) + else if ((aSqlType == SQL_SHORT || aSqlType == SQL_LONG || + aSqlType == SQL_DOUBLE || aSqlType == SQL_INT64) + && (aSqlSubType == 1 || + aSqlSubType == 2 || + (aSqlSubType == 0 && m_pSqlda->sqlvar[nColumnIndex-1].sqlscale < 0) ) ) { // decimal and numeric types switch(aSqlType) diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx index 79262d8f1d70..498bbaee3087 100644 --- a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx +++ b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx @@ -62,8 +62,9 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 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; - return getColumnTypeFromFBType(aType, aSubType); + return getColumnTypeFromFBType(aType, aSubType, aScale); } sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column) @@ -113,8 +114,9 @@ OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 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; - return getColumnTypeNameFromFBType(aType, aSubType); + return getColumnTypeNameFromFBType(aType, aSubType, aScale); } OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column) diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx index bd84bba0c9a9..e30a7a9b41f8 100644 --- a/connectivity/source/drivers/firebird/Util.cxx +++ b/connectivity/source/drivers/firebird/Util.cxx @@ -64,10 +64,15 @@ void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY& rStatusVector, } } -sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType) +sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short aScale) { 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 then imply numeric + if(aSubType == 0 && aScale < 0) + aSubType = 1; + switch (aType) { case SQL_TEXT: @@ -134,11 +139,16 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType) } } -OUString firebird::getColumnTypeNameFromFBType(short aType, short aSubType) +OUString firebird::getColumnTypeNameFromFBType(short aType, short aSubType, short aScale) { aType &= ~1; // Remove last bit -- it is used to denote whether column // can store Null, not needed for type determination - switch (aType) + + // if scale is set without subtype than imply numeric + if(aSubType == 0 && aScale < 0) + aSubType = 1; + + switch (aType) { case SQL_TEXT: return OUString("SQL_TEXT"); diff --git a/connectivity/source/drivers/firebird/Util.hxx b/connectivity/source/drivers/firebird/Util.hxx index b37b8718e9b8..dd0faf720b52 100644 --- a/connectivity/source/drivers/firebird/Util.hxx +++ b/connectivity/source/drivers/firebird/Util.hxx @@ -62,8 +62,8 @@ namespace connectivity const ::rtl::OUString& aCause, const css::uno::Reference< css::uno::XInterface >& _rxContext); - sal_Int32 getColumnTypeFromFBType(short aType, short aSubType); - ::rtl::OUString getColumnTypeNameFromFBType(short aType, short aSubType); + 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 |