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