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