summaryrefslogtreecommitdiff
path: root/connectivity/source/parse/sqliterator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'connectivity/source/parse/sqliterator.cxx')
-rw-r--r--connectivity/source/parse/sqliterator.cxx2247
1 files changed, 2247 insertions, 0 deletions
diff --git a/connectivity/source/parse/sqliterator.cxx b/connectivity/source/parse/sqliterator.cxx
new file mode 100644
index 000000000000..e1d805e9a1e5
--- /dev/null
+++ b/connectivity/source/parse/sqliterator.cxx
@@ -0,0 +1,2247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_connectivity.hxx"
+#include "connectivity/sqliterator.hxx"
+#include "connectivity/sdbcx/VTable.hxx"
+#include <connectivity/sqlparse.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/sqlerror.hxx>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdb/ErrorCondition.hpp>
+#ifdef SQL_TEST_PARSETREEITERATOR
+#include <iostream>
+#endif
+#include "connectivity/PColumn.hxx"
+#include "connectivity/dbtools.hxx"
+#include <tools/diagnose_ex.h>
+#include "TConnection.hxx"
+#include <comphelper/types.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+#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;
+using namespace ::dbtools;
+using namespace ::connectivity::parse;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+
+namespace connectivity
+{
+ struct OSQLParseTreeIteratorImpl
+ {
+ ::std::vector< TNodePair > m_aJoinConditions;
+ Reference< XConnection > m_xConnection;
+ Reference< XDatabaseMetaData > m_xDatabaseMetaData;
+ Reference< XNameAccess > m_xTableContainer;
+ Reference< XNameAccess > m_xQueryContainer;
+
+ ::boost::shared_ptr< OSQLTables > m_pTables; /// all tables which participate in the SQL statement
+ ::boost::shared_ptr< OSQLTables > m_pSubTables; /// all tables from sub queries not the tables from the select tables
+ ::boost::shared_ptr< QueryNameSet > m_pForbiddenQueryNames;
+
+ sal_uInt32 m_nIncludeMask;
+
+ bool m_bIsCaseSensitive;
+
+ OSQLParseTreeIteratorImpl( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxTables )
+ :m_xConnection( _rxConnection )
+ ,m_nIncludeMask( OSQLParseTreeIterator::All )
+ ,m_bIsCaseSensitive( true )
+ {
+ OSL_PRECOND( m_xConnection.is(), "OSQLParseTreeIteratorImpl::OSQLParseTreeIteratorImpl: invalid connection!" );
+ m_xDatabaseMetaData = m_xConnection->getMetaData();
+
+ m_bIsCaseSensitive = m_xDatabaseMetaData.is() && m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers();
+ m_pTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
+ m_pSubTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
+
+ m_xTableContainer = _rxTables;
+
+ DatabaseMetaData aMetaData( m_xConnection );
+ if ( aMetaData.supportsSubqueriesInFrom() )
+ {
+ // connections might support the XQueriesSupplier interface, if they implement the css.sdb.Connection
+ // service
+ Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY );
+ if ( xSuppQueries.is() )
+ m_xQueryContainer = xSuppQueries->getQueries();
+ }
+ }
+
+ public:
+ inline bool isQueryAllowed( const ::rtl::OUString& _rQueryName )
+ {
+ if ( !m_pForbiddenQueryNames.get() )
+ return true;
+ if ( m_pForbiddenQueryNames->find( _rQueryName ) == m_pForbiddenQueryNames->end() )
+ return true;
+ return false;
+ }
+ };
+
+ //-------------------------------------------------------------------------
+ /** helper class for temporarily adding a query name to a list of forbidden query names
+ */
+ class ForbidQueryName
+ {
+ ::boost::shared_ptr< QueryNameSet >& m_rpAllForbiddenNames;
+ ::rtl::OUString m_sForbiddenQueryName;
+
+ public:
+ ForbidQueryName( OSQLParseTreeIteratorImpl& _rIteratorImpl, const ::rtl::OUString _rForbiddenQueryName )
+ :m_rpAllForbiddenNames( _rIteratorImpl.m_pForbiddenQueryNames )
+ ,m_sForbiddenQueryName( _rForbiddenQueryName )
+ {
+ if ( !m_rpAllForbiddenNames.get() )
+ m_rpAllForbiddenNames.reset( new QueryNameSet );
+ m_rpAllForbiddenNames->insert( m_sForbiddenQueryName );
+ }
+
+ ~ForbidQueryName()
+ {
+ m_rpAllForbiddenNames->erase( m_sForbiddenQueryName );
+ }
+ };
+}
+//-----------------------------------------------------------------------------
+OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XConnection >& _rxConnection,
+ const Reference< XNameAccess >& _rxTables,
+ const OSQLParser& _rParser,
+ const OSQLParseNode* pRoot )
+ :m_rParser( _rParser )
+ ,m_pImpl( new OSQLParseTreeIteratorImpl( _rxConnection, _rxTables ) )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
+ setParseTree(pRoot);
+}
+
+//-----------------------------------------------------------------------------
+OSQLParseTreeIterator::OSQLParseTreeIterator( const OSQLParseTreeIterator& _rParentIterator, const OSQLParser& _rParser, const OSQLParseNode* pRoot )
+ :m_rParser( _rParser )
+ ,m_pImpl( new OSQLParseTreeIteratorImpl( _rParentIterator.m_pImpl->m_xConnection, _rParentIterator.m_pImpl->m_xTableContainer ) )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
+ m_pImpl->m_pForbiddenQueryNames = _rParentIterator.m_pImpl->m_pForbiddenQueryNames;
+ setParseTree( pRoot );
+}
+
+//-----------------------------------------------------------------------------
+OSQLParseTreeIterator::~OSQLParseTreeIterator()
+{
+ dispose();
+}
+
+// -----------------------------------------------------------------------------
+const OSQLTables& OSQLParseTreeIterator::getTables() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTables" );
+ return *m_pImpl->m_pTables;
+}
+
+// -----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::isCaseSensitive() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isCaseSensitive" );
+ return m_pImpl->m_bIsCaseSensitive;
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::dispose()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::dispose" );
+ m_aSelectColumns = NULL;
+ m_aGroupColumns = NULL;
+ m_aOrderColumns = NULL;
+ m_aParameters = NULL;
+ m_pImpl->m_xTableContainer = NULL;
+ m_pImpl->m_xDatabaseMetaData = NULL;
+ m_aCreateColumns = NULL;
+ m_pImpl->m_pTables->clear();
+ m_pImpl->m_pSubTables->clear();
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setParseTree" );
+ m_pImpl->m_pTables->clear();
+ m_pImpl->m_pSubTables->clear();
+
+ m_aSelectColumns = new OSQLColumns();
+ m_aGroupColumns = new OSQLColumns();
+ m_aOrderColumns = new OSQLColumns();
+ m_aParameters = new OSQLColumns();
+ m_aCreateColumns = new OSQLColumns();
+
+ m_pParseTree = pNewParseTree;
+ if (!m_pParseTree)
+ {
+ m_eStatementType = SQL_STATEMENT_UNKNOWN;
+ return;
+ }
+
+ // falls m_pParseTree aber keine Connection, dann Fehler
+ if ( !m_pImpl->m_xTableContainer.is() )
+ return;
+
+ m_aErrors = SQLException();
+
+
+ // Statement-Typ ermitteln ...
+ if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) )
+ {
+ m_eStatementType = SQL_STATEMENT_SELECT;
+ }
+ else if (SQL_ISRULE(m_pParseTree,insert_statement))
+ {
+ m_eStatementType = SQL_STATEMENT_INSERT;
+ }
+ else if (SQL_ISRULE(m_pParseTree,update_statement_searched))
+ {
+ m_eStatementType = SQL_STATEMENT_UPDATE;
+ }
+ else if (SQL_ISRULE(m_pParseTree,delete_statement_searched))
+ {
+ m_eStatementType = SQL_STATEMENT_DELETE;
+ }
+ else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec))
+ {
+ m_eStatementType = SQL_STATEMENT_ODBC_CALL;
+ }
+ else if (SQL_ISRULE(m_pParseTree->getChild(0),base_table_def))
+ {
+ m_eStatementType = SQL_STATEMENT_CREATE_TABLE;
+ m_pParseTree = m_pParseTree->getChild(0);
+ }
+ else
+ {
+ m_eStatementType = SQL_STATEMENT_UNKNOWN;
+ //aIteratorStatus.setInvalidStatement();
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+namespace
+{
+ //.........................................................................
+ static void impl_getRowString( const Reference< XRow >& _rxRow, const sal_Int32 _nColumnIndex, ::rtl::OUString& _out_rString )
+ {
+ _out_rString = _rxRow->getString( _nColumnIndex );
+ if ( _rxRow->wasNull() )
+ _out_rString= ::rtl::OUString();
+ }
+
+ //.........................................................................
+ static ::rtl::OUString lcl_findTableInMetaData(
+ const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rCatalog,
+ const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rTableName )
+ {
+ ::rtl::OUString sComposedName;
+
+ static const ::rtl::OUString s_sTableTypeView(RTL_CONSTASCII_USTRINGPARAM("VIEW"));
+ static const ::rtl::OUString s_sTableTypeTable(RTL_CONSTASCII_USTRINGPARAM("TABLE"));
+ static const ::rtl::OUString s_sWildcard = ::rtl::OUString::createFromAscii("%");
+
+ // we want all catalogues, all schemas, all tables
+ Sequence< ::rtl::OUString > sTableTypes(3);
+ sTableTypes[0] = s_sTableTypeView;
+ sTableTypes[1] = s_sTableTypeTable;
+ sTableTypes[2] = s_sWildcard; // just to be sure to include anything else ....
+
+ if ( _rxDBMeta.is() )
+ {
+ sComposedName = ::rtl::OUString();
+
+ Reference< XResultSet> xRes = _rxDBMeta->getTables(
+ _rCatalog.getLength() ? makeAny( _rCatalog ) : Any(), _rSchema.getLength() ? _rSchema : s_sWildcard, _rTableName, sTableTypes );
+
+ Reference< XRow > xCurrentRow( xRes, UNO_QUERY );
+ if ( xCurrentRow.is() && xRes->next() )
+ {
+ ::rtl::OUString sCatalog, sSchema, sName;
+
+ impl_getRowString( xCurrentRow, 1, sCatalog );
+ impl_getRowString( xCurrentRow, 2, sSchema );
+ impl_getRowString( xCurrentRow, 3, sName );
+
+ sComposedName = ::dbtools::composeTableName(
+ _rxDBMeta,
+ sCatalog,
+ sSchema,
+ sName,
+ sal_False,
+ ::dbtools::eInDataManipulation
+ );
+ }
+ }
+ return sComposedName;
+ }
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::impl_getQueryParameterColumns( const OSQLTable& _rQuery )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_getQueryParameterColumns" );
+ if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
+ // parameters not to be included in the traversal
+ return;
+
+ ::vos::ORef< OSQLColumns > pSubQueryParameterColumns( new OSQLColumns() );
+
+ // get the command and the EscapeProcessing properties from the sub query
+ ::rtl::OUString sSubQueryCommand;
+ sal_Bool bEscapeProcessing = sal_False;
+ try
+ {
+ Reference< XPropertySet > xQueryProperties( _rQuery, UNO_QUERY_THROW );
+ OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sSubQueryCommand );
+ OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ // parse the sub query
+ do {
+
+ if ( !bEscapeProcessing || ( sSubQueryCommand.getLength() == 0 ) )
+ break;
+
+ ::rtl::OUString sError;
+ ::std::auto_ptr< OSQLParseNode > pSubQueryNode( const_cast< OSQLParser& >( m_rParser ).parseTree( sError, sSubQueryCommand, sal_False ) );
+ if ( !pSubQueryNode.get() )
+ break;
+
+ OSQLParseTreeIterator aSubQueryIterator( *this, m_rParser, pSubQueryNode.get() );
+ aSubQueryIterator.traverseSome( Parameters | SelectColumns );
+ // SelectColumns might also contain parameters
+ // #i77635# - 2007-07-23 / frank.schoenheit@sun.com
+ pSubQueryParameterColumns = aSubQueryIterator.getParameters();
+ aSubQueryIterator.dispose();
+
+ } while ( false );
+
+ // copy the parameters of the sub query to our own parameter array
+ ::std::copy( pSubQueryParameterColumns->get().begin(), pSubQueryParameterColumns->get().end(),
+ ::std::insert_iterator< OSQLColumns::Vector >( m_aParameters->get(), m_aParameters->get().end() ) );
+}
+
+//-----------------------------------------------------------------------------
+OSQLTable OSQLParseTreeIterator::impl_locateRecordSource( const ::rtl::OUString& _rComposedName )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_locateRecordSource" );
+ if ( !_rComposedName.getLength() )
+ {
+ OSL_ENSURE( false, "OSQLParseTreeIterator::impl_locateRecordSource: no object name at all?" );
+ return OSQLTable();
+ }
+
+ OSQLTable aReturn;
+ ::rtl::OUString sComposedName( _rComposedName );
+
+ try
+ {
+ ::rtl::OUString sCatalog, sSchema, sName;
+ qualifiedNameComponents( m_pImpl->m_xDatabaseMetaData, sComposedName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
+
+ // check whether there is a query with the given name
+ bool bQueryDoesExist = m_pImpl->m_xQueryContainer.is() && m_pImpl->m_xQueryContainer->hasByName( sComposedName );
+
+ // check whether the table container contains an object with the given name
+ if ( !bQueryDoesExist && !m_pImpl->m_xTableContainer->hasByName( sComposedName ) )
+ sComposedName = lcl_findTableInMetaData( m_pImpl->m_xDatabaseMetaData, sCatalog, sSchema, sName );
+ bool bTableDoesExist = m_pImpl->m_xTableContainer->hasByName( sComposedName );
+
+ // now obtain the object
+
+ // if we're creating a table, and there already is a table or query with the same name,
+ // this is worth an error
+ if ( SQL_STATEMENT_CREATE_TABLE == m_eStatementType )
+ {
+ if ( bQueryDoesExist )
+ impl_appendError( IParseContext::ERROR_INVALID_QUERY_EXIST, &sName );
+ else if ( bTableDoesExist )
+ impl_appendError( IParseContext::ERROR_INVALID_TABLE_EXIST, &sName );
+ else
+ aReturn = impl_createTableObject( sName, sCatalog, sSchema );
+ }
+ else
+ {
+ // queries win over tables, so if there's a query with this name, take this, no matter if
+ // there's a table, too
+ if ( bQueryDoesExist )
+ {
+ if ( !m_pImpl->isQueryAllowed( sComposedName ) )
+ {
+ impl_appendError( m_rParser.getErrorHelper().getSQLException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES, NULL ) );
+ return NULL;
+ }
+
+ m_pImpl->m_xQueryContainer->getByName( sComposedName ) >>= aReturn;
+
+ // collect the parameters from the sub query
+ ForbidQueryName aForbidName( *m_pImpl, sComposedName );
+ impl_getQueryParameterColumns( aReturn );
+ }
+ else if ( bTableDoesExist )
+ m_pImpl->m_xTableContainer->getByName( sComposedName ) >>= aReturn;
+ else
+ {
+ if ( m_pImpl->m_xQueryContainer.is() )
+ // the connection on which we're working supports sub queries in from (else
+ // m_xQueryContainer would not have been set), so emit a better error message
+ impl_appendError( IParseContext::ERROR_INVALID_TABLE_OR_QUERY, &sName );
+ else
+ impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sName );
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sComposedName );
+ }
+
+ return aReturn;
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOneTableName" );
+ if ( ( m_pImpl->m_nIncludeMask & TableNames ) != TableNames )
+ // tables should not be included in the traversal
+ return;
+
+ OSL_ENSURE(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL");
+
+ Any aCatalog;
+ ::rtl::OUString aSchema,aTableName,aComposedName;
+ ::rtl::OUString aTableRange(rTableRange);
+
+ // Tabellenname abholen
+ OSQLParseNode::getTableComponents(pTableName,aCatalog,aSchema,aTableName,m_pImpl->m_xDatabaseMetaData);
+
+ // create the composed name like DOMAIN.USER.TABLE1
+ aComposedName = ::dbtools::composeTableName(m_pImpl->m_xDatabaseMetaData,
+ aCatalog.hasValue() ? ::comphelper::getString(aCatalog) : ::rtl::OUString(),
+ aSchema,
+ aTableName,
+ sal_False,
+ ::dbtools::eInDataManipulation);
+
+ // if there is no alias for the table name assign the orignal name to it
+ if ( !aTableRange.getLength() )
+ aTableRange = aComposedName;
+
+ // get the object representing this table/query
+ OSQLTable aTable = impl_locateRecordSource( aComposedName );
+ 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 Verknüpfung 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 )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getQualified_join" );
+ OSL_PRECOND( SQL_ISRULE( pTableRef, cross_union ) || SQL_ISRULE( pTableRef, qualified_join ) ,
+ "OSQLParseTreeIterator::getQualified_join: illegal node!" );
+
+ aTableRange = ::rtl::OUString();
+
+ const OSQLParseNode* pNode = getTableNode(_rTables,pTableRef->getChild(0),aTableRange);
+ if ( isTableNode( pNode ) )
+ traverseOneTableName( _rTables, pNode, aTableRange );
+
+ sal_uInt32 nPos = 4;
+ 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 ) )
+ traverseOneTableName( _rTables, pNode, aTableRange );
+}
+//-----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getTableNode( OSQLTables& _rTables, const OSQLParseNode *pTableRef,::rtl::OUString& rTableRange )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTableNode" );
+ OSL_PRECOND( SQL_ISRULE( pTableRef, table_ref ) || SQL_ISRULE( pTableRef, joined_table )
+ || SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ),
+ "OSQLParseTreeIterator::getTableNode: only to be called for table_ref nodes!" );
+
+ const OSQLParseNode* pTableNameNode = NULL;
+
+ if ( SQL_ISRULE( pTableRef, joined_table ) )
+ {
+ getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
+ }
+ if ( SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ) )
+ {
+ getQualified_join( _rTables, pTableRef, rTableRange );
+ }
+ else
+ {
+ rTableRange = OSQLParseNode::getTableRange(pTableRef);
+ if ( ( pTableRef->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
+ || ( pTableRef->count() == 5 ) // '(' joined_table ')' range_variable op_column_commalist
+ )
+ {
+ getQualified_join( _rTables, pTableRef->getChild(6 - pTableRef->count()), rTableRange );
+ }
+ else if ( pTableRef->count() == 3 ) // subquery range_variable op_column_commalist || '(' joined_table ')'
+ {
+ const OSQLParseNode* pSubQuery = pTableRef->getChild(0);
+ if ( pSubQuery->isToken() )
+ {
+ getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
+ }
+ else
+ {
+ OSL_ENSURE( pSubQuery->count() == 3, "sub queries should have 3 children!" );
+ const OSQLParseNode* pQueryExpression = pSubQuery->getChild(1);
+ if ( SQL_ISRULE( pQueryExpression, select_statement ) )
+ {
+ getSelect_statement( *m_pImpl->m_pSubTables, pQueryExpression );
+ }
+ else
+ {
+ OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: subquery which is no select_statement: not yet implemented!" );
+ }
+ }
+ }
+ else if ( pTableRef->count() == 2 ) // table_node table_primary_as_range_column
+ {
+ pTableNameNode = pTableRef->getChild(0);
+ }
+ else
+ OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: unhandled case!" );
+ }
+
+ return pTableNameNode;
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSelect_statement" );
+ if(SQL_ISRULE(pSelect,union_statement))
+ {
+ getSelect_statement(_rTables,pSelect->getChild(0));
+ //getSelect_statement(pSelect->getChild(3));
+ return;
+ }
+ OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1);
+
+ OSL_ENSURE(pTableRefCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: error in parse tree!");
+
+ const OSQLParseNode* pTableName = NULL;
+ ::rtl::OUString aTableRange;
+ for (sal_uInt32 i = 0; i < pTableRefCommalist->count(); i++)
+ { // from clause durchlaufen
+ aTableRange = ::rtl::OUString();
+
+ const OSQLParseNode* pTableListElement = pTableRefCommalist->getChild(i);
+ if ( isTableNode( pTableListElement ) )
+ {
+ traverseOneTableName( _rTables, pTableListElement, aTableRange );
+ }
+ else if ( SQL_ISRULE( pTableListElement, table_ref ) )
+ {
+ // Tabellenreferenz kann aus Tabellennamen, Tabellennamen (+),'('joined_table')'(+) bestehen
+ pTableName = pTableListElement->getChild(0);
+ if( isTableNode( pTableName ) )
+ { // Tabellennamen gefunden
+ aTableRange = OSQLParseNode::getTableRange(pTableListElement);
+ traverseOneTableName( _rTables, pTableName, aTableRange );
+ }
+ else if(SQL_ISPUNCTUATION(pTableName,"{"))
+ { // '{' SQL_TOKEN_OJ joined_table '}'
+ getQualified_join( _rTables, pTableListElement->getChild(2), aTableRange );
+ }
+ else
+ { // '(' joined_table ')' range_variable op_column_commalist
+ getTableNode( _rTables, pTableListElement, aTableRange );
+ }
+ }
+ else if (SQL_ISRULE( pTableListElement, qualified_join ) || SQL_ISRULE( pTableListElement, cross_union ) )
+ {
+ getQualified_join( _rTables, pTableListElement, aTableRange );
+ }
+ else if ( SQL_ISRULE( pTableListElement, joined_table ) )
+ {
+ getQualified_join( _rTables, pTableListElement->getChild(1), aTableRange );
+ }
+
+ // if (! aIteratorStatus.IsSuccessful()) break;
+ }
+}
+//-----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::traverseTableNames(OSQLTables& _rTables)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseTableNames" );
+ if ( m_pParseTree == NULL )
+ return false;
+
+ OSQLParseNode* pTableName = NULL;
+
+ switch ( m_eStatementType )
+ {
+ case SQL_STATEMENT_SELECT:
+ getSelect_statement( _rTables, m_pParseTree );
+ break;
+
+ case SQL_STATEMENT_CREATE_TABLE:
+ case SQL_STATEMENT_INSERT:
+ case SQL_STATEMENT_DELETE:
+ pTableName = m_pParseTree->getChild(2);
+ break;
+
+ case SQL_STATEMENT_UPDATE:
+ pTableName = m_pParseTree->getChild(1);
+ break;
+ default:
+ break;
+ }
+
+ if ( pTableName )
+ {
+ ::rtl::OUString sTableRange;
+ traverseOneTableName( _rTables, pTableName, sTableRange );
+ }
+
+ return !hasErrors();
+}
+//-----------------------------------------------------------------------------
+::rtl::OUString OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* _pDerivedColumn)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnAlias" );
+ OSL_ENSURE(SQL_ISRULE(_pDerivedColumn,derived_column),"No derived column!");
+ ::rtl::OUString sColumnAlias;
+ if(_pDerivedColumn->getChild(1)->count() == 2)
+ sColumnAlias = _pDerivedColumn->getChild(1)->getChild(1)->getTokenValue();
+ else if(!_pDerivedColumn->getChild(1)->isRule())
+ sColumnAlias = _pDerivedColumn->getChild(1)->getTokenValue();
+ return sColumnAlias;
+}
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ void lcl_getColumnRange( const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection,
+ ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange,
+ const OSQLColumns* _pSelectColumns, ::rtl::OUString& _out_rColumnAliasIfPresent )
+ {
+ _out_rColumnName = _out_rTableRange = _out_rColumnAliasIfPresent = ::rtl::OUString();
+ if ( SQL_ISRULE( _pColumnRef, column_ref ) )
+ {
+ if( _pColumnRef->count() > 1 )
+ {
+ for ( sal_Int32 i=0; i<((sal_Int32)_pColumnRef->count())-2; ++i )
+ _pColumnRef->getChild(i)->parseNodeToStr( _out_rTableRange, _rxConnection, NULL, sal_False, sal_False );
+ _out_rColumnName = _pColumnRef->getChild( _pColumnRef->count()-1 )->getChild(0)->getTokenValue();
+ }
+ else
+ _out_rColumnName = _pColumnRef->getChild(0)->getTokenValue();
+
+ // look up the column in the select column, to find an possible alias
+ if ( _pSelectColumns )
+ {
+ for ( OSQLColumns::Vector::const_iterator lookupColumn = _pSelectColumns->get().begin();
+ lookupColumn != _pSelectColumns->get().end();
+ ++lookupColumn
+ )
+ {
+ Reference< XPropertySet > xColumn( *lookupColumn );
+ try
+ {
+ ::rtl::OUString sName, sTableName;
+ xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) >>= sName;
+ xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sTableName;
+ if ( sName == _out_rColumnName && sTableName == _out_rTableRange )
+ xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= _out_rColumnAliasIfPresent;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ }
+ }
+ else if(SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec))
+ { // Funktion
+ _pColumnRef->parseNodeToStr( _out_rColumnName, _rxConnection );
+ }
+ else if(_pColumnRef->getNodeType() == SQL_NODE_NAME)
+ _out_rColumnName = _pColumnRef->getTokenValue();
+ }
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
+ ::rtl::OUString& _rColumnName,
+ ::rtl::OUString& _rTableRange) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
+ ::rtl::OUString sDummy;
+ lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, NULL, sDummy );
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
+ ::rtl::OUString& _rColumnName,
+ ::rtl::OUString& _rTableRange,
+ ::rtl::OUString& _out_rColumnAliasIfPresent ) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
+ lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, &*m_aSelectColumns, _out_rColumnAliasIfPresent );
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
+ const Reference< XConnection >& _rxConnection, ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
+ ::rtl::OUString sDummy;
+ lcl_getColumnRange( _pColumnRef, _rxConnection, _out_rColumnName, _out_rTableRange, NULL, sDummy );
+}
+
+//-----------------------------------------------------------------------------
+sal_Bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnTableRange" );
+ // Ermitteln ob alle Spalten zu einer Tabelle gehoeren
+ if (SQL_ISRULE(pNode,column_ref))
+ {
+ ::rtl::OUString aColName, aTableRange;
+ getColumnRange(pNode, aColName, aTableRange);
+ if (!aTableRange.getLength()) // keinen gefunden
+ {
+ // dann die Spalte in den Tabellen suchen
+ for (ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter)
+ {
+ if (aIter->second.is())
+ {
+ try
+ {
+ Reference< XNameAccess > xColumns = aIter->second->getColumns();
+ if(xColumns->hasByName(aColName))
+ {
+ Reference< XPropertySet > xColumn;
+ if (xColumns->getByName(aColName) >>= xColumn)
+ {
+ OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
+ aTableRange = aIter->first;
+ break;
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ }
+ if (!aTableRange.getLength())
+ return sal_False;
+ }
+
+
+ if (!rTableRange.getLength())
+ rTableRange = aTableRange;
+ else if (rTableRange != aTableRange)
+ return sal_False;
+ }
+ else
+ {
+ for (sal_uInt32 i = 0, ncount = pNode->count(); i < ncount; i++)
+ {
+ if (!getColumnTableRange(pNode->getChild(i), rTableRange))
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseCreateColumns(const OSQLParseNode* pSelectNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseCreateColumns" );
+ // aIteratorStatus.Clear();
+
+ if (!pSelectNode || m_eStatementType != SQL_STATEMENT_CREATE_TABLE || m_pImpl->m_pTables->empty())
+ {
+ impl_appendError( IParseContext::ERROR_GENERAL );
+ return;
+ }
+ if (!SQL_ISRULE(pSelectNode,base_table_element_commalist))
+ return ;
+
+ for (sal_uInt32 i = 0; i < pSelectNode->count(); i++)
+ {
+ OSQLParseNode *pColumnRef = pSelectNode->getChild(i);
+
+ if (SQL_ISRULE(pColumnRef,column_def))
+ {
+ ::rtl::OUString aColumnName;
+ ::rtl::OUString aTypeName;
+ ::rtl::OUString aTableRange;
+ sal_Int32 nType = DataType::VARCHAR;
+ sal_Int32 nLen = 0;
+ aColumnName = pColumnRef->getChild(0)->getTokenValue();
+
+ OSQLParseNode *pDatatype = pColumnRef->getChild(1);
+ if (pDatatype && SQL_ISRULE(pDatatype,character_string_type))
+ {
+ const OSQLParseNode *pType = pDatatype->getChild(0);
+ aTypeName = pType->getTokenValue();
+ if (pDatatype->count() == 2 && (pType->getTokenID() == SQL_TOKEN_CHAR || pType->getTokenID() == SQL_TOKEN_CHARACTER ))
+ nType = DataType::CHAR;
+
+ const OSQLParseNode *pParams = pDatatype->getChild(pDatatype->count()-1);
+ if ( pParams->count() )
+ {
+ nLen = pParams->getChild(1)->getTokenValue().toInt32();
+ }
+ }
+ else if(pDatatype && pDatatype->getNodeType() == SQL_NODE_KEYWORD)
+ {
+ aTypeName = ::rtl::OUString::createFromAscii("VARCHAR");
+ }
+
+ if (aTypeName.getLength())
+ {
+ //TODO:Create a new class for create statement to handle field length
+ OParseColumn* pColumn = new OParseColumn(aColumnName,aTypeName,::rtl::OUString(),::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,0,0,nType,sal_False,sal_False,isCaseSensitive());
+ pColumn->setFunction(sal_False);
+ pColumn->setRealName(aColumnName);
+
+ Reference< XPropertySet> xCol = pColumn;
+ m_aCreateColumns->get().push_back(xCol);
+ }
+ }
+
+ }
+}
+//-----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectColumnNames" );
+ if ( ( m_pImpl->m_nIncludeMask & SelectColumns ) != SelectColumns )
+ return true;
+
+ if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || m_pImpl->m_pTables->empty())
+ {
+ impl_appendError( IParseContext::ERROR_GENERAL );
+ return false;
+ }
+
+ if(SQL_ISRULE(pSelectNode,union_statement))
+ {
+ return traverseSelectColumnNames( pSelectNode->getChild( 0 ) )
+ /*&& traverseSelectColumnNames( pSelectNode->getChild( 3 ) )*/;
+ }
+
+ static ::rtl::OUString aEmptyString;
+ // nyi: mehr Pruefung auf korrekte Struktur!
+ if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*"))
+ {
+ // SELECT * ...
+ setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aEmptyString);
+ }
+ else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist))
+ {
+ // SELECT column[,column] oder SELECT COUNT(*) ...
+ OSQLParseNode * pSelection = pSelectNode->getChild(2);
+
+ for (sal_uInt32 i = 0; i < pSelection->count(); i++)
+ {
+ OSQLParseNode *pColumnRef = pSelection->getChild(i);
+
+ //if (SQL_ISRULE(pColumnRef,select_sublist))
+ if (SQL_ISRULE(pColumnRef,derived_column) &&
+ SQL_ISRULE(pColumnRef->getChild(0),column_ref) &&
+ pColumnRef->getChild(0)->count() == 3 &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(0)->getChild(2),"*"))
+ {
+ // alle Spalten der Tabelle
+ ::rtl::OUString aTableRange;
+ pColumnRef->getChild(0)->parseNodeToStr( aTableRange, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+ setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aTableRange);
+ continue;
+ }
+ else if (SQL_ISRULE(pColumnRef,derived_column))
+ {
+ ::rtl::OUString aColumnAlias(getColumnAlias(pColumnRef)); // kann leer sein
+ ::rtl::OUString sColumnName;
+ ::rtl::OUString aTableRange;
+ sal_Int32 nType = DataType::VARCHAR;
+ sal_Bool bFkt(sal_False);
+ pColumnRef = pColumnRef->getChild(0);
+ if (
+ pColumnRef->count() == 3 &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
+ )
+ pColumnRef = pColumnRef->getChild(1);
+
+ if (SQL_ISRULE(pColumnRef,column_ref))
+ {
+ getColumnRange(pColumnRef,sColumnName,aTableRange);
+ OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein");
+ }
+ else /*if (SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec) ||
+ SQL_ISRULE(pColumnRef,position_exp) || SQL_ISRULE(pColumnRef,extract_exp) ||
+ SQL_ISRULE(pColumnRef,length_exp) || SQL_ISRULE(pColumnRef,char_value_fct)||
+ SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))*/
+ {
+ /* Funktionsaufruf vorhanden */
+ pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_True );
+ ::rtl::OUString sTableRange;
+ // check if the column is also a parameter
+ traverseORCriteria(pColumnRef); // num_value_exp
+
+ // gehoeren alle beteiligten Spalten der Funktion zu einer Tabelle
+ if (m_pImpl->m_pTables->size() == 1)
+ {
+ aTableRange = m_pImpl->m_pTables->begin()->first;
+ }
+ else
+ {
+ getColumnTableRange(pColumnRef,aTableRange);
+ }
+ if ( pColumnRef->isRule() )
+ {
+ bFkt = sal_True;
+ nType = getFunctionReturnType(pColumnRef);
+ }
+ }
+ /*
+ else
+ {
+ aIteratorStatus.setStatementTooComplex();
+ return;
+ }
+ */
+ if(!aColumnAlias.getLength())
+ aColumnAlias = sColumnName;
+ setSelectColumnName(m_aSelectColumns,sColumnName,aColumnAlias,aTableRange,bFkt,nType,SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec));
+ }
+ }
+ }
+
+ return !hasErrors();
+}
+
+
+//-----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOrderByColumnNames" );
+ traverseByColumnNames( pSelectNode, sal_True );
+ return !hasErrors();
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseByColumnNames" );
+ // aIteratorStatus.Clear();
+
+ if (pSelectNode == NULL)
+ {
+ //aIteratorStatus.setInvalidStatement();
+ return;
+ }
+
+ if (m_eStatementType != SQL_STATEMENT_SELECT)
+ {
+ //aIteratorStatus.setInvalidStatement();
+ return;
+ }
+
+ if(SQL_ISRULE(pSelectNode,union_statement))
+ {
+ traverseByColumnNames(pSelectNode->getChild(0),_bOrder);
+ return;
+ }
+
+ OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
+
+ OSQLParseNode * pTableExp = pSelectNode->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator:table_exp error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ sal_uInt32 nPos = ( _bOrder ? 4 : 2 );
+
+ OSQLParseNode * pOptByClause = pTableExp->getChild(nPos);
+ OSL_ENSURE(pOptByClause != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ if ( pOptByClause->count() == 0 )
+ return;
+
+ OSL_ENSURE(pOptByClause->count() == 3,"OSQLParseTreeIterator: error in parse tree!");
+
+ OSQLParseNode * pOrderingSpecCommalist = pOptByClause->getChild(2);
+ OSL_ENSURE(pOrderingSpecCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(!_bOrder || SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OSQLParseTreeIterator:ordering_spec_commalist error in parse tree!");
+ OSL_ENSURE(pOrderingSpecCommalist->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
+
+ ::rtl::OUString sColumnName,aColumnAlias;
+ ::rtl::OUString aTableRange;
+ sal_uInt32 nCount = pOrderingSpecCommalist->count();
+ for (sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ OSQLParseNode* pColumnRef = pOrderingSpecCommalist->getChild(i);
+ OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ if ( _bOrder )
+ {
+ OSL_ENSURE(SQL_ISRULE(pColumnRef,ordering_spec),"OSQLParseTreeIterator:ordering_spec error in parse tree!");
+ OSL_ENSURE(pColumnRef->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
+
+ pColumnRef = pColumnRef->getChild(0);
+ }
+ aTableRange = ::rtl::OUString();
+ sColumnName = ::rtl::OUString();
+ if ( SQL_ISRULE(pColumnRef,column_ref) )
+ {
+ // Column-Name (und TableRange):
+ if(SQL_ISRULE(pColumnRef,column_ref))
+ getColumnRange(pColumnRef,sColumnName,aTableRange);
+ else // eine Expression
+ pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+
+ OSL_ENSURE(sColumnName.getLength(),"sColumnName darf nicht leer sein");
+ }
+ else
+ { // here I found a predicate
+ pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+ }
+ OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ if ( _bOrder )
+ {
+ // Ascending/Descending
+ OSQLParseNode * pOptAscDesc = pColumnRef->getParent()->getChild(1);
+ OSL_ENSURE(pOptAscDesc != NULL,"OSQLParseTreeIterator: error in parse tree!");
+
+ sal_Bool bAscending = pOptAscDesc && SQL_ISTOKEN(pOptAscDesc,ASC);
+ setOrderByColumnName(sColumnName, aTableRange,bAscending);
+ }
+ else
+ setGroupByColumnName(sColumnName, aTableRange);
+ }
+}
+//-----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode* pSelectNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseGroupByColumnNames" );
+ traverseByColumnNames( pSelectNode, sal_False );
+ return !hasErrors();
+}
+
+// -----------------------------------------------------------------------------
+namespace
+{
+ ::rtl::OUString lcl_generateParameterName( const OSQLParseNode& _rParentNode, const OSQLParseNode& _rParamNode )
+ {
+ ::rtl::OUString sColumnName( RTL_CONSTASCII_USTRINGPARAM( "param" ) );
+ const sal_Int32 nCount = (sal_Int32)_rParentNode.count();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ if ( _rParentNode.getChild(i) == &_rParamNode )
+ {
+ sColumnName += ::rtl::OUString::valueOf( i+1 );
+ break;
+ }
+ }
+ return sColumnName;
+ }
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameters" );
+ if ( _pNode == NULL )
+ return;
+
+ ::rtl::OUString sColumnName, sTableRange, aColumnAlias;
+ const OSQLParseNode* pParent = _pNode->getParent();
+ if ( pParent != NULL )
+ {
+ if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
+ {
+ sal_uInt32 nPos = 0;
+ if ( pParent->getChild(nPos) == _pNode )
+ nPos = 2;
+ const OSQLParseNode* pOther = pParent->getChild(nPos);
+ if ( SQL_ISRULE( pOther, column_ref ) )
+ getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
+ 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,other_like_predicate_part_2) )
+ {
+ 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_part_2) )
+ {
+ 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 );
+ lcl_generateParameterName( *pParent, *_pNode );
+ }
+ }
+ else if ( pParent->getNodeType() == SQL_NODE_COMMALISTRULE )
+ {
+ lcl_generateParameterName( *pParent, *_pNode );
+ }
+ }
+ traverseParameter( _pNode, pParent, sColumnName, sTableRange, aColumnAlias );
+ const sal_uInt32 nCount = _pNode->count();
+ for (sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ const OSQLParseNode* pChild = _pNode->getChild(i);
+ traverseParameters( pChild );
+ }
+}
+//-----------------------------------------------------------------------------
+bool OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectionCriteria" );
+ if ( pSelectNode == NULL )
+ return false;
+
+
+ // Parse Tree analysieren (je nach Statement-Typ)
+ // und Zeiger auf WHERE-Klausel setzen:
+ OSQLParseNode * pWhereClause = NULL;
+
+ if (m_eStatementType == SQL_STATEMENT_SELECT)
+ {
+ if(SQL_ISRULE(pSelectNode,union_statement))
+ {
+ return traverseSelectionCriteria( pSelectNode->getChild( 0 ) )
+ && traverseSelectionCriteria( pSelectNode->getChild( 3 ) );
+ }
+ OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
+
+ OSQLParseNode * pTableExp = pSelectNode->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ pWhereClause = pTableExp->getChild(1);
+ } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) {
+ OSL_ENSURE(pSelectNode->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+ pWhereClause = pSelectNode->getChild(4);
+ } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) {
+ OSL_ENSURE(pSelectNode->count() == 4,"OSQLParseTreeIterator: error in parse tree!");
+ pWhereClause = pSelectNode->getChild(3);
+ } else if (SQL_ISRULE(pSelectNode,delete_statement_positioned)) {
+ // nyi
+ OSL_ASSERT("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi");
+ } else {
+ // Anderes Statement. Keine Selektionskriterien.
+ return false;
+ }
+
+ if (! SQL_ISRULE(pWhereClause,where_clause)) {
+ // Die Where Clause ist meistens optional, d. h. es koennte sich auch
+ // um "optional_where_clause" handeln.
+ OSL_ENSURE(SQL_ISRULE(pWhereClause,opt_where_clause),"OSQLParseTreeIterator: error in parse tree!");
+ return false;
+ }
+
+ // Wenn es aber eine where_clause ist, dann darf sie nicht leer sein:
+ OSL_ENSURE(pWhereClause->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
+
+ OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1);
+ OSL_ENSURE(pComparisonPredicate != NULL,"OSQLParseTreeIterator: error in parse tree!");
+
+ //
+ // Und nun die Vergleichskriterien abarbeiten (rekursiv, alles ist erstmal ein OR-Kriterium):
+ //
+
+ traverseORCriteria(pComparisonPredicate);
+
+ return !hasErrors();
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseORCriteria(OSQLParseNode * pSearchCondition)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseORCriteria" );
+
+
+ if (
+ pSearchCondition->count() == 3 &&
+ SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
+ )
+ {
+ // Runde Klammern um den Ausdruck
+ traverseORCriteria(pSearchCondition->getChild(1));
+ } else if (SQL_ISRULE(pSearchCondition,search_condition) &&
+ pSearchCondition->count() == 3 &&
+ SQL_ISTOKEN(pSearchCondition->getChild(1),OR))
+ {
+ // OR-Verknuepfung:
+
+ for (int i = 0; i < 3; i++) {
+ if (i == 1) continue; // Schluesselwort OR ueberspringen
+
+ // Ist das erste Element wieder eine OR-Verknuepfung?
+ if (i == 0 &&
+ SQL_ISRULE(pSearchCondition->getChild(0),search_condition) &&
+ pSearchCondition->getChild(0)->count() == 3 &&
+ SQL_ISTOKEN(pSearchCondition->getChild(0)->getChild(1),OR))
+ {
+ // Dann rekursiv absteigen ...
+ traverseORCriteria(pSearchCondition->getChild(0));
+
+ } else {
+ // AND-Kriterien ...
+ traverseANDCriteria(pSearchCondition->getChild(i));
+ // if (! aIteratorStatus.IsSuccessful()) break;
+ }
+
+ // if (! aIteratorStatus.IsSuccessful()) break;
+ }
+ } else {
+ // Nur *ein* Kriterium oder eine AND-Verknuepfung von Kriterien.
+ // Direkt die AND-Kriterien behandeln.
+ traverseANDCriteria(pSearchCondition);
+ // if (! aIteratorStatus.IsSuccessful()) return;
+ }
+
+ // Fehler einfach weiterreichen.
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseANDCriteria" );
+
+
+ if (
+ SQL_ISRULE(pSearchCondition,boolean_primary) &&
+ pSearchCondition->count() == 3 &&
+ SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
+ )
+ {
+ // Runde Klammern
+ traverseANDCriteria(pSearchCondition->getChild(1));
+ }
+ // Das erste Element ist eine OR-Verknuepfung
+ else if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 )
+ {
+ // Dann rekursiv absteigen (dieselbe Row benutzen) ...
+ traverseORCriteria(pSearchCondition->getChild(0));
+// if (! aIteratorStatus.IsSuccessful())
+// return;
+
+ // Und mit dem rechten Child weitermachen:
+ traverseANDCriteria(pSearchCondition->getChild(2));
+ }
+ // Das erste Element ist (wieder) eine AND-Verknuepfung
+ else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 )
+ {
+ // Dann rekursiv absteigen (dieselbe Row benutzen) ...
+ traverseANDCriteria(pSearchCondition->getChild(0));
+// if (! aIteratorStatus.IsSuccessful())
+// return;
+
+ // Und mit dem rechten Child weitermachen:
+ traverseANDCriteria(pSearchCondition->getChild(2));
+ }
+ // Sonst einzelne Suchkriterien wie =, !=, ..., LIKE, IS NULL usw. behandeln:
+ else if (SQL_ISRULE(pSearchCondition,comparison_predicate) )
+ {
+ ::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() == 2,"OSQLParseTreeIterator: error in parse tree!");
+ const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
+
+ sal_Int32 nCurentPos = pPart2->count()-2;
+
+ 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!");
+
+ if (pOptEscape->count() != 0)
+ {
+ // aIteratorStatus.setStatementTooComplex();
+ return;
+ }
+
+ ::rtl::OUString aValue;
+ OSQLParseNode * pParam = NULL;
+ if (SQL_ISRULE(pNum_value_exp,parameter))
+ pParam = pNum_value_exp;
+ else if(pNum_value_exp->isToken())
+ // Normaler Wert
+ aValue = pNum_value_exp->getTokenValue();
+ else
+ {
+ pNum_value_exp->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+ pParam = pNum_value_exp;
+ }
+
+ traverseOnePredicate(pSearchCondition->getChild(0),aValue,pParam);
+// if (! aIteratorStatus.IsSuccessful())
+// return;
+ }
+ else if (SQL_ISRULE(pSearchCondition,in_predicate))
+ {
+ 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 = pPart2->getChild(2);
+ if ( SQL_ISRULE(pChild->getChild(0),subquery) )
+ {
+ traverseTableNames( *m_pImpl->m_pSubTables );
+ traverseSelectionCriteria(pChild->getChild(0)->getChild(1));
+ }
+ else
+ { // '(' value_exp_commalist ')'
+ pChild = pChild->getChild(1);
+ sal_Int32 nCount = pChild->count();
+ for (sal_Int32 i=0; i < nCount; ++i)
+ {
+ traverseANDCriteria(pChild->getChild(i));
+ }
+ }
+ }
+ else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
+ {
+ OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
+ const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
+ (void)pPart2;
+ OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"OSQLParseTreeIterator: error in parse tree!");
+
+ ::rtl::OUString aString;
+ traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL);
+ // if (! aIteratorStatus.IsSuccessful()) return;
+ }
+ else if (SQL_ISRULE(pSearchCondition,num_value_exp) || SQL_ISRULE(pSearchCondition,term))
+ {
+ ::rtl::OUString aString;
+ traverseOnePredicate(pSearchCondition->getChild(0),aString,pSearchCondition->getChild(0));
+ traverseOnePredicate(pSearchCondition->getChild(2),aString,pSearchCondition->getChild(2));
+ }
+ // Fehler einfach weiterreichen.
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode
+ ,const OSQLParseNode* _pColumnRef
+ ,const ::rtl::OUString& _aColumnName
+ ,const ::rtl::OUString& _aTableRange
+ ,const ::rtl::OUString& _rColumnAlias)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameter" );
+ if ( !SQL_ISRULE( _pParseNode, parameter ) )
+ return;
+
+ if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
+ // parameters not to be included in the traversal
+ return;
+
+ OSL_ENSURE(_pParseNode->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
+ OSQLParseNode * pMark = _pParseNode->getChild(0);
+ ::rtl::OUString sParameterName;
+
+ if (SQL_ISPUNCTUATION(pMark,"?"))
+ {
+ sParameterName = _rColumnAlias.getLength()
+ ? _rColumnAlias
+ : _aColumnName.getLength()
+ ? _aColumnName
+ : ::rtl::OUString::createFromAscii("?");
+ }
+ else if (SQL_ISPUNCTUATION(pMark,":"))
+ {
+ sParameterName = _pParseNode->getChild(1)->getTokenValue();
+ }
+ else if (SQL_ISPUNCTUATION(pMark,"["))
+ {
+ sParameterName = _pParseNode->getChild(1)->getTokenValue();
+ }
+ else
+ {
+ OSL_ASSERT("OSQLParseTreeIterator: error in parse tree!");
+ }
+
+ // found a parameter
+ if ( _pColumnRef && (SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec)) )
+ {// found a function as column_ref
+ ::rtl::OUString sFunctionName;
+ _pColumnRef->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+ 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(),
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,
+ 0,
+ 0,
+ nType,
+ sal_False,
+ sal_False,
+ isCaseSensitive());
+ pColumn->setFunction(sal_True);
+ pColumn->setAggregateFunction(sal_True);
+ pColumn->setRealName(sFunctionName);
+ m_aParameters->get().push_back(pColumn);
+ }
+ else
+ {
+ sal_Bool bNotFound = sal_True;
+ OSQLColumns::Vector::const_iterator aIter = ::connectivity::find(
+ m_aSelectColumns->get().begin(),
+ m_aSelectColumns->get().end(),
+ _aColumnName,::comphelper::UStringMixEqual( isCaseSensitive() )
+ );
+ if(aIter != m_aSelectColumns->get().end())
+ {
+ OParseColumn* pNewColumn = new OParseColumn(*aIter,isCaseSensitive());
+ pNewColumn->setName(sParameterName);
+ pNewColumn->setRealName(_aColumnName);
+ m_aParameters->get().push_back(pNewColumn);
+ bNotFound = sal_False;
+ }
+ else if(_aColumnName.getLength())// search in the tables for the right one
+ {
+
+ Reference<XPropertySet> xColumn = findColumn( _aColumnName, _aTableRange, true );
+
+ if ( xColumn.is() )
+ {
+ OParseColumn* pNewColumn = new OParseColumn(xColumn,isCaseSensitive());
+ pNewColumn->setName(sParameterName);
+ pNewColumn->setRealName(_aColumnName);
+ m_aParameters->get().push_back(pNewColumn);
+ bNotFound = sal_False;
+ }
+ }
+ if ( bNotFound )
+ {
+ sal_Int32 nType = DataType::VARCHAR;
+ OSQLParseNode* pParent = _pColumnRef ? _pColumnRef->getParent() : NULL;
+ if ( pParent && (SQL_ISRULE(pParent,general_set_fct) || SQL_ISRULE(pParent,set_fct_spec)) )
+ {
+ const sal_uInt32 nCount = _pColumnRef->count();
+ sal_uInt32 i = 0;
+ for(; i < nCount;++i)
+ {
+ if ( _pColumnRef->getChild(i) == _pParseNode )
+ break;
+ }
+ nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1);
+ }
+
+ ::rtl::OUString aNewColName( getUniqueColumnName( sParameterName ) );
+
+ OParseColumn* pColumn = new OParseColumn(aNewColName,
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,
+ 0,
+ 0,
+ nType,
+ sal_False,
+ sal_False,
+ isCaseSensitive() );
+ pColumn->setName(aNewColName);
+ pColumn->setRealName(sParameterName);
+ m_aParameters->get().push_back(pColumn);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseOnePredicate(
+ OSQLParseNode * pColumnRef,
+ ::rtl::OUString& rValue,
+ OSQLParseNode * pParseNode)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOnePredicate" );
+ if ( !pParseNode )
+ return;
+
+ // Column-Name (und TableRange):
+ ::rtl::OUString aColumnName, aTableRange, sColumnAlias;
+ getColumnRange( pColumnRef, aColumnName, aTableRange, sColumnAlias);
+
+ ::rtl::OUString aName;
+
+ /*if (SQL_ISRULE(pParseNode,parameter))
+ traverseParameter( pParseNode, pColumnRef, aColumnName, aTableRange, sColumnAlias );
+ else */if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange):
+ getColumnRange(pParseNode,aName,rValue);
+ else
+ {
+ traverseORCriteria(pParseNode);
+ // if (! aIteratorStatus.IsSuccessful()) return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseSome( sal_uInt32 _nIncludeMask )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSome" );
+ impl_traverse( _nIncludeMask );
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::traverseAll()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseAll" );
+ impl_traverse( All );
+}
+
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::impl_traverse( sal_uInt32 _nIncludeMask )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_traverse" );
+ impl_resetErrors();
+ m_pImpl->m_nIncludeMask = _nIncludeMask;
+
+ if ( !traverseTableNames( *m_pImpl->m_pTables ) )
+ return;
+
+ switch ( m_eStatementType )
+ {
+ case SQL_STATEMENT_SELECT:
+ {
+ const OSQLParseNode* pSelectNode = m_pParseTree;
+ traverseParameters( pSelectNode );
+ if ( !traverseSelectColumnNames( pSelectNode )
+ || !traverseOrderByColumnNames( pSelectNode )
+ || !traverseGroupByColumnNames( pSelectNode )
+ || !traverseSelectionCriteria( pSelectNode )
+ )
+ return;
+ }
+ break;
+ case SQL_STATEMENT_CREATE_TABLE:
+ {
+ //0 | 1 | 2 |3| 4 |5
+ //create table sc.foo ( a char(20), b char )
+ const OSQLParseNode* pCreateNode = m_pParseTree->getChild(4);
+ traverseCreateColumns(pCreateNode);
+ }
+ break;
+ case SQL_STATEMENT_INSERT:
+ break;
+ default:
+ break;
+ }
+}
+
+// Dummy-Implementationen:
+
+//-----------------------------------------------------------------------------
+OSQLTable OSQLParseTreeIterator::impl_createTableObject( const ::rtl::OUString& rTableName,
+ const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_createTableObject" );
+ OSL_PRECOND( m_eStatementType == SQL_STATEMENT_CREATE_TABLE,
+ "OSQLParseTreeIterator::impl_createTableObject: only to be called for CREATE TABLE statements!" );
+ // (in all other cases, m_pTables is to contain the table objects as obtained from the tables
+ // container of the connection (m_xTablesContainer)
+
+ OSQLTable aReturnTable = new OTable(
+ NULL,
+ sal_False,
+ rTableName,
+ ::rtl::OUString::createFromAscii("Table"),
+ ::rtl::OUString::createFromAscii("New Created Table"),
+ rSchemaName,
+ rCatalogName
+ );
+ return aReturnTable;
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::appendColumns" );
+
+ if (!_rTable.is())
+ return;
+
+ Reference<XNameAccess> xColumns = _rTable->getColumns();
+ if ( !xColumns.is() )
+ return;
+
+ Sequence< ::rtl::OUString > aColNames = xColumns->getElementNames();
+ const ::rtl::OUString* pBegin = aColNames.getConstArray();
+ const ::rtl::OUString* pEnd = pBegin + aColNames.getLength();
+
+ for(;pBegin != pEnd;++pBegin)
+ {
+
+ ::rtl::OUString aName(getUniqueColumnName(*pBegin));
+ Reference< XPropertySet > xColumn;
+ if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is())
+ {
+ OParseColumn* pColumn = new OParseColumn(aName
+ , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))
+ , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))
+ , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION)))
+ , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))
+ , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))
+ , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))
+ , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))
+ , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)))
+ , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))
+ , isCaseSensitive() );
+
+ pColumn->setTableName(_rTableAlias);
+ pColumn->setRealName(*pBegin);
+ Reference< XPropertySet> xCol = pColumn;
+ _rColumns->get().push_back(xCol);
+ }
+ else
+ impl_appendError( IParseContext::ERROR_INVALID_COLUMN, pBegin, &_rTableAlias );
+ }
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::setSelectColumnName(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString & rColumnName,const ::rtl::OUString & rColumnAlias, const ::rtl::OUString & rTableRange,sal_Bool bFkt,sal_Int32 _nType,sal_Bool bAggFkt)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setSelectColumnName" );
+ if(rColumnName.toChar() == '*' && !rTableRange.getLength())
+ { // SELECT * ...
+ OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
+ for(ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end();++aIter)
+ appendColumns(_rColumns,aIter->first,aIter->second);
+ }
+ else if( rColumnName.toChar() == '*' && rTableRange.getLength() )
+ { // SELECT <table>.*
+ OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
+ ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
+
+ if(aFind != m_pImpl->m_pTables->end())
+ appendColumns(_rColumns,rTableRange,aFind->second);
+ }
+ else if ( !rTableRange.getLength() )
+ { // SELECT <something> ...
+ // without table specified
+ if ( !bFkt )
+ {
+ Reference< XPropertySet> xNewColumn;
+
+ for ( OSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter )
+ {
+ if ( !aIter->second.is() )
+ continue;
+
+ Reference<XNameAccess> xColumns = aIter->second->getColumns();
+ Reference< XPropertySet > xColumn;
+ if ( !xColumns->hasByName( rColumnName )
+ || !( xColumns->getByName( rColumnName ) >>= xColumn )
+ )
+ continue;
+
+ ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
+
+ OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
+ xNewColumn = pColumn;
+ pColumn->setTableName(aIter->first);
+ pColumn->setName(aNewColName);
+ pColumn->setRealName(rColumnName);
+
+ break;
+ }
+
+ if ( !xNewColumn.is() )
+ {
+ // no function (due to the above !bFkt), no existing column
+ // => assume an expression
+ ::rtl::OUString aNewColName( getUniqueColumnName( rColumnAlias ) );
+ // did not find a column with this name in any of the tables
+ OParseColumn* pColumn = new OParseColumn(
+ aNewColName,
+ ::rtl::OUString::createFromAscii( "VARCHAR" ),
+ // TODO: does this match with _nType?
+ // Or should be fill this from the getTypeInfo of the connection?
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,
+ 0,
+ 0,
+ _nType,
+ sal_False,
+ sal_False,
+ isCaseSensitive()
+ );
+
+ xNewColumn = pColumn;
+ pColumn->setRealName( rColumnName );
+ }
+
+ _rColumns->get().push_back( xNewColumn );
+ }
+ else
+ {
+ ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
+
+ OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
+ pColumn->setFunction(sal_True);
+ pColumn->setAggregateFunction(bAggFkt);
+ pColumn->setRealName(rColumnName);
+
+ Reference< XPropertySet> xCol = pColumn;
+ _rColumns->get().push_back(xCol);
+ }
+ }
+ else // ColumnName und Tablename vorhanden
+ {
+ ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
+
+ sal_Bool bError = sal_False;
+ if (aFind != m_pImpl->m_pTables->end() && aFind->second.is())
+ {
+ if (bFkt)
+ {
+ ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
+
+ OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
+ pColumn->setFunction(sal_True);
+ pColumn->setAggregateFunction(bAggFkt);
+ pColumn->setRealName(rColumnName);
+ pColumn->setTableName(aFind->first);
+
+ Reference< XPropertySet> xCol = pColumn;
+ _rColumns->get().push_back(xCol);
+ }
+ else
+ {
+ Reference< XPropertySet > xColumn;
+ if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn))
+ {
+ ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
+
+ OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
+ pColumn->setName(aNewColName);
+ pColumn->setRealName(rColumnName);
+ pColumn->setTableName(aFind->first);
+
+ Reference< XPropertySet> xCol = pColumn;
+ _rColumns->get().push_back(xCol);
+ }
+ else
+ bError = sal_True;
+ }
+ }
+ else
+ bError = sal_True;
+
+ // Tabelle existiert nicht oder Feld nicht vorhanden
+ if (bError)
+ {
+ ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
+
+ OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,isCaseSensitive());
+ pColumn->setFunction(sal_True);
+ pColumn->setAggregateFunction(bAggFkt);
+
+ Reference< XPropertySet> xCol = pColumn;
+ _rColumns->get().push_back(xCol);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+::rtl::OUString OSQLParseTreeIterator::getUniqueColumnName(const ::rtl::OUString & rColumnName) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getUniqueColumnName" );
+ ::rtl::OUString aAlias(rColumnName);
+
+ OSQLColumns::Vector::const_iterator aIter = find(
+ m_aSelectColumns->get().begin(),
+ m_aSelectColumns->get().end(),
+ aAlias,
+ ::comphelper::UStringMixEqual( isCaseSensitive() )
+ );
+ sal_Int32 i=1;
+ while(aIter != m_aSelectColumns->get().end())
+ {
+ (aAlias = rColumnName) += ::rtl::OUString::valueOf(i++);
+ aIter = find(
+ m_aSelectColumns->get().begin(),
+ m_aSelectColumns->get().end(),
+ aAlias,
+ ::comphelper::UStringMixEqual( isCaseSensitive() )
+ );
+ }
+ return aAlias;
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::setOrderByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange,sal_Bool bAscending)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setOrderByColumnName" );
+ Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
+ if ( xColumn.is() )
+ m_aOrderColumns->get().push_back(new OOrderColumn(xColumn,isCaseSensitive(),bAscending));
+ else
+ {
+ sal_Int32 nId = rColumnName.toInt32();
+ if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
+ m_aOrderColumns->get().push_back(new OOrderColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive(),bAscending));
+ }
+
+#ifdef SQL_TEST_PARSETREEITERATOR
+ cout << "OSQLParseTreeIterator::setOrderByColumnName: "
+ << (const char *) rColumnName << ", "
+ << (const char *) rTableRange << ", "
+ << (bAscending ? "sal_True" : "sal_False")
+ << "\n";
+#endif
+}
+//-----------------------------------------------------------------------------
+void OSQLParseTreeIterator::setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setGroupByColumnName" );
+ Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
+ if ( xColumn.is() )
+ m_aGroupColumns->get().push_back(new OParseColumn(xColumn,isCaseSensitive()));
+ else
+ {
+ sal_Int32 nId = rColumnName.toInt32();
+ if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
+ m_aGroupColumns->get().push_back(new OParseColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive()));
+ }
+
+#ifdef SQL_TEST_PARSETREEITERATOR
+ cout << "OSQLParseTreeIterator::setOrderByColumnName: "
+ << (const char *) rColumnName << ", "
+ << (const char *) rTableRange << ", "
+ << (bAscending ? "sal_True" : "sal_False")
+ << "\n";
+#endif
+}
+
+//-----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getWhereTree" );
+
+
+ if (!m_pParseTree)
+ return NULL;
+
+ // Parse Tree analysieren (je nach Statement-Typ)
+ // und Zeiger auf WHERE-Klausel setzen:
+ OSQLParseNode * pWhereClause = NULL;
+ if(getStatementType() == SQL_STATEMENT_SELECT)
+ {
+ OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
+ OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ pWhereClause = pTableExp->getChild(1);
+ }
+ else if (SQL_ISRULE(m_pParseTree,update_statement_searched) ||
+ SQL_ISRULE(m_pParseTree,delete_statement_searched))
+ {
+ pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1);
+ }
+ if(pWhereClause->count() != 2)
+ pWhereClause = NULL;
+ return pWhereClause;
+}
+
+//-----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getOrderTree" );
+
+
+ if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
+ return NULL;
+
+ // Parse Tree analysieren (je nach Statement-Typ)
+ // und Zeiger auf ORDER-Klausel setzen:
+ OSQLParseNode * pOrderClause = NULL;
+ OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
+ OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ pOrderClause = pTableExp->getChild(4);
+ // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
+ if(pOrderClause->count() != 3)
+ pOrderClause = NULL;
+ return pOrderClause;
+}
+//-----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getGroupByTree" );
+ if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
+ return NULL;
+
+ // Parse Tree analysieren (je nach Statement-Typ)
+ // und Zeiger auf ORDER-Klausel setzen:
+ OSQLParseNode * pGroupClause = NULL;
+ OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
+ OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ pGroupClause = pTableExp->getChild(2);
+ // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
+ if(pGroupClause->count() != 3)
+ pGroupClause = NULL;
+ return pGroupClause;
+}
+//-----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const
+{
+ if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
+ return NULL;
+
+ // Parse Tree analysieren (je nach Statement-Typ)
+ // und Zeiger auf ORDER-Klausel setzen:
+ OSQLParseNode * pHavingClause = NULL;
+ OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
+ OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
+ OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
+ OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
+
+ pHavingClause = pTableExp->getChild(3);
+ // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
+ if(pHavingClause->count() < 1)
+ pHavingClause = NULL;
+ return pHavingClause;
+}
+// -----------------------------------------------------------------------------
+sal_Bool OSQLParseTreeIterator::isTableNode(const OSQLParseNode* _pTableNode) const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isTableNode" );
+ return _pTableNode && (SQL_ISRULE(_pTableNode,catalog_name) ||
+ SQL_ISRULE(_pTableNode,schema_name) ||
+ SQL_ISRULE(_pTableNode,table_name));
+}
+// -----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getSimpleWhereTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleWhereTree" );
+ const OSQLParseNode* pNode = getWhereTree();
+ return pNode ? pNode->getChild(1) : NULL;
+}
+// -----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getSimpleOrderTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleOrderTree" );
+ const OSQLParseNode* pNode = getOrderTree();
+ return pNode ? pNode->getChild(2) : NULL;
+}
+// -----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getSimpleGroupByTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleGroupByTree" );
+ const OSQLParseNode* pNode = getGroupByTree();
+ return pNode ? pNode->getChild(2) : NULL;
+}
+// -----------------------------------------------------------------------------
+const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleHavingTree" );
+ const OSQLParseNode* pNode = getHavingTree();
+ return pNode ? pNode->getChild(1) : NULL;
+}
+
+// -----------------------------------------------------------------------------
+Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
+ Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange );
+ if ( !xColumn.is() && _bLookInSubTables )
+ xColumn = findColumn( *m_pImpl->m_pSubTables, rColumnName, rTableRange );
+ return xColumn;
+}
+
+// -----------------------------------------------------------------------------
+Reference< XPropertySet > OSQLParseTreeIterator::findColumn(const OSQLTables& _rTables,const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
+ Reference< XPropertySet > xColumn;
+ if ( rTableRange.getLength() )
+ {
+ ConstOSQLTablesIterator aFind = _rTables.find(rTableRange);
+
+ if ( aFind != _rTables.end()
+ && aFind->second.is()
+ && aFind->second->getColumns().is()
+ && aFind->second->getColumns()->hasByName(rColumnName) )
+ aFind->second->getColumns()->getByName(rColumnName) >>= xColumn;
+ }
+ if ( !xColumn.is() )
+ {
+ OSQLTables::const_iterator aEnd = _rTables.end();
+ for(OSQLTables::const_iterator aIter = _rTables.begin(); aIter != aEnd; ++aIter)
+ {
+ if ( aIter->second.is() )
+ {
+ Reference<XNameAccess> xColumns = aIter->second->getColumns();
+ if( xColumns.is() && xColumns->hasByName(rColumnName) && (xColumns->getByName(rColumnName) >>= xColumn) )
+ {
+ OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
+ break; // diese Column darf nur einmal vorkommen
+ }
+ }
+ }
+ }
+ return xColumn;
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::impl_appendError( IParseContext::ErrorCode _eError, const ::rtl::OUString* _pReplaceToken1, const ::rtl::OUString* _pReplaceToken2 )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
+ ::rtl::OUString sErrorMessage = m_rParser.getContext().getErrorMessage( _eError );
+ if ( _pReplaceToken1 )
+ {
+ bool bTwoTokens = ( _pReplaceToken2 != NULL );
+ const sal_Char* pPlaceHolder1 = bTwoTokens ? "#1" : "#";
+ const ::rtl::OUString sPlaceHolder1 = ::rtl::OUString::createFromAscii( pPlaceHolder1 );
+
+ sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( sPlaceHolder1 ), sPlaceHolder1.getLength(), *_pReplaceToken1 );
+ if ( _pReplaceToken2 )
+ sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( ::rtl::OUString::createFromAscii( "#2" ) ), 2, *_pReplaceToken2 );
+ }
+
+ impl_appendError( SQLException(
+ sErrorMessage, NULL, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ) );
+}
+
+// -----------------------------------------------------------------------------
+void OSQLParseTreeIterator::impl_appendError( const SQLException& _rError )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
+ if ( m_aErrors.Message.getLength() )
+ {
+ SQLException* pErrorChain = &m_aErrors;
+ while ( pErrorChain->NextException.hasValue() )
+ pErrorChain = static_cast< SQLException* >( pErrorChain->NextException.pData );
+ pErrorChain->NextException <<= _rError;
+ }
+ else
+ m_aErrors = _rError;
+}
+// -----------------------------------------------------------------------------
+sal_Int32 OSQLParseTreeIterator::getFunctionReturnType(const OSQLParseNode* _pNode )
+{
+ sal_Int32 nType = DataType::OTHER;
+ ::rtl::OUString sFunctionName;
+ if ( SQL_ISRULE(_pNode,length_exp) )
+ {
+ _pNode->getChild(0)->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+ nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
+ }
+ else if ( SQL_ISRULE(_pNode,num_value_exp) || SQL_ISRULE(_pNode,term) || SQL_ISRULE(_pNode,factor) )
+ {
+ nType = DataType::DOUBLE;
+ }
+ else
+ {
+ _pNode->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
+
+ // MIN and MAX have another return type, we have to check the expression itself.
+ // @see http://qa.openoffice.org/issues/show_bug.cgi?id=99566
+ if ( SQL_ISRULE(_pNode,general_set_fct) && (SQL_ISTOKEN(_pNode->getChild(0),MIN) || SQL_ISTOKEN(_pNode->getChild(0),MAX) ))
+ {
+ const OSQLParseNode* pValueExp = _pNode->getChild(3);
+ if (SQL_ISRULE(pValueExp,column_ref))
+ {
+ ::rtl::OUString sColumnName;
+ ::rtl::OUString aTableRange;
+ getColumnRange(pValueExp,sColumnName,aTableRange);
+ OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein");
+ Reference<XPropertySet> xColumn = findColumn( sColumnName, aTableRange, true );
+
+ if ( xColumn.is() )
+ {
+ xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TYPE)) >>= nType;
+ }
+ }
+ else
+ {
+ if ( SQL_ISRULE(pValueExp,num_value_exp) || SQL_ISRULE(pValueExp,term) || SQL_ISRULE(pValueExp,factor) )
+ {
+ nType = DataType::DOUBLE;
+ }
+ else if ( SQL_ISRULE(pValueExp,datetime_primary) )
+ {
+ switch(pValueExp->getChild(0)->getTokenID() )
+ {
+ case SQL_TOKEN_CURRENT_DATE:
+ nType = DataType::DATE;
+ break;
+ case SQL_TOKEN_CURRENT_TIME:
+ nType = DataType::TIME;
+ break;
+ case SQL_TOKEN_CURRENT_TIMESTAMP:
+ nType = DataType::TIMESTAMP;
+ break;
+ }
+ }
+ else if ( SQL_ISRULE(pValueExp,value_exp_primary) )
+ {
+ nType = getFunctionReturnType(pValueExp->getChild(1));
+ }
+ else if ( SQL_ISRULE(pValueExp,concatenation)
+ || SQL_ISRULE(pValueExp,char_factor)
+ || SQL_ISRULE(pValueExp,bit_value_fct)
+ || SQL_ISRULE(pValueExp,char_value_fct)
+ || SQL_ISRULE(pValueExp,char_substring_fct)
+ || SQL_ISRULE(pValueExp,fold)
+ || SQL_ISTOKEN(pValueExp,STRING) )
+ {
+ nType = DataType::VARCHAR;
+ }
+ }
+ if ( nType == DataType::OTHER )
+ nType = DataType::DOUBLE;
+ }
+ else
+ nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
+ }
+
+ return nType;
+}
+