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()
// 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))
......
......@@ -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)
......
......@@ -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)
......
......@@ -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");
......
......@@ -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
......
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