office-gobmx/connectivity/source/commontools/predicateinput.cxx
Thomas Arnhold ba0a57702c remove OUString wrap for string literals
For some functions and all kinds of Exceptions.

CannotConvertException
CloseVetoException
DisposedException
EmptyUndoStackException
ErrorCodeIOException
Exception
GridInvalidDataException
GridInvalidModelException
IOException
IllegalAccessException
IllegalArgumentException
IllegalTypeException
IndexOutOfBoundsException
NoMasterException
NoSuchElementException
NoSupportException
PropertyVetoException
RuntimeException
SAXException
ScannerException
StorageWrappedTargetException
UnsupportedFlavorException
VetoException
WrappedTargetException
ZipIOException
throwGenericSQLException
throwIllegallArgumentException

createInstance
createInstanceWithContext
forName
getByName
getPackageManager
getPropertyValue
getUnpackedValueOrDefault
getValueByName
hasPropertyByName
openKey
setName
setPropertyValue
supportsService

bash command:

for i in `cat list`; do git grep "$i\s*(\s*OUString(\s*\"" -- '*.[hc]xx'
	| cut -d ':' -f1 | sort -u
	| xargs sed -i
		-e "s/\(\<$i\s*(\)\s*OUString(\s*\(\"[^\")\\]*\"\)\s*)\s*/\1\2/g"
		-e "s/\($i.*\)\"+ /\1\" + /g";
done

Change-Id: Iaf8e641b0abf28c082906014f87a183517630535
Reviewed-on: https://gerrit.libreoffice.org/4624
Tested-by: LibreOffice gerrit bot <gerrit@libreoffice.org>
Reviewed-by: Thomas Arnhold <thomas@arnhold.org>
Tested-by: Thomas Arnhold <thomas@arnhold.org>
2013-06-29 21:52:54 +00:00

