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