1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
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"
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
96 Reference
< XQueriesSupplier
> xSuppQueries( m_xConnection
, UNO_QUERY
);
97 if ( xSuppQueries
.is() )
98 m_xQueryContainer
= xSuppQueries
->getQueries();
103 inline bool isQueryAllowed( const OUString
& _rQueryName
)
105 if ( !m_pForbiddenQueryNames
.get() )
107 if ( m_pForbiddenQueryNames
->find( _rQueryName
) == m_pForbiddenQueryNames
->end() )
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
;
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
);
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
) )
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()
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
;
203 m_eStatementType
= SQL_STATEMENT_UNKNOWN
;
207 // If m_pParseTree, but no connection then return
208 if ( !m_pImpl
->m_xTableContainer
.is() )
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);
242 m_eStatementType
= SQL_STATEMENT_UNKNOWN
;
243 //aIteratorStatus.setInvalidStatement();
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(
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
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
332 if ( !bEscapeProcessing
|| ( sSubQueryCommand
.isEmpty() ) )
336 std::unique_ptr
< OSQLParseNode
> pSubQueryNode( const_cast< OSQLParser
& >( m_rParser
).parseTree( sError
, sSubQueryCommand
, false ) );
337 if ( !pSubQueryNode
.get() )
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();
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?" );
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
);
390 aReturn
= impl_createTableObject( sName
, sCatalog
, sSchema
);
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
) );
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
;
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
);
419 impl_appendError( IParseContext::ERROR_INVALID_TABLE_NOSUCH
, &sName
);
425 impl_appendError( IParseContext::ERROR_INVALID_TABLE_NOSUCH
, &sComposedName
);
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
438 OSL_ENSURE(pTableName
!= NULL
,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL");
441 OUString aSchema
,aTableName
,aComposedName
;
442 OUString
aTableRange(rTableRange
);
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(),
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
);
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!" );
508 const OSQLParseNode
* pNode
= getTableNode(_rTables
,pTableRef
->getChild(0),aTableRange
);
509 if ( isTableNode( pNode
) )
510 traverseOneTableName( _rTables
, pNode
, aTableRange
);
513 if( SQL_ISRULE(pTableRef
,cross_union
) || pTableRef
->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL
)
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));
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
);
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
);
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
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);
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));
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
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
);
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
)
667 OSQLParseNode
* pTableName
= NULL
;
669 switch ( m_eStatementType
)
671 case SQL_STATEMENT_SELECT
:
672 getSelect_statement( _rTables
, m_pParseTree
);
675 case SQL_STATEMENT_CREATE_TABLE
:
676 case SQL_STATEMENT_INSERT
:
677 case SQL_STATEMENT_DELETE
:
678 pTableName
= m_pParseTree
->getChild(2);
681 case SQL_STATEMENT_UPDATE
:
682 pTableName
= m_pParseTree
->getChild(1);
690 OUString sTableRange
;
691 traverseOneTableName( _rTables
, pTableName
, sTableRange
);
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();
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();
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();
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
;
749 catch( const Exception
& )
751 DBG_UNHANDLED_EXCEPTION();
756 else if(SQL_ISRULE(_pColumnRef
,general_set_fct
) || SQL_ISRULE(_pColumnRef
,set_fct_spec
))
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
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
)
788 lcl_getColumnRange( _pColumnRef
, _rxConnection
, _out_rColumnName
, _out_rTableRange
, NULL
, sDummy
);
792 bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode
* pNode
, OUString
&rTableRange
) const
795 if(impl_getColumnTableRange(pNode
, tmp
))
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
;
837 if (aTableRange
.isEmpty())
842 if (rTableRange
.isEmpty())
843 rTableRange
= aTableRange
;
844 else if (rTableRange
!= aTableRange
)
849 for (sal_uInt32 i
= 0, ncount
= pNode
->count(); i
< ncount
; i
++)
851 if (!getColumnTableRange(pNode
->getChild(i
), rTableRange
))
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
);
868 if (!SQL_ISRULE(pSelectNode
,base_table_element_commalist
))
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
;
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();
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
)
924 if (!pSelectNode
|| m_eStatementType
!= SQL_STATEMENT_SELECT
|| m_pImpl
->m_pTables
->empty())
926 impl_appendError( IParseContext::ERROR_GENERAL
);
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),"*"))
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
);
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
;
971 pColumnRef
= pColumnRef
->getChild(0);
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"
1001 nType
= getFunctionReturnType(pColumnRef
);
1007 aIteratorStatus.setStatementTooComplex();
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();
1039 if (m_eStatementType
!= SQL_STATEMENT_SELECT
)
1041 //aIteratorStatus.setInvalidStatement();
1045 if(SQL_ISRULE(pSelectNode
,union_statement
))
1047 traverseByColumnNames(pSelectNode
->getChild(0),_bOrder
);
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 )
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!");
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
);
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!");
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
);
1109 setGroupByColumnName(sColumnName
, aTableRange
);
1113 bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode
* pSelectNode
)
1115 traverseByColumnNames( pSelectNode
, false );
1116 return !hasErrors();
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 );
1139 void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode
* _pNode
)
1141 if ( _pNode
== NULL
)
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
)
1153 const OSQLParseNode
* pOther
= pParent
->getChild(nPos
);
1154 if ( SQL_ISRULE( pOther
, column_ref
) )
1155 getColumnRange( pOther
, sColumnName
, sTableRange
, aColumnAlias
);
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
);
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
);
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
)
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
)) {
1225 SAL_WARN( "connectivity.parse","OSQLParseTreeIterator::getSelectionCriteria: positioned nyi");
1227 // Other statement, no selection criteria
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!");
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
)
1257 SQL_ISRULE(pSearchCondition
,boolean_primary
) &&
1258 pSearchCondition
->count() == 3 &&
1259 SQL_ISPUNCTUATION(pSearchCondition
->getChild(0),"(") &&
1260 SQL_ISPUNCTUATION(pSearchCondition
->getChild(2),")")
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())
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())
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
) )
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())
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();
1320 OSQLParseNode
* pParam
= NULL
;
1321 if (SQL_ISRULE(pNum_value_exp
,parameter
))
1322 pParam
= pNum_value_exp
;
1323 else if(pNum_value_exp
->isToken())
1325 aValue
= pNum_value_exp
->getTokenValue();
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())
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));
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);
1365 OSL_ENSURE(SQL_ISTOKEN(pPart2
->getChild(0),IS
),"OSQLParseTreeIterator: error in parse tree!");
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
))
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
) )
1389 if ( ( m_pImpl
->m_nIncludeMask
& Parameters
) != Parameters
)
1390 // parameters not to be included in the traversal
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()
1401 : !_aColumnName
.isEmpty()
1405 else if (SQL_ISPUNCTUATION(pMark
,":"))
1407 sParameterName
= _pParseNode
->getChild(1)->getTokenValue();
1409 else if (SQL_ISPUNCTUATION(pMark
,"["))
1411 sParameterName
= _pParseNode
->getChild(1)->getTokenValue();
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();
1425 for(; i
< nCount
;++i
)
1427 if ( _pParentNode
->getChild(i
) == _pParseNode
)
1430 sal_Int32 nType
= ::connectivity::OSQLParser::getFunctionParameterType( _pParentNode
->getChild(0)->getTokenID(), i
-1);
1432 OParseColumn
* pColumn
= new OParseColumn( sParameterName
,
1436 ColumnValue::NULLABLE_UNKNOWN
,
1446 pColumn
->setFunction(true);
1447 pColumn
->setAggregateFunction(true);
1448 pColumn
->setRealName(sFunctionName
);
1449 m_aParameters
->get().push_back(pColumn
);
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
);
1467 else if(!_aColumnName
.isEmpty())// search in the tables for the right one
1470 Reference
<XPropertySet
> xColumn
= findColumn( _aColumnName
, _aTableRange
, true );
1474 OParseColumn
* pNewColumn
= new OParseColumn(xColumn
,isCaseSensitive());
1475 pNewColumn
->setName(sParameterName
);
1476 pNewColumn
->setRealName(_aColumnName
);
1477 m_aParameters
->get().push_back(pNewColumn
);
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();
1489 for(; i
< nCount
;++i
)
1491 if ( _pParentNode
->getChild(i
) == _pParseNode
)
1494 nType
= ::connectivity::OSQLParser::getFunctionParameterType( pParent
->getChild(0)->getTokenID(), i
+1);
1497 OUString
aNewColName( getUniqueColumnName( sParameterName
) );
1499 OParseColumn
* pColumn
= new OParseColumn(aNewColName
,
1503 ColumnValue::NULLABLE_UNKNOWN
,
1513 pColumn
->setName(aNewColName
);
1514 pColumn
->setRealName(sParameterName
);
1515 m_aParameters
->get().push_back(pColumn
);
1520 void OSQLParseTreeIterator::traverseOnePredicate(
1521 OSQLParseNode
* pColumnRef
,
1523 OSQLParseNode
* pParseNode
)
1528 // Column name (and TableRange):
1529 OUString aColumnName
, aTableRange
, sColumnAlias
;
1530 getColumnRange( pColumnRef
, aColumnName
, aTableRange
, sColumnAlias
);
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
);
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
)
1561 m_pImpl
->m_nIncludeMask
= _nIncludeMask
;
1563 if ( !traverseTableNames( *m_pImpl
->m_pTables
) )
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
)
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
);
1588 case SQL_STATEMENT_INSERT
:
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(
1611 OUString("New Created Table"),
1615 return aReturnTable
;
1618 void OSQLParseTreeIterator::appendColumns(::rtl::Reference
<OSQLColumns
>& _rColumns
,const OUString
& _rTableAlias
,const OSQLTable
& _rTable
)
1623 Reference
<XNameAccess
> xColumns
= _rTable
->getColumns();
1624 if ( !xColumns
.is() )
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
)))
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
);
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())
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
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() )
1691 Reference
<XNameAccess
> xColumns
= aIter
->second
->getColumns();
1692 Reference
< XPropertySet
> xColumn
;
1693 if ( !xColumns
->hasByName( rColumnName
)
1694 || !( xColumns
->getByName( rColumnName
) >>= xColumn
)
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
);
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(
1717 OUString("VARCHAR"),
1718 // TODO: does this match with _nType?
1719 // Or should be fill this from the getTypeInfo of the connection?
1722 ColumnValue::NULLABLE_UNKNOWN
,
1734 xNewColumn
= pColumn
;
1735 pColumn
->setRealName( rColumnName
);
1738 _rColumns
->get().push_back( xNewColumn
);
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())
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.");
1774 pColumn
->setTableName(aFind
->first
);
1776 Reference
< XPropertySet
> xCol
= pColumn
;
1777 _rColumns
->get().push_back(xCol
);
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
);
1801 // Table does not exist or lacking field
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(),
1826 ::comphelper::UStringMixEqual( isCaseSensitive() )
1829 while(aIter
!= m_aSelectColumns
->get().end())
1831 (aAlias
= rColumnName
) += OUString::number(i
++);
1833 m_aSelectColumns
->get().begin(),
1834 m_aSelectColumns
->get().end(),
1836 ::comphelper::UStringMixEqual( isCaseSensitive() )
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 );
1848 m_aOrderColumns
->get().push_back(new OOrderColumn( xColumn
, rTableRange
, isCaseSensitive(), bAscending
) );
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")
1865 void OSQLParseTreeIterator::setGroupByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
)
1867 Reference
<XPropertySet
> xColumn
= findColumn( rColumnName
, rTableRange
, false );
1869 m_aGroupColumns
->get().push_back(new OParseColumn(xColumn
,isCaseSensitive()));
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")
1887 const OSQLParseNode
* OSQLParseTreeIterator::getWhereTree() const
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
)
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
)
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
)
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();
2017 Reference
< XPropertySet
> xColumn( *lookupColumn
);
2021 xColumn
->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME
) ) >>= sName
;
2022 if ( sName
== rColumnName
)
2025 catch( const Exception
& )
2027 DBG_UNHANDLED_EXCEPTION();
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
);
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
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
;
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
;
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 );
2143 xColumn
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TYPE
)) >>= nType
;
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
;
2159 case SQL_TOKEN_CURRENT_TIME
:
2160 nType
= DataType::TIME
;
2162 case SQL_TOKEN_CURRENT_TIMESTAMP
:
2163 nType
= DataType::TIMESTAMP
;
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
;
2186 nType
= ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName
, &m_rParser
.getContext() );
2192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */