WiP tdf#74172 use DECIMAL and NUMERIC data types
Change-Id: I917cdf6e8d3ebfa7c9e4a52ca61adc5b8707ecfc Reviewed-on: https://gerrit.libreoffice.org/30447 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Lionel Elie Mamane <lionel@mamane.lu>
This commit is contained in:
parent
9357e99450
commit
21cc1826c7
@ -24,6 +24,7 @@ Column::Column()
|
||||
|
||||
void Column::construct()
|
||||
{
|
||||
OColumn::construct();
|
||||
m_sAutoIncrement = "GENERATED BY DEFAULT AS IDENTITY";
|
||||
registerProperty(OMetaConnection::getPropMap().getNameByIndex(
|
||||
PROPERTY_ID_AUTOINCREMENTCREATION),
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <com/sun/star/sdbc/XRow.hpp>
|
||||
#include <com/sun/star/sdbc/KeyRule.hpp>
|
||||
#include <com/sun/star/sdbc/Deferrability.hpp>
|
||||
#include <com/sun/star/sdbc/DataType.hpp>
|
||||
|
||||
using namespace connectivity::firebird;
|
||||
using namespace com::sun::star;
|
||||
@ -902,7 +903,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
|
||||
|
||||
// SQL_TEXT
|
||||
aRow[1] = new ORowSetValueDecorator(OUString("CHAR"));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int16(32767)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -914,7 +915,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
|
||||
|
||||
// SQL_VARYING
|
||||
aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR"));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int16(32767)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -935,44 +936,62 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo()
|
||||
}
|
||||
// SQL_SHORT
|
||||
aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT"));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT, 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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_LONG, 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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_INT64, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision
|
||||
aResults.push_back(aRow);
|
||||
|
||||
// Decimal Types common
|
||||
{
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
sal_Int16(ColumnSearch::FULL)); // Searchable
|
||||
aRow[12] = new ORowSetValueDecorator(true); // Autoincrement
|
||||
}
|
||||
|
||||
aRow[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params
|
||||
// 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
|
||||
aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL"));
|
||||
aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL);
|
||||
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);
|
||||
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
// SQL_FLOAT
|
||||
aRow[1] = new ORowSetValueDecorator(OUString("FLOAT"));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT, 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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_DOUBLE, 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));
|
||||
// aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT));
|
||||
// aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0));
|
||||
// aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 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
|
||||
@ -982,7 +1001,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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TIMESTAMP, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -995,7 +1014,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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_TIME, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -1008,7 +1027,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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_DATE, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -1021,7 +1040,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));
|
||||
aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BLOB, 0));
|
||||
aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length
|
||||
aRow[6] = new ORowSetValueDecorator(); // Create Params
|
||||
aRow[9] = new ORowSetValueDecorator(
|
||||
@ -1133,13 +1152,15 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
"relfields.RDB$DEFAULT_VALUE, " // 4
|
||||
"relfields.RDB$FIELD_POSITION, "// 5
|
||||
"fields.RDB$FIELD_TYPE, " // 6
|
||||
"fields.RDB$FIELD_LENGTH, " // 7
|
||||
"fields.RDB$FIELD_PRECISION, " // 8
|
||||
"fields.RDB$FIELD_SUB_TYPE, " // 7
|
||||
"fields.RDB$FIELD_LENGTH, " // 8
|
||||
"fields.RDB$FIELD_PRECISION, " // 9
|
||||
"fields.RDB$FIELD_SCALE, " // 10
|
||||
// Specifically use relfields null flag -- the one in fields is used
|
||||
// for domains, whether a specific field is nullable is set in relfields,
|
||||
// this is also the one we manually fiddle when changin NULL/NOT NULL
|
||||
// (see Table.cxx)
|
||||
"relfields.RDB$NULL_FLAG " // 9
|
||||
"relfields.RDB$NULL_FLAG " // 11
|
||||
"FROM RDB$RELATION_FIELDS relfields "
|
||||
"JOIN RDB$FIELDS fields "
|
||||
"on (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) "
|
||||
@ -1192,9 +1213,10 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2)));
|
||||
// 5. Datatype
|
||||
short aType = getFBTypeFromBlrType(xRow->getShort(6));
|
||||
aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType));
|
||||
short aSubType = xRow->getShort(7);
|
||||
aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType, aSubType));
|
||||
// 6. Typename (SQL_*)
|
||||
aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType));
|
||||
aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType));
|
||||
|
||||
// 7. Column Sizes
|
||||
{
|
||||
@ -1203,7 +1225,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
{
|
||||
case SQL_TEXT:
|
||||
case SQL_VARYING:
|
||||
aColumnSize = xRow->getShort(7);
|
||||
aColumnSize = xRow->getShort(8);
|
||||
break;
|
||||
case SQL_SHORT:
|
||||
case SQL_LONG:
|
||||
@ -1212,7 +1234,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
case SQL_D_FLOAT:
|
||||
case SQL_INT64:
|
||||
case SQL_QUAD:
|
||||
aColumnSize = xRow->getShort(8);
|
||||
aColumnSize = xRow->getShort(9);
|
||||
break;
|
||||
case SQL_TIMESTAMP:
|
||||
case SQL_BLOB:
|
||||
@ -1226,12 +1248,12 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
aCurrentRow[7] = new ORowSetValueDecorator(aColumnSize);
|
||||
}
|
||||
|
||||
// 9. Decimal Digits
|
||||
// TODO: implement
|
||||
aCurrentRow[9] = new ORowSetValueDecorator(sal_Int32(0));
|
||||
// 9. Decimal digits (scale)
|
||||
// fb stores a negative number
|
||||
aCurrentRow[9] = new ORowSetValueDecorator( (sal_Int16) -(xRow->getShort(10)) );
|
||||
|
||||
// 11. Nullable
|
||||
if (xRow->getShort(9))
|
||||
if (xRow->getShort(11))
|
||||
{
|
||||
aCurrentRow[11] = new ORowSetValueDecorator(ColumnValue::NO_NULLS);
|
||||
}
|
||||
@ -1265,7 +1287,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
|
||||
// 16. Bytes in Column for char
|
||||
if (aType == SQL_TEXT)
|
||||
{
|
||||
aCurrentRow[16] = new ORowSetValueDecorator(xRow->getShort(7));
|
||||
aCurrentRow[16] = new ORowSetValueDecorator(xRow->getShort(8));
|
||||
}
|
||||
else if (aType == SQL_VARYING)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <osl/diagnose.h>
|
||||
#include <propertyids.hxx>
|
||||
#include <time.h>
|
||||
#include <connectivity/dbtools.hxx>
|
||||
|
||||
#include <com/sun/star/sdbc/DataType.hpp>
|
||||
#include <com/sun/star/lang/DisposedException.hpp>
|
||||
@ -317,6 +318,32 @@ Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery()
|
||||
return m_xResultSet;
|
||||
}
|
||||
|
||||
sal_Int64 OPreparedStatement::toNumericWithoutDecimalPlace(const OUString& sSource)
|
||||
{
|
||||
OUString sNumber(sSource);
|
||||
|
||||
// cut off leading 0 eventually ( eg. 0.567 -> .567)
|
||||
sSource.startsWith(OUString("0"), &sNumber);
|
||||
|
||||
sal_Int32 nDotIndex = sNumber.indexOf((sal_Unicode)'.');
|
||||
|
||||
if( nDotIndex < 0)
|
||||
{
|
||||
return sNumber.toInt64(); // no dot -> it's an integer
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove dot
|
||||
OUStringBuffer sBuffer(15);
|
||||
if(nDotIndex > 0)
|
||||
{
|
||||
sBuffer.append(sNumber.copy(0, nDotIndex));
|
||||
}
|
||||
sBuffer.append(sNumber.copy(nDotIndex + 1));
|
||||
return sBuffer.makeStringAndClear().toInt64();
|
||||
}
|
||||
}
|
||||
|
||||
//----- XParameters -----------------------------------------------------------
|
||||
void SAL_CALL OPreparedStatement::setNull(sal_Int32 nIndex, sal_Int32 /*nSqlType*/)
|
||||
throw(SQLException, RuntimeException, std::exception)
|
||||
@ -561,13 +588,81 @@ void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Refere
|
||||
|
||||
void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException, std::exception)
|
||||
{
|
||||
(void) parameterIndex;
|
||||
(void) x;
|
||||
(void) sqlType;
|
||||
(void) scale;
|
||||
checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
XSQLVAR* pVar = m_pInSqlda->sqlvar + (parameterIndex - 1);
|
||||
int dType = (pVar->sqltype & ~1); // drop null flag
|
||||
|
||||
if(sqlType == DataType::DECIMAL || sqlType == DataType::NUMERIC)
|
||||
{
|
||||
double myDouble=0.0;
|
||||
OUString myString;
|
||||
if( x >>= myDouble )
|
||||
{
|
||||
myString = OUString::number( myDouble );
|
||||
}
|
||||
else
|
||||
{
|
||||
x >>= myString;
|
||||
}
|
||||
|
||||
// fill in the number with nulls in fractional part.
|
||||
// We need this because e.g. 0.450 != 0.045 despite
|
||||
// their scale is equal
|
||||
OUStringBuffer sBuffer(15);
|
||||
sBuffer.append(myString);
|
||||
if(myString.indexOf('.') != -1) // there is a dot
|
||||
{
|
||||
for(sal_Int32 i=myString.copy(myString.indexOf('.')+1).getLength(); i<scale;i++)
|
||||
{
|
||||
sBuffer.append('0');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (sal_Int32 i=0; i<scale; i++)
|
||||
{
|
||||
sBuffer.append('0');
|
||||
}
|
||||
}
|
||||
myString = sBuffer.makeStringAndClear();
|
||||
// set value depending on type
|
||||
sal_Int16 n16Value = 0;
|
||||
sal_Int32 n32Value = 0;
|
||||
sal_Int64 n64Value = 0;
|
||||
switch(dType)
|
||||
{
|
||||
case SQL_SHORT:
|
||||
n16Value = (sal_Int16) toNumericWithoutDecimalPlace(myString);
|
||||
setValue< sal_Int16 >(parameterIndex,
|
||||
n16Value,
|
||||
dType);
|
||||
break;
|
||||
case SQL_LONG:
|
||||
case SQL_DOUBLE: // TODO FIXME 32 bits
|
||||
n32Value = (sal_Int32) toNumericWithoutDecimalPlace(myString);
|
||||
setValue< sal_Int32 >(parameterIndex,
|
||||
n32Value,
|
||||
dType);
|
||||
break;
|
||||
case SQL_INT64:
|
||||
n64Value = (sal_Int64) toNumericWithoutDecimalPlace(myString);
|
||||
setValue< sal_Int64 >(parameterIndex,
|
||||
n64Value,
|
||||
dType);
|
||||
break;
|
||||
default:
|
||||
SAL_WARN("connectivity.firebird",
|
||||
"No Firebird sql type found for numeric or decimal types");
|
||||
::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,6 +79,13 @@ namespace connectivity
|
||||
*/
|
||||
void closeBlobAfterWriting(isc_blob_handle& rBlobHandle);
|
||||
|
||||
/**
|
||||
* Take out the number part of a fix point decimal without
|
||||
* the information of where is the fracional part from a
|
||||
* string representation of a number. (e.g. 54.654 -> 54654)
|
||||
*/
|
||||
sal_Int64 toNumericWithoutDecimalPlace(const OUString& sSource);
|
||||
|
||||
protected:
|
||||
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
|
||||
const css::uno::Any& rValue)
|
||||
|
@ -376,6 +376,58 @@ bool OResultSet::isNull(const sal_Int32 nColumnIndex)
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
OUString OResultSet::makeNumericString(const sal_Int32 nColumnIndex)
|
||||
{
|
||||
// minus because firebird stores scale as a negative number
|
||||
int nDecimalCount = -(m_pSqlda->sqlvar[nColumnIndex-1].sqlscale);
|
||||
if(nDecimalCount < 0)
|
||||
{
|
||||
// scale should be always positive
|
||||
assert(false);
|
||||
return OUString();
|
||||
}
|
||||
|
||||
OUStringBuffer sRetBuffer;
|
||||
T nAllDigits = *reinterpret_cast<T*>(m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
|
||||
sal_Int64 nDecimalCountExp = pow10Integer(nDecimalCount);
|
||||
|
||||
if(nAllDigits < 0)
|
||||
{
|
||||
sRetBuffer.append('-');
|
||||
nAllDigits = -nAllDigits; // abs
|
||||
}
|
||||
|
||||
sRetBuffer.append((sal_Int64) (nAllDigits / nDecimalCountExp) );
|
||||
if( nDecimalCount > 0)
|
||||
{
|
||||
sRetBuffer.append('.');
|
||||
|
||||
sal_Int64 nFractionalPart = nAllDigits % nDecimalCountExp;
|
||||
|
||||
int iCount = 0; // digit count
|
||||
sal_Int64 nFracTemp = nFractionalPart;
|
||||
while(nFracTemp>0)
|
||||
{
|
||||
nFracTemp /= 10;
|
||||
iCount++;
|
||||
}
|
||||
|
||||
int nMissingNulls = nDecimalCount - iCount;
|
||||
|
||||
// append nulls after dot and before nFractionalPart
|
||||
for(int i=0; i<nMissingNulls; i++)
|
||||
{
|
||||
sRetBuffer.append('0');
|
||||
}
|
||||
|
||||
// the rest
|
||||
sRetBuffer.append(nFractionalPart);
|
||||
}
|
||||
|
||||
return sRetBuffer.makeStringAndClear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
|
||||
{
|
||||
@ -398,18 +450,25 @@ 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;
|
||||
switch (m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1)
|
||||
{
|
||||
case SQL_TEXT:
|
||||
case SQL_VARYING:
|
||||
return getString(nColumnIndex);
|
||||
case SQL_SHORT:
|
||||
if(nSqlSubType == 0 || nSqlSubType == 1) //numeric or decimal
|
||||
return getString(nColumnIndex);
|
||||
return getShort(nColumnIndex);
|
||||
case SQL_LONG:
|
||||
if(nSqlSubType == 0 || nSqlSubType == 1) //numeric or decimal
|
||||
return getString(nColumnIndex);
|
||||
return getInt(nColumnIndex);
|
||||
case SQL_FLOAT:
|
||||
return getFloat(nColumnIndex);
|
||||
case SQL_DOUBLE:
|
||||
if(nSqlSubType == 0 || nSqlSubType == 1) //numeric or decimal
|
||||
return getString(nColumnIndex);
|
||||
return getDouble(nColumnIndex);
|
||||
case SQL_D_FLOAT:
|
||||
return getFloat(nColumnIndex);
|
||||
@ -420,6 +479,8 @@ ORowSetValue OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_S
|
||||
case SQL_TYPE_DATE:
|
||||
return getDate(nColumnIndex);
|
||||
case SQL_INT64:
|
||||
if(nSqlSubType == 0 || nSqlSubType == 1) //numeric or decimal
|
||||
return getString(nColumnIndex);
|
||||
return getLong(nColumnIndex);
|
||||
case SQL_BLOB:
|
||||
case SQL_NULL:
|
||||
@ -502,6 +563,7 @@ OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT
|
||||
{
|
||||
// &~1 to remove the "can contain NULL" indicator
|
||||
int aSqlType = m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1;
|
||||
int aSqlSubType = m_pSqlda->sqlvar[nColumnIndex-1].sqlsubtype;
|
||||
if (aSqlType == SQL_TEXT )
|
||||
{
|
||||
return OUString(m_pSqlda->sqlvar[nColumnIndex-1].sqldata,
|
||||
@ -517,6 +579,26 @@ 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))
|
||||
{
|
||||
// decimal and numeric types
|
||||
switch(aSqlType)
|
||||
{
|
||||
case SQL_SHORT:
|
||||
return makeNumericString<sal_Int16>(nColumnIndex);
|
||||
case SQL_LONG:
|
||||
return makeNumericString<sal_Int32>(nColumnIndex);
|
||||
case SQL_DOUBLE:
|
||||
// TODO FIXME 64 bits?
|
||||
case SQL_INT64:
|
||||
return makeNumericString<sal_Int64>(nColumnIndex);
|
||||
default:
|
||||
assert(false);
|
||||
return OUString(); // never reached
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return retrieveValue< ORowSetValue >(nColumnIndex, 0);
|
||||
|
@ -101,6 +101,9 @@ namespace connectivity
|
||||
|
||||
bool isNull(const sal_Int32 nColumnIndex);
|
||||
|
||||
template <typename T> OUString makeNumericString(
|
||||
const sal_Int32 nColumnIndex);
|
||||
|
||||
template <typename T> T retrieveValue(const sal_Int32 nColumnIndex,
|
||||
const ISC_SHORT nType);
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <com/sun/star/sdbc/ColumnValue.hpp>
|
||||
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
|
||||
#include <com/sun/star/sdbc/XRow.hpp>
|
||||
#include <com/sun/star/sdbc/DataType.hpp>
|
||||
|
||||
using namespace connectivity::firebird;
|
||||
|
||||
@ -62,8 +63,9 @@ 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;
|
||||
|
||||
return getColumnTypeFromFBType(aType);
|
||||
return getColumnTypeFromFBType(aType, aSubType);
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column)
|
||||
@ -118,8 +120,9 @@ 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;
|
||||
|
||||
return getColumnTypeNameFromFBType(aType);
|
||||
return getColumnTypeNameFromFBType(aType, aSubType);
|
||||
}
|
||||
|
||||
OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column)
|
||||
@ -191,15 +194,44 @@ sal_Bool SAL_CALL OResultSetMetaData::isSigned(sal_Int32 column)
|
||||
sal_Int32 SAL_CALL OResultSetMetaData::getPrecision(sal_Int32 column)
|
||||
throw(SQLException, RuntimeException, std::exception)
|
||||
{
|
||||
// TODO: implement
|
||||
(void) column;
|
||||
sal_Int32 nType = getColumnType(column);
|
||||
if( (nType == DataType::NUMERIC || nType == DataType::DECIMAL)
|
||||
&& !m_sTableName.isEmpty() )
|
||||
{
|
||||
OUString sColumnName = getColumnName( column );
|
||||
|
||||
// RDB$FIELD_SOURCE is a unique name of column per database
|
||||
OUString sSql = "SELECT RDB$FIELD_PRECISION FROM RDB$FIELDS "
|
||||
" INNER JOIN RDB$RELATION_FIELDS "
|
||||
" ON RDB$RELATION_FIELDS.RDB$FIELD_SOURCE = RDB$FIELDS.RDB$FIELD_NAME "
|
||||
"WHERE RDB$RELATION_FIELDS.RDB$RELATION_NAME = '"
|
||||
+ escapeWith(getTableName(column), '\'', '\'') + "' AND "
|
||||
"RDB$RELATION_FIELDS.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())
|
||||
{
|
||||
return (sal_Int32) xRow->getShort(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SAL_WARN("connectivity.firebird","Column '"
|
||||
<< sColumnName
|
||||
<< "' not found in database");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sal_Int32 SAL_CALL OResultSetMetaData::getScale(sal_Int32 column)
|
||||
throw(css::sdbc::SQLException, css::uno::RuntimeException, std::exception)
|
||||
{
|
||||
return m_pSqlda->sqlvar[column-1].sqlscale;
|
||||
return -(m_pSqlda->sqlvar[column-1].sqlscale); // fb stores negative number
|
||||
}
|
||||
|
||||
sal_Int32 SAL_CALL OResultSetMetaData::isNullable(sal_Int32 column)
|
||||
|
@ -65,7 +65,7 @@ void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY& rStatusVector,
|
||||
}
|
||||
}
|
||||
|
||||
sal_Int32 firebird::getColumnTypeFromFBType(short aType)
|
||||
sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType)
|
||||
{
|
||||
aType &= ~1; // Remove last bit -- it is used to denote whether column
|
||||
// can store Null, not needed for type determination
|
||||
@ -76,12 +76,24 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType)
|
||||
case SQL_VARYING:
|
||||
return DataType::VARCHAR;
|
||||
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_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;
|
||||
@ -96,6 +108,10 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType)
|
||||
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;
|
||||
@ -107,7 +123,7 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType)
|
||||
}
|
||||
}
|
||||
|
||||
OUString firebird::getColumnTypeNameFromFBType(short aType)
|
||||
OUString firebird::getColumnTypeNameFromFBType(short aType, short aSubType)
|
||||
{
|
||||
aType &= ~1; // Remove last bit -- it is used to denote whether column
|
||||
// can store Null, not needed for type determination
|
||||
@ -118,12 +134,24 @@ OUString firebird::getColumnTypeNameFromFBType(short aType)
|
||||
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");
|
||||
@ -138,6 +166,10 @@ OUString firebird::getColumnTypeNameFromFBType(short aType)
|
||||
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");
|
||||
@ -540,4 +572,14 @@ OUString firebird::escapeWith( const OUString& sText, const char aKey, const cha
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
sal_Int64 firebird::pow10Integer(int nDecimalCount)
|
||||
{
|
||||
sal_Int64 nRet = 1;
|
||||
for(int i=0; i< nDecimalCount; i++)
|
||||
{
|
||||
nRet *= 10;
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@ -53,8 +53,8 @@ namespace connectivity
|
||||
const css::uno::Reference< css::uno::XInterface >& _rxContext)
|
||||
throw (css::sdbc::SQLException);
|
||||
|
||||
sal_Int32 getColumnTypeFromFBType(short aType);
|
||||
::rtl::OUString getColumnTypeNameFromFBType(short aType);
|
||||
sal_Int32 getColumnTypeFromFBType(short aType, short aSubType);
|
||||
::rtl::OUString getColumnTypeNameFromFBType(short aType, short aSubType);
|
||||
|
||||
/**
|
||||
* Internally (i.e. in RDB$FIELD_TYPE) firebird stores the data type
|
||||
@ -73,6 +73,7 @@ namespace connectivity
|
||||
OString extractSingleTableFromSelect( const OStringVector &vec );
|
||||
|
||||
OUString escapeWith( const OUString& sText, const char aKey, const char aEscapeChar);
|
||||
sal_Int64 pow10Integer( int nDecimalCount );
|
||||
}
|
||||
}
|
||||
#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_FIREBIRD_UTIL_HXX
|
||||
|
Loading…
x
Reference in New Issue
Block a user