bump product version to 5.0.4.1
[LibreOffice.git] / connectivity / source / parse / sqliterator.cxx
blob4e5b8b473574fdcd4608dcbd3297cc27df7f9bfd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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"
43 #include <iterator>
44 #include <memory>
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;
59 namespace connectivity
61 struct OSQLParseTreeIteratorImpl
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;
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;
73 sal_uInt32 m_nIncludeMask;
75 bool m_bIsCaseSensitive;
77 OSQLParseTreeIteratorImpl( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxTables )
78 :m_xConnection( _rxConnection )
79 ,m_nIncludeMask( OSQLParseTreeIterator::All )
80 ,m_bIsCaseSensitive( true )
82 OSL_PRECOND( m_xConnection.is(), "OSQLParseTreeIteratorImpl::OSQLParseTreeIteratorImpl: invalid connection!" );
83 m_xDatabaseMetaData = m_xConnection->getMetaData();
85 m_bIsCaseSensitive = m_xDatabaseMetaData.is() && m_xDatabaseMetaData->supportsMixedCaseQuotedIdentifiers();
86 m_pTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
87 m_pSubTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
89 m_xTableContainer = _rxTables;
91 DatabaseMetaData aMetaData( m_xConnection );
92 if ( aMetaData.supportsSubqueriesInFrom() )
94 // connections might support the XQueriesSupplier interface, if they implement the css.sdb.Connection
95 // service
96 Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY );
97 if ( xSuppQueries.is() )
98 m_xQueryContainer = xSuppQueries->getQueries();
102 public:
103 inline bool isQueryAllowed( const OUString& _rQueryName )
105 if ( !m_pForbiddenQueryNames.get() )
106 return true;
107 if ( m_pForbiddenQueryNames->find( _rQueryName ) == m_pForbiddenQueryNames->end() )
108 return true;
109 return false;
114 /** helper class for temporarily adding a query name to a list of forbidden query names
116 class ForbidQueryName
118 std::shared_ptr< QueryNameSet >& m_rpAllForbiddenNames;
119 OUString m_sForbiddenQueryName;
121 public:
122 ForbidQueryName( OSQLParseTreeIteratorImpl& _rIteratorImpl, const OUString& _rForbiddenQueryName )
123 :m_rpAllForbiddenNames( _rIteratorImpl.m_pForbiddenQueryNames )
124 ,m_sForbiddenQueryName( _rForbiddenQueryName )
126 if ( !m_rpAllForbiddenNames.get() )
127 m_rpAllForbiddenNames.reset( new QueryNameSet );
128 m_rpAllForbiddenNames->insert( m_sForbiddenQueryName );
131 ~ForbidQueryName()
133 m_rpAllForbiddenNames->erase( m_sForbiddenQueryName );
138 OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XConnection >& _rxConnection,
139 const Reference< XNameAccess >& _rxTables,
140 const OSQLParser& _rParser,
141 const OSQLParseNode* pRoot )
142 :m_rParser( _rParser )
143 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rxConnection, _rxTables ) )
145 setParseTree(pRoot);
149 OSQLParseTreeIterator::OSQLParseTreeIterator( const OSQLParseTreeIterator& _rParentIterator, const OSQLParser& _rParser, const OSQLParseNode* pRoot )
150 :m_rParser( _rParser )
151 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rParentIterator.m_pImpl->m_xConnection, _rParentIterator.m_pImpl->m_xTableContainer ) )
153 m_pImpl->m_pForbiddenQueryNames = _rParentIterator.m_pImpl->m_pForbiddenQueryNames;
154 setParseTree( pRoot );
158 OSQLParseTreeIterator::~OSQLParseTreeIterator()
160 dispose();
164 const OSQLTables& OSQLParseTreeIterator::getTables() const
166 return *m_pImpl->m_pTables;
170 bool OSQLParseTreeIterator::isCaseSensitive() const
172 return m_pImpl->m_bIsCaseSensitive;
176 void OSQLParseTreeIterator::dispose()
178 m_aSelectColumns = NULL;
179 m_aGroupColumns = NULL;
180 m_aOrderColumns = NULL;
181 m_aParameters = NULL;
182 m_pImpl->m_xTableContainer = NULL;
183 m_pImpl->m_xDatabaseMetaData = NULL;
184 m_aCreateColumns = NULL;
185 m_pImpl->m_pTables->clear();
186 m_pImpl->m_pSubTables->clear();
189 void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree)
191 m_pImpl->m_pTables->clear();
192 m_pImpl->m_pSubTables->clear();
194 m_aSelectColumns = new OSQLColumns();
195 m_aGroupColumns = new OSQLColumns();
196 m_aOrderColumns = new OSQLColumns();
197 m_aParameters = new OSQLColumns();
198 m_aCreateColumns = new OSQLColumns();
200 m_pParseTree = pNewParseTree;
201 if (!m_pParseTree)
203 m_eStatementType = SQL_STATEMENT_UNKNOWN;
204 return;
207 // If m_pParseTree, but no connection then return
208 if ( !m_pImpl->m_xTableContainer.is() )
209 return;
211 m_aErrors = SQLException();
214 // Determine statement type ...
215 if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) )
217 m_eStatementType = SQL_STATEMENT_SELECT;
219 else if (SQL_ISRULE(m_pParseTree,insert_statement))
221 m_eStatementType = SQL_STATEMENT_INSERT;
223 else if (SQL_ISRULE(m_pParseTree,update_statement_searched))
225 m_eStatementType = SQL_STATEMENT_UPDATE;
227 else if (SQL_ISRULE(m_pParseTree,delete_statement_searched))
229 m_eStatementType = SQL_STATEMENT_DELETE;
231 else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec))
233 m_eStatementType = SQL_STATEMENT_ODBC_CALL;
235 else if (SQL_ISRULE(m_pParseTree->getChild(0),base_table_def))
237 m_eStatementType = SQL_STATEMENT_CREATE_TABLE;
238 m_pParseTree = m_pParseTree->getChild(0);
240 else
242 m_eStatementType = SQL_STATEMENT_UNKNOWN;
243 //aIteratorStatus.setInvalidStatement();
244 return;
249 namespace
252 static void impl_getRowString( const Reference< XRow >& _rxRow, const sal_Int32 _nColumnIndex, OUString& _out_rString )
254 _out_rString = _rxRow->getString( _nColumnIndex );
255 if ( _rxRow->wasNull() )
256 _out_rString.clear();
260 static OUString lcl_findTableInMetaData(
261 const Reference< XDatabaseMetaData >& _rxDBMeta, const OUString& _rCatalog,
262 const OUString& _rSchema, const OUString& _rTableName )
264 OUString sComposedName;
266 static const char s_sTableTypeView[] = "VIEW";
267 static const char s_sTableTypeTable[] = "TABLE";
268 static const char s_sWildcard[] = "%" ;
270 // we want all catalogues, all schemas, all tables
271 Sequence< OUString > sTableTypes(3);
272 sTableTypes[0] = s_sTableTypeView;
273 sTableTypes[1] = s_sTableTypeTable;
274 sTableTypes[2] = s_sWildcard; // just to be sure to include anything else ....
276 if ( _rxDBMeta.is() )
278 sComposedName.clear();
280 Reference< XResultSet> xRes = _rxDBMeta->getTables(
281 !_rCatalog.isEmpty() ? makeAny( _rCatalog ) : Any(), !_rSchema.isEmpty() ? _rSchema : s_sWildcard, _rTableName, sTableTypes );
283 Reference< XRow > xCurrentRow( xRes, UNO_QUERY );
284 if ( xCurrentRow.is() && xRes->next() )
286 OUString sCatalog, sSchema, sName;
288 impl_getRowString( xCurrentRow, 1, sCatalog );
289 impl_getRowString( xCurrentRow, 2, sSchema );
290 impl_getRowString( xCurrentRow, 3, sName );
292 sComposedName = ::dbtools::composeTableName(
293 _rxDBMeta,
294 sCatalog,
295 sSchema,
296 sName,
297 false,
298 ::dbtools::eInDataManipulation
302 return sComposedName;
307 void OSQLParseTreeIterator::impl_getQueryParameterColumns( const OSQLTable& _rQuery )
309 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
310 // parameters not to be included in the traversal
311 return;
313 ::rtl::Reference< OSQLColumns > pSubQueryParameterColumns( new OSQLColumns() );
315 // get the command and the EscapeProcessing properties from the sub query
316 OUString sSubQueryCommand;
317 bool bEscapeProcessing = false;
320 Reference< XPropertySet > xQueryProperties( _rQuery, UNO_QUERY_THROW );
321 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sSubQueryCommand );
322 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing );
324 catch( const Exception& )
326 DBG_UNHANDLED_EXCEPTION();
329 // parse the sub query
330 do {
332 if ( !bEscapeProcessing || ( sSubQueryCommand.isEmpty() ) )
333 break;
335 OUString sError;
336 std::unique_ptr< OSQLParseNode > pSubQueryNode( const_cast< OSQLParser& >( m_rParser ).parseTree( sError, sSubQueryCommand, false ) );
337 if ( !pSubQueryNode.get() )
338 break;
340 OSQLParseTreeIterator aSubQueryIterator( *this, m_rParser, pSubQueryNode.get() );
341 aSubQueryIterator.traverseSome( Parameters | SelectColumns );
342 // SelectColumns might also contain parameters
343 // #i77635# - 2007-07-23 / frank.schoenheit@sun.com
344 pSubQueryParameterColumns = aSubQueryIterator.getParameters();
345 aSubQueryIterator.dispose();
347 } while ( false );
349 // copy the parameters of the sub query to our own parameter array
350 ::std::copy( pSubQueryParameterColumns->get().begin(), pSubQueryParameterColumns->get().end(),
351 ::std::insert_iterator< OSQLColumns::Vector >( m_aParameters->get(), m_aParameters->get().end() ) );
355 OSQLTable OSQLParseTreeIterator::impl_locateRecordSource( const OUString& _rComposedName )
357 if ( _rComposedName.isEmpty() )
359 SAL_WARN( "connectivity.parse", "OSQLParseTreeIterator::impl_locateRecordSource: no object name at all?" );
360 return OSQLTable();
363 OSQLTable aReturn;
364 OUString sComposedName( _rComposedName );
368 OUString sCatalog, sSchema, sName;
369 qualifiedNameComponents( m_pImpl->m_xDatabaseMetaData, sComposedName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
371 // check whether there is a query with the given name
372 bool bQueryDoesExist = m_pImpl->m_xQueryContainer.is() && m_pImpl->m_xQueryContainer->hasByName( sComposedName );
374 // check whether the table container contains an object with the given name
375 if ( !bQueryDoesExist && !m_pImpl->m_xTableContainer->hasByName( sComposedName ) )
376 sComposedName = lcl_findTableInMetaData( m_pImpl->m_xDatabaseMetaData, sCatalog, sSchema, sName );
377 bool bTableDoesExist = m_pImpl->m_xTableContainer->hasByName( sComposedName );
379 // now obtain the object
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 if ( SQL_STATEMENT_CREATE_TABLE == m_eStatementType )
385 if ( bQueryDoesExist )
386 impl_appendError( IParseContext::ERROR_INVALID_QUERY_EXIST, &sName );
387 else if ( bTableDoesExist )
388 impl_appendError( IParseContext::ERROR_INVALID_TABLE_EXIST, &sName );
389 else
390 aReturn = impl_createTableObject( sName, sCatalog, sSchema );
392 else
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 if ( bQueryDoesExist )
398 if ( !m_pImpl->isQueryAllowed( sComposedName ) )
400 impl_appendError( m_rParser.getErrorHelper().getSQLException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES, NULL ) );
401 return NULL;
404 m_pImpl->m_xQueryContainer->getByName( sComposedName ) >>= aReturn;
406 // collect the parameters from the sub query
407 ForbidQueryName aForbidName( *m_pImpl, sComposedName );
408 impl_getQueryParameterColumns( aReturn );
410 else if ( bTableDoesExist )
411 m_pImpl->m_xTableContainer->getByName( sComposedName ) >>= aReturn;
412 else
414 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 impl_appendError( IParseContext::ERROR_INVALID_TABLE_OR_QUERY, &sName );
418 else
419 impl_appendError( IParseContext::ERROR_INVALID_TABLE_NOSUCH, &sName );
423 catch(Exception&)
425 impl_appendError( IParseContext::ERROR_INVALID_TABLE_NOSUCH, &sComposedName );
428 return aReturn;
432 void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const OUString & rTableRange )
434 if ( ( m_pImpl->m_nIncludeMask & TableNames ) != TableNames )
435 // tables should not be included in the traversal
436 return;
438 OSL_ENSURE(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL");
440 Any aCatalog;
441 OUString aSchema,aTableName,aComposedName;
442 OUString aTableRange(rTableRange);
444 // Get table name
445 OSQLParseNode::getTableComponents(pTableName,aCatalog,aSchema,aTableName,m_pImpl->m_xDatabaseMetaData);
447 // create the composed name like DOMAIN.USER.TABLE1
448 aComposedName = ::dbtools::composeTableName(m_pImpl->m_xDatabaseMetaData,
449 aCatalog.hasValue() ? ::comphelper::getString(aCatalog) : OUString(),
450 aSchema,
451 aTableName,
452 false,
453 ::dbtools::eInDataManipulation);
455 // if there is no alias for the table name assign the orignal name to it
456 if ( aTableRange.isEmpty() )
457 aTableRange = aComposedName;
459 // get the object representing this table/query
460 OSQLTable aTable = impl_locateRecordSource( aComposedName );
461 if ( aTable.is() )
462 _rTables[ aTableRange ] = aTable;
465 void OSQLParseTreeIterator::impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition)
467 if (i_pJoinCondition->count() == 3 && // Expression with brackets
468 SQL_ISPUNCTUATION(i_pJoinCondition->getChild(0),"(") &&
469 SQL_ISPUNCTUATION(i_pJoinCondition->getChild(2),")"))
471 impl_fillJoinConditions(i_pJoinCondition->getChild(1));
473 else if (SQL_ISRULEOR2(i_pJoinCondition,search_condition,boolean_term) && // AND/OR logic operation:
474 i_pJoinCondition->count() == 3)
476 // Only allow AND logic operation
477 if ( SQL_ISTOKEN(i_pJoinCondition->getChild(1),AND) )
479 impl_fillJoinConditions(i_pJoinCondition->getChild(0));
480 impl_fillJoinConditions(i_pJoinCondition->getChild(1));
483 else if (SQL_ISRULE(i_pJoinCondition,comparison_predicate))
485 // only the comparison of columns is allowed
486 OSL_ENSURE(i_pJoinCondition->count() == 3,"OQueryDesignView::InsertJoinConnection: error in the parse tree");
487 if (SQL_ISRULE(i_pJoinCondition->getChild(0),column_ref) &&
488 SQL_ISRULE(i_pJoinCondition->getChild(2),column_ref) &&
489 i_pJoinCondition->getChild(1)->getNodeType() == SQL_NODE_EQUAL)
491 m_pImpl->m_aJoinConditions.push_back( TNodePair(i_pJoinCondition->getChild(0),i_pJoinCondition->getChild(2)) );
496 ::std::vector< TNodePair >& OSQLParseTreeIterator::getJoinConditions() const
498 return m_pImpl->m_aJoinConditions;
501 void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, OUString& aTableRange )
503 OSL_PRECOND( SQL_ISRULE( pTableRef, cross_union ) || SQL_ISRULE( pTableRef, qualified_join ) ,
504 "OSQLParseTreeIterator::getQualified_join: illegal node!" );
506 aTableRange.clear();
508 const OSQLParseNode* pNode = getTableNode(_rTables,pTableRef->getChild(0),aTableRange);
509 if ( isTableNode( pNode ) )
510 traverseOneTableName( _rTables, pNode, aTableRange );
512 sal_uInt32 nPos = 4;
513 if( SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL)
515 nPos = 3;
516 // join_condition,named_columns_join
517 if ( SQL_ISRULE( pTableRef, qualified_join ) )
519 const OSQLParseNode* pJoin_spec = pTableRef->getChild(4);
520 if ( SQL_ISRULE( pJoin_spec, join_condition ) )
522 impl_fillJoinConditions(pJoin_spec->getChild(1));
524 else
526 const OSQLParseNode* pColumnCommalist = pJoin_spec->getChild(2);
527 // All columns in the column_commalist ...
528 for (sal_uInt32 i = 0; i < pColumnCommalist->count(); i++)
530 const OSQLParseNode * pCol = pColumnCommalist->getChild(i);
531 // add twice because the column must exists in both tables
532 m_pImpl->m_aJoinConditions.push_back( TNodePair(pCol,pCol) );
538 pNode = getTableNode(_rTables,pTableRef->getChild(nPos),aTableRange);
539 if ( isTableNode( pNode ) )
540 traverseOneTableName( _rTables, pNode, aTableRange );
543 const OSQLParseNode* OSQLParseTreeIterator::getTableNode( OSQLTables& _rTables, const OSQLParseNode *pTableRef,OUString& rTableRange )
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!" );
549 const OSQLParseNode* pTableNameNode = NULL;
551 if ( SQL_ISRULE( pTableRef, joined_table ) )
553 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
555 if ( SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ) )
557 getQualified_join( _rTables, pTableRef, rTableRange );
559 else
561 rTableRange = OSQLParseNode::getTableRange(pTableRef);
562 if ( ( pTableRef->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
563 || ( pTableRef->count() == 5 ) // '(' joined_table ')' range_variable op_column_commalist
566 getQualified_join( _rTables, pTableRef->getChild(6 - pTableRef->count()), rTableRange );
568 else if ( pTableRef->count() == 3 ) // subquery range_variable op_column_commalist || '(' joined_table ')'
570 const OSQLParseNode* pSubQuery = pTableRef->getChild(0);
571 if ( pSubQuery->isToken() )
573 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
575 else
577 OSL_ENSURE( pSubQuery->count() == 3, "sub queries should have 3 children!" );
578 const OSQLParseNode* pQueryExpression = pSubQuery->getChild(1);
579 if ( SQL_ISRULE( pQueryExpression, select_statement ) )
581 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
590 else
592 SAL_WARN( "connectivity.parse", "OSQLParseTreeIterator::getTableNode: subquery which is no select_statement: not yet implemented!" );
596 else if ( pTableRef->count() == 2 ) // table_node table_primary_as_range_column
598 pTableNameNode = pTableRef->getChild(0);
600 else
601 SAL_WARN( "connectivity.parse", "OSQLParseTreeIterator::getTableNode: unhandled case!" );
604 return pTableNameNode;
607 void OSQLParseTreeIterator::getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect)
609 if(SQL_ISRULE(pSelect,union_statement))
611 getSelect_statement(_rTables,pSelect->getChild(0));
612 //getSelect_statement(pSelect->getChild(3));
613 return;
615 OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1);
617 OSL_ENSURE(pTableRefCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
618 OSL_ENSURE(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: error in parse tree!");
620 const OSQLParseNode* pTableName = NULL;
621 OUString aTableRange;
622 for (sal_uInt32 i = 0; i < pTableRefCommalist->count(); i++)
623 { // Process FROM clause
624 aTableRange.clear();
626 const OSQLParseNode* pTableListElement = pTableRefCommalist->getChild(i);
627 if ( isTableNode( pTableListElement ) )
629 traverseOneTableName( _rTables, pTableListElement, aTableRange );
631 else if ( SQL_ISRULE( pTableListElement, table_ref ) )
633 // Table references can be made up of table names, table names (+),'('joined_table')'(+)
634 pTableName = pTableListElement->getChild(0);
635 if( isTableNode( pTableName ) )
636 { // Found table names
637 aTableRange = OSQLParseNode::getTableRange(pTableListElement);
638 traverseOneTableName( _rTables, pTableName, aTableRange );
640 else if(SQL_ISPUNCTUATION(pTableName,"{"))
641 { // '{' SQL_TOKEN_OJ joined_table '}'
642 getQualified_join( _rTables, pTableListElement->getChild(2), aTableRange );
644 else
645 { // '(' joined_table ')' range_variable op_column_commalist
646 getTableNode( _rTables, pTableListElement, aTableRange );
649 else if (SQL_ISRULE( pTableListElement, qualified_join ) || SQL_ISRULE( pTableListElement, cross_union ) )
651 getQualified_join( _rTables, pTableListElement, aTableRange );
653 else if ( SQL_ISRULE( pTableListElement, joined_table ) )
655 getQualified_join( _rTables, pTableListElement->getChild(1), aTableRange );
658 // if (! aIteratorStatus.IsSuccessful()) break;
662 bool OSQLParseTreeIterator::traverseTableNames(OSQLTables& _rTables)
664 if ( m_pParseTree == NULL )
665 return false;
667 OSQLParseNode* pTableName = NULL;
669 switch ( m_eStatementType )
671 case SQL_STATEMENT_SELECT:
672 getSelect_statement( _rTables, m_pParseTree );
673 break;
675 case SQL_STATEMENT_CREATE_TABLE:
676 case SQL_STATEMENT_INSERT:
677 case SQL_STATEMENT_DELETE:
678 pTableName = m_pParseTree->getChild(2);
679 break;
681 case SQL_STATEMENT_UPDATE:
682 pTableName = m_pParseTree->getChild(1);
683 break;
684 default:
685 break;
688 if ( pTableName )
690 OUString sTableRange;
691 traverseOneTableName( _rTables, pTableName, sTableRange );
694 return !hasErrors();
697 OUString OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* _pDerivedColumn)
699 OSL_ENSURE(SQL_ISRULE(_pDerivedColumn,derived_column),"No derived column!");
700 OUString sColumnAlias;
701 if(_pDerivedColumn->getChild(1)->count() == 2)
702 sColumnAlias = _pDerivedColumn->getChild(1)->getChild(1)->getTokenValue();
703 else if(!_pDerivedColumn->getChild(1)->isRule())
704 sColumnAlias = _pDerivedColumn->getChild(1)->getTokenValue();
705 return sColumnAlias;
709 namespace
711 void lcl_getColumnRange( const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection,
712 OUString& _out_rColumnName, OUString& _out_rTableRange,
713 const OSQLColumns* _pSelectColumns, OUString& _out_rColumnAliasIfPresent )
715 _out_rColumnName.clear();
716 _out_rTableRange.clear();
717 _out_rColumnAliasIfPresent.clear();
718 if ( SQL_ISRULE( _pColumnRef, column_ref ) )
720 if( _pColumnRef->count() > 1 )
722 for ( sal_Int32 i=0; i<((sal_Int32)_pColumnRef->count())-2; ++i )
723 _pColumnRef->getChild(i)->parseNodeToStr( _out_rTableRange, _rxConnection, NULL, false, false );
724 _out_rColumnName = _pColumnRef->getChild( _pColumnRef->count()-1 )->getChild(0)->getTokenValue();
726 else
727 _out_rColumnName = _pColumnRef->getChild(0)->getTokenValue();
729 // look up the column in the select column, to find an possible alias
730 if ( _pSelectColumns )
732 for ( OSQLColumns::Vector::const_iterator lookupColumn = _pSelectColumns->get().begin();
733 lookupColumn != _pSelectColumns->get().end();
734 ++lookupColumn
737 Reference< XPropertySet > xColumn( *lookupColumn );
740 OUString sName, sTableName;
741 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) >>= sName;
742 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sTableName;
743 if ( sName == _out_rColumnName && ( _out_rTableRange.isEmpty() || sTableName == _out_rTableRange ) )
745 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= _out_rColumnAliasIfPresent;
746 break;
749 catch( const Exception& )
751 DBG_UNHANDLED_EXCEPTION();
756 else if(SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec))
757 { // Function
758 _pColumnRef->parseNodeToStr( _out_rColumnName, _rxConnection );
760 else if(_pColumnRef->getNodeType() == SQL_NODE_NAME)
761 _out_rColumnName = _pColumnRef->getTokenValue();
766 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
767 OUString& _rColumnName,
768 OUString& _rTableRange) const
770 OUString sDummy;
771 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, NULL, sDummy );
775 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
776 OUString& _rColumnName,
777 OUString& _rTableRange,
778 OUString& _out_rColumnAliasIfPresent ) const
780 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, &*m_aSelectColumns, _out_rColumnAliasIfPresent );
784 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
785 const Reference< XConnection >& _rxConnection, OUString& _out_rColumnName, OUString& _out_rTableRange )
787 OUString sDummy;
788 lcl_getColumnRange( _pColumnRef, _rxConnection, _out_rColumnName, _out_rTableRange, NULL, sDummy );
792 bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, OUString &rTableRange) const
794 OUString tmp;
795 if(impl_getColumnTableRange(pNode, tmp))
797 rTableRange = tmp;
798 return true;
800 else
801 return false;
804 bool OSQLParseTreeIterator::impl_getColumnTableRange(const OSQLParseNode* pNode, OUString &rTableRange) const
806 // See if all columns belong to one table
807 if (SQL_ISRULE(pNode,column_ref))
809 OUString aColName, aTableRange;
810 getColumnRange(pNode, aColName, aTableRange);
811 if (aTableRange.isEmpty()) // None found
813 // Look for the columns in the tables
814 for (OSQLTables::const_iterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter)
816 if (aIter->second.is())
820 Reference< XNameAccess > xColumns = aIter->second->getColumns();
821 if(xColumns->hasByName(aColName))
823 Reference< XPropertySet > xColumn;
824 if (xColumns->getByName(aColName) >>= xColumn)
826 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
827 aTableRange = aIter->first;
828 break;
832 catch(Exception&)
837 if (aTableRange.isEmpty())
838 return false;
842 if (rTableRange.isEmpty())
843 rTableRange = aTableRange;
844 else if (rTableRange != aTableRange)
845 return false;
847 else
849 for (sal_uInt32 i = 0, ncount = pNode->count(); i < ncount; i++)
851 if (!getColumnTableRange(pNode->getChild(i), rTableRange))
852 return false;
855 return true;
859 void OSQLParseTreeIterator::traverseCreateColumns(const OSQLParseNode* pSelectNode)
861 // aIteratorStatus.Clear();
863 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_CREATE_TABLE || m_pImpl->m_pTables->empty())
865 impl_appendError( IParseContext::ERROR_GENERAL );
866 return;
868 if (!SQL_ISRULE(pSelectNode,base_table_element_commalist))
869 return ;
871 for (sal_uInt32 i = 0; i < pSelectNode->count(); i++)
873 OSQLParseNode *pColumnRef = pSelectNode->getChild(i);
875 if (SQL_ISRULE(pColumnRef,column_def))
877 OUString aColumnName;
878 OUString aTypeName;
879 sal_Int32 nType = DataType::VARCHAR;
880 aColumnName = pColumnRef->getChild(0)->getTokenValue();
882 OSQLParseNode *pDatatype = pColumnRef->getChild(1);
883 if (pDatatype && SQL_ISRULE(pDatatype,character_string_type))
885 const OSQLParseNode *pType = pDatatype->getChild(0);
886 aTypeName = pType->getTokenValue();
887 if (pDatatype->count() == 2 && (pType->getTokenID() == SQL_TOKEN_CHAR || pType->getTokenID() == SQL_TOKEN_CHARACTER ))
888 nType = DataType::CHAR;
890 const OSQLParseNode *pParams = pDatatype->getChild(pDatatype->count()-1);
891 if ( pParams->count() )
893 sal_Int32 nLen = pParams->getChild(1)->getTokenValue().toInt32();
894 (void)nLen;
897 else if(pDatatype && pDatatype->getNodeType() == SQL_NODE_KEYWORD)
899 aTypeName = "VARCHAR";
902 if (!aTypeName.isEmpty())
904 //TODO:Create a new class for create statement to handle field length
905 OParseColumn* pColumn = new OParseColumn(aColumnName,aTypeName,OUString(),OUString(),
906 ColumnValue::NULLABLE_UNKNOWN,0,0,nType,false,false,isCaseSensitive(),
907 OUString(),OUString(),OUString());
908 pColumn->setFunction(false);
909 pColumn->setRealName(aColumnName);
911 Reference< XPropertySet> xCol = pColumn;
912 m_aCreateColumns->get().push_back(xCol);
919 bool OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode)
921 if ( ( m_pImpl->m_nIncludeMask & SelectColumns ) != SelectColumns )
922 return true;
924 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || m_pImpl->m_pTables->empty())
926 impl_appendError( IParseContext::ERROR_GENERAL );
927 return false;
930 if(SQL_ISRULE(pSelectNode,union_statement))
932 return traverseSelectColumnNames( pSelectNode->getChild( 0 ) )
933 /*&& traverseSelectColumnNames( pSelectNode->getChild( 3 ) )*/;
936 static OUString aEmptyString;
937 // nyi: more checks for correct structure!
938 if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*"))
940 // SELECT * ...
941 setSelectColumnName(m_aSelectColumns,OUString("*"), aEmptyString,aEmptyString);
943 else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist))
945 // SELECT column[,column] oder SELECT COUNT(*) ...
946 OSQLParseNode * pSelection = pSelectNode->getChild(2);
948 for (sal_uInt32 i = 0; i < pSelection->count(); i++)
950 OSQLParseNode *pColumnRef = pSelection->getChild(i);
952 //if (SQL_ISRULE(pColumnRef,select_sublist))
953 if (SQL_ISRULE(pColumnRef,derived_column) &&
954 SQL_ISRULE(pColumnRef->getChild(0),column_ref) &&
955 pColumnRef->getChild(0)->count() == 3 &&
956 SQL_ISPUNCTUATION(pColumnRef->getChild(0)->getChild(2),"*"))
958 // All the table's columns
959 OUString aTableRange;
960 pColumnRef->getChild(0)->parseNodeToStr( aTableRange, m_pImpl->m_xConnection, NULL, false, false );
961 setSelectColumnName(m_aSelectColumns,OUString("*"), aEmptyString,aTableRange);
962 continue;
964 else if (SQL_ISRULE(pColumnRef,derived_column))
966 OUString aColumnAlias(getColumnAlias(pColumnRef)); // can be empty
967 OUString sColumnName;
968 OUString aTableRange;
969 sal_Int32 nType = DataType::VARCHAR;
970 bool bFkt(false);
971 pColumnRef = pColumnRef->getChild(0);
972 while (
973 pColumnRef->getKnownRuleID() != OSQLParseNode::subquery &&
974 pColumnRef->count() == 3 &&
975 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
976 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
978 pColumnRef = pColumnRef->getChild(1);
980 if (SQL_ISRULE(pColumnRef,column_ref))
982 getColumnRange(pColumnRef,sColumnName,aTableRange);
983 OSL_ENSURE(!sColumnName.isEmpty(),"Column name must not be empty!");
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))*/
990 // Function call present
991 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, false, true );
992 // check if the column is also a parameter
993 traverseSearchCondition(pColumnRef); // num_value_exp
995 if ( pColumnRef->isRule() )
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 bFkt = true;
1001 nType = getFunctionReturnType(pColumnRef);
1005 else
1007 aIteratorStatus.setStatementTooComplex();
1008 return;
1011 if(aColumnAlias.isEmpty())
1012 aColumnAlias = sColumnName;
1013 setSelectColumnName(m_aSelectColumns,sColumnName,aColumnAlias,aTableRange,bFkt,nType,SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec));
1018 return !hasErrors();
1023 bool OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode)
1025 traverseByColumnNames( pSelectNode, true );
1026 return !hasErrors();
1029 void OSQLParseTreeIterator::traverseByColumnNames(const OSQLParseNode* pSelectNode, bool _bOrder)
1031 // aIteratorStatus.Clear();
1033 if (pSelectNode == NULL)
1035 //aIteratorStatus.setInvalidStatement();
1036 return;
1039 if (m_eStatementType != SQL_STATEMENT_SELECT)
1041 //aIteratorStatus.setInvalidStatement();
1042 return;
1045 if(SQL_ISRULE(pSelectNode,union_statement))
1047 traverseByColumnNames(pSelectNode->getChild(0),_bOrder);
1048 return;
1051 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1053 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!");
1058 sal_uInt32 nPos = ( _bOrder ? ORDER_BY_CHILD_POS : 2 );
1060 OSQLParseNode * pOptByClause = pTableExp->getChild(nPos);
1061 OSL_ENSURE(pOptByClause != NULL,"OSQLParseTreeIterator: error in parse tree!");
1062 if ( pOptByClause->count() == 0 )
1063 return;
1065 OSL_ENSURE(pOptByClause->count() == 3,"OSQLParseTreeIterator: error in parse tree!");
1067 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!");
1072 OUString sColumnName;
1073 OUString aTableRange;
1074 sal_uInt32 nCount = pOrderingSpecCommalist->count();
1075 for (sal_uInt32 i = 0; i < nCount; ++i)
1077 OSQLParseNode* pColumnRef = pOrderingSpecCommalist->getChild(i);
1078 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
1079 if ( _bOrder )
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!");
1084 pColumnRef = pColumnRef->getChild(0);
1086 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
1087 aTableRange.clear();
1088 sColumnName.clear();
1089 if ( SQL_ISRULE(pColumnRef,column_ref) )
1091 // Column name (and TableRange):
1092 getColumnRange(pColumnRef,sColumnName,aTableRange);
1094 else
1095 { // here I found a predicate
1096 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, false, false );
1098 OSL_ENSURE(!sColumnName.isEmpty(),"sColumnName must not be empty!");
1099 if ( _bOrder )
1101 // Ascending/Descending
1102 OSQLParseNode * pOptAscDesc = pColumnRef->getParent()->getChild(1);
1103 OSL_ENSURE(pOptAscDesc != NULL,"OSQLParseTreeIterator: error in parse tree!");
1105 bool bAscending = ! (pOptAscDesc && SQL_ISTOKEN(pOptAscDesc,DESC));
1106 setOrderByColumnName(sColumnName, aTableRange,bAscending);
1108 else
1109 setGroupByColumnName(sColumnName, aTableRange);
1113 bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode* pSelectNode)
1115 traverseByColumnNames( pSelectNode, false );
1116 return !hasErrors();
1120 namespace
1122 OUString lcl_generateParameterName( const OSQLParseNode& _rParentNode, const OSQLParseNode& _rParamNode )
1124 OUString sColumnName( "param" );
1125 const sal_Int32 nCount = (sal_Int32)_rParentNode.count();
1126 for ( sal_Int32 i = 0; i < nCount; ++i )
1128 if ( _rParentNode.getChild(i) == &_rParamNode )
1130 sColumnName += OUString::number( i+1 );
1131 break;
1134 return sColumnName;
1139 void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode)
1141 if ( _pNode == NULL )
1142 return;
1144 OUString sColumnName, sTableRange, aColumnAlias;
1145 const OSQLParseNode* pParent = _pNode->getParent();
1146 if ( pParent != NULL )
1148 if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1150 sal_uInt32 nPos = 0;
1151 if ( pParent->getChild(nPos) == _pNode )
1152 nPos = 2;
1153 const OSQLParseNode* pOther = pParent->getChild(nPos);
1154 if ( SQL_ISRULE( pOther, column_ref ) )
1155 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1156 else
1157 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, false, false );
1158 } // if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1159 else if ( SQL_ISRULE(pParent,other_like_predicate_part_2) )
1161 const OSQLParseNode* pOther = pParent->getParent()->getChild(0);
1162 if ( SQL_ISRULE( pOther, column_ref ) )
1163 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1164 else
1165 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, false, false );
1167 else if ( SQL_ISRULE(pParent,between_predicate_part_2) )
1169 const OSQLParseNode* pOther = pParent->getParent()->getChild(0);
1170 if ( SQL_ISRULE( pOther, column_ref ) )
1171 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1172 else
1174 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, false, false );
1175 lcl_generateParameterName( *pParent, *_pNode );
1178 else if ( pParent->getNodeType() == SQL_NODE_COMMALISTRULE )
1180 lcl_generateParameterName( *pParent, *_pNode );
1183 traverseParameter( _pNode, pParent, sColumnName, sTableRange, aColumnAlias );
1184 const sal_uInt32 nCount = _pNode->count();
1185 for (sal_uInt32 i = 0; i < nCount; ++i)
1187 const OSQLParseNode* pChild = _pNode->getChild(i);
1188 traverseParameters( pChild );
1192 bool OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode)
1194 if ( pSelectNode == NULL )
1195 return false;
1198 // Analyse parse tree (depending on statement type)
1199 // and set pointer to WHERE clause:
1200 OSQLParseNode * pWhereClause = NULL;
1202 if (m_eStatementType == SQL_STATEMENT_SELECT)
1204 if(SQL_ISRULE(pSelectNode,union_statement))
1206 return traverseSelectionCriteria( pSelectNode->getChild( 0 ) )
1207 && traverseSelectionCriteria( pSelectNode->getChild( 3 ) );
1209 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1211 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!");
1216 pWhereClause = pTableExp->getChild(1);
1217 } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) {
1218 OSL_ENSURE(pSelectNode->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1219 pWhereClause = pSelectNode->getChild(4);
1220 } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) {
1221 OSL_ENSURE(pSelectNode->count() == 4,"OSQLParseTreeIterator: error in parse tree!");
1222 pWhereClause = pSelectNode->getChild(3);
1223 } 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 return false;
1231 if (!pWhereClause || !SQL_ISRULE(pWhereClause,where_clause))
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 return false;
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!");
1241 OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1);
1242 OSL_ENSURE(pComparisonPredicate != NULL,"OSQLParseTreeIterator: error in parse tree!");
1245 // Process the comparison criteria now
1248 traverseSearchCondition(pComparisonPredicate);
1250 return !hasErrors();
1254 void OSQLParseTreeIterator::traverseSearchCondition(OSQLParseNode * pSearchCondition)
1256 if (
1257 SQL_ISRULE(pSearchCondition,boolean_primary) &&
1258 pSearchCondition->count() == 3 &&
1259 SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
1260 SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
1263 // Round brackets
1264 traverseSearchCondition(pSearchCondition->getChild(1));
1266 // The first element is an OR logical operation
1267 else if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 )
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 traverseSearchCondition(pSearchCondition->getChild(0));
1273 // if (! aIteratorStatus.IsSuccessful())
1274 // return;
1276 // Continue with the right child
1277 traverseSearchCondition(pSearchCondition->getChild(2));
1279 // The first element is an AND logical operation (again)
1280 else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 )
1282 // Then process recursively (use the same row)
1283 traverseSearchCondition(pSearchCondition->getChild(0));
1284 // if (! aIteratorStatus.IsSuccessful())
1285 // return;
1287 // Continue with the right child
1288 traverseSearchCondition(pSearchCondition->getChild(2));
1290 // Else, process single search criteria (like =, !=, ..., LIKE, IS NULL etc.)
1291 else if (SQL_ISRULE(pSearchCondition,comparison_predicate) )
1293 OUString aValue;
1294 pSearchCondition->getChild(2)->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, false, false );
1295 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pSearchCondition->getChild(2));
1296 impl_fillJoinConditions(pSearchCondition);
1297 // if (! aIteratorStatus.IsSuccessful())
1298 // return;
1300 else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1302 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1303 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1305 sal_Int32 nCurentPos = pPart2->count()-2;
1307 OSQLParseNode * pNum_value_exp = pPart2->getChild(nCurentPos);
1308 OSQLParseNode * pOptEscape = pPart2->getChild(nCurentPos+1);
1310 OSL_ENSURE(pNum_value_exp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1311 OSL_ENSURE(pOptEscape != NULL,"OSQLParseTreeIterator: error in parse tree!");
1313 if (pOptEscape->count() != 0)
1315 // aIteratorStatus.setStatementTooComplex();
1316 return;
1319 OUString aValue;
1320 OSQLParseNode * pParam = NULL;
1321 if (SQL_ISRULE(pNum_value_exp,parameter))
1322 pParam = pNum_value_exp;
1323 else if(pNum_value_exp->isToken())
1324 // Normal value
1325 aValue = pNum_value_exp->getTokenValue();
1326 else
1328 pNum_value_exp->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, false, false );
1329 pParam = pNum_value_exp;
1332 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pParam);
1333 // if (! aIteratorStatus.IsSuccessful())
1334 // return;
1336 else if (SQL_ISRULE(pSearchCondition,in_predicate))
1338 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1339 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1341 traverseSearchCondition(pSearchCondition->getChild(0));
1342 // if (! aIteratorStatus.IsSuccessful()) return;
1344 OSQLParseNode* pChild = pPart2->getChild(2);
1345 if ( SQL_ISRULE(pChild->getChild(0),subquery) )
1347 traverseTableNames( *m_pImpl->m_pSubTables );
1348 traverseSelectionCriteria(pChild->getChild(0)->getChild(1));
1350 else
1351 { // '(' value_exp_commalist ')'
1352 pChild = pChild->getChild(1);
1353 sal_Int32 nCount = pChild->count();
1354 for (sal_Int32 i=0; i < nCount; ++i)
1356 traverseSearchCondition(pChild->getChild(i));
1360 else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1362 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1363 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1364 (void)pPart2;
1365 OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"OSQLParseTreeIterator: error in parse tree!");
1367 OUString aString;
1368 traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL);
1369 // if (! aIteratorStatus.IsSuccessful()) return;
1371 else if (SQL_ISRULE(pSearchCondition,num_value_exp) || SQL_ISRULE(pSearchCondition,term))
1373 OUString aString;
1374 traverseOnePredicate(pSearchCondition->getChild(0),aString,pSearchCondition->getChild(0));
1375 traverseOnePredicate(pSearchCondition->getChild(2),aString,pSearchCondition->getChild(2));
1377 // Just pass on the error
1380 void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode
1381 ,const OSQLParseNode* _pParentNode
1382 ,const OUString& _aColumnName
1383 ,OUString& _aTableRange
1384 ,const OUString& _rColumnAlias)
1386 if ( !SQL_ISRULE( _pParseNode, parameter ) )
1387 return;
1389 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
1390 // parameters not to be included in the traversal
1391 return;
1393 OSL_ENSURE(_pParseNode->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
1394 OSQLParseNode * pMark = _pParseNode->getChild(0);
1395 OUString sParameterName;
1397 if (SQL_ISPUNCTUATION(pMark,"?"))
1399 sParameterName = !_rColumnAlias.isEmpty()
1400 ? _rColumnAlias
1401 : !_aColumnName.isEmpty()
1402 ? _aColumnName
1403 : OUString("?");
1405 else if (SQL_ISPUNCTUATION(pMark,":"))
1407 sParameterName = _pParseNode->getChild(1)->getTokenValue();
1409 else if (SQL_ISPUNCTUATION(pMark,"["))
1411 sParameterName = _pParseNode->getChild(1)->getTokenValue();
1413 else
1415 SAL_WARN( "connectivity.parse","OSQLParseTreeIterator: error in parse tree!");
1418 // found a parameter
1419 if ( _pParentNode && (SQL_ISRULE(_pParentNode,general_set_fct) || SQL_ISRULE(_pParentNode,set_fct_spec)) )
1420 {// found a function as column_ref
1421 OUString sFunctionName;
1422 _pParentNode->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, false, false );
1423 const sal_uInt32 nCount = _pParentNode->count();
1424 sal_uInt32 i = 0;
1425 for(; i < nCount;++i)
1427 if ( _pParentNode->getChild(i) == _pParseNode )
1428 break;
1430 sal_Int32 nType = ::connectivity::OSQLParser::getFunctionParameterType( _pParentNode->getChild(0)->getTokenID(), i-1);
1432 OParseColumn* pColumn = new OParseColumn( sParameterName,
1433 OUString(),
1434 OUString(),
1435 OUString(),
1436 ColumnValue::NULLABLE_UNKNOWN,
1439 nType,
1440 false,
1441 false,
1442 isCaseSensitive(),
1443 OUString(),
1444 OUString(),
1445 OUString());
1446 pColumn->setFunction(true);
1447 pColumn->setAggregateFunction(true);
1448 pColumn->setRealName(sFunctionName);
1449 m_aParameters->get().push_back(pColumn);
1451 else
1453 bool bNotFound = true;
1454 OSQLColumns::Vector::const_iterator aIter = ::connectivity::find(
1455 m_aSelectColumns->get().begin(),
1456 m_aSelectColumns->get().end(),
1457 _aColumnName,::comphelper::UStringMixEqual( isCaseSensitive() )
1459 if(aIter != m_aSelectColumns->get().end())
1461 OParseColumn* pNewColumn = new OParseColumn(*aIter,isCaseSensitive());
1462 pNewColumn->setName(sParameterName);
1463 pNewColumn->setRealName(_aColumnName);
1464 m_aParameters->get().push_back(pNewColumn);
1465 bNotFound = false;
1467 else if(!_aColumnName.isEmpty())// search in the tables for the right one
1470 Reference<XPropertySet> xColumn = findColumn( _aColumnName, _aTableRange, true );
1472 if ( xColumn.is() )
1474 OParseColumn* pNewColumn = new OParseColumn(xColumn,isCaseSensitive());
1475 pNewColumn->setName(sParameterName);
1476 pNewColumn->setRealName(_aColumnName);
1477 m_aParameters->get().push_back(pNewColumn);
1478 bNotFound = false;
1481 if ( bNotFound )
1483 sal_Int32 nType = DataType::VARCHAR;
1484 OSQLParseNode* pParent = _pParentNode ? _pParentNode->getParent() : NULL;
1485 if ( pParent && (SQL_ISRULE(pParent,general_set_fct) || SQL_ISRULE(pParent,set_fct_spec)) )
1487 const sal_uInt32 nCount = _pParentNode->count();
1488 sal_uInt32 i = 0;
1489 for(; i < nCount;++i)
1491 if ( _pParentNode->getChild(i) == _pParseNode )
1492 break;
1494 nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1);
1497 OUString aNewColName( getUniqueColumnName( sParameterName ) );
1499 OParseColumn* pColumn = new OParseColumn(aNewColName,
1500 OUString(),
1501 OUString(),
1502 OUString(),
1503 ColumnValue::NULLABLE_UNKNOWN,
1506 nType,
1507 false,
1508 false,
1509 isCaseSensitive(),
1510 OUString(),
1511 OUString(),
1512 OUString());
1513 pColumn->setName(aNewColName);
1514 pColumn->setRealName(sParameterName);
1515 m_aParameters->get().push_back(pColumn);
1520 void OSQLParseTreeIterator::traverseOnePredicate(
1521 OSQLParseNode * pColumnRef,
1522 OUString& rValue,
1523 OSQLParseNode * pParseNode)
1525 if ( !pParseNode )
1526 return;
1528 // Column name (and TableRange):
1529 OUString aColumnName, aTableRange, sColumnAlias;
1530 getColumnRange( pColumnRef, aColumnName, aTableRange, sColumnAlias);
1532 OUString aName;
1534 /*if (SQL_ISRULE(pParseNode,parameter))
1535 traverseParameter( pParseNode, pColumnRef, aColumnName, aTableRange, sColumnAlias );
1536 else */if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange):
1537 getColumnRange(pParseNode,aName,rValue);
1538 else
1540 traverseSearchCondition(pParseNode);
1541 // if (! aIteratorStatus.IsSuccessful()) return;
1546 void OSQLParseTreeIterator::traverseSome( sal_uInt32 _nIncludeMask )
1548 impl_traverse( _nIncludeMask );
1552 void OSQLParseTreeIterator::traverseAll()
1554 impl_traverse( All );
1558 void OSQLParseTreeIterator::impl_traverse( sal_uInt32 _nIncludeMask )
1560 impl_resetErrors();
1561 m_pImpl->m_nIncludeMask = _nIncludeMask;
1563 if ( !traverseTableNames( *m_pImpl->m_pTables ) )
1564 return;
1566 switch ( m_eStatementType )
1568 case SQL_STATEMENT_SELECT:
1570 const OSQLParseNode* pSelectNode = m_pParseTree;
1571 traverseParameters( pSelectNode );
1572 if ( !traverseSelectColumnNames( pSelectNode )
1573 || !traverseOrderByColumnNames( pSelectNode )
1574 || !traverseGroupByColumnNames( pSelectNode )
1575 || !traverseSelectionCriteria( pSelectNode )
1577 return;
1579 break;
1580 case SQL_STATEMENT_CREATE_TABLE:
1582 //0 | 1 | 2 |3| 4 |5
1583 //create table sc.foo ( a char(20), b char )
1584 const OSQLParseNode* pCreateNode = m_pParseTree->getChild(4);
1585 traverseCreateColumns(pCreateNode);
1587 break;
1588 case SQL_STATEMENT_INSERT:
1589 break;
1590 default:
1591 break;
1595 // Dummy implementations
1598 OSQLTable OSQLParseTreeIterator::impl_createTableObject( const OUString& rTableName,
1599 const OUString& rCatalogName, const OUString& rSchemaName )
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)
1606 OSQLTable aReturnTable = new OTable(
1607 NULL,
1608 false,
1609 rTableName,
1610 OUString("Table"),
1611 OUString("New Created Table"),
1612 rSchemaName,
1613 rCatalogName
1615 return aReturnTable;
1618 void OSQLParseTreeIterator::appendColumns(::rtl::Reference<OSQLColumns>& _rColumns,const OUString& _rTableAlias,const OSQLTable& _rTable)
1620 if (!_rTable.is())
1621 return;
1623 Reference<XNameAccess> xColumns = _rTable->getColumns();
1624 if ( !xColumns.is() )
1625 return;
1627 Sequence< OUString > aColNames = xColumns->getElementNames();
1628 const OUString* pBegin = aColNames.getConstArray();
1629 const OUString* pEnd = pBegin + aColNames.getLength();
1631 for(;pBegin != pEnd;++pBegin)
1634 OUString aName(getUniqueColumnName(*pBegin));
1635 Reference< XPropertySet > xColumn;
1636 if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is())
1638 OParseColumn* pColumn = new OParseColumn(aName
1639 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))
1640 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))
1641 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION)))
1642 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))
1643 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))
1644 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))
1645 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))
1646 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)))
1647 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))
1648 , isCaseSensitive()
1649 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CATALOGNAME)))
1650 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCHEMANAME)))
1651 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TABLENAME))));
1653 pColumn->setTableName(_rTableAlias);
1654 pColumn->setRealName(*pBegin);
1655 Reference< XPropertySet> xCol = pColumn;
1656 _rColumns->get().push_back(xCol);
1658 else
1659 impl_appendError( IParseContext::ERROR_INVALID_COLUMN, pBegin, &_rTableAlias );
1663 void OSQLParseTreeIterator::setSelectColumnName(::rtl::Reference<OSQLColumns>& _rColumns,const OUString & rColumnName,const OUString & rColumnAlias, const OUString & rTableRange, bool bFkt, sal_Int32 _nType, bool bAggFkt)
1665 if(rColumnName.toChar() == '*' && rTableRange.isEmpty())
1666 { // SELECT * ...
1667 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1668 for(OSQLTables::const_iterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end();++aIter)
1669 appendColumns(_rColumns,aIter->first,aIter->second);
1671 else if( rColumnName.toChar() == '*' && !rTableRange.isEmpty() )
1672 { // SELECT <table>.*
1673 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1674 OSQLTables::const_iterator aFind = m_pImpl->m_pTables->find(rTableRange);
1676 if(aFind != m_pImpl->m_pTables->end())
1677 appendColumns(_rColumns,rTableRange,aFind->second);
1679 else if ( rTableRange.isEmpty() )
1680 { // SELECT <something> ...
1681 // without table specified
1682 if ( !bFkt )
1684 Reference< XPropertySet> xNewColumn;
1686 for ( OSQLTables::iterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter )
1688 if ( !aIter->second.is() )
1689 continue;
1691 Reference<XNameAccess> xColumns = aIter->second->getColumns();
1692 Reference< XPropertySet > xColumn;
1693 if ( !xColumns->hasByName( rColumnName )
1694 || !( xColumns->getByName( rColumnName ) >>= xColumn )
1696 continue;
1698 OUString aNewColName(getUniqueColumnName(rColumnAlias));
1700 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1701 xNewColumn = pColumn;
1702 pColumn->setTableName(aIter->first);
1703 pColumn->setName(aNewColName);
1704 pColumn->setRealName(rColumnName);
1706 break;
1709 if ( !xNewColumn.is() )
1711 // no function (due to the above !bFkt), no existing column
1712 // => assume an expression
1713 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,
1725 _nType,
1726 false,
1727 false,
1728 isCaseSensitive(),
1729 OUString(),
1730 OUString(),
1731 OUString()
1734 xNewColumn = pColumn;
1735 pColumn->setRealName( rColumnName );
1738 _rColumns->get().push_back( xNewColumn );
1740 else
1742 OUString aNewColName(getUniqueColumnName(rColumnAlias));
1744 OParseColumn* pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(),
1745 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,false,false,isCaseSensitive(),
1746 OUString(),OUString(),OUString());
1747 pColumn->setFunction(true);
1748 pColumn->setAggregateFunction(bAggFkt);
1749 pColumn->setRealName(rColumnName);
1751 Reference< XPropertySet> xCol = pColumn;
1752 _rColumns->get().push_back(xCol);
1755 else // ColumnName and TableName exist
1757 OSQLTables::const_iterator aFind = m_pImpl->m_pTables->find(rTableRange);
1759 bool bError = false;
1760 if (aFind != m_pImpl->m_pTables->end() && aFind->second.is())
1762 if (bFkt)
1764 OUString aNewColName(getUniqueColumnName(rColumnAlias));
1766 OParseColumn* pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(),
1767 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,false,false,isCaseSensitive(),
1768 OUString(),OUString(),OUString());
1769 pColumn->setFunction(true);
1770 pColumn->setAggregateFunction(bAggFkt);
1771 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 pColumn->setTableName(aFind->first);
1776 Reference< XPropertySet> xCol = pColumn;
1777 _rColumns->get().push_back(xCol);
1779 else
1781 Reference< XPropertySet > xColumn;
1782 if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn))
1784 OUString aNewColName(getUniqueColumnName(rColumnAlias));
1786 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1787 pColumn->setName(aNewColName);
1788 pColumn->setRealName(rColumnName);
1789 pColumn->setTableName(aFind->first);
1791 Reference< XPropertySet> xCol = pColumn;
1792 _rColumns->get().push_back(xCol);
1794 else
1795 bError = true;
1798 else
1799 bError = true;
1801 // Table does not exist or lacking field
1802 if (bError)
1804 OUString aNewColName(getUniqueColumnName(rColumnAlias));
1806 OParseColumn* pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(),
1807 ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,false,false,isCaseSensitive(),
1808 OUString(),OUString(),OUString());
1809 pColumn->setFunction(true);
1810 pColumn->setAggregateFunction(bAggFkt);
1812 Reference< XPropertySet> xCol = pColumn;
1813 _rColumns->get().push_back(xCol);
1818 OUString OSQLParseTreeIterator::getUniqueColumnName(const OUString & rColumnName) const
1820 OUString aAlias(rColumnName);
1822 OSQLColumns::Vector::const_iterator aIter = find(
1823 m_aSelectColumns->get().begin(),
1824 m_aSelectColumns->get().end(),
1825 aAlias,
1826 ::comphelper::UStringMixEqual( isCaseSensitive() )
1828 sal_Int32 i=1;
1829 while(aIter != m_aSelectColumns->get().end())
1831 (aAlias = rColumnName) += OUString::number(i++);
1832 aIter = find(
1833 m_aSelectColumns->get().begin(),
1834 m_aSelectColumns->get().end(),
1835 aAlias,
1836 ::comphelper::UStringMixEqual( isCaseSensitive() )
1839 return aAlias;
1842 void OSQLParseTreeIterator::setOrderByColumnName(const OUString & rColumnName, OUString & rTableRange, bool bAscending)
1844 Reference<XPropertySet> xColumn = findSelectColumn( rColumnName );
1845 if ( !xColumn.is() )
1846 xColumn = findColumn ( rColumnName, rTableRange, false );
1847 if ( xColumn.is() )
1848 m_aOrderColumns->get().push_back(new OOrderColumn( xColumn, rTableRange, isCaseSensitive(), bAscending ) );
1849 else
1851 sal_Int32 nId = rColumnName.toInt32();
1852 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1853 m_aOrderColumns->get().push_back( new OOrderColumn( ( m_aSelectColumns->get() )[nId-1], isCaseSensitive(), bAscending ) );
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
1865 void OSQLParseTreeIterator::setGroupByColumnName(const OUString & rColumnName, OUString & rTableRange)
1867 Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
1868 if ( xColumn.is() )
1869 m_aGroupColumns->get().push_back(new OParseColumn(xColumn,isCaseSensitive()));
1870 else
1872 sal_Int32 nId = rColumnName.toInt32();
1873 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1874 m_aGroupColumns->get().push_back(new OParseColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive()));
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
1887 const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const
1889 if (!m_pParseTree)
1890 return NULL;
1892 // Analyse parse tree (depending on statement type)
1893 // and set pointer to WHERE clause:
1894 OSQLParseNode * pWhereClause = NULL;
1895 if(getStatementType() == SQL_STATEMENT_SELECT)
1897 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1898 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!");
1903 pWhereClause = pTableExp->getChild(1);
1905 else if (SQL_ISRULE(m_pParseTree,update_statement_searched) ||
1906 SQL_ISRULE(m_pParseTree,delete_statement_searched))
1908 pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1);
1910 if(pWhereClause && pWhereClause->count() != 2)
1911 pWhereClause = NULL;
1912 return pWhereClause;
1916 const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const
1918 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1919 return NULL;
1921 // Analyse parse tree (depending on statement type)
1922 // and set pointer to ORDER clause:
1923 OSQLParseNode * pOrderClause = NULL;
1924 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1925 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!");
1930 pOrderClause = pTableExp->getChild(ORDER_BY_CHILD_POS);
1931 // If it is a order_by, it must not be empty
1932 if(pOrderClause->count() != 3)
1933 pOrderClause = NULL;
1934 return pOrderClause;
1937 const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const
1939 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1940 return NULL;
1942 // Analyse parse tree (depending on statement type)
1943 // and set pointer to ORDER clause:
1944 OSQLParseNode * pGroupClause = NULL;
1945 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1946 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!");
1951 pGroupClause = pTableExp->getChild(2);
1952 // If it is an order_by, it must not be empty
1953 if(pGroupClause->count() != 3)
1954 pGroupClause = NULL;
1955 return pGroupClause;
1958 const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const
1960 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1961 return NULL;
1963 // Analyse parse tree (depending on statement type)
1964 // and set pointer to ORDER clause:
1965 OSQLParseNode * pHavingClause = NULL;
1966 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1967 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!");
1972 pHavingClause = pTableExp->getChild(3);
1973 // If it is an order_by, then it must not be empty
1974 if(pHavingClause->count() < 1)
1975 pHavingClause = NULL;
1976 return pHavingClause;
1979 bool OSQLParseTreeIterator::isTableNode(const OSQLParseNode* _pTableNode)
1981 return _pTableNode && (SQL_ISRULE(_pTableNode,catalog_name) ||
1982 SQL_ISRULE(_pTableNode,schema_name) ||
1983 SQL_ISRULE(_pTableNode,table_name));
1986 const OSQLParseNode* OSQLParseTreeIterator::getSimpleWhereTree() const
1988 const OSQLParseNode* pNode = getWhereTree();
1989 return pNode ? pNode->getChild(1) : NULL;
1992 const OSQLParseNode* OSQLParseTreeIterator::getSimpleOrderTree() const
1994 const OSQLParseNode* pNode = getOrderTree();
1995 return pNode ? pNode->getChild(2) : NULL;
1998 const OSQLParseNode* OSQLParseTreeIterator::getSimpleGroupByTree() const
2000 const OSQLParseNode* pNode = getGroupByTree();
2001 return pNode ? pNode->getChild(2) : NULL;
2004 const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const
2006 const OSQLParseNode* pNode = getHavingTree();
2007 return pNode ? pNode->getChild(1) : NULL;
2011 Reference< XPropertySet > OSQLParseTreeIterator::findSelectColumn( const OUString & rColumnName )
2013 for ( OSQLColumns::Vector::const_iterator lookupColumn = m_aSelectColumns->get().begin();
2014 lookupColumn != m_aSelectColumns->get().end();
2015 ++lookupColumn )
2017 Reference< XPropertySet > xColumn( *lookupColumn );
2020 OUString sName;
2021 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= sName;
2022 if ( sName == rColumnName )
2023 return xColumn;
2025 catch( const Exception& )
2027 DBG_UNHANDLED_EXCEPTION();
2030 return NULL;
2034 Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const OUString & rColumnName, OUString & rTableRange, bool _bLookInSubTables )
2036 Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange );
2037 if ( !xColumn.is() && _bLookInSubTables )
2038 xColumn = findColumn( *m_pImpl->m_pSubTables, rColumnName, rTableRange );
2039 return xColumn;
2043 Reference< XPropertySet > OSQLParseTreeIterator::findColumn(const OSQLTables& _rTables, const OUString & rColumnName, OUString & rTableRange)
2045 Reference< XPropertySet > xColumn;
2046 if ( !rTableRange.isEmpty() )
2048 OSQLTables::const_iterator aFind = _rTables.find(rTableRange);
2050 if ( aFind != _rTables.end()
2051 && aFind->second.is()
2052 && aFind->second->getColumns().is()
2053 && aFind->second->getColumns()->hasByName(rColumnName) )
2054 aFind->second->getColumns()->getByName(rColumnName) >>= xColumn;
2056 if ( !xColumn.is() )
2058 const OSQLTables::const_iterator aEnd = _rTables.end();
2059 for(OSQLTables::const_iterator aIter = _rTables.begin(); aIter != aEnd; ++aIter)
2061 if ( aIter->second.is() )
2063 Reference<XNameAccess> xColumns = aIter->second->getColumns();
2064 if( xColumns.is() && xColumns->hasByName(rColumnName) && (xColumns->getByName(rColumnName) >>= xColumn) )
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 rTableRange = getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TABLENAME)));
2070 break; // This column must only exits once
2075 return xColumn;
2079 void OSQLParseTreeIterator::impl_appendError( IParseContext::ErrorCode _eError, const OUString* _pReplaceToken1, const OUString* _pReplaceToken2 )
2081 OUString sErrorMessage = m_rParser.getContext().getErrorMessage( _eError );
2082 if ( _pReplaceToken1 )
2084 bool bTwoTokens = ( _pReplaceToken2 != NULL );
2085 const sal_Char* pPlaceHolder1 = bTwoTokens ? "#1" : "#";
2086 const OUString sPlaceHolder1 = OUString::createFromAscii( pPlaceHolder1 );
2088 sErrorMessage = sErrorMessage.replaceFirst( sPlaceHolder1, *_pReplaceToken1 );
2089 if ( _pReplaceToken2 )
2090 sErrorMessage = sErrorMessage.replaceFirst( "#2" , *_pReplaceToken2 );
2093 impl_appendError( SQLException(
2094 sErrorMessage, NULL, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ) );
2098 void OSQLParseTreeIterator::impl_appendError( const SQLException& _rError )
2100 if ( !m_aErrors.Message.isEmpty() )
2102 SQLException* pErrorChain = &m_aErrors;
2103 while ( pErrorChain->NextException.hasValue() )
2104 pErrorChain = static_cast< SQLException* >( pErrorChain->NextException.pData );
2105 pErrorChain->NextException <<= _rError;
2107 else
2108 m_aErrors = _rError;
2111 sal_Int32 OSQLParseTreeIterator::getFunctionReturnType(const OSQLParseNode* _pNode )
2113 sal_Int32 nType = DataType::OTHER;
2114 OUString sFunctionName;
2115 if ( SQL_ISRULE(_pNode,length_exp) )
2117 _pNode->getChild(0)->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, false, false );
2118 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
2120 else if ( SQL_ISRULE(_pNode,num_value_exp) || SQL_ISRULE(_pNode,term) || SQL_ISRULE(_pNode,factor) )
2122 nType = DataType::DOUBLE;
2124 else
2126 _pNode->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, false, false );
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 if ( SQL_ISRULE(_pNode,general_set_fct) && (SQL_ISTOKEN(_pNode->getChild(0),MIN) || SQL_ISTOKEN(_pNode->getChild(0),MAX) ))
2132 const OSQLParseNode* pValueExp = _pNode->getChild(3);
2133 if (SQL_ISRULE(pValueExp,column_ref))
2135 OUString sColumnName;
2136 OUString aTableRange;
2137 getColumnRange(pValueExp,sColumnName,aTableRange);
2138 OSL_ENSURE(!sColumnName.isEmpty(),"Columnname must not be empty!");
2139 Reference<XPropertySet> xColumn = findColumn( sColumnName, aTableRange, true );
2141 if ( xColumn.is() )
2143 xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TYPE)) >>= nType;
2146 else
2148 if ( SQL_ISRULE(pValueExp,num_value_exp) || SQL_ISRULE(pValueExp,term) || SQL_ISRULE(pValueExp,factor) )
2150 nType = DataType::DOUBLE;
2152 else if ( SQL_ISRULE(pValueExp,datetime_primary) )
2154 switch(pValueExp->getChild(0)->getTokenID() )
2156 case SQL_TOKEN_CURRENT_DATE:
2157 nType = DataType::DATE;
2158 break;
2159 case SQL_TOKEN_CURRENT_TIME:
2160 nType = DataType::TIME;
2161 break;
2162 case SQL_TOKEN_CURRENT_TIMESTAMP:
2163 nType = DataType::TIMESTAMP;
2164 break;
2167 else if ( SQL_ISRULE(pValueExp,value_exp_primary) )
2169 nType = getFunctionReturnType(pValueExp->getChild(1));
2171 else if ( SQL_ISRULE(pValueExp,concatenation)
2172 || SQL_ISRULE(pValueExp,char_factor)
2173 || SQL_ISRULE(pValueExp,bit_value_fct)
2174 || SQL_ISRULE(pValueExp,char_value_fct)
2175 || SQL_ISRULE(pValueExp,char_substring_fct)
2176 || SQL_ISRULE(pValueExp,fold)
2177 || SQL_ISTOKEN(pValueExp,STRING) )
2179 nType = DataType::VARCHAR;
2182 if ( nType == DataType::OTHER )
2183 nType = DataType::DOUBLE;
2185 else
2186 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
2189 return nType;
2192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */