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