Kaydet (Commit) 4a193d39 authored tarafından Tamás Bunth's avatar Tamás Bunth

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/33660Reviewed-by: 's avatarLionel Elie Mamane <lionel@mamane.lu>
Tested-by: 's avatarTamás Bunth <btomi96@gmail.com>
üst e7606f1f
...@@ -857,7 +857,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -857,7 +857,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_TEXT // SQL_TEXT
aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); 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[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -869,7 +869,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -869,7 +869,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_VARYING // SQL_VARYING
aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); 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[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -890,17 +890,17 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -890,17 +890,17 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
} }
// SQL_SHORT // SQL_SHORT
aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT")); 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 aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision
aResults.push_back(aRow); aResults.push_back(aRow);
// SQL_LONG // SQL_LONG
aRow[1] = new ORowSetValueDecorator(OUString("INTEGER")); 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 aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision
aResults.push_back(aRow); aResults.push_back(aRow);
// SQL_INT64 // SQL_INT64
aRow[1] = new ORowSetValueDecorator(OUString("BIGINT")); 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 aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision
aResults.push_back(aRow); aResults.push_back(aRow);
...@@ -930,22 +930,22 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -930,22 +930,22 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
// SQL_FLOAT // SQL_FLOAT
aRow[1] = new ORowSetValueDecorator(OUString("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[3] = new ORowSetValueDecorator(sal_Int16(7)); // Precision
aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale
aResults.push_back(aRow); aResults.push_back(aRow);
// SQL_DOUBLE // SQL_DOUBLE
aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION")); 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[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale
aResults.push_back(aRow); aResults.push_back(aRow);
// // SQL_D_FLOAT // // SQL_D_FLOAT
// aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0)); // aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0, 0));
// aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 0)); // aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 0, 0));
// aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision // aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision
// aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale // aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale
// aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale // aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale
...@@ -955,7 +955,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -955,7 +955,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_TIMESTAMP // SQL_TIMESTAMP
// TODO: precision? // TODO: precision?
aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP")); 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[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -968,7 +968,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -968,7 +968,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_TYPE_TIME // SQL_TYPE_TIME
// TODO: precision? // TODO: precision?
aRow[1] = new ORowSetValueDecorator(OUString("TIME")); 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[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -981,7 +981,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -981,7 +981,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_TYPE_DATE // SQL_TYPE_DATE
// TODO: precision? // TODO: precision?
aRow[1] = new ORowSetValueDecorator(OUString("DATE")); 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[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -994,7 +994,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -994,7 +994,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_BLOB // SQL_BLOB
// TODO: precision? // TODO: precision?
aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); 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[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -1007,7 +1007,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() ...@@ -1007,7 +1007,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
// SQL_BOOLEAN // SQL_BOOLEAN
// TODO FIXME precision // TODO FIXME precision
aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN")); 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[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length
aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[6] = new ORowSetValueDecorator(); // Create Params
aRow[9] = new ORowSetValueDecorator( aRow[9] = new ORowSetValueDecorator(
...@@ -1180,9 +1180,10 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( ...@@ -1180,9 +1180,10 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
// 5. Datatype // 5. Datatype
short aType = getFBTypeFromBlrType(xRow->getShort(6)); short aType = getFBTypeFromBlrType(xRow->getShort(6));
short aSubType = xRow->getShort(7); 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_*) // 6. Typename (SQL_*)
aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType)); aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType, aScale));
// 7. Column Sizes // 7. Column Sizes
{ {
...@@ -1216,7 +1217,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( ...@@ -1216,7 +1217,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
// 9. Decimal digits (scale) // 9. Decimal digits (scale)
// fb stores a negative number // fb stores a negative number
aCurrentRow[9] = new ORowSetValueDecorator( (sal_Int16) -(xRow->getShort(10)) ); aCurrentRow[9] = new ORowSetValueDecorator( (sal_Int16) -(aScale) );
// 11. Nullable // 11. Nullable
if (xRow->getShort(11)) if (xRow->getShort(11))
......
...@@ -447,6 +447,13 @@ ORowSetValue OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_S ...@@ -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 // Basically we just have to map to the correct direct request and
// ORowSetValue does the rest for us here. // ORowSetValue does the rest for us here.
int nSqlSubType = m_pSqlda->sqlvar[nColumnIndex-1].sqlsubtype; 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) switch (m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1)
{ {
case SQL_TEXT: case SQL_TEXT:
...@@ -577,9 +584,11 @@ OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT ...@@ -577,9 +584,11 @@ OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT
aLength, aLength,
RTL_TEXTENCODING_UTF8); RTL_TEXTENCODING_UTF8);
} }
else if ((aSqlType == SQL_SHORT || aSqlType == SQL_LONG else if ((aSqlType == SQL_SHORT || aSqlType == SQL_LONG ||
|| aSqlType == SQL_DOUBLE || aSqlType == SQL_INT64) aSqlType == SQL_DOUBLE || aSqlType == SQL_INT64)
&& (aSqlSubType == 1 || aSqlSubType == 2)) && (aSqlSubType == 1 ||
aSqlSubType == 2 ||
(aSqlSubType == 0 && m_pSqlda->sqlvar[nColumnIndex-1].sqlscale < 0) ) )
{ {
// decimal and numeric types // decimal and numeric types
switch(aSqlType) switch(aSqlType)
......
...@@ -62,8 +62,9 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column) ...@@ -62,8 +62,9 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column)
short aType = m_pSqlda->sqlvar[column-1].sqltype; short aType = m_pSqlda->sqlvar[column-1].sqltype;
short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype; 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) sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column)
...@@ -113,8 +114,9 @@ OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column) ...@@ -113,8 +114,9 @@ OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column)
short aType = m_pSqlda->sqlvar[column-1].sqltype; short aType = m_pSqlda->sqlvar[column-1].sqltype;
short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype; 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) OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column)
......
...@@ -64,10 +64,15 @@ void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY& rStatusVector, ...@@ -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 aType &= ~1; // Remove last bit -- it is used to denote whether column
// can store Null, not needed for type determination // 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) switch (aType)
{ {
case SQL_TEXT: case SQL_TEXT:
...@@ -134,11 +139,16 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType) ...@@ -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 aType &= ~1; // Remove last bit -- it is used to denote whether column
// can store Null, not needed for type determination // 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: case SQL_TEXT:
return OUString("SQL_TEXT"); return OUString("SQL_TEXT");
......
...@@ -62,8 +62,8 @@ namespace connectivity ...@@ -62,8 +62,8 @@ namespace connectivity
const ::rtl::OUString& aCause, const ::rtl::OUString& aCause,
const css::uno::Reference< css::uno::XInterface >& _rxContext); const css::uno::Reference< css::uno::XInterface >& _rxContext);
sal_Int32 getColumnTypeFromFBType(short aType, short aSubType); sal_Int32 getColumnTypeFromFBType(short aType, short aSubType, short aScale);
::rtl::OUString getColumnTypeNameFromFBType(short aType, short aSubType); ::rtl::OUString getColumnTypeNameFromFBType(short aType, short aSubType, short aScale);
/** /**
* Internally (i.e. in RDB$FIELD_TYPE) firebird stores the data type * Internally (i.e. in RDB$FIELD_TYPE) firebird stores the data type
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment