diff options
author | Ocke Janssen [oj] <Ocke.Janssen@sun.com> | 2010-02-08 14:05:16 +0100 |
---|---|---|
committer | Ocke Janssen [oj] <Ocke.Janssen@sun.com> | 2010-02-08 14:05:16 +0100 |
commit | 5f71d659243796e2fea2514860ed7d020a3d6d5b (patch) | |
tree | 7b4baaf96a621404fb19f2d28e8d47a1fb4605bf | |
parent | 1e76109004db25f8d4906852124252738e54403a (diff) |
dba33f: #i108730# impl case case and rank functions
-rw-r--r-- | connectivity/inc/connectivity/dbtools.hxx | 9 | ||||
-rw-r--r-- | connectivity/inc/connectivity/sqliterator.hxx | 8 | ||||
-rw-r--r-- | connectivity/inc/connectivity/sqlnode.hxx | 2 | ||||
-rw-r--r-- | connectivity/qa/connectivity/tools/CRMDatabase.java | 2 | ||||
-rw-r--r-- | connectivity/source/commontools/TColumnsHelper.cxx | 24 | ||||
-rw-r--r-- | connectivity/source/commontools/dbtools.cxx | 46 | ||||
-rw-r--r-- | connectivity/source/commontools/dbtools2.cxx | 23 | ||||
-rw-r--r-- | connectivity/source/drivers/evoab2/NStatement.cxx | 7 | ||||
-rw-r--r-- | connectivity/source/drivers/file/fcomp.cxx | 35 | ||||
-rw-r--r-- | connectivity/source/drivers/kab/KStatement.cxx | 11 | ||||
-rwxr-xr-x | connectivity/source/drivers/macab/MacabStatement.cxx | 11 | ||||
-rw-r--r-- | connectivity/source/drivers/mozab/MResultSet.cxx | 21 | ||||
-rw-r--r-- | connectivity/source/parse/sqliterator.cxx | 103 | ||||
-rw-r--r-- | connectivity/source/parse/sqlnode.cxx | 52 |
14 files changed, 224 insertions, 130 deletions
diff --git a/connectivity/inc/connectivity/dbtools.hxx b/connectivity/inc/connectivity/dbtools.hxx index 3f09571287b5..79fb42f7f3ce 100644 --- a/connectivity/inc/connectivity/dbtools.hxx +++ b/connectivity/inc/connectivity/dbtools.hxx @@ -229,6 +229,15 @@ namespace dbtools const ::rtl::OUString& _rName ); + /** returns the primary key columns of the table + */ + OOO_DLLPUBLIC_DBTOOLS ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> getPrimaryKeyColumns_throw( + const ::com::sun::star::uno::Any& i_aTable + ); + OOO_DLLPUBLIC_DBTOOLS ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> getPrimaryKeyColumns_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& i_xTable + ); + /** get fields for a result set given by a "command descriptor" <p>A command descriptor here means: diff --git a/connectivity/inc/connectivity/sqliterator.hxx b/connectivity/inc/connectivity/sqliterator.hxx index e8e4c8e6a6f2..86ca3ebe85ff 100644 --- a/connectivity/inc/connectivity/sqliterator.hxx +++ b/connectivity/inc/connectivity/sqliterator.hxx @@ -43,6 +43,7 @@ #include <map> #include <memory> +#include <vector> namespace connectivity { @@ -50,6 +51,8 @@ namespace connectivity class OSQLParseNode; class OSQLParser; + typedef ::std::pair<const OSQLParseNode*,const OSQLParseNode* > TNodePair; + enum OSQLStatementType { SQL_STATEMENT_UNKNOWN, SQL_STATEMENT_SELECT, @@ -282,6 +285,10 @@ namespace connectivity // tries to find the correct type of the function sal_Int32 getFunctionReturnType(const OSQLParseNode* _pNode ); + + // returns a lis of all joined columns + ::std::vector< TNodePair >& getJoinConditions() const; + private: /** traverses the list of table names, and filles _rTables */ @@ -354,6 +361,7 @@ namespace connectivity { m_aErrors = ::com::sun::star::sdbc::SQLException(); } + void impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition); }; } diff --git a/connectivity/inc/connectivity/sqlnode.hxx b/connectivity/inc/connectivity/sqlnode.hxx index 965babf6dd38..05ba06c3ee27 100644 --- a/connectivity/inc/connectivity/sqlnode.hxx +++ b/connectivity/inc/connectivity/sqlnode.hxx @@ -232,6 +232,8 @@ namespace connectivity comparison_predicate_part_2, parenthesized_boolean_value_expression, character_string_type, + other_like_predicate_part_2, + between_predicate_part_2, rule_count, // letzter_wert UNKNOWN_RULE // ID indicating that a node is no rule with a matching Rule-enum value (see getKnownRuleID) }; diff --git a/connectivity/qa/connectivity/tools/CRMDatabase.java b/connectivity/qa/connectivity/tools/CRMDatabase.java index 7a6cb7e8c034..dc238354706a 100644 --- a/connectivity/qa/connectivity/tools/CRMDatabase.java +++ b/connectivity/qa/connectivity/tools/CRMDatabase.java @@ -288,7 +288,7 @@ public class CRMDatabase m_database.getDataSource().createQuery( "parseable", "SELECT * FROM \"customers\"" ); m_database.getDataSource().createQuery( "parseable native", "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_VIEWS", false ); m_database.getDataSource().createQuery( "unparseable", - "SELECT CAST( \"ID\" AS VARCHAR(3) ) AS \"ID_VARCHAR\" FROM \"products\"", false ); + "SELECT {fn DAYOFMONTH ('2001-01-01')} AS \"ID_VARCHAR\" FROM \"products\"", false ); validateUnparseable(); } diff --git a/connectivity/source/commontools/TColumnsHelper.cxx b/connectivity/source/commontools/TColumnsHelper.cxx index 8a539405c333..b01be870c9e6 100644 --- a/connectivity/source/commontools/TColumnsHelper.cxx +++ b/connectivity/source/commontools/TColumnsHelper.cxx @@ -124,29 +124,7 @@ sdbcx::ObjectType OColumnsHelper::createObject(const ::rtl::OUString& _rName) if ( pColDesc ) { Reference<XPropertySet> xPr = m_pTable; - Reference<XKeysSupplier> xKeysSup(xPr,UNO_QUERY); - Reference<XNameAccess> xPrimaryKeyColumns; - if ( xKeysSup.is() ) - { - const Reference<XIndexAccess> xKeys = xKeysSup->getKeys(); - if ( xKeys.is() ) - { - ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); - const sal_Int32 nKeyCount = xKeys->getCount(); - for(sal_Int32 nKeyIter = 0; nKeyIter < nKeyCount;++nKeyIter) - { - const Reference<XPropertySet> xKey(xKeys->getByIndex(nKeyIter),UNO_QUERY_THROW); - sal_Int32 nType = 0; - xKey->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; - if ( nType == KeyType::PRIMARY ) - { - const Reference<XColumnsSupplier> xColS(xKey,UNO_QUERY_THROW); - xPrimaryKeyColumns = xColS->getColumns(); - break; - } - } // for(sal_Int32 nKeyIter = 0; nKeyIter < nKeyCount;++) - } - } + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xPr); sal_Int32 nField11 = pColDesc->nField11; if ( nField11 != ColumnValue::NO_NULLS && xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(_rName) ) { diff --git a/connectivity/source/commontools/dbtools.cxx b/connectivity/source/commontools/dbtools.cxx index 79f9f9707c26..31fd7dc4de0f 100644 --- a/connectivity/source/commontools/dbtools.cxx +++ b/connectivity/source/commontools/dbtools.cxx @@ -63,8 +63,10 @@ #include <com/sun/star/sdbc/XRow.hpp> #include <com/sun/star/sdbc/XRowSet.hpp> #include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> #include <com/sun/star/sdbcx/Privilege.hpp> #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> #include <com/sun/star/sdbcx/XTablesSupplier.hpp> #include <com/sun/star/task/XInteractionHandler.hpp> #include <com/sun/star/task/XInteractionRequest.hpp> @@ -531,6 +533,46 @@ Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,co Reference< XComponent > xDummy; return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy ); } +//------------------------------------------------------------------------------ +Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable) +{ + const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW); + return getPrimaryKeyColumns_throw(xTable); +} +//------------------------------------------------------------------------------ +Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable) +{ + Reference<XNameAccess> xKeyColumns; + const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY); + if ( xKeySup.is() ) + { + const Reference<XIndexAccess> xKeys = xKeySup->getKeys(); + if ( xKeys.is() ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + const ::rtl::OUString sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE); + Reference<XPropertySet> xProp; + const sal_Int32 nCount = xKeys->getCount(); + for(sal_Int32 i = 0;i< nCount;++i) + { + xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW); + if ( xProp.is() ) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(sPropName) >>= nKeyType; + if(KeyType::PRIMARY == nKeyType) + { + const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW); + xKeyColumns = xKeyColsSup->getColumns(); + break; + } + } + } + } + } + + return xKeyColumns; +} //------------------------------------------------------------------------------ namespace @@ -2054,7 +2096,7 @@ namespace connectivity void release(oslInterlockedCount& _refCount, ::cppu::OBroadcastHelper& rBHelper, - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, + Reference< XInterface >& _xInterface, ::com::sun::star::lang::XComponent* _pObject) { if (osl_decrementInterlockedCount( &_refCount ) == 0) @@ -2064,7 +2106,7 @@ void release(oslInterlockedCount& _refCount, if (!rBHelper.bDisposed && !rBHelper.bInDispose) { // remember the parent - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xParent; + Reference< XInterface > xParent; { ::osl::MutexGuard aGuard( rBHelper.rMutex ); xParent = _xInterface; diff --git a/connectivity/source/commontools/dbtools2.cxx b/connectivity/source/commontools/dbtools2.cxx index a0b4ab4e3aa9..4afcc657a8c0 100644 --- a/connectivity/source/commontools/dbtools2.cxx +++ b/connectivity/source/commontools/dbtools2.cxx @@ -534,28 +534,7 @@ Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; - Reference<XKeysSupplier> xKeysSup(_xTable,UNO_QUERY); - Reference<XNameAccess> xPrimaryKeyColumns; - if ( xKeysSup.is() ) - { - const Reference<XIndexAccess> xKeys = xKeysSup->getKeys(); - if ( xKeys.is() ) - { - const sal_Int32 nKeyCount = xKeys->getCount(); - for(sal_Int32 nKeyIter = 0; nKeyIter < nKeyCount;++nKeyIter) - { - const Reference<XPropertySet> xKey(xKeys->getByIndex(nKeyIter),UNO_QUERY_THROW); - sal_Int32 nType = 0; - xKey->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; - if ( nType == KeyType::PRIMARY ) - { - const Reference<XColumnsSupplier> xColS(xKey,UNO_QUERY_THROW); - xPrimaryKeyColumns = xColS->getColumns(); - break; - } - } // for(sal_Int32 nKeyIter = 0; nKeyIter < nKeyCount;++) - } - } + Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable); xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType); if ( !xProp.is() ) diff --git a/connectivity/source/drivers/evoab2/NStatement.cxx b/connectivity/source/drivers/evoab2/NStatement.cxx index 2ddcd84c87a0..b8779b703eb0 100644 --- a/connectivity/source/drivers/evoab2/NStatement.cxx +++ b/connectivity/source/drivers/evoab2/NStatement.cxx @@ -381,15 +381,16 @@ EBookQuery *OCommonStatement::whereAnalysis( const OSQLParseNode* parseTree ) // SQL like else if( SQL_ISRULE( parseTree, like_predicate ) ) { - ENSURE_OR_THROW( parseTree->count() >= 4, "unexpected like_predicate structure" ); + ENSURE_OR_THROW( parseTree->count() == 2, "unexpected like_predicate structure" ); + const OSQLParseNode* pPart2 = parseTree->getChild(1); if( ! SQL_ISRULE( parseTree->getChild( 0 ), column_ref) ) m_pConnection->throwGenericSQLException(STR_QUERY_INVALID_LIKE_COLUMN,*this); ::rtl::OUString aColumnName( impl_getColumnRefColumnName_throw( *parseTree->getChild( 0 ) ) ); - OSQLParseNode *pAtom = parseTree->getChild( parseTree->count() - 2 ); // Match String - bool bNotLike = parseTree->count() == 5; + OSQLParseNode *pAtom = pPart2->getChild( pPart2->count() - 2 ); // Match String + bool bNotLike = pPart2->getChild(0)->isToken(); if( !( pAtom->getNodeType() == SQL_NODE_STRING || pAtom->getNodeType() == SQL_NODE_NAME || diff --git a/connectivity/source/drivers/file/fcomp.cxx b/connectivity/source/drivers/file/fcomp.cxx index 66d0d142e6e3..9c5b1d1db481 100644 --- a/connectivity/source/drivers/file/fcomp.cxx +++ b/connectivity/source/drivers/file/fcomp.cxx @@ -291,17 +291,14 @@ OOperand* OPredicateCompiler::execute_COMPARE(OSQLParseNode* pPredicateNode) th //------------------------------------------------------------------ OOperand* OPredicateCompiler::execute_LIKE(OSQLParseNode* pPredicateNode) throw(SQLException, RuntimeException) { - DBG_ASSERT(pPredicateNode->count() >= 4,"OFILECursor: Fehler im Parse Tree"); + DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Fehler im Parse Tree"); + const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); - sal_Int32 ePredicateType; sal_Unicode cEscape = L'\0'; - if (pPredicateNode->count() == 5) - ePredicateType = SQLFilterOperator::NOT_LIKE; - else - ePredicateType = SQLFilterOperator::LIKE; + const bool bNotLike = pPart2->getChild(0)->isToken(); - OSQLParseNode* pAtom = pPredicateNode->getChild(pPredicateNode->count()-2); - OSQLParseNode* pOptEscape = pPredicateNode->getChild(pPredicateNode->count()-1); + OSQLParseNode* pAtom = pPart2->getChild(pPredicateNode->count()-2); + OSQLParseNode* pOptEscape = pPart2->getChild(pPredicateNode->count()-1); if (!(pAtom->getNodeType() == SQL_NODE_STRING || SQL_ISRULE(pAtom,parameter))) { @@ -325,9 +322,9 @@ OOperand* OPredicateCompiler::execute_LIKE(OSQLParseNode* pPredicateNode) throw( execute(pPredicateNode->getChild(0)); execute(pAtom); - OBoolOperator* pOperator = (ePredicateType == SQLFilterOperator::LIKE) - ? new OOp_LIKE(cEscape) - : new OOp_NOTLIKE(cEscape); + OBoolOperator* pOperator = bNotLike + ? new OOp_NOTLIKE(cEscape) + : new OOp_LIKE(cEscape); m_aCodeList.push_back(pOperator); return NULL; @@ -335,11 +332,12 @@ OOperand* OPredicateCompiler::execute_LIKE(OSQLParseNode* pPredicateNode) throw( //------------------------------------------------------------------ OOperand* OPredicateCompiler::execute_BETWEEN(OSQLParseNode* pPredicateNode) throw(SQLException, RuntimeException) { - DBG_ASSERT(pPredicateNode->count() == 6,"OFILECursor: Fehler im Parse Tree"); + DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Fehler im Parse Tree"); OSQLParseNode* pColumn = pPredicateNode->getChild(0); - OSQLParseNode* p1stValue = pPredicateNode->getChild(3); - OSQLParseNode* p2ndtValue = pPredicateNode->getChild(5); + const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); + OSQLParseNode* p1stValue = pPart2->getChild(3); + OSQLParseNode* p2ndtValue = pPart2->getChild(5); if ( !(p1stValue->getNodeType() == SQL_NODE_STRING || SQL_ISRULE(p1stValue,parameter)) @@ -349,7 +347,7 @@ OOperand* OPredicateCompiler::execute_BETWEEN(OSQLParseNode* pPredicateNode) thr m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_BETWEEN,NULL); } - sal_Bool bNot = SQL_ISTOKEN(pPredicateNode->getChild(1),NOT); + sal_Bool bNot = SQL_ISTOKEN(pPart2->getChild(0),NOT); OOperand* pColumnOp = execute(pColumn); OOperand* pOb1 = execute(p1stValue); @@ -414,11 +412,12 @@ OOperand* OPredicateCompiler::execute_BETWEEN(OSQLParseNode* pPredicateNode) thr //------------------------------------------------------------------ OOperand* OPredicateCompiler::execute_ISNULL(OSQLParseNode* pPredicateNode) throw(SQLException, RuntimeException) { - DBG_ASSERT(pPredicateNode->count() >= 3,"OFILECursor: Fehler im Parse Tree"); - DBG_ASSERT(SQL_ISTOKEN(pPredicateNode->getChild(1),IS),"OFILECursor: Fehler im Parse Tree"); + DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Fehler im Parse Tree"); + const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); + DBG_ASSERT(SQL_ISTOKEN(pPart2->getChild(0),IS),"OFILECursor: Fehler im Parse Tree"); sal_Int32 ePredicateType; - if (SQL_ISTOKEN(pPredicateNode->getChild(2),NOT)) + if (SQL_ISTOKEN(pPart2->getChild(1),NOT)) ePredicateType = SQLFilterOperator::NOT_SQLNULL; else ePredicateType = SQLFilterOperator::SQLNULL; diff --git a/connectivity/source/drivers/kab/KStatement.cxx b/connectivity/source/drivers/kab/KStatement.cxx index aaa245d4bdcc..963a29f2725f 100644 --- a/connectivity/source/drivers/kab/KStatement.cxx +++ b/connectivity/source/drivers/kab/KStatement.cxx @@ -188,12 +188,13 @@ KabCondition *KabCommonStatement::analyseWhereClause(const OSQLParseNode *pParse } } } - else if (pParseNode->count() == 4) + else if (SQL_ISRULE(pParseNode, test_for_null) || SQL_ISRULE(pParseNode, like_predicate)) { - const OSQLParseNode *pLeft = pParseNode->getChild(0), - *pMiddleLeft = pParseNode->getChild(1), - *pMiddleRight = pParseNode->getChild(2), - *pRight = pParseNode->getChild(3); + const OSQLParseNode *pLeft = pParseNode->getChild(0); + const OSQLParseNode* pPart2 = pParseNode->getChild(1); + const OSQLParseNode *pMiddleLeft = pPart2->getChild(0), + *pMiddleRight = pPart2->getChild(1), + *pRight = pPart2->getChild(2); if (SQL_ISRULE(pParseNode, test_for_null)) { diff --git a/connectivity/source/drivers/macab/MacabStatement.cxx b/connectivity/source/drivers/macab/MacabStatement.cxx index 142ad4debcfb..728bd0f2ac43 100755 --- a/connectivity/source/drivers/macab/MacabStatement.cxx +++ b/connectivity/source/drivers/macab/MacabStatement.cxx @@ -191,12 +191,13 @@ MacabCondition *MacabCommonStatement::analyseWhereClause(const OSQLParseNode *pP } } } - else if (pParseNode->count() == 4) + else if (SQL_ISRULE(pParseNode, test_for_null) || SQL_ISRULE(pParseNode, like_predicate)) { - const OSQLParseNode *pLeft = pParseNode->getChild(0), - *pMiddleLeft = pParseNode->getChild(1), - *pMiddleRight = pParseNode->getChild(2), - *pRight = pParseNode->getChild(3); + const OSQLParseNode *pLeft = pParseNode->getChild(0); + const OSQLParseNode* pPart2 = pParseNode->getChild(1); + const OSQLParseNode *pMiddleLeft = pPart2->getChild(0), + *pMiddleRight = pPart2->getChild(1), + *pRight = pPart2->getChild(2); if (SQL_ISRULE(pParseNode, test_for_null)) { diff --git a/connectivity/source/drivers/mozab/MResultSet.cxx b/connectivity/source/drivers/mozab/MResultSet.cxx index 8e0193f303c8..428ea64256e6 100644 --- a/connectivity/source/drivers/mozab/MResultSet.cxx +++ b/connectivity/source/drivers/mozab/MResultSet.cxx @@ -885,7 +885,7 @@ void OResultSet::analyseWhereClause( const OSQLParseNode* parseT } else if (SQL_ISRULE(parseTree,like_predicate)) { - OSL_ENSURE(parseTree->count() >= 4, "Error parsing LIKE predicate"); + OSL_ENSURE(parseTree->count() == 2, "Error parsing LIKE predicate"); OSL_TRACE("analyseSQL : Got LIKE rule\n"); @@ -898,9 +898,11 @@ void OResultSet::analyseWhereClause( const OSQLParseNode* parseT OSQLParseNode *pColumn; OSQLParseNode *pAtom; OSQLParseNode *pOptEscape; + const OSQLParseNode* pPart2 = parseTree->getChild(1); pColumn = parseTree->getChild(0); // Match Item - pAtom = parseTree->getChild(parseTree->count()-2); // Match String - pOptEscape = parseTree->getChild(parseTree->count()-1); // Opt Escape Rule + pAtom = pPart2->getChild(parseTree->count()-2); // Match String + pOptEscape = pPart2->getChild(parseTree->count()-1); // Opt Escape Rule + const bool bNot = SQL_ISTOKEN(pPart2->getChild(0), NOT); if (!(pAtom->getNodeType() == SQL_NODE_STRING || pAtom->getNodeType() == SQL_NODE_NAME || @@ -948,7 +950,7 @@ void OResultSet::analyseWhereClause( const OSQLParseNode* parseT matchString.indexOf ( MATCHCHAR ) == -1 ) { // Simple string , eg. "to match" - if ( parseTree->count() == 5 ) + if ( bNot ) op = MQueryOp::DoesNotContain; else op = MQueryOp::Contains; @@ -964,12 +966,12 @@ void OResultSet::analyseWhereClause( const OSQLParseNode* parseT matchString = matchString.replaceAt( 0, 1, rtl::OUString() ); matchString = matchString.replaceAt( matchString.getLength() -1 , 1, rtl::OUString() ); - if ( parseTree->count() == 5 ) + if (bNot) op = MQueryOp::DoesNotContain; else op = MQueryOp::Contains; } - else if ( parseTree->count() == 5 ) + else if ( bNot ) { // We currently can't handle a 'NOT LIKE' when there are '%' or // '_' dispersed throughout @@ -1023,15 +1025,16 @@ void OResultSet::analyseWhereClause( const OSQLParseNode* parseT } else if (SQL_ISRULE(parseTree,test_for_null)) { - OSL_ENSURE(parseTree->count() >= 3,"Error in ParseTree"); - OSL_ENSURE(SQL_ISTOKEN(parseTree->getChild(1),IS),"Error in ParseTree"); + OSL_ENSURE(parseTree->count() == 2,"Error in ParseTree"); + const OSQLParseNode* pPart2 = parseTree->getChild(1); + OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"Error in ParseTree"); if (!SQL_ISRULE(parseTree->getChild(0),column_ref)) { m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_IS_NULL_COLUMN, *this ); } - if (SQL_ISTOKEN(parseTree->getChild(2),NOT)) + if (SQL_ISTOKEN(pPart2->getChild(1),NOT)) { op = MQueryOp::Exists; } diff --git a/connectivity/source/parse/sqliterator.cxx b/connectivity/source/parse/sqliterator.cxx index 42486ed73ab5..18d3ce25ad98 100644 --- a/connectivity/source/parse/sqliterator.cxx +++ b/connectivity/source/parse/sqliterator.cxx @@ -53,6 +53,10 @@ #include "diagnose_ex.h" #include <rtl/logfile.hxx> +#define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \ + (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2))) + using namespace ::comphelper; using namespace ::connectivity; using namespace ::connectivity::sdbcx; @@ -70,6 +74,7 @@ namespace connectivity { struct OSQLParseTreeIteratorImpl { + ::std::vector< TNodePair > m_aJoinConditions; Reference< XConnection > m_xConnection; Reference< XDatabaseMetaData > m_xDatabaseMetaData; Reference< XNameAccess > m_xTableContainer; @@ -479,7 +484,42 @@ void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQ if ( aTable.is() ) _rTables[ aTableRange ] = aTable; } - +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition) +{ + if (i_pJoinCondition->count() == 3 && // Ausdruck is geklammert + SQL_ISPUNCTUATION(i_pJoinCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(i_pJoinCondition->getChild(2),")")) + { + impl_fillJoinConditions(i_pJoinCondition->getChild(1)); + } + else if (SQL_ISRULEOR2(i_pJoinCondition,search_condition,boolean_term) && // AND/OR-Verknuepfung: + i_pJoinCondition->count() == 3) + { + // nur AND Verknpfung zulassen + if ( SQL_ISTOKEN(i_pJoinCondition->getChild(1),AND) ) + { + impl_fillJoinConditions(i_pJoinCondition->getChild(0)); + impl_fillJoinConditions(i_pJoinCondition->getChild(1)); + } + } + else if (SQL_ISRULE(i_pJoinCondition,comparison_predicate)) + { + // only the comparison of columns is allowed + OSL_ENSURE(i_pJoinCondition->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree"); + if (SQL_ISRULE(i_pJoinCondition->getChild(0),column_ref) && + SQL_ISRULE(i_pJoinCondition->getChild(2),column_ref) && + i_pJoinCondition->getChild(1)->getNodeType() == SQL_NODE_EQUAL) + { + m_pImpl->m_aJoinConditions.push_back( TNodePair(i_pJoinCondition->getChild(0),i_pJoinCondition->getChild(2)) ); + } + } +} +//----------------------------------------------------------------------------- +::std::vector< TNodePair >& OSQLParseTreeIterator::getJoinConditions() const +{ + return m_pImpl->m_aJoinConditions; +} //----------------------------------------------------------------------------- void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange ) { @@ -494,8 +534,30 @@ void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLP traverseOneTableName( _rTables, pNode, aTableRange ); sal_uInt32 nPos = 4; - if(SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL) + if( SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL) + { nPos = 3; + // join_condition,named_columns_join + if ( SQL_ISRULE( pTableRef, qualified_join ) ) + { + const OSQLParseNode* pJoin_spec = pTableRef->getChild(4); + if ( SQL_ISRULE( pJoin_spec, join_condition ) ) + { + impl_fillJoinConditions(pJoin_spec->getChild(1)); + } + else + { + const OSQLParseNode* pColumnCommalist = pJoin_spec->getChild(2); + // Alle Columns in der column_commalist ... + for (sal_uInt32 i = 0; i < pColumnCommalist->count(); i++) + { + const OSQLParseNode * pCol = pColumnCommalist->getChild(i); + // add twice because the column must exists in both tables + m_pImpl->m_aJoinConditions.push_back( TNodePair(pCol,pCol) ); + } + } + } + } pNode = getTableNode(_rTables,pTableRef->getChild(nPos),aTableRange); if ( isTableNode( pNode ) ) @@ -1118,17 +1180,17 @@ void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode) else pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); } // if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X - else if ( SQL_ISRULE(pParent,like_predicate) ) + else if ( SQL_ISRULE(pParent,other_like_predicate_part_2) ) { - const OSQLParseNode* pOther = pParent->getChild(0); + const OSQLParseNode* pOther = pParent->getParent()->getChild(0); if ( SQL_ISRULE( pOther, column_ref ) ) getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias); else pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); } - else if ( SQL_ISRULE(pParent,between_predicate) ) + else if ( SQL_ISRULE(pParent,between_predicate_part_2) ) { - const OSQLParseNode* pOther = pParent->getChild(0); + const OSQLParseNode* pOther = pParent->getParent()->getChild(0); if ( SQL_ISRULE( pOther, column_ref ) ) getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias); else @@ -1307,17 +1369,19 @@ void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition ::rtl::OUString aValue; pSearchCondition->getChild(2)->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); traverseOnePredicate(pSearchCondition->getChild(0),aValue,pSearchCondition->getChild(2)); + impl_fillJoinConditions(pSearchCondition); // if (! aIteratorStatus.IsSuccessful()) // return; } else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) { - OSL_ENSURE(pSearchCondition->count() >= 4,"OSQLParseTreeIterator: error in parse tree!"); + OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); + const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); - sal_Int32 nCurentPos = pSearchCondition->count()-2; + sal_Int32 nCurentPos = pPart2->count()-2; - OSQLParseNode * pNum_value_exp = pSearchCondition->getChild(nCurentPos); - OSQLParseNode * pOptEscape = pSearchCondition->getChild(nCurentPos+1); + OSQLParseNode * pNum_value_exp = pPart2->getChild(nCurentPos); + OSQLParseNode * pOptEscape = pPart2->getChild(nCurentPos+1); OSL_ENSURE(pNum_value_exp != NULL,"OSQLParseTreeIterator: error in parse tree!"); OSL_ENSURE(pOptEscape != NULL,"OSQLParseTreeIterator: error in parse tree!"); @@ -1347,12 +1411,13 @@ void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition } else if (SQL_ISRULE(pSearchCondition,in_predicate)) { - OSL_ENSURE(pSearchCondition->count() == 4,"OSQLParseTreeIterator: error in parse tree!"); + OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); + const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); traverseORCriteria(pSearchCondition->getChild(0)); // if (! aIteratorStatus.IsSuccessful()) return; - OSQLParseNode* pChild = pSearchCondition->getChild(3); + OSQLParseNode* pChild = pPart2->getChild(2); if ( SQL_ISRULE(pChild->getChild(0),subquery) ) { traverseTableNames( *m_pImpl->m_pSubTables ); @@ -1370,8 +1435,9 @@ void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition } else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) { - OSL_ENSURE(pSearchCondition->count() >= 3,"OSQLParseTreeIterator: error in parse tree!"); - OSL_ENSURE(SQL_ISTOKEN(pSearchCondition->getChild(1),IS),"OSQLParseTreeIterator: error in parse tree!"); + OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); + const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); + OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"OSQLParseTreeIterator: error in parse tree!"); ::rtl::OUString aString; traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL); @@ -1430,7 +1496,14 @@ void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode {// found a function as column_ref ::rtl::OUString sFunctionName; _pColumnRef->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); - sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() ); + const sal_uInt32 nCount = _pColumnRef->count(); + sal_uInt32 i = 0; + for(; i < nCount;++i) + { + if ( _pColumnRef->getChild(i) == _pParseNode ) + break; + } + sal_Int32 nType = ::connectivity::OSQLParser::getFunctionParameterType( _pColumnRef->getParent()->getChild(0)->getTokenID(), i+1); OParseColumn* pColumn = new OParseColumn( sParameterName, ::rtl::OUString(), diff --git a/connectivity/source/parse/sqlnode.cxx b/connectivity/source/parse/sqlnode.cxx index 12f608c68d47..f2a9085ae800 100644 --- a/connectivity/source/parse/sqlnode.cxx +++ b/connectivity/source/parse/sqlnode.cxx @@ -680,7 +680,7 @@ void OSQLParseNode::impl_parseTableRangeNodeToString_throw(::rtl::OUStringBuffer void OSQLParseNode::impl_parseLikeNodeToString_throw( ::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseNode::impl_parseLikeNodeToString_throw" ); - OSL_ENSURE(count() >= 4,"count != 5: Prepare for GPF"); + OSL_ENSURE(count() == 2,"count != 2: Prepare for GPF"); const OSQLParseNode* pEscNode = NULL; const OSQLParseNode* pParaNode = NULL; @@ -717,13 +717,14 @@ void OSQLParseNode::impl_parseLikeNodeToString_throw( ::rtl::OUStringBuffer& rSt if (bAddName) m_aChildren[0]->impl_parseNodeToString_throw( rString, aNewParam ); - m_aChildren[1]->impl_parseNodeToString_throw( rString, aNewParam ); - if(count() == 5) - m_aChildren[2]->impl_parseNodeToString_throw( rString, aNewParam ); + const OSQLParseNode* pPart2 = m_aChildren[1]; + pPart2->getChild(1)->impl_parseNodeToString_throw( rString, aNewParam ); + if (SQL_ISTOKEN(pPart2->getChild(0), NOT)) + pPart2->getChild(2)->impl_parseNodeToString_throw( rString, aNewParam ); - sal_Int32 nCurentPos = m_aChildren.size()-2; - pParaNode = m_aChildren[nCurentPos]; - pEscNode = m_aChildren[nCurentPos+1]; + sal_Int32 nCurentPos = pPart2->count() - 2; + pParaNode = pPart2->getChild(nCurentPos); + pEscNode = pPart2->getChild(nCurentPos+1); if (pParaNode->isToken()) { @@ -1428,7 +1429,9 @@ OSQLParser::OSQLParser(const ::com::sun::star::uno::Reference< ::com::sun::star: { OSQLParseNode::bit_value_fct, "bit_value_fct" }, { OSQLParseNode::comparison_predicate_part_2, "comparison_predicate_part_2" }, { OSQLParseNode::parenthesized_boolean_value_expression, "parenthesized_boolean_value_expression" }, - { OSQLParseNode::character_string_type, "character_string_type" } + { OSQLParseNode::character_string_type, "character_string_type" }, + { OSQLParseNode::other_like_predicate_part_2, "other_like_predicate_part_2" }, + { OSQLParseNode::between_predicate_part_2, "between_predicate_part_2" } }; size_t nRuleMapCount = sizeof( aRuleDescriptions ) / sizeof( aRuleDescriptions[0] ); OSL_ENSURE( nRuleMapCount == size_t( OSQLParseNode::rule_count ), "OSQLParser::OSQLParser: added a new rule? Adjust this map!" ); @@ -1990,39 +1993,34 @@ void OSQLParseNode::negateSearchCondition(OSQLParseNode*& pSearchCondition,sal_B else if(bNegate && (SQL_ISRULE(pSearchCondition,test_for_null) || SQL_ISRULE(pSearchCondition,in_predicate) || SQL_ISRULE(pSearchCondition,between_predicate) || SQL_ISRULE(pSearchCondition,boolean_test) )) { + OSQLParseNode* pPart2 = pSearchCondition; + if ( !SQL_ISRULE(pSearchCondition,boolean_test) ) + pPart2 = pSearchCondition->getChild(1); sal_uInt32 nNotPos = 0; - // row_value_constructor not SQL_TOKEN_IN in_predicate_value - // row_value_constructor not SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor - if ( SQL_ISRULE( pSearchCondition, in_predicate ) - || SQL_ISRULE( pSearchCondition, between_predicate ) - ) + if ( SQL_ISRULE( pSearchCondition, test_for_null ) ) nNotPos = 1; - // row_value_constructor SQL_TOKEN_IS not SQL_TOKEN_NULL - // boolean_primary SQL_TOKEN_IS not truth_value - else if ( SQL_ISRULE( pSearchCondition, test_for_null ) - || SQL_ISRULE( pSearchCondition, boolean_test ) - ) + else if ( SQL_ISRULE( pSearchCondition, boolean_test ) ) nNotPos = 2; - OSQLParseNode* pNot = pSearchCondition->getChild(nNotPos); + OSQLParseNode* pNot = pPart2->getChild(nNotPos); OSQLParseNode* pNotNot = NULL; if(pNot->isRule()) pNotNot = new OSQLParseNode(::rtl::OUString::createFromAscii("NOT"),SQL_NODE_KEYWORD,SQL_TOKEN_NOT); else pNotNot = new OSQLParseNode(::rtl::OUString(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::sql_not)); - pSearchCondition->replace(pNot, pNotNot); + pPart2->replace(pNot, pNotNot); delete pNot; } else if(bNegate && (SQL_ISRULE(pSearchCondition,like_predicate))) { - OSQLParseNode* pCheckForNOT = pSearchCondition->getChild( 1 ); - if ( SQL_ISTOKEN(pCheckForNOT,NOT) ) - delete pSearchCondition->removeAt( 1 ); + OSQLParseNode* pNot = pSearchCondition->getChild( 1 )->getChild( 0 ); + OSQLParseNode* pNotNot = NULL; + if(pNot->isRule()) + pNotNot = new OSQLParseNode(::rtl::OUString::createFromAscii("NOT"),SQL_NODE_KEYWORD,SQL_TOKEN_NOT); else - { - OSQLParseNode* pNot = new OSQLParseNode( ::rtl::OUString::createFromAscii( "NOT" ), SQL_NODE_KEYWORD, SQL_TOKEN_NOT ); - pSearchCondition->insert( 1, pNot ); - } + pNotNot = new OSQLParseNode(::rtl::OUString(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::sql_not)); + pSearchCondition->getChild( 1 )->replace(pNot, pNotNot); + delete pNot; } } //----------------------------------------------------------------------------- |