xref: /trunk/main/connectivity/source/parse/sqliterator.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbtools.hxx"
26 #include <iterator>
27 #include "connectivity/sqliterator.hxx"
28 #include "connectivity/sdbcx/VTable.hxx"
29 #include <connectivity/sqlparse.hxx>
30 #include <connectivity/dbtools.hxx>
31 #include <connectivity/sqlerror.hxx>
32 #include <com/sun/star/sdbc/ColumnValue.hpp>
33 #include <com/sun/star/sdbc/DataType.hpp>
34 #include <com/sun/star/sdbc/XRow.hpp>
35 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
36 #include <com/sun/star/sdb/ErrorCondition.hpp>
37 #ifdef SQL_TEST_PARSETREEITERATOR
38 #include <iostream>
39 #endif
40 #include "connectivity/PColumn.hxx"
41 #include "connectivity/dbtools.hxx"
42 #include <tools/diagnose_ex.h>
43 #include "TConnection.hxx"
44 #include <comphelper/types.hxx>
45 #include <connectivity/dbmetadata.hxx>
46 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
47 #include "diagnose_ex.h"
48 #include <rtl/logfile.hxx>
49 
50 #define SQL_ISRULEOR2(pParseNode, e1,e2)    ((pParseNode)->isRule() && (\
51                                             (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
52                                             (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
53 
54 using namespace ::comphelper;
55 using namespace ::connectivity;
56 using namespace ::connectivity::sdbcx;
57 using namespace ::dbtools;
58 using namespace ::connectivity::parse;
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::sdbcx;
63 using namespace ::com::sun::star::beans;
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::sdb;
66 
67 namespace connectivity
68 {
69     struct OSQLParseTreeIteratorImpl
70     {
71         ::std::vector< TNodePair >      m_aJoinConditions;
72         Reference< XConnection >        m_xConnection;
73         Reference< XDatabaseMetaData >  m_xDatabaseMetaData;
74         Reference< XNameAccess >        m_xTableContainer;
75         Reference< XNameAccess >        m_xQueryContainer;
76 
77         ::boost::shared_ptr< OSQLTables >   m_pTables;      /// all tables which participate in the SQL statement
78         ::boost::shared_ptr< OSQLTables >   m_pSubTables;   /// all tables from sub queries not the tables from the select tables
79         ::boost::shared_ptr< QueryNameSet > m_pForbiddenQueryNames;
80 
81         sal_uInt32                      m_nIncludeMask;
82 
83         bool                            m_bIsCaseSensitive;
84 
OSQLParseTreeIteratorImplconnectivity::OSQLParseTreeIteratorImpl85         OSQLParseTreeIteratorImpl( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxTables )
86             :m_xConnection( _rxConnection )
87             ,m_nIncludeMask( OSQLParseTreeIterator::All )
88             ,m_bIsCaseSensitive( true )
89         {
90             OSL_PRECOND( m_xConnection.is(), "OSQLParseTreeIteratorImpl::OSQLParseTreeIteratorImpl: invalid connection!" );
91             m_xDatabaseMetaData = m_xConnection->getMetaData();
92 
93             m_bIsCaseSensitive = m_xDatabaseMetaData.is() && m_xDatabaseMetaData->supportsMixedCaseQuotedIdentifiers();
94             m_pTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
95             m_pSubTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
96 
97             m_xTableContainer = _rxTables;
98 
99             DatabaseMetaData aMetaData( m_xConnection );
100             if ( aMetaData.supportsSubqueriesInFrom() )
101             {
102                 // connections might support the XQueriesSupplier interface, if they implement the css.sdb.Connection
103                 // service
104                 Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY );
105                 if ( xSuppQueries.is() )
106                     m_xQueryContainer = xSuppQueries->getQueries();
107             }
108         }
109 
110     public:
isQueryAllowedconnectivity::OSQLParseTreeIteratorImpl111         inline  bool    isQueryAllowed( const ::rtl::OUString& _rQueryName )
112         {
113             if ( !m_pForbiddenQueryNames.get() )
114                 return true;
115             if ( m_pForbiddenQueryNames->find( _rQueryName ) == m_pForbiddenQueryNames->end() )
116                 return true;
117             return false;
118         }
119     };
120 
121     //-------------------------------------------------------------------------
122     /** helper class for temporarily adding a query name to a list of forbidden query names
123     */
124     class ForbidQueryName
125     {
126         ::boost::shared_ptr< QueryNameSet >&    m_rpAllForbiddenNames;
127         ::rtl::OUString                         m_sForbiddenQueryName;
128 
129     public:
ForbidQueryName(OSQLParseTreeIteratorImpl & _rIteratorImpl,const::rtl::OUString _rForbiddenQueryName)130         ForbidQueryName( OSQLParseTreeIteratorImpl& _rIteratorImpl, const ::rtl::OUString _rForbiddenQueryName )
131             :m_rpAllForbiddenNames( _rIteratorImpl.m_pForbiddenQueryNames )
132             ,m_sForbiddenQueryName( _rForbiddenQueryName )
133         {
134             if ( !m_rpAllForbiddenNames.get() )
135                 m_rpAllForbiddenNames.reset( new QueryNameSet );
136             m_rpAllForbiddenNames->insert( m_sForbiddenQueryName );
137         }
138 
~ForbidQueryName()139         ~ForbidQueryName()
140         {
141             m_rpAllForbiddenNames->erase( m_sForbiddenQueryName );
142         }
143     };
144 }
145 //-----------------------------------------------------------------------------
OSQLParseTreeIterator(const Reference<XConnection> & _rxConnection,const Reference<XNameAccess> & _rxTables,const OSQLParser & _rParser,const OSQLParseNode * pRoot)146 OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XConnection >& _rxConnection,
147                                              const Reference< XNameAccess >& _rxTables,
148                                              const OSQLParser& _rParser,
149                                              const OSQLParseNode* pRoot )
150     :m_rParser( _rParser )
151     ,m_pImpl( new OSQLParseTreeIteratorImpl( _rxConnection, _rxTables ) )
152 {
153     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
154     setParseTree(pRoot);
155 }
156 
157 //-----------------------------------------------------------------------------
OSQLParseTreeIterator(const OSQLParseTreeIterator & _rParentIterator,const OSQLParser & _rParser,const OSQLParseNode * pRoot)158 OSQLParseTreeIterator::OSQLParseTreeIterator( const OSQLParseTreeIterator& _rParentIterator, const OSQLParser& _rParser, const OSQLParseNode* pRoot )
159     :m_rParser( _rParser )
160     ,m_pImpl( new OSQLParseTreeIteratorImpl( _rParentIterator.m_pImpl->m_xConnection, _rParentIterator.m_pImpl->m_xTableContainer ) )
161 {
162     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
163     m_pImpl->m_pForbiddenQueryNames = _rParentIterator.m_pImpl->m_pForbiddenQueryNames;
164     setParseTree( pRoot );
165 }
166 
167 //-----------------------------------------------------------------------------
~OSQLParseTreeIterator()168 OSQLParseTreeIterator::~OSQLParseTreeIterator()
169 {
170     dispose();
171 }
172 
173 // -----------------------------------------------------------------------------
getTables() const174 const OSQLTables& OSQLParseTreeIterator::getTables() const
175 {
176     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTables" );
177     return *m_pImpl->m_pTables;
178 }
179 
180 // -----------------------------------------------------------------------------
isCaseSensitive() const181 bool OSQLParseTreeIterator::isCaseSensitive() const
182 {
183     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isCaseSensitive" );
184     return m_pImpl->m_bIsCaseSensitive;
185 }
186 
187 // -----------------------------------------------------------------------------
dispose()188 void OSQLParseTreeIterator::dispose()
189 {
190     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::dispose" );
191     m_aSelectColumns    = NULL;
192     m_aGroupColumns     = NULL;
193     m_aOrderColumns     = NULL;
194     m_aParameters       = NULL;
195     m_pImpl->m_xTableContainer  = NULL;
196     m_pImpl->m_xDatabaseMetaData = NULL;
197     m_aCreateColumns    = NULL;
198     m_pImpl->m_pTables->clear();
199     m_pImpl->m_pSubTables->clear();
200 }
201 //-----------------------------------------------------------------------------
setParseTree(const OSQLParseNode * pNewParseTree)202 void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree)
203 {
204     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setParseTree" );
205     m_pImpl->m_pTables->clear();
206     m_pImpl->m_pSubTables->clear();
207 
208     m_aSelectColumns = new OSQLColumns();
209     m_aGroupColumns = new OSQLColumns();
210     m_aOrderColumns = new OSQLColumns();
211     m_aParameters    = new OSQLColumns();
212     m_aCreateColumns = new OSQLColumns();
213 
214     m_pParseTree = pNewParseTree;
215     if (!m_pParseTree)
216     {
217         m_eStatementType = SQL_STATEMENT_UNKNOWN;
218         return;
219     }
220 
221     // falls m_pParseTree aber keine Connection, dann Fehler
222     if ( !m_pImpl->m_xTableContainer.is() )
223         return;
224 
225     m_aErrors = SQLException();
226 
227 
228     // Statement-Typ ermitteln ...
229     if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) )
230     {
231         m_eStatementType = SQL_STATEMENT_SELECT;
232     }
233     else if (SQL_ISRULE(m_pParseTree,insert_statement))
234     {
235         m_eStatementType = SQL_STATEMENT_INSERT;
236     }
237     else if (SQL_ISRULE(m_pParseTree,update_statement_searched))
238     {
239         m_eStatementType = SQL_STATEMENT_UPDATE;
240     }
241     else if (SQL_ISRULE(m_pParseTree,delete_statement_searched))
242     {
243         m_eStatementType = SQL_STATEMENT_DELETE;
244     }
245     else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec))
246     {
247         m_eStatementType = SQL_STATEMENT_ODBC_CALL;
248     }
249     else if (SQL_ISRULE(m_pParseTree->getChild(0),base_table_def))
250     {
251         m_eStatementType = SQL_STATEMENT_CREATE_TABLE;
252         m_pParseTree = m_pParseTree->getChild(0);
253     }
254     else
255     {
256         m_eStatementType = SQL_STATEMENT_UNKNOWN;
257         //aIteratorStatus.setInvalidStatement();
258         return;
259     }
260 }
261 
262 //-----------------------------------------------------------------------------
263 namespace
264 {
265     //.........................................................................
impl_getRowString(const Reference<XRow> & _rxRow,const sal_Int32 _nColumnIndex,::rtl::OUString & _out_rString)266     static void impl_getRowString( const Reference< XRow >& _rxRow, const sal_Int32 _nColumnIndex, ::rtl::OUString& _out_rString )
267     {
268         _out_rString = _rxRow->getString( _nColumnIndex );
269         if ( _rxRow->wasNull() )
270             _out_rString= ::rtl::OUString();
271     }
272 
273     //.........................................................................
lcl_findTableInMetaData(const Reference<XDatabaseMetaData> & _rxDBMeta,const::rtl::OUString & _rCatalog,const::rtl::OUString & _rSchema,const::rtl::OUString & _rTableName)274     static ::rtl::OUString lcl_findTableInMetaData(
275         const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rCatalog,
276         const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rTableName )
277     {
278         ::rtl::OUString sComposedName;
279 
280         static const ::rtl::OUString s_sTableTypeView(RTL_CONSTASCII_USTRINGPARAM("VIEW"));
281         static const ::rtl::OUString s_sTableTypeTable(RTL_CONSTASCII_USTRINGPARAM("TABLE"));
282         static const ::rtl::OUString s_sWildcard = ::rtl::OUString::createFromAscii("%");
283 
284         // we want all catalogues, all schemas, all tables
285         Sequence< ::rtl::OUString > sTableTypes(3);
286         sTableTypes[0] = s_sTableTypeView;
287         sTableTypes[1] = s_sTableTypeTable;
288         sTableTypes[2] = s_sWildcard;   // just to be sure to include anything else ....
289 
290         if ( _rxDBMeta.is() )
291         {
292             sComposedName = ::rtl::OUString();
293 
294             Reference< XResultSet> xRes = _rxDBMeta->getTables(
295                 _rCatalog.getLength() ? makeAny( _rCatalog ) : Any(), _rSchema.getLength() ? _rSchema : s_sWildcard, _rTableName, sTableTypes );
296 
297             Reference< XRow > xCurrentRow( xRes, UNO_QUERY );
298             if ( xCurrentRow.is() && xRes->next() )
299             {
300                 ::rtl::OUString sCatalog, sSchema, sName;
301 
302                 impl_getRowString( xCurrentRow, 1, sCatalog );
303                 impl_getRowString( xCurrentRow, 2, sSchema );
304                 impl_getRowString( xCurrentRow, 3, sName );
305 
306                 sComposedName = ::dbtools::composeTableName(
307                     _rxDBMeta,
308                     sCatalog,
309                     sSchema,
310                     sName,
311                     sal_False,
312                     ::dbtools::eInDataManipulation
313                 );
314             }
315         }
316         return sComposedName;
317     }
318 }
319 
320 //-----------------------------------------------------------------------------
impl_getQueryParameterColumns(const OSQLTable & _rQuery)321 void OSQLParseTreeIterator::impl_getQueryParameterColumns( const OSQLTable& _rQuery  )
322 {
323     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_getQueryParameterColumns" );
324     if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
325         // parameters not to be included in the traversal
326         return;
327 
328     ::vos::ORef< OSQLColumns > pSubQueryParameterColumns( new OSQLColumns() );
329 
330     // get the command and the EscapeProcessing properties from the sub query
331     ::rtl::OUString sSubQueryCommand;
332     sal_Bool bEscapeProcessing = sal_False;
333     try
334     {
335         Reference< XPropertySet > xQueryProperties( _rQuery, UNO_QUERY_THROW );
336         OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sSubQueryCommand );
337         OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing );
338     }
339     catch( const Exception& )
340     {
341         DBG_UNHANDLED_EXCEPTION();
342     }
343 
344     // parse the sub query
345     do {
346 
347     if ( !bEscapeProcessing || ( sSubQueryCommand.getLength() == 0 ) )
348         break;
349 
350     ::rtl::OUString sError;
351     ::std::auto_ptr< OSQLParseNode > pSubQueryNode( const_cast< OSQLParser& >( m_rParser ).parseTree( sError, sSubQueryCommand, sal_False ) );
352     if ( !pSubQueryNode.get() )
353         break;
354 
355     OSQLParseTreeIterator aSubQueryIterator( *this, m_rParser, pSubQueryNode.get() );
356     aSubQueryIterator.traverseSome( Parameters | SelectColumns );
357         // SelectColumns might also contain parameters
358         // #i77635# - 2007-07-23 / frank.schoenheit@sun.com
359     pSubQueryParameterColumns = aSubQueryIterator.getParameters();
360     aSubQueryIterator.dispose();
361 
362     } while ( false );
363 
364     // copy the parameters of the sub query to our own parameter array
365     ::std::copy( pSubQueryParameterColumns->get().begin(), pSubQueryParameterColumns->get().end(),
366         ::std::insert_iterator< OSQLColumns::Vector >( m_aParameters->get(), m_aParameters->get().end() ) );
367 }
368 
369 //-----------------------------------------------------------------------------
impl_locateRecordSource(const::rtl::OUString & _rComposedName)370 OSQLTable OSQLParseTreeIterator::impl_locateRecordSource( const ::rtl::OUString& _rComposedName )
371 {
372     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_locateRecordSource" );
373     if ( !_rComposedName.getLength() )
374     {
375         OSL_ENSURE( false, "OSQLParseTreeIterator::impl_locateRecordSource: no object name at all?" );
376         return OSQLTable();
377     }
378 
379     OSQLTable aReturn;
380     ::rtl::OUString sComposedName( _rComposedName );
381 
382     try
383     {
384         ::rtl::OUString sCatalog, sSchema, sName;
385         qualifiedNameComponents( m_pImpl->m_xDatabaseMetaData, sComposedName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
386 
387         // check whether there is a query with the given name
388         bool bQueryDoesExist = m_pImpl->m_xQueryContainer.is() && m_pImpl->m_xQueryContainer->hasByName( sComposedName );
389 
390         // check whether the table container contains an object with the given name
391         if ( !bQueryDoesExist && !m_pImpl->m_xTableContainer->hasByName( sComposedName ) )
392             sComposedName = lcl_findTableInMetaData( m_pImpl->m_xDatabaseMetaData, sCatalog, sSchema, sName );
393         bool bTableDoesExist = m_pImpl->m_xTableContainer->hasByName( sComposedName );
394 
395         // now obtain the object
396 
397         // if we're creating a table, and there already is a table or query with the same name,
398         // this is worth an error
399         if ( SQL_STATEMENT_CREATE_TABLE == m_eStatementType )
400         {
401             if ( bQueryDoesExist )
402                 impl_appendError( IParseContext::ERROR_INVALID_QUERY_EXIST, &sName );
403             else if ( bTableDoesExist )
404                 impl_appendError( IParseContext::ERROR_INVALID_TABLE_EXIST, &sName );
405             else
406                 aReturn = impl_createTableObject( sName, sCatalog, sSchema );
407         }
408         else
409         {
410             // queries win over tables, so if there's a query with this name, take this, no matter if
411             // there's a table, too
412             if ( bQueryDoesExist )
413             {
414                 if  ( !m_pImpl->isQueryAllowed( sComposedName ) )
415                 {
416                     impl_appendError( m_rParser.getErrorHelper().getSQLException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES, NULL ) );
417                     return NULL;
418                 }
419 
420                 m_pImpl->m_xQueryContainer->getByName( sComposedName ) >>= aReturn;
421 
422                 // collect the parameters from the sub query
423                 ForbidQueryName aForbidName( *m_pImpl, sComposedName );
424                 impl_getQueryParameterColumns( aReturn );
425             }
426             else if ( bTableDoesExist )
427                 m_pImpl->m_xTableContainer->getByName( sComposedName ) >>= aReturn;
428             else
429             {
430                 if ( m_pImpl->m_xQueryContainer.is() )
431                     // the connection on which we're working supports sub queries in from (else
432                     // m_xQueryContainer would not have been set), so emit a better error message
433                     impl_appendError( IParseContext::ERROR_INVALID_TABLE_OR_QUERY, &sName );
434                 else
435                     impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sName );
436             }
437         }
438     }
439     catch(Exception&)
440     {
441         impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sComposedName );
442     }
443 
444     return aReturn;
445 }
446 
447 //-----------------------------------------------------------------------------
traverseOneTableName(OSQLTables & _rTables,const OSQLParseNode * pTableName,const::rtl::OUString & rTableRange)448 void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange )
449 {
450     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOneTableName" );
451     if ( ( m_pImpl->m_nIncludeMask & TableNames ) != TableNames )
452         // tables should not be included in the traversal
453         return;
454 
455     OSL_ENSURE(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL");
456 
457     Any aCatalog;
458     ::rtl::OUString aSchema,aTableName,aComposedName;
459     ::rtl::OUString aTableRange(rTableRange);
460 
461     // Tabellenname abholen
462     OSQLParseNode::getTableComponents(pTableName,aCatalog,aSchema,aTableName,m_pImpl->m_xDatabaseMetaData);
463 
464     // create the composed name like DOMAIN.USER.TABLE1
465     aComposedName = ::dbtools::composeTableName(m_pImpl->m_xDatabaseMetaData,
466                                 aCatalog.hasValue() ? ::comphelper::getString(aCatalog) : ::rtl::OUString(),
467                                 aSchema,
468                                 aTableName,
469                                 sal_False,
470                                 ::dbtools::eInDataManipulation);
471 
472     // if there is no alias for the table name assign the orignal name to it
473     if ( !aTableRange.getLength() )
474         aTableRange = aComposedName;
475 
476     // get the object representing this table/query
477     OSQLTable aTable = impl_locateRecordSource( aComposedName );
478     if ( aTable.is() )
479         _rTables[ aTableRange ] = aTable;
480 }
481 //-----------------------------------------------------------------------------
impl_fillJoinConditions(const OSQLParseNode * i_pJoinCondition)482 void OSQLParseTreeIterator::impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition)
483 {
484     if (i_pJoinCondition->count() == 3 &&   // Ausdruck is geklammert
485         SQL_ISPUNCTUATION(i_pJoinCondition->getChild(0),"(") &&
486         SQL_ISPUNCTUATION(i_pJoinCondition->getChild(2),")"))
487     {
488         impl_fillJoinConditions(i_pJoinCondition->getChild(1));
489     }
490     else if (SQL_ISRULEOR2(i_pJoinCondition,search_condition,boolean_term)  &&          // AND/OR-Verknuepfung:
491              i_pJoinCondition->count() == 3)
492     {
493         // nur AND Verkn�pfung zulassen
494         if ( SQL_ISTOKEN(i_pJoinCondition->getChild(1),AND) )
495         {
496             impl_fillJoinConditions(i_pJoinCondition->getChild(0));
497             impl_fillJoinConditions(i_pJoinCondition->getChild(1));
498         }
499     }
500     else if (SQL_ISRULE(i_pJoinCondition,comparison_predicate))
501     {
502         // only the comparison of columns is allowed
503         OSL_ENSURE(i_pJoinCondition->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree");
504         if (SQL_ISRULE(i_pJoinCondition->getChild(0),column_ref) &&
505               SQL_ISRULE(i_pJoinCondition->getChild(2),column_ref) &&
506                i_pJoinCondition->getChild(1)->getNodeType() == SQL_NODE_EQUAL)
507         {
508             m_pImpl->m_aJoinConditions.push_back( TNodePair(i_pJoinCondition->getChild(0),i_pJoinCondition->getChild(2)) );
509         }
510     }
511 }
512 //-----------------------------------------------------------------------------
getJoinConditions() const513 ::std::vector< TNodePair >& OSQLParseTreeIterator::getJoinConditions() const
514 {
515     return m_pImpl->m_aJoinConditions;
516 }
517 //-----------------------------------------------------------------------------
getQualified_join(OSQLTables & _rTables,const OSQLParseNode * pTableRef,::rtl::OUString & aTableRange)518 void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange )
519 {
520     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getQualified_join" );
521     OSL_PRECOND( SQL_ISRULE( pTableRef, cross_union ) || SQL_ISRULE( pTableRef, qualified_join ) ,
522         "OSQLParseTreeIterator::getQualified_join: illegal node!" );
523 
524     aTableRange = ::rtl::OUString();
525 
526     const OSQLParseNode* pNode = getTableNode(_rTables,pTableRef->getChild(0),aTableRange);
527     if ( isTableNode( pNode ) )
528         traverseOneTableName( _rTables, pNode, aTableRange );
529 
530     sal_uInt32 nPos = 4;
531     if( SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL)
532     {
533         nPos = 3;
534         // join_condition,named_columns_join
535         if ( SQL_ISRULE( pTableRef, qualified_join ) )
536         {
537             const OSQLParseNode* pJoin_spec = pTableRef->getChild(4);
538             if ( SQL_ISRULE( pJoin_spec, join_condition ) )
539             {
540                 impl_fillJoinConditions(pJoin_spec->getChild(1));
541             }
542             else
543             {
544                 const OSQLParseNode* pColumnCommalist = pJoin_spec->getChild(2);
545                 // Alle Columns in der column_commalist ...
546                 for (sal_uInt32 i = 0; i < pColumnCommalist->count(); i++)
547                 {
548                     const OSQLParseNode * pCol = pColumnCommalist->getChild(i);
549                     // add twice because the column must exists in both tables
550                     m_pImpl->m_aJoinConditions.push_back( TNodePair(pCol,pCol) );
551                 }
552             }
553         }
554     }
555 
556     pNode = getTableNode(_rTables,pTableRef->getChild(nPos),aTableRange);
557     if ( isTableNode( pNode ) )
558         traverseOneTableName( _rTables, pNode, aTableRange );
559 }
560 //-----------------------------------------------------------------------------
getTableNode(OSQLTables & _rTables,const OSQLParseNode * pTableRef,::rtl::OUString & rTableRange)561 const OSQLParseNode* OSQLParseTreeIterator::getTableNode( OSQLTables& _rTables, const OSQLParseNode *pTableRef,::rtl::OUString& rTableRange )
562 {
563     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTableNode" );
564     OSL_PRECOND( SQL_ISRULE( pTableRef, table_ref ) || SQL_ISRULE( pTableRef, joined_table )
565               || SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ),
566         "OSQLParseTreeIterator::getTableNode: only to be called for table_ref nodes!" );
567 
568     const OSQLParseNode* pTableNameNode = NULL;
569 
570     if ( SQL_ISRULE( pTableRef, joined_table ) )
571     {
572         getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
573     }
574     if ( SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ) )
575     {
576         getQualified_join( _rTables, pTableRef, rTableRange );
577     }
578     else
579     {
580         rTableRange = OSQLParseNode::getTableRange(pTableRef);
581         if  (   ( pTableRef->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
582             ||  ( pTableRef->count() == 5 ) // '(' joined_table ')' range_variable op_column_commalist
583             )
584         {
585             getQualified_join( _rTables, pTableRef->getChild(6 - pTableRef->count()), rTableRange );
586         }
587         else if ( pTableRef->count() == 3 ) // subquery range_variable op_column_commalist || '(' joined_table ')'
588         {
589             const OSQLParseNode* pSubQuery = pTableRef->getChild(0);
590             if ( pSubQuery->isToken() )
591             {
592                 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
593             }
594             else
595             {
596                 OSL_ENSURE( pSubQuery->count() == 3, "sub queries should have 3 children!" );
597                 const OSQLParseNode* pQueryExpression = pSubQuery->getChild(1);
598                 if ( SQL_ISRULE( pQueryExpression, select_statement ) )
599                 {
600                     getSelect_statement( *m_pImpl->m_pSubTables, pQueryExpression );
601                 }
602                 else
603                 {
604                     OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: subquery which is no select_statement: not yet implemented!" );
605                 }
606             }
607         }
608         else if ( pTableRef->count() == 2 ) // table_node table_primary_as_range_column
609         {
610             pTableNameNode = pTableRef->getChild(0);
611         }
612         else
613             OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: unhandled case!" );
614     }
615 
616     return pTableNameNode;
617 }
618 //-----------------------------------------------------------------------------
getSelect_statement(OSQLTables & _rTables,const OSQLParseNode * pSelect)619 void OSQLParseTreeIterator::getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect)
620 {
621     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSelect_statement" );
622     if(SQL_ISRULE(pSelect,union_statement))
623     {
624         getSelect_statement(_rTables,pSelect->getChild(0));
625         //getSelect_statement(pSelect->getChild(3));
626         return;
627     }
628     OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1);
629 
630     OSL_ENSURE(pTableRefCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
631     OSL_ENSURE(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: error in parse tree!");
632 
633     const OSQLParseNode* pTableName = NULL;
634     ::rtl::OUString aTableRange;
635     for (sal_uInt32 i = 0; i < pTableRefCommalist->count(); i++)
636     { // from clause durchlaufen
637         aTableRange = ::rtl::OUString();
638 
639         const OSQLParseNode* pTableListElement = pTableRefCommalist->getChild(i);
640         if ( isTableNode( pTableListElement ) )
641         {
642             traverseOneTableName( _rTables, pTableListElement, aTableRange );
643         }
644         else if ( SQL_ISRULE( pTableListElement, table_ref ) )
645         {
646             // Tabellenreferenz kann aus Tabellennamen, Tabellennamen (+),'('joined_table')'(+) bestehen
647             pTableName = pTableListElement->getChild(0);
648             if( isTableNode( pTableName ) )
649             {   // Tabellennamen gefunden
650                 aTableRange = OSQLParseNode::getTableRange(pTableListElement);
651                 traverseOneTableName( _rTables, pTableName, aTableRange );
652             }
653             else if(SQL_ISPUNCTUATION(pTableName,"{"))
654             {   // '{' SQL_TOKEN_OJ joined_table '}'
655                 getQualified_join( _rTables, pTableListElement->getChild(2), aTableRange );
656             }
657             else
658             {   // '(' joined_table ')' range_variable op_column_commalist
659                 getTableNode( _rTables, pTableListElement, aTableRange );
660             }
661         }
662         else if (SQL_ISRULE( pTableListElement, qualified_join ) || SQL_ISRULE( pTableListElement, cross_union ) )
663         {
664             getQualified_join( _rTables, pTableListElement, aTableRange );
665         }
666         else if ( SQL_ISRULE( pTableListElement, joined_table ) )
667         {
668             getQualified_join( _rTables, pTableListElement->getChild(1), aTableRange );
669         }
670 
671         //  if (! aIteratorStatus.IsSuccessful()) break;
672     }
673 }
674 //-----------------------------------------------------------------------------
traverseTableNames(OSQLTables & _rTables)675 bool OSQLParseTreeIterator::traverseTableNames(OSQLTables& _rTables)
676 {
677     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseTableNames" );
678     if ( m_pParseTree == NULL )
679         return false;
680 
681     OSQLParseNode* pTableName = NULL;
682 
683     switch ( m_eStatementType )
684     {
685         case SQL_STATEMENT_SELECT:
686             getSelect_statement( _rTables, m_pParseTree );
687             break;
688 
689         case SQL_STATEMENT_CREATE_TABLE:
690         case SQL_STATEMENT_INSERT:
691         case SQL_STATEMENT_DELETE:
692             pTableName = m_pParseTree->getChild(2);
693             break;
694 
695         case SQL_STATEMENT_UPDATE:
696             pTableName = m_pParseTree->getChild(1);
697             break;
698         default:
699             break;
700     }
701 
702     if ( pTableName )
703     {
704         ::rtl::OUString sTableRange;
705         traverseOneTableName( _rTables, pTableName, sTableRange );
706     }
707 
708     return !hasErrors();
709 }
710 //-----------------------------------------------------------------------------
getColumnAlias(const OSQLParseNode * _pDerivedColumn)711 ::rtl::OUString OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* _pDerivedColumn)
712 {
713     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnAlias" );
714     OSL_ENSURE(SQL_ISRULE(_pDerivedColumn,derived_column),"No derived column!");
715     ::rtl::OUString sColumnAlias;
716     if(_pDerivedColumn->getChild(1)->count() == 2)
717         sColumnAlias = _pDerivedColumn->getChild(1)->getChild(1)->getTokenValue();
718     else if(!_pDerivedColumn->getChild(1)->isRule())
719         sColumnAlias = _pDerivedColumn->getChild(1)->getTokenValue();
720     return sColumnAlias;
721 }
722 
723 // -----------------------------------------------------------------------------
724 namespace
725 {
lcl_getColumnRange(const OSQLParseNode * _pColumnRef,const Reference<XConnection> & _rxConnection,::rtl::OUString & _out_rColumnName,::rtl::OUString & _out_rTableRange,const OSQLColumns * _pSelectColumns,::rtl::OUString & _out_rColumnAliasIfPresent)726     void lcl_getColumnRange( const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection,
727         ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange,
728         const OSQLColumns* _pSelectColumns, ::rtl::OUString& _out_rColumnAliasIfPresent )
729     {
730         _out_rColumnName = _out_rTableRange = _out_rColumnAliasIfPresent = ::rtl::OUString();
731         if ( SQL_ISRULE( _pColumnRef, column_ref ) )
732         {
733             if( _pColumnRef->count() > 1 )
734             {
735                 for ( sal_Int32 i=0; i<((sal_Int32)_pColumnRef->count())-2; ++i )
736                     _pColumnRef->getChild(i)->parseNodeToStr( _out_rTableRange, _rxConnection, NULL, sal_False, sal_False );
737                 _out_rColumnName = _pColumnRef->getChild( _pColumnRef->count()-1 )->getChild(0)->getTokenValue();
738             }
739             else
740                 _out_rColumnName = _pColumnRef->getChild(0)->getTokenValue();
741 
742             // look up the column in the select column, to find an possible alias
743             if ( _pSelectColumns )
744             {
745                 for (   OSQLColumns::Vector::const_iterator lookupColumn = _pSelectColumns->get().begin();
746                         lookupColumn != _pSelectColumns->get().end();
747                         ++lookupColumn
748                     )
749                 {
750                     Reference< XPropertySet > xColumn( *lookupColumn );
751                     try
752                     {
753                         ::rtl::OUString sName, sTableName;
754                         xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) >>= sName;
755                         xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sTableName;
756                         if ( sName == _out_rColumnName && sTableName == _out_rTableRange )
757                             xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= _out_rColumnAliasIfPresent;
758                     }
759                     catch( const Exception& )
760                     {
761                         DBG_UNHANDLED_EXCEPTION();
762                     }
763                 }
764             }
765         }
766         else if(SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec))
767         { // Funktion
768             _pColumnRef->parseNodeToStr( _out_rColumnName, _rxConnection );
769         }
770         else  if(_pColumnRef->getNodeType() == SQL_NODE_NAME)
771             _out_rColumnName = _pColumnRef->getTokenValue();
772     }
773 }
774 
775 // -----------------------------------------------------------------------------
getColumnRange(const OSQLParseNode * _pColumnRef,::rtl::OUString & _rColumnName,::rtl::OUString & _rTableRange) const776 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
777                         ::rtl::OUString& _rColumnName,
778                         ::rtl::OUString& _rTableRange) const
779 {
780     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
781     ::rtl::OUString sDummy;
782     lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, NULL, sDummy );
783 }
784 
785 // -----------------------------------------------------------------------------
getColumnRange(const OSQLParseNode * _pColumnRef,::rtl::OUString & _rColumnName,::rtl::OUString & _rTableRange,::rtl::OUString & _out_rColumnAliasIfPresent) const786 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
787                         ::rtl::OUString& _rColumnName,
788                         ::rtl::OUString& _rTableRange,
789                         ::rtl::OUString& _out_rColumnAliasIfPresent ) const
790 {
791     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
792     lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, &*m_aSelectColumns, _out_rColumnAliasIfPresent );
793 }
794 
795 //-----------------------------------------------------------------------------
getColumnRange(const OSQLParseNode * _pColumnRef,const Reference<XConnection> & _rxConnection,::rtl::OUString & _out_rColumnName,::rtl::OUString & _out_rTableRange)796 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
797     const Reference< XConnection >& _rxConnection, ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange )
798 {
799     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
800     ::rtl::OUString sDummy;
801     lcl_getColumnRange( _pColumnRef, _rxConnection, _out_rColumnName, _out_rTableRange, NULL, sDummy );
802 }
803 
804 //-----------------------------------------------------------------------------
getColumnTableRange(const OSQLParseNode * pNode,::rtl::OUString & rTableRange) const805 sal_Bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const
806 {
807     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnTableRange" );
808     // Ermitteln ob alle Spalten zu einer Tabelle gehoeren
809     if (SQL_ISRULE(pNode,column_ref))
810     {
811         ::rtl::OUString aColName, aTableRange;
812         getColumnRange(pNode, aColName, aTableRange);
813         if (!aTableRange.getLength())   // keinen gefunden
814         {
815             // dann die Spalte in den Tabellen suchen
816             for (ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter)
817             {
818                 if (aIter->second.is())
819                 {
820                     try
821                     {
822                         Reference< XNameAccess > xColumns = aIter->second->getColumns();
823                         if(xColumns->hasByName(aColName))
824                         {
825                             Reference< XPropertySet > xColumn;
826                             if (xColumns->getByName(aColName) >>= xColumn)
827                             {
828                                 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
829                                 aTableRange = aIter->first;
830                                 break;
831                             }
832                         }
833                     }
834                     catch(Exception&)
835                     {
836                     }
837                 }
838             }
839             if (!aTableRange.getLength())
840                 return sal_False;
841         }
842 
843 
844         if (!rTableRange.getLength())
845             rTableRange = aTableRange;
846         else if (rTableRange != aTableRange)
847             return sal_False;
848     }
849     else
850     {
851         for (sal_uInt32 i = 0, ncount = pNode->count(); i < ncount; i++)
852         {
853             if (!getColumnTableRange(pNode->getChild(i), rTableRange))
854                 return sal_False;
855         }
856     }
857     return sal_True;
858 }
859 
860 //-----------------------------------------------------------------------------
traverseCreateColumns(const OSQLParseNode * pSelectNode)861 void OSQLParseTreeIterator::traverseCreateColumns(const OSQLParseNode* pSelectNode)
862 {
863     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseCreateColumns" );
864     //  aIteratorStatus.Clear();
865 
866     if (!pSelectNode || m_eStatementType != SQL_STATEMENT_CREATE_TABLE || m_pImpl->m_pTables->empty())
867     {
868         impl_appendError( IParseContext::ERROR_GENERAL );
869         return;
870     }
871     if (!SQL_ISRULE(pSelectNode,base_table_element_commalist))
872         return ;
873 
874     for (sal_uInt32 i = 0; i < pSelectNode->count(); i++)
875     {
876         OSQLParseNode *pColumnRef = pSelectNode->getChild(i);
877 
878         if (SQL_ISRULE(pColumnRef,column_def))
879         {
880             ::rtl::OUString aColumnName;
881             ::rtl::OUString aTypeName;
882             ::rtl::OUString aTableRange;
883             sal_Int32 nType = DataType::VARCHAR;
884             sal_Int32 nLen  = 0;
885             aColumnName = pColumnRef->getChild(0)->getTokenValue();
886 
887             OSQLParseNode *pDatatype = pColumnRef->getChild(1);
888             if (pDatatype && SQL_ISRULE(pDatatype,character_string_type))
889             {
890                 const OSQLParseNode *pType = pDatatype->getChild(0);
891                 aTypeName = pType->getTokenValue();
892                 if (pDatatype->count() == 2 && (pType->getTokenID() == SQL_TOKEN_CHAR || pType->getTokenID() == SQL_TOKEN_CHARACTER ))
893                     nType = DataType::CHAR;
894 
895                 const OSQLParseNode *pParams = pDatatype->getChild(pDatatype->count()-1);
896                 if ( pParams->count() )
897                 {
898                     nLen = pParams->getChild(1)->getTokenValue().toInt32();
899                 }
900             }
901             else if(pDatatype && pDatatype->getNodeType() == SQL_NODE_KEYWORD)
902             {
903                 aTypeName = ::rtl::OUString::createFromAscii("VARCHAR");
904             }
905 
906             if (aTypeName.getLength())
907             {
908                 //TODO:Create a new class for create statement to handle field length
909                 OParseColumn* pColumn = new OParseColumn(aColumnName,aTypeName,::rtl::OUString(),::rtl::OUString(),
910                     ColumnValue::NULLABLE_UNKNOWN,0,0,nType,sal_False,sal_False,isCaseSensitive());
911                 pColumn->setFunction(sal_False);
912                 pColumn->setRealName(aColumnName);
913 
914                 Reference< XPropertySet> xCol = pColumn;
915                 m_aCreateColumns->get().push_back(xCol);
916             }
917         }
918 
919     }
920 }
921 //-----------------------------------------------------------------------------
traverseSelectColumnNames(const OSQLParseNode * pSelectNode)922 bool OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode)
923 {
924     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectColumnNames" );
925     if ( ( m_pImpl->m_nIncludeMask & SelectColumns ) != SelectColumns )
926         return true;
927 
928     if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || m_pImpl->m_pTables->empty())
929     {
930         impl_appendError( IParseContext::ERROR_GENERAL );
931         return false;
932     }
933 
934     if(SQL_ISRULE(pSelectNode,union_statement))
935     {
936         return  traverseSelectColumnNames( pSelectNode->getChild( 0 ) )
937             /*&&  traverseSelectColumnNames( pSelectNode->getChild( 3 ) )*/;
938     }
939 
940     static ::rtl::OUString aEmptyString;
941     // nyi: mehr Pruefung auf korrekte Struktur!
942     if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*"))
943     {
944         // SELECT * ...
945         setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aEmptyString);
946     }
947     else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist))
948     {
949         // SELECT column[,column] oder SELECT COUNT(*) ...
950         OSQLParseNode * pSelection = pSelectNode->getChild(2);
951 
952         for (sal_uInt32 i = 0; i < pSelection->count(); i++)
953         {
954             OSQLParseNode *pColumnRef = pSelection->getChild(i);
955 
956             //if (SQL_ISRULE(pColumnRef,select_sublist))
957             if (SQL_ISRULE(pColumnRef,derived_column) &&
958                 SQL_ISRULE(pColumnRef->getChild(0),column_ref) &&
959                 pColumnRef->getChild(0)->count() == 3 &&
960                 SQL_ISPUNCTUATION(pColumnRef->getChild(0)->getChild(2),"*"))
961             {
962                 // alle Spalten der Tabelle
963                 ::rtl::OUString aTableRange;
964                 pColumnRef->getChild(0)->parseNodeToStr( aTableRange, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
965                 setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aTableRange);
966                 continue;
967             }
968             else if (SQL_ISRULE(pColumnRef,derived_column))
969             {
970                 ::rtl::OUString aColumnAlias(getColumnAlias(pColumnRef)); // kann leer sein
971                 ::rtl::OUString sColumnName;
972                 ::rtl::OUString aTableRange;
973                 sal_Int32 nType = DataType::VARCHAR;
974                 sal_Bool bFkt(sal_False);
975                 pColumnRef = pColumnRef->getChild(0);
976                 if (
977                         pColumnRef->count() == 3 &&
978                         SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
979                         SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
980                     )
981                     pColumnRef = pColumnRef->getChild(1);
982 
983                 if (SQL_ISRULE(pColumnRef,column_ref))
984                 {
985                     getColumnRange(pColumnRef,sColumnName,aTableRange);
986                     OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein");
987                 }
988                 else /*if (SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec)    ||
989                          SQL_ISRULE(pColumnRef,position_exp)    || SQL_ISRULE(pColumnRef,extract_exp)   ||
990                          SQL_ISRULE(pColumnRef,length_exp)      || SQL_ISRULE(pColumnRef,char_value_fct)||
991                          SQL_ISRULE(pColumnRef,num_value_exp)   || SQL_ISRULE(pColumnRef,term))*/
992                 {
993                     /* Funktionsaufruf vorhanden */
994                     pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_True );
995                     ::rtl::OUString sTableRange;
996                     // check if the column is also a parameter
997                     traverseORCriteria(pColumnRef); // num_value_exp
998 
999                     // gehoeren alle beteiligten Spalten der Funktion zu einer Tabelle
1000                     if (m_pImpl->m_pTables->size() == 1)
1001                     {
1002                         aTableRange = m_pImpl->m_pTables->begin()->first;
1003                     }
1004                     else
1005                     {
1006                         getColumnTableRange(pColumnRef,aTableRange);
1007                     }
1008                     if ( pColumnRef->isRule() )
1009                     {
1010                         bFkt = sal_True;
1011                         nType = getFunctionReturnType(pColumnRef);
1012                     }
1013                 }
1014                 /*
1015                 else
1016                 {
1017                     aIteratorStatus.setStatementTooComplex();
1018                     return;
1019                 }
1020                 */
1021                 if(!aColumnAlias.getLength())
1022                     aColumnAlias = sColumnName;
1023                 setSelectColumnName(m_aSelectColumns,sColumnName,aColumnAlias,aTableRange,bFkt,nType,SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec));
1024             }
1025         }
1026     }
1027 
1028     return !hasErrors();
1029 }
1030 
1031 
1032 //-----------------------------------------------------------------------------
traverseOrderByColumnNames(const OSQLParseNode * pSelectNode)1033 bool OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode)
1034 {
1035     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOrderByColumnNames" );
1036     traverseByColumnNames( pSelectNode, sal_True );
1037     return !hasErrors();
1038 }
1039 //-----------------------------------------------------------------------------
traverseByColumnNames(const OSQLParseNode * pSelectNode,sal_Bool _bOrder)1040 void OSQLParseTreeIterator::traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder)
1041 {
1042     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseByColumnNames" );
1043     //  aIteratorStatus.Clear();
1044 
1045     if (pSelectNode == NULL)
1046     {
1047         //aIteratorStatus.setInvalidStatement();
1048         return;
1049     }
1050 
1051     if (m_eStatementType != SQL_STATEMENT_SELECT)
1052     {
1053         //aIteratorStatus.setInvalidStatement();
1054         return;
1055     }
1056 
1057     if(SQL_ISRULE(pSelectNode,union_statement))
1058     {
1059         traverseByColumnNames(pSelectNode->getChild(0),_bOrder);
1060         return;
1061     }
1062 
1063     OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1064 
1065     OSQLParseNode * pTableExp = pSelectNode->getChild(3);
1066     OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1067     OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator:table_exp error in parse tree!");
1068     OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
1069 
1070     sal_uInt32 nPos = ( _bOrder ? ORDER_BY_CHILD_POS : 2 );
1071 
1072     OSQLParseNode * pOptByClause = pTableExp->getChild(nPos);
1073     OSL_ENSURE(pOptByClause != NULL,"OSQLParseTreeIterator: error in parse tree!");
1074     if ( pOptByClause->count() == 0 )
1075         return;
1076 
1077     OSL_ENSURE(pOptByClause->count() == 3,"OSQLParseTreeIterator: error in parse tree!");
1078 
1079     OSQLParseNode * pOrderingSpecCommalist = pOptByClause->getChild(2);
1080     OSL_ENSURE(pOrderingSpecCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
1081     OSL_ENSURE(!_bOrder || SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OSQLParseTreeIterator:ordering_spec_commalist error in parse tree!");
1082     OSL_ENSURE(pOrderingSpecCommalist->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
1083 
1084     ::rtl::OUString sColumnName,aColumnAlias;
1085     ::rtl::OUString aTableRange;
1086     sal_uInt32 nCount = pOrderingSpecCommalist->count();
1087     for (sal_uInt32 i = 0; i < nCount; ++i)
1088     {
1089         OSQLParseNode* pColumnRef  = pOrderingSpecCommalist->getChild(i);
1090         OSL_ENSURE(pColumnRef  != NULL,"OSQLParseTreeIterator: error in parse tree!");
1091         if ( _bOrder )
1092         {
1093             OSL_ENSURE(SQL_ISRULE(pColumnRef,ordering_spec),"OSQLParseTreeIterator:ordering_spec error in parse tree!");
1094             OSL_ENSURE(pColumnRef->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1095 
1096             pColumnRef = pColumnRef->getChild(0);
1097         }
1098         aTableRange = ::rtl::OUString();
1099         sColumnName = ::rtl::OUString();
1100         if ( SQL_ISRULE(pColumnRef,column_ref) )
1101         {
1102             // Column-Name (und TableRange):
1103             if(SQL_ISRULE(pColumnRef,column_ref))
1104                 getColumnRange(pColumnRef,sColumnName,aTableRange);
1105             else // eine Expression
1106                 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1107 
1108             OSL_ENSURE(sColumnName.getLength(),"sColumnName darf nicht leer sein");
1109         }
1110         else
1111         {   // here I found a predicate
1112             pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1113         }
1114         OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
1115         if ( _bOrder )
1116         {
1117             // Ascending/Descending
1118             OSQLParseNode * pOptAscDesc = pColumnRef->getParent()->getChild(1);
1119             OSL_ENSURE(pOptAscDesc != NULL,"OSQLParseTreeIterator: error in parse tree!");
1120 
1121             sal_Bool bAscending = pOptAscDesc && SQL_ISTOKEN(pOptAscDesc,ASC);
1122             setOrderByColumnName(sColumnName, aTableRange,bAscending);
1123         }
1124         else
1125             setGroupByColumnName(sColumnName, aTableRange);
1126     }
1127 }
1128 //-----------------------------------------------------------------------------
traverseGroupByColumnNames(const OSQLParseNode * pSelectNode)1129 bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode* pSelectNode)
1130 {
1131     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseGroupByColumnNames" );
1132     traverseByColumnNames( pSelectNode, sal_False );
1133     return !hasErrors();
1134 }
1135 
1136 // -----------------------------------------------------------------------------
1137 namespace
1138 {
lcl_generateParameterName(const OSQLParseNode & _rParentNode,const OSQLParseNode & _rParamNode)1139     ::rtl::OUString lcl_generateParameterName( const OSQLParseNode& _rParentNode, const OSQLParseNode& _rParamNode )
1140     {
1141         ::rtl::OUString sColumnName( RTL_CONSTASCII_USTRINGPARAM( "param" ) );
1142         const sal_Int32 nCount = (sal_Int32)_rParentNode.count();
1143         for ( sal_Int32 i = 0; i < nCount; ++i )
1144         {
1145             if ( _rParentNode.getChild(i) == &_rParamNode )
1146             {
1147                 sColumnName += ::rtl::OUString::valueOf( i+1 );
1148                 break;
1149             }
1150         }
1151         return sColumnName;
1152     }
1153 }
1154 
1155 // -----------------------------------------------------------------------------
traverseParameters(const OSQLParseNode * _pNode)1156 void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode)
1157 {
1158     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameters" );
1159     if ( _pNode == NULL )
1160         return;
1161 
1162     ::rtl::OUString sColumnName, sTableRange, aColumnAlias;
1163     const OSQLParseNode* pParent = _pNode->getParent();
1164     if ( pParent != NULL )
1165     {
1166         if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1167         {
1168             sal_uInt32 nPos = 0;
1169             if ( pParent->getChild(nPos) == _pNode )
1170                 nPos = 2;
1171             const OSQLParseNode* pOther = pParent->getChild(nPos);
1172             if ( SQL_ISRULE( pOther, column_ref ) )
1173                 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1174             else
1175                 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1176         } // if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1177         else if ( SQL_ISRULE(pParent,other_like_predicate_part_2) )
1178         {
1179             const OSQLParseNode* pOther = pParent->getParent()->getChild(0);
1180             if ( SQL_ISRULE( pOther, column_ref ) )
1181                 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1182             else
1183                 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1184         }
1185         else if ( SQL_ISRULE(pParent,between_predicate_part_2) )
1186         {
1187             const OSQLParseNode* pOther = pParent->getParent()->getChild(0);
1188             if ( SQL_ISRULE( pOther, column_ref ) )
1189                 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1190             else
1191             {
1192                 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1193                 lcl_generateParameterName( *pParent, *_pNode );
1194             }
1195         }
1196         else if ( pParent->getNodeType() == SQL_NODE_COMMALISTRULE )
1197         {
1198             lcl_generateParameterName( *pParent, *_pNode );
1199         }
1200     }
1201     traverseParameter( _pNode, pParent, sColumnName, sTableRange, aColumnAlias );
1202     const sal_uInt32 nCount = _pNode->count();
1203     for (sal_uInt32 i = 0; i < nCount; ++i)
1204     {
1205         const OSQLParseNode* pChild  = _pNode->getChild(i);
1206         traverseParameters( pChild );
1207     }
1208 }
1209 //-----------------------------------------------------------------------------
traverseSelectionCriteria(const OSQLParseNode * pSelectNode)1210 bool OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode)
1211 {
1212     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectionCriteria" );
1213     if ( pSelectNode == NULL )
1214         return false;
1215 
1216 
1217     // Parse Tree analysieren (je nach Statement-Typ)
1218     // und Zeiger auf WHERE-Klausel setzen:
1219     OSQLParseNode * pWhereClause = NULL;
1220 
1221     if (m_eStatementType == SQL_STATEMENT_SELECT)
1222     {
1223         if(SQL_ISRULE(pSelectNode,union_statement))
1224         {
1225             return  traverseSelectionCriteria( pSelectNode->getChild( 0 ) )
1226                 &&  traverseSelectionCriteria( pSelectNode->getChild( 3 ) );
1227         }
1228         OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1229 
1230         OSQLParseNode * pTableExp = pSelectNode->getChild(3);
1231         OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1232         OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1233         OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
1234 
1235         pWhereClause = pTableExp->getChild(1);
1236     } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) {
1237         OSL_ENSURE(pSelectNode->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1238         pWhereClause = pSelectNode->getChild(4);
1239     } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) {
1240         OSL_ENSURE(pSelectNode->count() == 4,"OSQLParseTreeIterator: error in parse tree!");
1241         pWhereClause = pSelectNode->getChild(3);
1242     } else if (SQL_ISRULE(pSelectNode,delete_statement_positioned)) {
1243         // nyi
1244         OSL_ASSERT("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi");
1245     } else {
1246         // Anderes Statement. Keine Selektionskriterien.
1247         return false;
1248     }
1249 
1250     if (! SQL_ISRULE(pWhereClause,where_clause)) {
1251         // Die Where Clause ist meistens optional, d. h. es koennte sich auch
1252         // um "optional_where_clause" handeln.
1253         OSL_ENSURE(SQL_ISRULE(pWhereClause,opt_where_clause),"OSQLParseTreeIterator: error in parse tree!");
1254         return false;
1255     }
1256 
1257     // Wenn es aber eine where_clause ist, dann darf sie nicht leer sein:
1258     OSL_ENSURE(pWhereClause->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1259 
1260     OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1);
1261     OSL_ENSURE(pComparisonPredicate != NULL,"OSQLParseTreeIterator: error in parse tree!");
1262 
1263     //
1264     // Und nun die Vergleichskriterien abarbeiten (rekursiv, alles ist erstmal ein OR-Kriterium):
1265     //
1266 
1267     traverseORCriteria(pComparisonPredicate);
1268 
1269     return !hasErrors();
1270 }
1271 
1272 //-----------------------------------------------------------------------------
traverseORCriteria(OSQLParseNode * pSearchCondition)1273 void OSQLParseTreeIterator::traverseORCriteria(OSQLParseNode * pSearchCondition)
1274 {
1275     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseORCriteria" );
1276 
1277 
1278     if (
1279             pSearchCondition->count() == 3 &&
1280             SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
1281             SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
1282         )
1283     {
1284         // Runde Klammern um den Ausdruck
1285         traverseORCriteria(pSearchCondition->getChild(1));
1286     } else if (SQL_ISRULE(pSearchCondition,search_condition) &&
1287         pSearchCondition->count() == 3 &&
1288         SQL_ISTOKEN(pSearchCondition->getChild(1),OR))
1289     {
1290         // OR-Verknuepfung:
1291 
1292         for (int i = 0; i < 3; i++) {
1293             if (i == 1) continue;       // Schluesselwort OR ueberspringen
1294 
1295             // Ist das erste Element wieder eine OR-Verknuepfung?
1296             if (i == 0 &&
1297                 SQL_ISRULE(pSearchCondition->getChild(0),search_condition) &&
1298                 pSearchCondition->getChild(0)->count() == 3 &&
1299                 SQL_ISTOKEN(pSearchCondition->getChild(0)->getChild(1),OR))
1300             {
1301                 // Dann rekursiv absteigen ...
1302                 traverseORCriteria(pSearchCondition->getChild(0));
1303 
1304             } else {
1305                 // AND-Kriterien ...
1306                 traverseANDCriteria(pSearchCondition->getChild(i));
1307                 //  if (! aIteratorStatus.IsSuccessful()) break;
1308             }
1309 
1310             //  if (! aIteratorStatus.IsSuccessful()) break;
1311         }
1312     } else {
1313         // Nur *ein* Kriterium oder eine AND-Verknuepfung von Kriterien.
1314         // Direkt die AND-Kriterien behandeln.
1315         traverseANDCriteria(pSearchCondition);
1316         //  if (! aIteratorStatus.IsSuccessful()) return;
1317     }
1318 
1319     // Fehler einfach weiterreichen.
1320 }
1321 
1322 //-----------------------------------------------------------------------------
traverseANDCriteria(OSQLParseNode * pSearchCondition)1323 void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition)
1324 {
1325     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseANDCriteria" );
1326 
1327 
1328     if (
1329             SQL_ISRULE(pSearchCondition,boolean_primary) &&
1330             pSearchCondition->count() == 3 &&
1331             SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
1332             SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
1333         )
1334     {
1335         // Runde Klammern
1336         traverseANDCriteria(pSearchCondition->getChild(1));
1337     }
1338     // Das erste Element ist eine OR-Verknuepfung
1339     else  if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 )
1340     {
1341         // Dann rekursiv absteigen (dieselbe Row benutzen) ...
1342         traverseORCriteria(pSearchCondition->getChild(0));
1343 //      if (! aIteratorStatus.IsSuccessful())
1344 //          return;
1345 
1346         // Und mit dem rechten Child weitermachen:
1347         traverseANDCriteria(pSearchCondition->getChild(2));
1348     }
1349     // Das erste Element ist (wieder) eine AND-Verknuepfung
1350     else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 )
1351     {
1352         // Dann rekursiv absteigen (dieselbe Row benutzen) ...
1353         traverseANDCriteria(pSearchCondition->getChild(0));
1354 //      if (! aIteratorStatus.IsSuccessful())
1355 //          return;
1356 
1357         // Und mit dem rechten Child weitermachen:
1358         traverseANDCriteria(pSearchCondition->getChild(2));
1359     }
1360      // Sonst einzelne Suchkriterien wie =, !=, ..., LIKE, IS NULL usw. behandeln:
1361     else if (SQL_ISRULE(pSearchCondition,comparison_predicate) )
1362     {
1363         ::rtl::OUString aValue;
1364         pSearchCondition->getChild(2)->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1365         traverseOnePredicate(pSearchCondition->getChild(0),aValue,pSearchCondition->getChild(2));
1366         impl_fillJoinConditions(pSearchCondition);
1367 //      if (! aIteratorStatus.IsSuccessful())
1368 //          return;
1369     }
1370     else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1371     {
1372         OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1373         const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1374 
1375         sal_Int32 nCurentPos = pPart2->count()-2;
1376 
1377         OSQLParseNode * pNum_value_exp  = pPart2->getChild(nCurentPos);
1378         OSQLParseNode * pOptEscape      = pPart2->getChild(nCurentPos+1);
1379 
1380         OSL_ENSURE(pNum_value_exp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1381         OSL_ENSURE(pOptEscape != NULL,"OSQLParseTreeIterator: error in parse tree!");
1382 
1383         if (pOptEscape->count() != 0)
1384         {
1385             //  aIteratorStatus.setStatementTooComplex();
1386             return;
1387         }
1388 
1389         ::rtl::OUString aValue;
1390         OSQLParseNode * pParam = NULL;
1391         if (SQL_ISRULE(pNum_value_exp,parameter))
1392             pParam = pNum_value_exp;
1393         else if(pNum_value_exp->isToken())
1394             // Normaler Wert
1395             aValue = pNum_value_exp->getTokenValue();
1396         else
1397         {
1398             pNum_value_exp->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1399             pParam = pNum_value_exp;
1400         }
1401 
1402         traverseOnePredicate(pSearchCondition->getChild(0),aValue,pParam);
1403 //      if (! aIteratorStatus.IsSuccessful())
1404 //          return;
1405     }
1406     else if (SQL_ISRULE(pSearchCondition,in_predicate))
1407     {
1408         OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1409         const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1410 
1411         traverseORCriteria(pSearchCondition->getChild(0));
1412         //  if (! aIteratorStatus.IsSuccessful()) return;
1413 
1414         OSQLParseNode* pChild = pPart2->getChild(2);
1415         if ( SQL_ISRULE(pChild->getChild(0),subquery) )
1416         {
1417             traverseTableNames( *m_pImpl->m_pSubTables );
1418             traverseSelectionCriteria(pChild->getChild(0)->getChild(1));
1419         }
1420         else
1421         { // '(' value_exp_commalist ')'
1422             pChild = pChild->getChild(1);
1423             sal_Int32 nCount = pChild->count();
1424             for (sal_Int32 i=0; i < nCount; ++i)
1425             {
1426                 traverseANDCriteria(pChild->getChild(i));
1427             }
1428         }
1429     }
1430     else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1431     {
1432         OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1433         const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1434         (void)pPart2;
1435         OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"OSQLParseTreeIterator: error in parse tree!");
1436 
1437         ::rtl::OUString aString;
1438         traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL);
1439         //  if (! aIteratorStatus.IsSuccessful()) return;
1440     }
1441     else if (SQL_ISRULE(pSearchCondition,num_value_exp) || SQL_ISRULE(pSearchCondition,term))
1442     {
1443         ::rtl::OUString aString;
1444         traverseOnePredicate(pSearchCondition->getChild(0),aString,pSearchCondition->getChild(0));
1445         traverseOnePredicate(pSearchCondition->getChild(2),aString,pSearchCondition->getChild(2));
1446     }
1447     // Fehler einfach weiterreichen.
1448 }
1449 //-----------------------------------------------------------------------------
traverseParameter(const OSQLParseNode * _pParseNode,const OSQLParseNode * _pParentNode,const::rtl::OUString & _aColumnName,const::rtl::OUString & _aTableRange,const::rtl::OUString & _rColumnAlias)1450 void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode
1451                                               ,const OSQLParseNode* _pParentNode
1452                                               ,const ::rtl::OUString& _aColumnName
1453                                               ,const ::rtl::OUString& _aTableRange
1454                                               ,const ::rtl::OUString& _rColumnAlias)
1455 {
1456     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameter" );
1457     if ( !SQL_ISRULE( _pParseNode, parameter ) )
1458         return;
1459 
1460     if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
1461         // parameters not to be included in the traversal
1462         return;
1463 
1464     OSL_ENSURE(_pParseNode->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
1465     OSQLParseNode * pMark = _pParseNode->getChild(0);
1466     ::rtl::OUString sParameterName;
1467 
1468     if (SQL_ISPUNCTUATION(pMark,"?"))
1469     {
1470         sParameterName =    _rColumnAlias.getLength()
1471                         ?   _rColumnAlias
1472                         :   _aColumnName.getLength()
1473                         ?   _aColumnName
1474                         :   ::rtl::OUString::createFromAscii("?");
1475     }
1476     else if (SQL_ISPUNCTUATION(pMark,":"))
1477     {
1478         sParameterName = _pParseNode->getChild(1)->getTokenValue();
1479     }
1480     else if (SQL_ISPUNCTUATION(pMark,"["))
1481     {
1482         sParameterName = _pParseNode->getChild(1)->getTokenValue();
1483     }
1484     else
1485     {
1486         OSL_ASSERT("OSQLParseTreeIterator: error in parse tree!");
1487     }
1488 
1489     // found a parameter
1490     if ( _pParentNode && (SQL_ISRULE(_pParentNode,general_set_fct) || SQL_ISRULE(_pParentNode,set_fct_spec)) )
1491     {// found a function as column_ref
1492         ::rtl::OUString sFunctionName;
1493         _pParentNode->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1494         const sal_uInt32 nCount = _pParentNode->count();
1495         sal_uInt32 i = 0;
1496         for(; i < nCount;++i)
1497         {
1498             if ( _pParentNode->getChild(i) == _pParseNode )
1499                 break;
1500         }
1501         sal_Int32 nType = ::connectivity::OSQLParser::getFunctionParameterType( _pParentNode->getChild(0)->getTokenID(), i-1);
1502 
1503         OParseColumn* pColumn = new OParseColumn(   sParameterName,
1504                                                     ::rtl::OUString(),
1505                                                     ::rtl::OUString(),
1506                                                     ::rtl::OUString(),
1507                                                     ColumnValue::NULLABLE_UNKNOWN,
1508                                                     0,
1509                                                     0,
1510                                                     nType,
1511                                                     sal_False,
1512                                                     sal_False,
1513                                                     isCaseSensitive());
1514         pColumn->setFunction(sal_True);
1515         pColumn->setAggregateFunction(sal_True);
1516         pColumn->setRealName(sFunctionName);
1517         m_aParameters->get().push_back(pColumn);
1518     }
1519     else
1520     {
1521         sal_Bool bNotFound = sal_True;
1522         OSQLColumns::Vector::const_iterator aIter = ::connectivity::find(
1523             m_aSelectColumns->get().begin(),
1524             m_aSelectColumns->get().end(),
1525             _aColumnName,::comphelper::UStringMixEqual( isCaseSensitive() )
1526         );
1527         if(aIter != m_aSelectColumns->get().end())
1528         {
1529             OParseColumn* pNewColumn = new OParseColumn(*aIter,isCaseSensitive());
1530             pNewColumn->setName(sParameterName);
1531             pNewColumn->setRealName(_aColumnName);
1532             m_aParameters->get().push_back(pNewColumn);
1533             bNotFound = sal_False;
1534         }
1535         else if(_aColumnName.getLength())// search in the tables for the right one
1536         {
1537 
1538             Reference<XPropertySet> xColumn = findColumn( _aColumnName, _aTableRange, true );
1539 
1540             if ( xColumn.is() )
1541             {
1542                 OParseColumn* pNewColumn = new OParseColumn(xColumn,isCaseSensitive());
1543                 pNewColumn->setName(sParameterName);
1544                 pNewColumn->setRealName(_aColumnName);
1545                 m_aParameters->get().push_back(pNewColumn);
1546                 bNotFound = sal_False;
1547             }
1548         }
1549         if ( bNotFound )
1550         {
1551             sal_Int32 nType = DataType::VARCHAR;
1552             OSQLParseNode* pParent = _pParentNode ? _pParentNode->getParent() : NULL;
1553             if ( pParent && (SQL_ISRULE(pParent,general_set_fct) || SQL_ISRULE(pParent,set_fct_spec)) )
1554             {
1555                 const sal_uInt32 nCount = _pParentNode->count();
1556                 sal_uInt32 i = 0;
1557                 for(; i < nCount;++i)
1558                 {
1559                     if ( _pParentNode->getChild(i) == _pParseNode )
1560                         break;
1561                 }
1562                 nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1);
1563             }
1564 
1565             ::rtl::OUString aNewColName( getUniqueColumnName( sParameterName ) );
1566 
1567             OParseColumn* pColumn = new OParseColumn(aNewColName,
1568                                                     ::rtl::OUString(),
1569                                                     ::rtl::OUString(),
1570                                                     ::rtl::OUString(),
1571                                                     ColumnValue::NULLABLE_UNKNOWN,
1572                                                     0,
1573                                                     0,
1574                                                     nType,
1575                                                     sal_False,
1576                                                     sal_False,
1577                                                     isCaseSensitive() );
1578             pColumn->setName(aNewColName);
1579             pColumn->setRealName(sParameterName);
1580             m_aParameters->get().push_back(pColumn);
1581         }
1582     }
1583 }
1584 //-----------------------------------------------------------------------------
traverseOnePredicate(OSQLParseNode * pColumnRef,::rtl::OUString & rValue,OSQLParseNode * pParseNode)1585 void OSQLParseTreeIterator::traverseOnePredicate(
1586                                 OSQLParseNode * pColumnRef,
1587                                 ::rtl::OUString& rValue,
1588                                 OSQLParseNode * pParseNode)
1589 {
1590     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOnePredicate" );
1591     if ( !pParseNode )
1592         return;
1593 
1594     // Column-Name (und TableRange):
1595     ::rtl::OUString aColumnName, aTableRange, sColumnAlias;
1596     getColumnRange( pColumnRef, aColumnName, aTableRange, sColumnAlias);
1597 
1598     ::rtl::OUString aName;
1599 
1600     /*if (SQL_ISRULE(pParseNode,parameter))
1601         traverseParameter( pParseNode, pColumnRef, aColumnName, aTableRange, sColumnAlias );
1602     else */if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange):
1603         getColumnRange(pParseNode,aName,rValue);
1604     else
1605     {
1606         traverseORCriteria(pParseNode);
1607         //  if (! aIteratorStatus.IsSuccessful()) return;
1608     }
1609 }
1610 
1611 //-----------------------------------------------------------------------------
traverseSome(sal_uInt32 _nIncludeMask)1612 void OSQLParseTreeIterator::traverseSome( sal_uInt32 _nIncludeMask )
1613 {
1614     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSome" );
1615     impl_traverse( _nIncludeMask );
1616 }
1617 
1618 //-----------------------------------------------------------------------------
traverseAll()1619 void OSQLParseTreeIterator::traverseAll()
1620 {
1621     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseAll" );
1622     impl_traverse( All );
1623 }
1624 
1625 //-----------------------------------------------------------------------------
impl_traverse(sal_uInt32 _nIncludeMask)1626 void OSQLParseTreeIterator::impl_traverse( sal_uInt32 _nIncludeMask )
1627 {
1628     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_traverse" );
1629     impl_resetErrors();
1630     m_pImpl->m_nIncludeMask = _nIncludeMask;
1631 
1632     if ( !traverseTableNames( *m_pImpl->m_pTables ) )
1633         return;
1634 
1635     switch ( m_eStatementType )
1636     {
1637     case SQL_STATEMENT_SELECT:
1638     {
1639         const OSQLParseNode* pSelectNode = m_pParseTree;
1640         traverseParameters( pSelectNode );
1641         if  (   !traverseSelectColumnNames( pSelectNode )
1642             ||  !traverseOrderByColumnNames( pSelectNode )
1643             ||  !traverseGroupByColumnNames( pSelectNode )
1644             ||  !traverseSelectionCriteria( pSelectNode )
1645             )
1646             return;
1647     }
1648     break;
1649     case SQL_STATEMENT_CREATE_TABLE:
1650     {
1651         //0     |  1  |  2   |3|        4         |5
1652         //create table sc.foo ( a char(20), b char )
1653         const OSQLParseNode* pCreateNode = m_pParseTree->getChild(4);
1654         traverseCreateColumns(pCreateNode);
1655     }
1656     break;
1657     case SQL_STATEMENT_INSERT:
1658         break;
1659     default:
1660         break;
1661     }
1662 }
1663 
1664 // Dummy-Implementationen:
1665 
1666 //-----------------------------------------------------------------------------
impl_createTableObject(const::rtl::OUString & rTableName,const::rtl::OUString & rCatalogName,const::rtl::OUString & rSchemaName)1667 OSQLTable OSQLParseTreeIterator::impl_createTableObject( const ::rtl::OUString& rTableName,
1668     const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName )
1669 {
1670     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_createTableObject" );
1671     OSL_PRECOND( m_eStatementType == SQL_STATEMENT_CREATE_TABLE,
1672         "OSQLParseTreeIterator::impl_createTableObject: only to be called for CREATE TABLE statements!" );
1673         // (in all other cases, m_pTables is to contain the table objects as obtained from the tables
1674         // container of the connection (m_xTablesContainer)
1675 
1676     OSQLTable aReturnTable = new OTable(
1677         NULL,
1678         sal_False,
1679         rTableName,
1680         ::rtl::OUString::createFromAscii("Table"),
1681         ::rtl::OUString::createFromAscii("New Created Table"),
1682         rSchemaName,
1683         rCatalogName
1684     );
1685     return aReturnTable;
1686 }
1687 //-----------------------------------------------------------------------------
appendColumns(::vos::ORef<OSQLColumns> & _rColumns,const::rtl::OUString & _rTableAlias,const OSQLTable & _rTable)1688 void OSQLParseTreeIterator::appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable)
1689 {
1690     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::appendColumns" );
1691 
1692     if (!_rTable.is())
1693         return;
1694 
1695     Reference<XNameAccess> xColumns = _rTable->getColumns();
1696     if ( !xColumns.is() )
1697         return;
1698 
1699     Sequence< ::rtl::OUString > aColNames =  xColumns->getElementNames();
1700     const ::rtl::OUString* pBegin = aColNames.getConstArray();
1701     const ::rtl::OUString* pEnd = pBegin + aColNames.getLength();
1702 
1703     for(;pBegin != pEnd;++pBegin)
1704     {
1705 
1706         ::rtl::OUString aName(getUniqueColumnName(*pBegin));
1707         Reference< XPropertySet > xColumn;
1708         if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is())
1709         {
1710             OParseColumn* pColumn = new OParseColumn(aName
1711                                                 ,   getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))
1712                                                 ,   getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))
1713                                                 ,   getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION)))
1714                                                 ,   getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))
1715                                                 ,   getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))
1716                                                 ,   getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))
1717                                                 ,   getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))
1718                                                 ,   getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)))
1719                                                 ,   getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))
1720                                                 ,   isCaseSensitive() );
1721 
1722             pColumn->setTableName(_rTableAlias);
1723             pColumn->setRealName(*pBegin);
1724             Reference< XPropertySet> xCol = pColumn;
1725             _rColumns->get().push_back(xCol);
1726         }
1727         else
1728             impl_appendError( IParseContext::ERROR_INVALID_COLUMN, pBegin, &_rTableAlias );
1729     }
1730 }
1731 //-----------------------------------------------------------------------------
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)1732 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)
1733 {
1734     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setSelectColumnName" );
1735     if(rColumnName.toChar() == '*' && !rTableRange.getLength())
1736     {   // SELECT * ...
1737         OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1738         for(ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end();++aIter)
1739             appendColumns(_rColumns,aIter->first,aIter->second);
1740     }
1741     else if( rColumnName.toChar() == '*' && rTableRange.getLength() )
1742     {   // SELECT <table>.*
1743         OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1744         ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
1745 
1746         if(aFind != m_pImpl->m_pTables->end())
1747             appendColumns(_rColumns,rTableRange,aFind->second);
1748     }
1749     else if ( !rTableRange.getLength() )
1750     {   // SELECT <something> ...
1751         // without table specified
1752         if ( !bFkt )
1753         {
1754             Reference< XPropertySet> xNewColumn;
1755 
1756             for ( OSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter )
1757             {
1758                 if ( !aIter->second.is() )
1759                     continue;
1760 
1761                 Reference<XNameAccess> xColumns = aIter->second->getColumns();
1762                 Reference< XPropertySet > xColumn;
1763                 if  (   !xColumns->hasByName( rColumnName )
1764                     ||  !( xColumns->getByName( rColumnName ) >>= xColumn )
1765                     )
1766                     continue;
1767 
1768                 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1769 
1770                 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1771                 xNewColumn = pColumn;
1772                 pColumn->setTableName(aIter->first);
1773                 pColumn->setName(aNewColName);
1774                 pColumn->setRealName(rColumnName);
1775 
1776                 break;
1777             }
1778 
1779             if ( !xNewColumn.is() )
1780             {
1781                 // no function (due to the above !bFkt), no existing column
1782                 // => assume an expression
1783                 ::rtl::OUString aNewColName( getUniqueColumnName( rColumnAlias ) );
1784                 // did not find a column with this name in any of the tables
1785                 OParseColumn* pColumn = new OParseColumn(
1786                     aNewColName,
1787                     ::rtl::OUString::createFromAscii( "VARCHAR" ),
1788                         // TODO: does this match with _nType?
1789                         // Or should be fill this from the getTypeInfo of the connection?
1790                     ::rtl::OUString(),
1791                     ::rtl::OUString(),
1792                     ColumnValue::NULLABLE_UNKNOWN,
1793                     0,
1794                     0,
1795                     _nType,
1796                     sal_False,
1797                     sal_False,
1798                     isCaseSensitive()
1799                 );
1800 
1801                 xNewColumn = pColumn;
1802                 pColumn->setRealName( rColumnName );
1803             }
1804 
1805             _rColumns->get().push_back( xNewColumn );
1806         }
1807         else
1808         {
1809             ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1810 
1811             OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
1812                 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
1813             pColumn->setFunction(sal_True);
1814             pColumn->setAggregateFunction(bAggFkt);
1815             pColumn->setRealName(rColumnName);
1816 
1817             Reference< XPropertySet> xCol = pColumn;
1818             _rColumns->get().push_back(xCol);
1819         }
1820     }
1821     else    // ColumnName und Tablename vorhanden
1822     {
1823         ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
1824 
1825         sal_Bool bError = sal_False;
1826         if (aFind != m_pImpl->m_pTables->end() && aFind->second.is())
1827         {
1828             if (bFkt)
1829             {
1830                 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1831 
1832                 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
1833                     ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
1834                 pColumn->setFunction(sal_True);
1835                 pColumn->setAggregateFunction(bAggFkt);
1836                 pColumn->setRealName(rColumnName);
1837                 pColumn->setTableName(aFind->first);
1838 
1839                 Reference< XPropertySet> xCol = pColumn;
1840                 _rColumns->get().push_back(xCol);
1841             }
1842             else
1843             {
1844                 Reference< XPropertySet > xColumn;
1845                 if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn))
1846                 {
1847                     ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1848 
1849                     OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1850                     pColumn->setName(aNewColName);
1851                     pColumn->setRealName(rColumnName);
1852                     pColumn->setTableName(aFind->first);
1853 
1854                     Reference< XPropertySet> xCol = pColumn;
1855                     _rColumns->get().push_back(xCol);
1856                 }
1857                 else
1858                     bError = sal_True;
1859             }
1860         }
1861         else
1862             bError = sal_True;
1863 
1864         // Tabelle existiert nicht oder Feld nicht vorhanden
1865         if (bError)
1866         {
1867             ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1868 
1869             OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
1870                 ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,isCaseSensitive());
1871             pColumn->setFunction(sal_True);
1872             pColumn->setAggregateFunction(bAggFkt);
1873 
1874             Reference< XPropertySet> xCol = pColumn;
1875             _rColumns->get().push_back(xCol);
1876         }
1877     }
1878 }
1879 //-----------------------------------------------------------------------------
getUniqueColumnName(const::rtl::OUString & rColumnName) const1880 ::rtl::OUString OSQLParseTreeIterator::getUniqueColumnName(const ::rtl::OUString & rColumnName) const
1881 {
1882     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getUniqueColumnName" );
1883     ::rtl::OUString aAlias(rColumnName);
1884 
1885     OSQLColumns::Vector::const_iterator aIter = find(
1886         m_aSelectColumns->get().begin(),
1887         m_aSelectColumns->get().end(),
1888         aAlias,
1889         ::comphelper::UStringMixEqual( isCaseSensitive() )
1890     );
1891     sal_Int32 i=1;
1892     while(aIter != m_aSelectColumns->get().end())
1893     {
1894         (aAlias = rColumnName) += ::rtl::OUString::valueOf(i++);
1895         aIter = find(
1896             m_aSelectColumns->get().begin(),
1897             m_aSelectColumns->get().end(),
1898             aAlias,
1899             ::comphelper::UStringMixEqual( isCaseSensitive() )
1900         );
1901     }
1902     return aAlias;
1903 }
1904 //-----------------------------------------------------------------------------
setOrderByColumnName(const::rtl::OUString & rColumnName,const::rtl::OUString & rTableRange,sal_Bool bAscending)1905 void OSQLParseTreeIterator::setOrderByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange,sal_Bool bAscending)
1906 {
1907     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setOrderByColumnName" );
1908     Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
1909     if ( xColumn.is() )
1910         m_aOrderColumns->get().push_back(new OOrderColumn( xColumn, rTableRange, isCaseSensitive(), bAscending ) );
1911     else
1912     {
1913         sal_Int32 nId = rColumnName.toInt32();
1914         if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1915             m_aOrderColumns->get().push_back( new OOrderColumn( ( m_aSelectColumns->get() )[nId-1], isCaseSensitive(), bAscending ) );
1916     }
1917 
1918 #ifdef SQL_TEST_PARSETREEITERATOR
1919     cout << "OSQLParseTreeIterator::setOrderByColumnName: "
1920          << (const char *) rColumnName << ", "
1921          << (const char *) rTableRange << ", "
1922          << (bAscending ? "sal_True" : "sal_False")
1923          << "\n";
1924 #endif
1925 }
1926 //-----------------------------------------------------------------------------
setGroupByColumnName(const::rtl::OUString & rColumnName,const::rtl::OUString & rTableRange)1927 void OSQLParseTreeIterator::setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
1928 {
1929     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setGroupByColumnName" );
1930     Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
1931     if ( xColumn.is() )
1932         m_aGroupColumns->get().push_back(new OParseColumn(xColumn,isCaseSensitive()));
1933     else
1934     {
1935         sal_Int32 nId = rColumnName.toInt32();
1936         if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1937             m_aGroupColumns->get().push_back(new OParseColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive()));
1938     }
1939 
1940 #ifdef SQL_TEST_PARSETREEITERATOR
1941     cout << "OSQLParseTreeIterator::setOrderByColumnName: "
1942          << (const char *) rColumnName << ", "
1943          << (const char *) rTableRange << ", "
1944          << (bAscending ? "sal_True" : "sal_False")
1945          << "\n";
1946 #endif
1947 }
1948 
1949 //-----------------------------------------------------------------------------
getWhereTree() const1950 const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const
1951 {
1952     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getWhereTree" );
1953 
1954 
1955     if (!m_pParseTree)
1956         return NULL;
1957 
1958     // Parse Tree analysieren (je nach Statement-Typ)
1959     // und Zeiger auf WHERE-Klausel setzen:
1960     OSQLParseNode * pWhereClause = NULL;
1961     if(getStatementType() == SQL_STATEMENT_SELECT)
1962     {
1963         OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1964         OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1965         OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1966         OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1967         OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
1968 
1969         pWhereClause = pTableExp->getChild(1);
1970     }
1971     else if (SQL_ISRULE(m_pParseTree,update_statement_searched) ||
1972              SQL_ISRULE(m_pParseTree,delete_statement_searched))
1973     {
1974         pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1);
1975     }
1976     if(pWhereClause->count() != 2)
1977         pWhereClause = NULL;
1978     return pWhereClause;
1979 }
1980 
1981 //-----------------------------------------------------------------------------
getOrderTree() const1982 const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const
1983 {
1984     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getOrderTree" );
1985 
1986 
1987     if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1988         return NULL;
1989 
1990     // Parse Tree analysieren (je nach Statement-Typ)
1991     // und Zeiger auf ORDER-Klausel setzen:
1992     OSQLParseNode * pOrderClause = NULL;
1993     OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1994     OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1995     OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1996     OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1997     OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
1998 
1999     pOrderClause = pTableExp->getChild(ORDER_BY_CHILD_POS);
2000     // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
2001     if(pOrderClause->count() != 3)
2002         pOrderClause = NULL;
2003     return pOrderClause;
2004 }
2005 //-----------------------------------------------------------------------------
getGroupByTree() const2006 const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const
2007 {
2008     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getGroupByTree" );
2009     if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
2010         return NULL;
2011 
2012     // Parse Tree analysieren (je nach Statement-Typ)
2013     // und Zeiger auf ORDER-Klausel setzen:
2014     OSQLParseNode * pGroupClause = NULL;
2015     OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
2016     OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
2017     OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
2018     OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
2019     OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
2020 
2021     pGroupClause = pTableExp->getChild(2);
2022     // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
2023     if(pGroupClause->count() != 3)
2024         pGroupClause = NULL;
2025     return pGroupClause;
2026 }
2027 //-----------------------------------------------------------------------------
getHavingTree() const2028 const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const
2029 {
2030     if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
2031         return NULL;
2032 
2033     // Parse Tree analysieren (je nach Statement-Typ)
2034     // und Zeiger auf ORDER-Klausel setzen:
2035     OSQLParseNode * pHavingClause = NULL;
2036     OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
2037     OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
2038     OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
2039     OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
2040     OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!");
2041 
2042     pHavingClause = pTableExp->getChild(3);
2043     // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
2044     if(pHavingClause->count() < 1)
2045         pHavingClause = NULL;
2046     return pHavingClause;
2047 }
2048 // -----------------------------------------------------------------------------
isTableNode(const OSQLParseNode * _pTableNode) const2049 sal_Bool OSQLParseTreeIterator::isTableNode(const OSQLParseNode* _pTableNode) const
2050 {
2051     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isTableNode" );
2052     return _pTableNode && (SQL_ISRULE(_pTableNode,catalog_name) ||
2053                            SQL_ISRULE(_pTableNode,schema_name)  ||
2054                            SQL_ISRULE(_pTableNode,table_name));
2055 }
2056 // -----------------------------------------------------------------------------
getSimpleWhereTree() const2057 const OSQLParseNode* OSQLParseTreeIterator::getSimpleWhereTree() const
2058 {
2059     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleWhereTree" );
2060     const OSQLParseNode* pNode = getWhereTree();
2061     return pNode ? pNode->getChild(1) : NULL;
2062 }
2063 // -----------------------------------------------------------------------------
getSimpleOrderTree() const2064 const OSQLParseNode* OSQLParseTreeIterator::getSimpleOrderTree() const
2065 {
2066     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleOrderTree" );
2067     const OSQLParseNode* pNode = getOrderTree();
2068     return pNode ? pNode->getChild(2) : NULL;
2069 }
2070 // -----------------------------------------------------------------------------
getSimpleGroupByTree() const2071 const OSQLParseNode* OSQLParseTreeIterator::getSimpleGroupByTree() const
2072 {
2073     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleGroupByTree" );
2074     const OSQLParseNode* pNode = getGroupByTree();
2075     return pNode ? pNode->getChild(2) : NULL;
2076 }
2077 // -----------------------------------------------------------------------------
getSimpleHavingTree() const2078 const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const
2079 {
2080     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleHavingTree" );
2081     const OSQLParseNode* pNode = getHavingTree();
2082     return pNode ? pNode->getChild(1) : NULL;
2083 }
2084 
2085 // -----------------------------------------------------------------------------
findColumn(const::rtl::OUString & rColumnName,const::rtl::OUString & rTableRange,bool _bLookInSubTables)2086 Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables )
2087 {
2088     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
2089     Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange );
2090     if ( !xColumn.is() && _bLookInSubTables )
2091         xColumn = findColumn( *m_pImpl->m_pSubTables, rColumnName, rTableRange );
2092     return xColumn;
2093 }
2094 
2095 // -----------------------------------------------------------------------------
findColumn(const OSQLTables & _rTables,const::rtl::OUString & rColumnName,const::rtl::OUString & rTableRange)2096 Reference< XPropertySet > OSQLParseTreeIterator::findColumn(const OSQLTables& _rTables,const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
2097 {
2098     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
2099     Reference< XPropertySet > xColumn;
2100     if ( rTableRange.getLength() )
2101     {
2102         ConstOSQLTablesIterator aFind = _rTables.find(rTableRange);
2103 
2104         if ( aFind != _rTables.end()
2105             && aFind->second.is()
2106             && aFind->second->getColumns().is()
2107             && aFind->second->getColumns()->hasByName(rColumnName) )
2108             aFind->second->getColumns()->getByName(rColumnName) >>= xColumn;
2109     }
2110     if ( !xColumn.is() )
2111     {
2112         OSQLTables::const_iterator aEnd = _rTables.end();
2113         for(OSQLTables::const_iterator aIter = _rTables.begin(); aIter != aEnd; ++aIter)
2114         {
2115             if ( aIter->second.is() )
2116             {
2117                 Reference<XNameAccess> xColumns = aIter->second->getColumns();
2118                 if( xColumns.is() && xColumns->hasByName(rColumnName) && (xColumns->getByName(rColumnName) >>= xColumn) )
2119                 {
2120                     OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
2121                     break; // diese Column darf nur einmal vorkommen
2122                 }
2123             }
2124         }
2125     }
2126     return xColumn;
2127 }
2128 
2129 // -----------------------------------------------------------------------------
impl_appendError(IParseContext::ErrorCode _eError,const::rtl::OUString * _pReplaceToken1,const::rtl::OUString * _pReplaceToken2)2130 void OSQLParseTreeIterator::impl_appendError( IParseContext::ErrorCode _eError, const ::rtl::OUString* _pReplaceToken1, const ::rtl::OUString* _pReplaceToken2 )
2131 {
2132     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
2133     ::rtl::OUString sErrorMessage = m_rParser.getContext().getErrorMessage( _eError );
2134     if ( _pReplaceToken1 )
2135     {
2136         bool bTwoTokens = ( _pReplaceToken2 != NULL );
2137         const sal_Char* pPlaceHolder1 = bTwoTokens ? "#1" : "#";
2138         const ::rtl::OUString sPlaceHolder1 = ::rtl::OUString::createFromAscii( pPlaceHolder1 );
2139 
2140         sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( sPlaceHolder1 ), sPlaceHolder1.getLength(), *_pReplaceToken1 );
2141         if ( _pReplaceToken2 )
2142             sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( ::rtl::OUString::createFromAscii( "#2" ) ), 2, *_pReplaceToken2 );
2143     }
2144 
2145     impl_appendError( SQLException(
2146         sErrorMessage, NULL, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ) );
2147 }
2148 
2149 // -----------------------------------------------------------------------------
impl_appendError(const SQLException & _rError)2150 void OSQLParseTreeIterator::impl_appendError( const SQLException& _rError )
2151 {
2152     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
2153     if ( m_aErrors.Message.getLength() )
2154     {
2155         SQLException* pErrorChain = &m_aErrors;
2156         while ( pErrorChain->NextException.hasValue() )
2157             pErrorChain = static_cast< SQLException* >( pErrorChain->NextException.pData );
2158         pErrorChain->NextException <<= _rError;
2159     }
2160     else
2161         m_aErrors = _rError;
2162 }
2163 // -----------------------------------------------------------------------------
getFunctionReturnType(const OSQLParseNode * _pNode)2164 sal_Int32 OSQLParseTreeIterator::getFunctionReturnType(const OSQLParseNode* _pNode )
2165 {
2166     sal_Int32 nType = DataType::OTHER;
2167     ::rtl::OUString sFunctionName;
2168     if ( SQL_ISRULE(_pNode,length_exp) )
2169     {
2170         _pNode->getChild(0)->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
2171         nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
2172     }
2173     else if ( SQL_ISRULE(_pNode,num_value_exp) || SQL_ISRULE(_pNode,term) || SQL_ISRULE(_pNode,factor) )
2174     {
2175         nType = DataType::DOUBLE;
2176     }
2177     else
2178     {
2179         _pNode->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
2180 
2181         // MIN and MAX have another return type, we have to check the expression itself.
2182         // @see http://qa.openoffice.org/issues/show_bug.cgi?id=99566
2183         if ( SQL_ISRULE(_pNode,general_set_fct) && (SQL_ISTOKEN(_pNode->getChild(0),MIN) || SQL_ISTOKEN(_pNode->getChild(0),MAX) ))
2184         {
2185             const OSQLParseNode* pValueExp = _pNode->getChild(3);
2186             if (SQL_ISRULE(pValueExp,column_ref))
2187             {
2188                 ::rtl::OUString sColumnName;
2189                 ::rtl::OUString aTableRange;
2190                 getColumnRange(pValueExp,sColumnName,aTableRange);
2191                 OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein");
2192                 Reference<XPropertySet> xColumn = findColumn( sColumnName, aTableRange, true );
2193 
2194                 if ( xColumn.is() )
2195                 {
2196                     xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TYPE)) >>= nType;
2197                 }
2198             }
2199             else
2200             {
2201                 if ( SQL_ISRULE(pValueExp,num_value_exp) || SQL_ISRULE(pValueExp,term) || SQL_ISRULE(pValueExp,factor) )
2202                 {
2203                     nType = DataType::DOUBLE;
2204                 }
2205                 else if ( SQL_ISRULE(pValueExp,datetime_primary) )
2206                 {
2207                     switch(pValueExp->getChild(0)->getTokenID() )
2208                     {
2209                         case SQL_TOKEN_CURRENT_DATE:
2210                             nType = DataType::DATE;
2211                             break;
2212                         case SQL_TOKEN_CURRENT_TIME:
2213                             nType = DataType::TIME;
2214                             break;
2215                         case SQL_TOKEN_CURRENT_TIMESTAMP:
2216                             nType = DataType::TIMESTAMP;
2217                             break;
2218                     }
2219                 }
2220                 else if ( SQL_ISRULE(pValueExp,value_exp_primary) )
2221                 {
2222                     nType = getFunctionReturnType(pValueExp->getChild(1));
2223                 }
2224                 else if ( SQL_ISRULE(pValueExp,concatenation)
2225                         || SQL_ISRULE(pValueExp,char_factor)
2226                         || SQL_ISRULE(pValueExp,bit_value_fct)
2227                         || SQL_ISRULE(pValueExp,char_value_fct)
2228                         || SQL_ISRULE(pValueExp,char_substring_fct)
2229                         || SQL_ISRULE(pValueExp,fold)
2230                         || SQL_ISTOKEN(pValueExp,STRING) )
2231                 {
2232                     nType = DataType::VARCHAR;
2233                 }
2234             }
2235             if ( nType == DataType::OTHER )
2236                 nType = DataType::DOUBLE;
2237         }
2238         else
2239             nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
2240     }
2241 
2242     return nType;
2243 }
2244