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