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