445 lines
20 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <connectivity/predicateinput.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/types.hxx>
#include <connectivity/dbtools.hxx>
#include <com/sun/star/i18n/LocaleData.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/sdbc/ColumnValue.hpp>
#include <com/sun/star/util/NumberFormatter.hpp>
#include <osl/diagnose.h>
#include <connectivity/sqlnode.hxx>
#include <connectivity/PColumn.hxx>
#include <comphelper/numbers.hxx>
#include <boost/shared_ptr.hpp>
//.........................................................................
namespace dbtools
{
//.........................................................................
using ::com::sun::star::sdbc::XConnection;
using ::com::sun::star::util::XNumberFormatsSupplier;
using ::com::sun::star::util::NumberFormatter;
using ::com::sun::star::util::XNumberFormatter;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::XComponentContext;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::lang::Locale;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::i18n::LocaleData;
using ::com::sun::star::i18n::XLocaleData;
using ::com::sun::star::i18n::LocaleDataItem;
using namespace ::com::sun::star::sdbc;
using namespace ::connectivity;
using ::connectivity::OSQLParseNode;
//=====================================================================
//---------------------------------------------------------------------
static sal_Unicode lcl_getSeparatorChar( const OUString& _rSeparator, sal_Unicode _nFallback )
{
OSL_ENSURE( !_rSeparator.isEmpty(), "::lcl_getSeparatorChar: invalid separator string!" );
sal_Unicode nReturn( _nFallback );
if ( !_rSeparator.isEmpty() )
nReturn = static_cast< sal_Char >( _rSeparator.getStr()[0] );
return nReturn;
}
//=====================================================================
//= OPredicateInputController
//=====================================================================
//---------------------------------------------------------------------
sal_Bool OPredicateInputController::getSeparatorChars( const Locale& _rLocale, sal_Unicode& _rDecSep, sal_Unicode& _rThdSep ) const
{
_rDecSep = '.';
_rThdSep = ',';
try
{
LocaleDataItem aLocaleData;
if ( m_xLocaleData.is() )
{
aLocaleData = m_xLocaleData->getLocaleItem( _rLocale );
_rDecSep = lcl_getSeparatorChar( aLocaleData.decimalSeparator, _rDecSep );
_rThdSep = lcl_getSeparatorChar( aLocaleData.decimalSeparator, _rThdSep );
return sal_True;
}
}
catch( const Exception& )
{
OSL_FAIL( "OPredicateInputController::getSeparatorChars: caught an exception!" );
}
return sal_False;
}
//---------------------------------------------------------------------
OPredicateInputController::OPredicateInputController(
const Reference< XComponentContext >& rxContext, const Reference< XConnection >& _rxConnection, const IParseContext* _pParseContext )
: m_xConnection( _rxConnection )
,m_aParser( rxContext, _pParseContext )
{
try
{
// create a number formatter / number formats supplier pair
OSL_ENSURE( rxContext.is(), "OPredicateInputController::OPredicateInputController: need a service factory!" );
if ( rxContext.is() )
{
m_xFormatter = Reference< XNumberFormatter >(
NumberFormatter::create(rxContext),
UNO_QUERY_THROW
);
}
Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats( m_xConnection, sal_True );
if ( !xNumberFormats.is() )
::comphelper::disposeComponent( m_xFormatter );
else
m_xFormatter->attachNumberFormatsSupplier( xNumberFormats );
// create the locale data
if ( rxContext.is() )
{
m_xLocaleData = LocaleData::create( rxContext );
}
}
catch( const Exception& )
{
OSL_FAIL( "OPredicateInputController::OPredicateInputController: caught an exception!" );
}
}
//---------------------------------------------------------------------
OSQLParseNode* OPredicateInputController::implPredicateTree(OUString& _rErrorMessage, const OUString& _rStatement, const Reference< XPropertySet > & _rxField) const
{
OSQLParseNode* pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, _rStatement, m_xFormatter, _rxField );
if ( !pReturn )
{ // is it a text field ?
sal_Int32 nType = DataType::OTHER;
_rxField->getPropertyValue("Type") >>= nType;
if ( ( DataType::CHAR == nType )
|| ( DataType::VARCHAR == nType )
|| ( DataType::LONGVARCHAR == nType )
|| ( DataType::CLOB == nType )
)
{ // yes -> force a quoted text and try again
OUString sQuoted( _rStatement );
if ( !sQuoted.isEmpty()
&& ( (sQuoted.getStr()[0] != '\'')
|| (sQuoted.getStr()[ sQuoted.getLength() - 1 ] != '\'' )
)
)
{
static const OUString sSingleQuote( "'" );
static const OUString sDoubleQuote( "''" );
sal_Int32 nIndex = -1;
sal_Int32 nTemp = 0;
while ( -1 != ( nIndex = sQuoted.indexOf( '\'',nTemp ) ) )
{
sQuoted = sQuoted.replaceAt( nIndex, 1, sDoubleQuote );
nTemp = nIndex+2;
}
OUString sTemp( sSingleQuote );
( sTemp += sQuoted ) += sSingleQuote;
sQuoted = sTemp;
}
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sQuoted, m_xFormatter, _rxField );
}
// one more fallback: for numeric fields, and value strings containing a decimal/thousands separator
// problem which is to be solved with this:
// * a system locale "german"
// * a column formatted with an english number format
// => the output is german (as we use the system locale for this), i.e. "3,4"
// => the input does not recognize the german text, as predicateTree uses the number format
// of the column to determine the main locale - the locale on the context is only a fallback
if ( ( DataType::FLOAT == nType )
|| ( DataType::REAL == nType )
|| ( DataType::DOUBLE == nType )
|| ( DataType::NUMERIC == nType )
|| ( DataType::DECIMAL == nType )
)
{
const IParseContext& rParseContext = m_aParser.getContext();
// get the separators for the locale of our parse context
sal_Unicode nCtxDecSep;
sal_Unicode nCtxThdSep;
getSeparatorChars( rParseContext.getPreferredLocale(), nCtxDecSep, nCtxThdSep );
// determine the locale of the column we're building a predicate string for
sal_Unicode nFmtDecSep( nCtxDecSep );
sal_Unicode nFmtThdSep( nCtxThdSep );
try
{
Reference< XPropertySetInfo > xPSI( _rxField->getPropertySetInfo() );
if ( xPSI.is() && xPSI->hasPropertyByName("FormatKey") )
{
sal_Int32 nFormatKey = 0;
_rxField->getPropertyValue("FormatKey") >>= nFormatKey;
if ( nFormatKey && m_xFormatter.is() )
{
Locale aFormatLocale;
::comphelper::getNumberFormatProperty(
m_xFormatter,
nFormatKey,
OUString( "Locale" )
) >>= aFormatLocale;
// valid locale
if ( !aFormatLocale.Language.isEmpty() )
{
getSeparatorChars( aFormatLocale, nFmtDecSep, nCtxThdSep );
}
}
}
}
catch( const Exception& )
{
OSL_FAIL( "OPredicateInputController::implPredicateTree: caught an exception while dealing with the formats!" );
}
sal_Bool bDecDiffers = ( nCtxDecSep != nFmtDecSep );
sal_Bool bFmtDiffers = ( nCtxThdSep != nFmtThdSep );
if ( bDecDiffers || bFmtDiffers )
{ // okay, at least one differs
// "translate" the value into the "format locale"
OUString sTranslated( _rStatement );
const sal_Unicode nIntermediate( '_' );
sTranslated = sTranslated.replace( nCtxDecSep, nIntermediate );
sTranslated = sTranslated.replace( nCtxThdSep, nFmtThdSep );
sTranslated = sTranslated.replace( nIntermediate, nFmtDecSep );
pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sTranslated, m_xFormatter, _rxField );
}
}
}
return pReturn;
}
//---------------------------------------------------------------------
sal_Bool OPredicateInputController::normalizePredicateString(
OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField, OUString* _pErrorMessage ) const
{
OSL_ENSURE( m_xConnection.is() && m_xFormatter.is() && _rxField.is(),
"OPredicateInputController::normalizePredicateString: invalid state or params!" );
sal_Bool bSuccess = sal_False;
if ( m_xConnection.is() && m_xFormatter.is() && _rxField.is() )
{
// parse the string
OUString sError;
OUString sTransformedText( _rPredicateValue );
OSQLParseNode* pParseNode = implPredicateTree( sError, sTransformedText, _rxField );
if ( _pErrorMessage ) *_pErrorMessage = sError;
if ( pParseNode )
{
const IParseContext& rParseContext = m_aParser.getContext();
sal_Unicode nDecSeparator, nThousandSeparator;
getSeparatorChars( rParseContext.getPreferredLocale(), nDecSeparator, nThousandSeparator );
// translate it back into a string
sTransformedText = OUString();
pParseNode->parseNodeToPredicateStr(
sTransformedText, m_xConnection, m_xFormatter, _rxField, OUString(),
rParseContext.getPreferredLocale(), (sal_Char)nDecSeparator, &rParseContext
);
_rPredicateValue = sTransformedText;
delete pParseNode;
bSuccess = sal_True;
}
}
return bSuccess;
}
//---------------------------------------------------------------------
OUString OPredicateInputController::getPredicateValue(
const OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField,
sal_Bool _bForStatementUse, OUString* _pErrorMessage ) const
{
OSL_ENSURE( _rxField.is(), "OPredicateInputController::getPredicateValue: invalid params!" );
OUString sReturn;
if ( _rxField.is() )
{
OUString sValue( _rPredicateValue );
// a little problem : if the field is a text field, the normalizePredicateString added two
// '-characters to the text. If we would give this to predicateTree this would add
// two additional '-characters which we don't want. So check the field format.
// FS - 06.01.00 - 71532
sal_Bool bValidQuotedText = ( sValue.getLength() >= 2 )
&& ( sValue.getStr()[0] == '\'' )
&& ( sValue.getStr()[ sValue.getLength() - 1 ] == '\'' );
// again : as normalizePredicateString always did a conversion on the value text,
// bValidQuotedText == sal_True implies that we have a text field, as no other field
// values will be formatted with the quote characters
if ( bValidQuotedText )
{
sValue = sValue.copy( 1, sValue.getLength() - 2 );
static const OUString sSingleQuote( "'" );
static const OUString sDoubleQuote( "''" );
sal_Int32 nIndex = -1;
sal_Int32 nTemp = 0;
while ( -1 != ( nIndex = sValue.indexOf( sDoubleQuote,nTemp ) ) )
{
sValue = sValue.replaceAt( nIndex, 2, sSingleQuote );
nTemp = nIndex+2;
}
}
// The following is mostly stolen from the former implementation in the parameter dialog
// (dbaccess/source/ui/dlg/paramdialog.cxx). I do not fully understand this .....
OUString sError;
OSQLParseNode* pParseNode = implPredicateTree( sError, sValue, _rxField );
if ( _pErrorMessage )
*_pErrorMessage = sError;
sReturn = implParseNode(pParseNode,_bForStatementUse);
}
return sReturn;
}
OUString OPredicateInputController::getPredicateValue(
const OUString& _sField, const OUString& _rPredicateValue, sal_Bool _bForStatementUse, OUString* _pErrorMessage ) const
{
OUString sReturn = _rPredicateValue;
OUString sError;
OUString sField = _sField;
sal_Int32 nIndex = 0;
sField = sField.getToken(0,'(',nIndex);
if(nIndex == -1)
sField = _sField;
sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sField,&m_aParser.getContext());
if ( nType == DataType::OTHER || sField.isEmpty() )
{
// first try the international version
OUString sSql;
sSql += OUString("SELECT * ");
sSql += OUString(" FROM x WHERE ");
sSql += sField;
sSql += _rPredicateValue;
::std::auto_ptr<OSQLParseNode> pParseNode( const_cast< OSQLParser& >( m_aParser ).parseTree( sError, sSql, sal_True ) );
nType = DataType::DOUBLE;
if ( pParseNode.get() )
{
OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
if ( pColumnRef )
{
}
}
}
Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
parse::OParseColumn* pColumn = new parse::OParseColumn( sField,
OUString(),
OUString(),
OUString(),
ColumnValue::NULLABLE_UNKNOWN,
0,
0,
nType,
sal_False,
sal_False,
xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),
OUString(),
OUString(),
OUString());
Reference<XPropertySet> xColumn = pColumn;
pColumn->setFunction(sal_True);
pColumn->setRealName(sField);
OSQLParseNode* pParseNode = implPredicateTree( sError, _rPredicateValue, xColumn );
if ( _pErrorMessage )
*_pErrorMessage = sError;
return pParseNode ? implParseNode(pParseNode,_bForStatementUse) : sReturn;
}
OUString OPredicateInputController::implParseNode(OSQLParseNode* pParseNode,sal_Bool _bForStatementUse) const
{
OUString sReturn;
if ( pParseNode )
{
boost::shared_ptr<OSQLParseNode> xTakeOwnership(pParseNode);
OSQLParseNode* pOdbcSpec = pParseNode->getByRule( OSQLParseNode::odbc_fct_spec );
if ( pOdbcSpec )
{
if ( _bForStatementUse )
{
OSQLParseNode* pFuncSpecParent = pOdbcSpec->getParent();
OSL_ENSURE( pFuncSpecParent, "OPredicateInputController::getPredicateValue: an ODBC func spec node without parent?" );
if ( pFuncSpecParent )
pFuncSpecParent->parseNodeToStr(sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True);
}
else
{
OSQLParseNode* pValueNode = pOdbcSpec->getChild(1);
if ( SQL_NODE_STRING == pValueNode->getNodeType() )
sReturn = pValueNode->getTokenValue();
else
pValueNode->parseNodeToStr(sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True);
}
}
else
{
if ( pParseNode->count() >= 3 )
{
OSQLParseNode* pValueNode = pParseNode->getChild(2);
OSL_ENSURE( pValueNode, "OPredicateInputController::getPredicateValue: invalid node child!" );
if ( !_bForStatementUse )
{
if ( SQL_NODE_STRING == pValueNode->getNodeType() )
sReturn = pValueNode->getTokenValue();
else
pValueNode->parseNodeToStr(
sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True
);
}
else
pValueNode->parseNodeToStr(
sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True
);
}
else
OSL_FAIL( "OPredicateInputController::getPredicateValue: unknown/invalid structure (noodbc)!" );
}
}
return sReturn;
}
//.........................................................................
} // namespace dbtools
//.........................................................................
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */