Kaydet (Commit) 5a96c7cb authored tarafından Lionel Elie Mamane's avatar Lionel Elie Mamane

fdo#86852 correctly recognise NULL values in query parameter values dialog

Change-Id: I3c0cf976e0a9fbafe6eee768799a2f48c2ee0ea9
üst e4b8b700
...@@ -54,6 +54,7 @@ namespace dbtools ...@@ -54,6 +54,7 @@ namespace dbtools
using ::com::sun::star::i18n::LocaleData; using ::com::sun::star::i18n::LocaleData;
using ::com::sun::star::i18n::XLocaleData; using ::com::sun::star::i18n::XLocaleData;
using ::com::sun::star::i18n::LocaleDataItem; using ::com::sun::star::i18n::LocaleDataItem;
using ::com::sun::star::uno::Any;
using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbc;
using namespace ::connectivity; using namespace ::connectivity;
...@@ -283,9 +284,9 @@ namespace dbtools ...@@ -283,9 +284,9 @@ namespace dbtools
} }
OUString OPredicateInputController::getPredicateValue( OUString OPredicateInputController::getPredicateValueStr(
const OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField, const OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField,
bool _bForStatementUse, OUString* _pErrorMessage ) const OUString* _pErrorMessage ) const
{ {
OSL_ENSURE( _rxField.is(), "OPredicateInputController::getPredicateValue: invalid params!" ); OSL_ENSURE( _rxField.is(), "OPredicateInputController::getPredicateValue: invalid params!" );
OUString sReturn; OUString sReturn;
...@@ -293,28 +294,84 @@ namespace dbtools ...@@ -293,28 +294,84 @@ namespace dbtools
{ {
OUString sValue( _rPredicateValue ); OUString sValue( _rPredicateValue );
// a little problem : if the field is a text field, the normalizePredicateString added two // The following is mostly stolen from the former implementation in the parameter dialog
// '-characters to the text. If we would give this to predicateTree this would add // (dbaccess/source/ui/dlg/paramdialog.cxx). I do not fully understand this .....
// two additional '-characters which we don't want. So check the field format.
// FS - 06.01.00 - 71532 OUString sError;
bool bValidQuotedText = sValue.startsWith("'") && sValue.endsWith("'"); OSQLParseNode* pParseNode = implPredicateTree( sError, sValue, _rxField );
// again : as normalizePredicateString always did a conversion on the value text, if ( _pErrorMessage )
// bValidQuotedText == sal_True implies that we have a text field, as no other field *_pErrorMessage = sError;
// values will be formatted with the quote characters
if ( bValidQuotedText ) implParseNode(pParseNode, true) >>= sReturn;
{ }
sValue = sValue.copy( 1, sValue.getLength() - 2 );
static const char sSingleQuote[] = "'";
static const char sDoubleQuote[] = "''";
sal_Int32 nIndex = -1; return sReturn;
sal_Int32 nTemp = 0; }
while ( -1 != ( nIndex = sValue.indexOf( sDoubleQuote,nTemp ) ) )
OUString OPredicateInputController::getPredicateValueStr(
const OUString& _sField, const OUString& _rPredicateValue, 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 = "SELECT * FROM x WHERE " + sField + _rPredicateValue;
boost::scoped_ptr<OSQLParseNode> pParseNode( const_cast< OSQLParser& >( m_aParser ).parseTree( sError, sSql, true ) );
nType = DataType::DOUBLE;
if ( pParseNode.get() )
{
OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
if ( pColumnRef )
{ {
sValue = sValue.replaceAt( nIndex, 2, sSingleQuote );
nTemp = nIndex+2;
} }
} }
}
Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
parse::OParseColumn* pColumn = new parse::OParseColumn( sField,
OUString(),
OUString(),
OUString(),
ColumnValue::NULLABLE_UNKNOWN,
0,
0,
nType,
false,
false,
xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),
OUString(),
OUString(),
OUString());
Reference<XPropertySet> xColumn = pColumn;
pColumn->setFunction(true);
pColumn->setRealName(sField);
OSQLParseNode* pParseNode = implPredicateTree( sError, _rPredicateValue, xColumn );
if ( _pErrorMessage )
*_pErrorMessage = sError;
if(pParseNode)
{
implParseNode(pParseNode, true) >>= sReturn;
}
return sReturn;
}
Any OPredicateInputController::getPredicateValue(
const OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField,
OUString* _pErrorMessage ) const
{
OSL_ENSURE( _rxField.is(), "OPredicateInputController::getPredicateValue: invalid params!" );
if ( _rxField.is() )
{
OUString sValue( _rPredicateValue );
// The following is mostly stolen from the former implementation in the parameter dialog // 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 ..... // (dbaccess/source/ui/dlg/paramdialog.cxx). I do not fully understand this .....
...@@ -324,16 +381,15 @@ namespace dbtools ...@@ -324,16 +381,15 @@ namespace dbtools
if ( _pErrorMessage ) if ( _pErrorMessage )
*_pErrorMessage = sError; *_pErrorMessage = sError;
sReturn = implParseNode(pParseNode,_bForStatementUse); return implParseNode(pParseNode, false);
} }
return sReturn; return Any();
} }
OUString OPredicateInputController::getPredicateValue( Any OPredicateInputController::getPredicateValue(
const OUString& _sField, const OUString& _rPredicateValue, bool _bForStatementUse, OUString* _pErrorMessage ) const const OUString& _sField, const OUString& _rPredicateValue, OUString* _pErrorMessage ) const
{ {
OUString sReturn = _rPredicateValue;
OUString sError; OUString sError;
OUString sField = _sField; OUString sField = _sField;
sal_Int32 nIndex = 0; sal_Int32 nIndex = 0;
...@@ -378,14 +434,16 @@ namespace dbtools ...@@ -378,14 +434,16 @@ namespace dbtools
OSQLParseNode* pParseNode = implPredicateTree( sError, _rPredicateValue, xColumn ); OSQLParseNode* pParseNode = implPredicateTree( sError, _rPredicateValue, xColumn );
if ( _pErrorMessage ) if ( _pErrorMessage )
*_pErrorMessage = sError; *_pErrorMessage = sError;
return pParseNode ? implParseNode(pParseNode,_bForStatementUse) : sReturn; return pParseNode ? implParseNode(pParseNode, false) : Any();
} }
OUString OPredicateInputController::implParseNode(OSQLParseNode* pParseNode, bool _bForStatementUse) const Any OPredicateInputController::implParseNode(OSQLParseNode* pParseNode, bool _bForStatementUse) const
{ {
OUString sReturn; if ( ! pParseNode )
if ( pParseNode ) return Any();
else
{ {
OUString sReturn;
boost::shared_ptr<OSQLParseNode> xTakeOwnership(pParseNode); boost::shared_ptr<OSQLParseNode> xTakeOwnership(pParseNode);
OSQLParseNode* pOdbcSpec = pParseNode->getByRule( OSQLParseNode::odbc_fct_spec ); OSQLParseNode* pOdbcSpec = pParseNode->getByRule( OSQLParseNode::odbc_fct_spec );
if ( pOdbcSpec ) if ( pOdbcSpec )
...@@ -408,7 +466,13 @@ namespace dbtools ...@@ -408,7 +466,13 @@ namespace dbtools
} }
else else
{ {
if (pParseNode->count() >= 3) if (pParseNode->getKnownRuleID() == OSQLParseNode::test_for_null )
{
assert(pParseNode->count() == 2);
return Any();
}
// LEM this seems overly permissive as test...
else if (pParseNode->count() >= 3)
{ {
OSQLParseNode* pValueNode = pParseNode->getChild(2); OSQLParseNode* pValueNode = pParseNode->getChild(2);
assert(pValueNode && "OPredicateInputController::getPredicateValue: invalid node child!"); assert(pValueNode && "OPredicateInputController::getPredicateValue: invalid node child!");
...@@ -427,10 +491,13 @@ namespace dbtools ...@@ -427,10 +491,13 @@ namespace dbtools
); );
} }
else else
{
OSL_FAIL( "OPredicateInputController::getPredicateValue: unknown/invalid structure (noodbc)!" ); OSL_FAIL( "OPredicateInputController::getPredicateValue: unknown/invalid structure (noodbc)!" );
return Any();
}
} }
return Any(sReturn);
} }
return sReturn;
} }
} // namespace dbtools } // namespace dbtools
......
...@@ -1510,11 +1510,11 @@ namespace ...@@ -1510,11 +1510,11 @@ namespace
if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(sColumnName) ) if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(sColumnName) )
{ {
Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(sColumnName),UNO_QUERY); Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(sColumnName),UNO_QUERY);
sValue = i_aPredicateInputController.getPredicateValue(sValue,xColumn,true); sValue = i_aPredicateInputController.getPredicateValueStr(sValue,xColumn);
} }
else else
{ {
sValue = i_aPredicateInputController.getPredicateValue(pAndIter->Name,sValue,true); sValue = i_aPredicateInputController.getPredicateValueStr(pAndIter->Name,sValue);
} }
lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet); lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
++pAndIter; ++pAndIter;
......
...@@ -95,12 +95,6 @@ namespace dbaui ...@@ -95,12 +95,6 @@ namespace dbaui
pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME));
m_pAllParams->InsertEntry(pValues->Name); m_pAllParams->InsertEntry(pValues->Name);
if (!pValues->Value.hasValue())
// it won't have a value, 'cause it's default constructed. But may be later we support
// initializing this dialog with values
pValues->Value = makeAny( OUString() );
// default the values to an empty string
m_aVisitedParams.push_back(0); m_aVisitedParams.push_back(0);
// not visited, not dirty // not visited, not dirty
} }
...@@ -239,7 +233,7 @@ namespace dbaui ...@@ -239,7 +233,7 @@ namespace dbaui
OUString sValue; OUString sValue;
pValues->Value >>= sValue; pValues->Value >>= sValue;
pValues->Value <<= OUString( m_aPredicateInput.getPredicateValue( sValue, xParamAsSet, false ) ); pValues->Value <<= m_aPredicateInput.getPredicateValue( sValue, xParamAsSet );
} }
} }
catch(Exception&) catch(Exception&)
......
...@@ -346,7 +346,8 @@ bool DlgFilterCrit::getCondition(const ListBox& _rField,const ListBox& _rComp,co ...@@ -346,7 +346,8 @@ bool DlgFilterCrit::getCondition(const ListBox& _rField,const ListBox& _rComp,co
_rFilter.Handle = GetOSQLPredicateType( _rComp.GetSelectEntry() ); _rFilter.Handle = GetOSQLPredicateType( _rComp.GetSelectEntry() );
if ( SQLFilterOperator::SQLNULL != _rFilter.Handle && _rFilter.Handle != SQLFilterOperator::NOT_SQLNULL ) if ( SQLFilterOperator::SQLNULL != _rFilter.Handle && _rFilter.Handle != SQLFilterOperator::NOT_SQLNULL )
{ {
OUString sPredicateValue = m_aPredicateInput.getPredicateValue( _rValue.GetText(), getMatchingColumn( _rValue ), false ); OUString sPredicateValue;
m_aPredicateInput.getPredicateValue( _rValue.GetText(), getMatchingColumn( _rValue ) ) >>= sPredicateValue;
if ( _rFilter.Handle == SQLFilterOperator::LIKE || if ( _rFilter.Handle == SQLFilterOperator::LIKE ||
_rFilter.Handle == SQLFilterOperator::NOT_LIKE ) _rFilter.Handle == SQLFilterOperator::NOT_LIKE )
::Replace_OS_PlaceHolder( sPredicateValue ); ::Replace_OS_PlaceHolder( sPredicateValue );
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <com/sun/star/i18n/XLocaleData4.hpp> #include <com/sun/star/i18n/XLocaleData4.hpp>
#include <connectivity/sqlparse.hxx> #include <connectivity/sqlparse.hxx>
#include <connectivity/dbtoolsdllapi.hxx> #include <connectivity/dbtoolsdllapi.hxx>
#include <com/sun/star/uno/Any.hxx>
namespace dbtools namespace dbtools
...@@ -74,30 +75,46 @@ namespace dbtools ...@@ -74,30 +75,46 @@ namespace dbtools
OUString* _pErrorMessage = NULL OUString* _pErrorMessage = NULL
) const; ) const;
/** get's a value of the predicate which can be used in a WHERE clause. /** get the value of the predicate, as a string to be used in a WHERE clause
@param _rPredicateValue @param _rPredicateValue
the value which has been normalized using normalizePredicateString the value which has been normalized using normalizePredicateString
@param _rxField @param _rxField
is the field for which a predicate is to be entered is the field for which a predicate is to be entered
@param _bForStatementUse
If <TRUE/>, the returned value can be used in an SQL statement. If <FALSE/>, it can be used
for instance for setting parameter values.
@param _pErrorMessage @param _pErrorMessage
If not <NULL/>, and a parsing error occurs, the error message will be copied to the string the argument If not <NULL/>, and a parsing error occurs, the error message will be copied to the string the argument
points to. points to.
@see normalizePredicateString @see normalizePredicateString
*/ */
OUString getPredicateValue( OUString getPredicateValueStr(
const OUString& _rPredicateValue, const OUString& _rPredicateValue,
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _rxField, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _rxField,
bool _bForStatementUse,
OUString* _pErrorMessage = NULL OUString* _pErrorMessage = NULL
) const; ) const;
OUString getPredicateValue( OUString getPredicateValueStr(
const OUString& _sField
, const OUString& _rPredicateValue
, OUString* _pErrorMessage = NULL) const;
/** get the value of the predicate, either as an empty or as a string
@param _rPredicateValue
the value which has been normalized using normalizePredicateString
@param _rxField
is the field for which a predicate is to be entered
@param _pErrorMessage
If not <NULL/>, and a parsing error occurs, the error message will be copied to the string the argument
points to.
@see normalizePredicateString
*/
::com::sun::star::uno::Any getPredicateValue(
const OUString& _rPredicateValue,
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _rxField,
OUString* _pErrorMessage = NULL
) const;
::com::sun::star::uno::Any getPredicateValue(
const OUString& _sField const OUString& _sField
, const OUString& _rPredicateValue , const OUString& _rPredicateValue
, bool _bForStatementUse
, OUString* _pErrorMessage = NULL) const; , OUString* _pErrorMessage = NULL) const;
private: private:
...@@ -113,7 +130,7 @@ namespace dbtools ...@@ -113,7 +130,7 @@ namespace dbtools
sal_Unicode& _rThdSep sal_Unicode& _rThdSep
) const; ) const;
OUString implParseNode(::connectivity::OSQLParseNode* pParseNode, bool _bForStatementUse) const; ::com::sun::star::uno::Any implParseNode(::connectivity::OSQLParseNode* pParseNode, bool _bForStatementUse) const;
}; };
......
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