/src/libreoffice/connectivity/source/parse/sqlnode.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/macros.h> |
21 | | #include <connectivity/sqlnode.hxx> |
22 | | #include <connectivity/sqlerror.hxx> |
23 | | #include <connectivity/sqlbison_exports.hxx> |
24 | | #include <connectivity/internalnode.hxx> |
25 | | #define YYBISON 1 |
26 | | #include <sqlbison.hxx> |
27 | | #include <connectivity/sqlparse.hxx> |
28 | | #include <connectivity/sqlscan.hxx> |
29 | | #include <com/sun/star/lang/Locale.hpp> |
30 | | #include <com/sun/star/util/XNumberFormatter.hpp> |
31 | | #include <com/sun/star/util/XNumberFormatTypes.hpp> |
32 | | #include <com/sun/star/i18n/LocaleData.hpp> |
33 | | #include <com/sun/star/i18n/NumberFormatIndex.hpp> |
34 | | #include <com/sun/star/beans/XPropertySet.hpp> |
35 | | #include <com/sun/star/sdbc/XDatabaseMetaData.hpp> |
36 | | #include <com/sun/star/sdbc/DataType.hpp> |
37 | | #include <com/sun/star/sdbc/SQLException.hpp> |
38 | | #include <com/sun/star/sdb/XQueriesSupplier.hpp> |
39 | | #include <com/sun/star/sdb/ErrorCondition.hpp> |
40 | | #include <com/sun/star/util/XNumberFormatsSupplier.hpp> |
41 | | #include <com/sun/star/util/XNumberFormats.hpp> |
42 | | #include <com/sun/star/util/NumberFormat.hpp> |
43 | | #include <com/sun/star/i18n/KParseType.hpp> |
44 | | #include <com/sun/star/i18n/KParseTokens.hpp> |
45 | | #include <com/sun/star/i18n/CharacterClassification.hpp> |
46 | | #include <connectivity/dbconversion.hxx> |
47 | | #include <com/sun/star/util/DateTime.hpp> |
48 | | #include <com/sun/star/util/Time.hpp> |
49 | | #include <com/sun/star/util/Date.hpp> |
50 | | #include <TConnection.hxx> |
51 | | #include <comphelper/numbers.hxx> |
52 | | #include <connectivity/dbtools.hxx> |
53 | | #include <connectivity/dbmetadata.hxx> |
54 | | #include <comphelper/diagnose_ex.hxx> |
55 | | #include <string.h> |
56 | | #include <algorithm> |
57 | | #include <functional> |
58 | | #include <memory> |
59 | | #include <string_view> |
60 | | #include <tuple> |
61 | | |
62 | | #include <rtl/ustrbuf.hxx> |
63 | | #include <sal/log.hxx> |
64 | | #include <utility> |
65 | | |
66 | | using namespace ::com::sun::star::sdbc; |
67 | | using namespace ::com::sun::star::util; |
68 | | using namespace ::com::sun::star::beans; |
69 | | using namespace ::com::sun::star::sdb; |
70 | | using namespace ::com::sun::star::uno; |
71 | | using namespace ::com::sun::star::lang; |
72 | | using namespace ::com::sun::star::i18n; |
73 | | using namespace ::com::sun::star; |
74 | | using namespace ::osl; |
75 | | using namespace ::dbtools; |
76 | | using namespace ::comphelper; |
77 | | |
78 | | namespace |
79 | | { |
80 | | |
81 | | bool lcl_saveConvertToNumber(const Reference< XNumberFormatter > & _xFormatter,sal_Int32 _nKey,const OUString& _sValue,double& _nrValue) |
82 | 0 | { |
83 | 0 | bool bRet = false; |
84 | 0 | try |
85 | 0 | { |
86 | 0 | _nrValue = _xFormatter->convertStringToNumber(_nKey, _sValue); |
87 | 0 | bRet = true; |
88 | 0 | } |
89 | 0 | catch(Exception&) |
90 | 0 | { |
91 | 0 | } |
92 | 0 | return bRet; |
93 | 0 | } |
94 | | |
95 | | void replaceAndReset(connectivity::OSQLParseNode*& _pResetNode,connectivity::OSQLParseNode* _pNewNode) |
96 | 0 | { |
97 | 0 | _pResetNode->getParent()->replaceAndDelete(_pResetNode, _pNewNode); |
98 | 0 | _pResetNode = _pNewNode; |
99 | 0 | } |
100 | | |
101 | | /** quotes a string and search for quotes inside the string and replace them with the new quote |
102 | | @param rValue |
103 | | The value to be quoted. |
104 | | @param rQuote |
105 | | The quote |
106 | | @param rQuoteToReplace |
107 | | The quote to replace with |
108 | | @return |
109 | | The quoted string. |
110 | | */ |
111 | | OUString SetQuotation(const OUString& rValue, std::u16string_view rQuote, std::u16string_view rQuoteToReplace) |
112 | 0 | { |
113 | | // Replace quotes with double quotes or the parser gets into problems |
114 | 0 | if (!rQuote.empty()) |
115 | 0 | return rQuote + rValue.replaceAll(rQuote, rQuoteToReplace) + rQuote; |
116 | 0 | return rValue; |
117 | 0 | } |
118 | | |
119 | | bool columnMatchP(const connectivity::OSQLParseNode* pSubTree, const connectivity::SQLParseNodeParameter& rParam) |
120 | 0 | { |
121 | 0 | using namespace connectivity; |
122 | 0 | assert(SQL_ISRULE(pSubTree,column_ref)); |
123 | |
|
124 | 0 | if(!rParam.xField.is()) |
125 | 0 | return false; |
126 | | |
127 | | // retrieve the field's name & table range |
128 | 0 | OUString aFieldName; |
129 | 0 | try |
130 | 0 | { |
131 | 0 | sal_Int32 nNamePropertyId = PROPERTY_ID_NAME; |
132 | 0 | if ( rParam.xField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) ) |
133 | 0 | nNamePropertyId = PROPERTY_ID_REALNAME; |
134 | 0 | rParam.xField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( nNamePropertyId ) ) >>= aFieldName; |
135 | 0 | } |
136 | 0 | catch ( Exception& ) |
137 | 0 | { |
138 | 0 | } |
139 | |
|
140 | 0 | if(!pSubTree->count()) |
141 | 0 | return false; |
142 | | |
143 | 0 | const OSQLParseNode* pCol = pSubTree->getChild(pSubTree->count()-1); |
144 | 0 | if (SQL_ISRULE(pCol,column_val)) |
145 | 0 | { |
146 | 0 | assert(pCol->count() == 1); |
147 | 0 | pCol = pCol->getChild(0); |
148 | 0 | } |
149 | 0 | const OSQLParseNode* pTable(nullptr); |
150 | 0 | switch (pSubTree->count()) |
151 | 0 | { |
152 | 0 | case 1: |
153 | 0 | break; |
154 | 0 | case 3: |
155 | 0 | pTable = pSubTree->getChild(0); |
156 | 0 | break; |
157 | 0 | case 5: |
158 | 0 | case 7: |
159 | 0 | SAL_WARN("connectivity.parse", "SQL: catalog and/or schema in column_ref in predicate"); |
160 | 0 | break; |
161 | 0 | default: |
162 | 0 | SAL_WARN("connectivity.parse", "columnMatchP: SQL grammar changed; column_ref has " << pSubTree->count() << " children"); |
163 | 0 | assert(false); |
164 | 0 | break; |
165 | 0 | } |
166 | | // TODO: not all DBMS match column names case-insensitively... |
167 | | // see XDatabaseMetaData::supportsMixedCaseIdentifiers() |
168 | | // and XDatabaseMetaData::supportsMixedCaseQuotedIdentifiers() |
169 | 0 | if ( // table name matches (or no table name)? |
170 | 0 | ( !pTable || pTable->getTokenValue().equalsIgnoreAsciiCase(rParam.sPredicateTableAlias) ) |
171 | 0 | && // column name matches? |
172 | 0 | pCol->getTokenValue().equalsIgnoreAsciiCase(aFieldName) |
173 | 0 | ) |
174 | 0 | return true; |
175 | 0 | return false; |
176 | 0 | } |
177 | | } |
178 | | |
179 | | namespace connectivity |
180 | | { |
181 | | |
182 | | SQLParseNodeParameter::SQLParseNodeParameter( const Reference< XConnection >& _rxConnection, |
183 | | const Reference< XNumberFormatter >& _xFormatter, const Reference< XPropertySet >& _xField, |
184 | | OUString _sPredicateTableAlias, |
185 | | const Locale& _rLocale, const IParseContext* _pContext, |
186 | | bool _bIntl, bool _bQuote, OUString _sDecSep, bool _bPredicate, bool _bParseToSDBC ) |
187 | 0 | :rLocale(_rLocale) |
188 | 0 | ,aMetaData( _rxConnection ) |
189 | 0 | ,pParser( nullptr ) |
190 | 0 | ,pSubQueryHistory( std::make_shared<QueryNameSet>() ) |
191 | 0 | ,xFormatter(_xFormatter) |
192 | 0 | ,xField(_xField) |
193 | 0 | ,sPredicateTableAlias(std::move(_sPredicateTableAlias)) |
194 | 0 | ,m_rContext( _pContext ? *_pContext : OSQLParser::s_aDefaultContext ) |
195 | 0 | ,sDecSep(std::move(_sDecSep)) |
196 | 0 | ,bQuote(_bQuote) |
197 | 0 | ,bInternational(_bIntl) |
198 | 0 | ,bPredicate(_bPredicate) |
199 | 0 | ,bParseToSDBCLevel( _bParseToSDBC ) |
200 | 0 | { |
201 | 0 | } |
202 | | |
203 | | OUString OSQLParseNode::convertDateString(const SQLParseNodeParameter& rParam, std::u16string_view rString) |
204 | 0 | { |
205 | 0 | Date aDate = DBTypeConversion::toDate(rString); |
206 | 0 | Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); |
207 | 0 | Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); |
208 | |
|
209 | 0 | double fDate = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier)); |
210 | 0 | sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::DATE_SYS_DDMMYYYY, rParam.rLocale); |
211 | 0 | return rParam.xFormatter->convertNumberToString(nKey, fDate); |
212 | 0 | } |
213 | | |
214 | | |
215 | | OUString OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rParam, const OUString& rString) |
216 | 0 | { |
217 | 0 | DateTime aDate = DBTypeConversion::toDateTime(rString); |
218 | | |
219 | | // round here in case of re-normalization on a rounded value |
220 | 0 | if (aDate.NanoSeconds) |
221 | 0 | { |
222 | 0 | DBTypeConversion::roundDateTimeFraction(aDate, rParam.aMetaData.getMaxDateTimeLiteralFractionDigits()); |
223 | 0 | return DBTypeConversion::toDateTimeString(aDate); |
224 | 0 | } |
225 | | |
226 | 0 | Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); |
227 | 0 | Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); |
228 | |
|
229 | 0 | double fDateTime = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier)); |
230 | 0 | sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::DATETIME_SYS_DDMMYYYY_HHMMSS, rParam.rLocale); |
231 | 0 | return rParam.xFormatter->convertNumberToString(nKey, fDateTime); |
232 | 0 | } |
233 | | |
234 | | |
235 | | OUString OSQLParseNode::convertTimeString(const SQLParseNodeParameter& rParam, std::u16string_view rString) |
236 | 0 | { |
237 | 0 | css::util::Time aTime = DBTypeConversion::toTime(rString); |
238 | | |
239 | | // Same fallback as convertDateTimeString() above |
240 | 0 | if (aTime.NanoSeconds) |
241 | 0 | { |
242 | | // Discarding the day-carry return: only time is relevant here |
243 | 0 | std::ignore = DBTypeConversion::roundTimeFraction(aTime, rParam.aMetaData.getMaxDateTimeLiteralFractionDigits()); |
244 | 0 | return DBTypeConversion::toTimeString(aTime); |
245 | 0 | } |
246 | | |
247 | 0 | Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); |
248 | |
|
249 | 0 | Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); |
250 | |
|
251 | 0 | double fTime = DBTypeConversion::toDouble(aTime); |
252 | 0 | sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::TIME_HHMMSS, rParam.rLocale); |
253 | 0 | return rParam.xFormatter->convertNumberToString(nKey, fTime); |
254 | 0 | } |
255 | | |
256 | | |
257 | | void OSQLParseNode::parseNodeToStr(OUString& rString, |
258 | | const Reference< XConnection >& _rxConnection, |
259 | | const IParseContext* pContext, |
260 | | bool _bIntl, |
261 | | bool _bQuote) const |
262 | 0 | { |
263 | 0 | parseNodeToStr( |
264 | 0 | rString, _rxConnection, nullptr, nullptr, OUString(), |
265 | 0 | pContext ? pContext->getPreferredLocale() : OParseContext::getDefaultLocale(), |
266 | 0 | pContext, _bIntl, _bQuote, u"."_ustr, false ); |
267 | 0 | } |
268 | | |
269 | | |
270 | | void OSQLParseNode::parseNodeToPredicateStr(OUString& rString, |
271 | | const Reference< XConnection >& _rxConnection, |
272 | | const Reference< XNumberFormatter > & xFormatter, |
273 | | const css::lang::Locale& rIntl, |
274 | | const OUString& rDec, |
275 | | const IParseContext* pContext ) const |
276 | 0 | { |
277 | 0 | OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); |
278 | |
|
279 | 0 | if (xFormatter.is()) |
280 | 0 | parseNodeToStr(rString, _rxConnection, xFormatter, nullptr, OUString(), rIntl, pContext, true, true, rDec, true); |
281 | 0 | } |
282 | | |
283 | | |
284 | | void OSQLParseNode::parseNodeToPredicateStr(OUString& rString, |
285 | | const Reference< XConnection > & _rxConnection, |
286 | | const Reference< XNumberFormatter > & xFormatter, |
287 | | const Reference< XPropertySet > & _xField, |
288 | | const OUString &_sPredicateTableAlias, |
289 | | const css::lang::Locale& rIntl, |
290 | | const OUString& rDec, |
291 | | const IParseContext* pContext ) const |
292 | 0 | { |
293 | 0 | OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); |
294 | |
|
295 | 0 | if (xFormatter.is()) |
296 | 0 | parseNodeToStr( rString, _rxConnection, xFormatter, _xField, _sPredicateTableAlias, rIntl, pContext, true, true, rDec, true ); |
297 | 0 | } |
298 | | |
299 | | |
300 | | void OSQLParseNode::parseNodeToStr(OUString& rString, |
301 | | const Reference< XConnection > & _rxConnection, |
302 | | const Reference< XNumberFormatter > & xFormatter, |
303 | | const Reference< XPropertySet > & _xField, |
304 | | const OUString &_sPredicateTableAlias, |
305 | | const css::lang::Locale& rIntl, |
306 | | const IParseContext* pContext, |
307 | | bool _bIntl, |
308 | | bool _bQuote, |
309 | | const OUString& _rDecSep, |
310 | | bool _bPredicate) const |
311 | 0 | { |
312 | 0 | OSL_ENSURE( _rxConnection.is(), "OSQLParseNode::parseNodeToStr: invalid connection!" ); |
313 | |
|
314 | 0 | if ( !_rxConnection.is() ) |
315 | 0 | return; |
316 | | |
317 | 0 | OUStringBuffer sBuffer(rString); |
318 | 0 | try |
319 | 0 | { |
320 | 0 | OSQLParseNode::impl_parseNodeToString_throw( sBuffer, |
321 | 0 | SQLParseNodeParameter( |
322 | 0 | _rxConnection, xFormatter, _xField, _sPredicateTableAlias, rIntl, pContext, |
323 | 0 | _bIntl, _bQuote, _rDecSep, _bPredicate, false |
324 | 0 | ) ); |
325 | 0 | } |
326 | 0 | catch( const SQLException& ) |
327 | 0 | { |
328 | 0 | SAL_WARN( "connectivity.parse", "OSQLParseNode::parseNodeToStr: this should not throw!" ); |
329 | | // our callers don't expect this method to throw anything. The only known situation |
330 | | // where impl_parseNodeToString_throw can throw is when there is a cyclic reference |
331 | | // in the sub queries, but this cannot be the case here, as we do not parse to |
332 | | // SDBC level. |
333 | 0 | } |
334 | 0 | rString = sBuffer.makeStringAndClear(); |
335 | 0 | } |
336 | | |
337 | | bool OSQLParseNode::parseNodeToExecutableStatement( OUString& _out_rString, const Reference< XConnection >& _rxConnection, |
338 | | OSQLParser& _rParser, css::sdbc::SQLException* _pErrorHolder ) const |
339 | 0 | { |
340 | 0 | OSL_PRECOND( _rxConnection.is(), "OSQLParseNode::parseNodeToExecutableStatement: invalid connection!" ); |
341 | 0 | SQLParseNodeParameter aParseParam( _rxConnection, |
342 | 0 | nullptr, nullptr, OUString(), OParseContext::getDefaultLocale(), nullptr, false, true, u"."_ustr, false, true ); |
343 | |
|
344 | 0 | if ( aParseParam.aMetaData.supportsSubqueriesInFrom() ) |
345 | 0 | { |
346 | 0 | Reference< XQueriesSupplier > xSuppQueries( _rxConnection, UNO_QUERY ); |
347 | 0 | OSL_ENSURE( xSuppQueries.is(), "OSQLParseNode::parseNodeToExecutableStatement: cannot substitute everything without a QueriesSupplier!" ); |
348 | 0 | if ( xSuppQueries.is() ) |
349 | 0 | aParseParam.xQueries = xSuppQueries->getQueries(); |
350 | 0 | } |
351 | |
|
352 | 0 | aParseParam.pParser = &_rParser; |
353 | | |
354 | | // LIMIT keyword differs in Firebird |
355 | 0 | OSQLParseNode* pTableExp = getChild(3); |
356 | 0 | Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData() ); |
357 | 0 | OUString sLimitValue; |
358 | 0 | if( pTableExp->getChild(6)->count() >= 2 && pTableExp->getChild(6)->getChild(1) |
359 | 0 | && (xMeta->getURL().equalsIgnoreAsciiCase("sdbc:embedded:firebird") |
360 | 0 | || xMeta->getURL().startsWithIgnoreAsciiCase("sdbc:firebird:"))) |
361 | 0 | { |
362 | 0 | sLimitValue = pTableExp->getChild(6)->getChild(1)->getTokenValue(); |
363 | 0 | delete pTableExp->removeAt(6); |
364 | 0 | } |
365 | |
|
366 | 0 | _out_rString.clear(); |
367 | 0 | OUStringBuffer sBuffer; |
368 | 0 | bool bSuccess = false; |
369 | 0 | try |
370 | 0 | { |
371 | 0 | impl_parseNodeToString_throw( sBuffer, aParseParam ); |
372 | 0 | bSuccess = true; |
373 | 0 | } |
374 | 0 | catch( const SQLException& e ) |
375 | 0 | { |
376 | 0 | if ( _pErrorHolder ) |
377 | 0 | *_pErrorHolder = e; |
378 | 0 | } |
379 | |
|
380 | 0 | if(sLimitValue.getLength() > 0) |
381 | 0 | { |
382 | 0 | static constexpr char SELECT_KEYWORD[] = "SELECT"; |
383 | 0 | sBuffer.insert(sBuffer.indexOf(SELECT_KEYWORD) + strlen(SELECT_KEYWORD), |
384 | 0 | Concat2View(" FIRST " + sLimitValue)); |
385 | 0 | } |
386 | |
|
387 | 0 | _out_rString = sBuffer.makeStringAndClear(); |
388 | 0 | return bSuccess; |
389 | 0 | } |
390 | | |
391 | | |
392 | | namespace |
393 | | { |
394 | | bool lcl_isAliasNamePresent( const OSQLParseNode& _rTableNameNode ) |
395 | 0 | { |
396 | 0 | return !OSQLParseNode::getTableRange(_rTableNameNode.getParent()).isEmpty(); |
397 | 0 | } |
398 | | } |
399 | | |
400 | | |
401 | | void OSQLParseNode::impl_parseNodeToString_throw(OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple) const |
402 | 0 | { |
403 | 0 | if ( isToken() ) |
404 | 0 | { |
405 | 0 | parseLeaf(rString,rParam); |
406 | 0 | return; |
407 | 0 | } |
408 | | |
409 | | // Let's see how many nodes this subtree has |
410 | 0 | sal_uInt32 nCount = count(); |
411 | |
|
412 | 0 | bool bHandled = false; |
413 | 0 | switch ( getKnownRuleID() ) |
414 | 0 | { |
415 | | // special handling for parameters |
416 | 0 | case parameter: |
417 | 0 | { |
418 | 0 | bSimple=false; |
419 | 0 | if(!rString.isEmpty()) |
420 | 0 | rString.append(" "); |
421 | 0 | if (nCount == 1) // ? |
422 | 0 | m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false ); |
423 | 0 | else if (rParam.bParseToSDBCLevel && rParam.aMetaData.shouldSubstituteParameterNames()) |
424 | 0 | { |
425 | 0 | rString.append("?"); |
426 | 0 | } |
427 | 0 | else if (nCount == 2) // :Name |
428 | 0 | { |
429 | 0 | m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false ); |
430 | 0 | rString.append(m_aChildren[1]->m_aNodeValue); |
431 | 0 | } // [Name] |
432 | 0 | else |
433 | 0 | { |
434 | 0 | assert (nCount == 3); |
435 | 0 | m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false ); |
436 | 0 | rString.append(m_aChildren[1]->m_aNodeValue); |
437 | 0 | rString.append(m_aChildren[2]->m_aNodeValue); |
438 | 0 | } |
439 | 0 | bHandled = true; |
440 | 0 | } |
441 | 0 | break; |
442 | | |
443 | | // table refs |
444 | 0 | case table_ref: |
445 | 0 | bSimple=false; |
446 | 0 | if ( ( nCount == 2 ) || ( nCount == 3 ) || ( nCount == 5 ) ) |
447 | 0 | { |
448 | 0 | impl_parseTableRangeNodeToString_throw( rString, rParam ); |
449 | 0 | bHandled = true; |
450 | 0 | } |
451 | 0 | break; |
452 | | |
453 | | // table name - might be a query name |
454 | 0 | case table_name: |
455 | 0 | bSimple=false; |
456 | 0 | bHandled = impl_parseTableNameNodeToString_throw( rString, rParam ); |
457 | 0 | break; |
458 | | |
459 | 0 | case as_clause: |
460 | 0 | bSimple=false; |
461 | 0 | assert(nCount == 0 || nCount == 2); |
462 | 0 | if (nCount == 2) |
463 | 0 | { |
464 | 0 | if ( rParam.aMetaData.generateASBeforeCorrelationName() ) |
465 | 0 | rString.append(" AS "); |
466 | 0 | m_aChildren[1]->impl_parseNodeToString_throw( rString, rParam, false ); |
467 | 0 | } |
468 | 0 | bHandled = true; |
469 | 0 | break; |
470 | | |
471 | 0 | case opt_as: |
472 | 0 | assert(nCount == 0); |
473 | 0 | bHandled = true; |
474 | 0 | break; |
475 | | |
476 | 0 | case like_predicate: |
477 | | // Depending on whether international is given, LIKE is treated differently |
478 | | // international: *, ? are placeholders |
479 | | // else SQL92 conform: %, _ |
480 | 0 | impl_parseLikeNodeToString_throw( rString, rParam, bSimple ); |
481 | 0 | bHandled = true; |
482 | 0 | break; |
483 | | |
484 | 0 | case general_set_fct: |
485 | 0 | case set_fct_spec: |
486 | 0 | case position_exp: |
487 | 0 | case extract_exp: |
488 | 0 | case length_exp: |
489 | 0 | case char_value_fct: |
490 | 0 | bSimple=false; |
491 | 0 | if (!addDateValue(rString, rParam)) |
492 | 0 | { |
493 | | // Do not quote function name |
494 | 0 | SQLParseNodeParameter aNewParam(rParam); |
495 | 0 | aNewParam.bQuote = ( SQL_ISRULE(this,length_exp) || SQL_ISRULE(this,char_value_fct) ); |
496 | |
|
497 | 0 | m_aChildren[0]->impl_parseNodeToString_throw( rString, aNewParam, false ); |
498 | 0 | aNewParam.bQuote = rParam.bQuote; |
499 | | //aNewParam.bPredicate = sal_False; // disable [ ] around names // look at i73215 |
500 | 0 | OUStringBuffer aStringPara; |
501 | 0 | for (sal_uInt32 i=1; i<nCount; i++) |
502 | 0 | { |
503 | 0 | const OSQLParseNode * pSubTree = m_aChildren[i].get(); |
504 | 0 | if (pSubTree) |
505 | 0 | { |
506 | 0 | pSubTree->impl_parseNodeToString_throw( aStringPara, aNewParam, false ); |
507 | | |
508 | | // In the comma lists, put commas in-between all subtrees |
509 | 0 | if ((m_eNodeType == SQLNodeType::CommaListRule) && (i < (nCount - 1))) |
510 | 0 | aStringPara.append(","); |
511 | 0 | } |
512 | 0 | else |
513 | 0 | i++; |
514 | 0 | } |
515 | 0 | rString.append(aStringPara); |
516 | 0 | } |
517 | 0 | bHandled = true; |
518 | 0 | break; |
519 | | |
520 | 0 | case factor: |
521 | 0 | bSimple = false; |
522 | 0 | if (nCount == 2 && m_aChildren[0] && m_aChildren[1] |
523 | 0 | && (SQL_ISPUNCTUATION(m_aChildren[0], "-") || SQL_ISPUNCTUATION(m_aChildren[0], "+")) |
524 | 0 | && (m_aChildren[1]->getNodeType() == SQLNodeType::IntNum |
525 | 0 | || m_aChildren[1]->getNodeType() == SQLNodeType::ApproxNum)) |
526 | 0 | { |
527 | | // A signed number ("+" or "-" plus either IntNum or ApproxNum) |
528 | | // The default processing would first add the sign, then process the number, which |
529 | | // would see that rString is not empty already, and insert a space between the sign |
530 | | // and the digits. Avoid that unneeded space. |
531 | 0 | OUStringBuffer aFactorPara; |
532 | 0 | m_aChildren[1]->impl_parseNodeToString_throw(aFactorPara, rParam, bSimple); |
533 | | // Insert a space before the signed number, similar to parseLeaf for IntNum / ApproxNum |
534 | 0 | if (!rString.isEmpty()) |
535 | 0 | rString.append(" "); |
536 | 0 | rString.append(m_aChildren[0]->getTokenValue() + aFactorPara); |
537 | 0 | bHandled = true; |
538 | 0 | } |
539 | 0 | break; |
540 | | |
541 | 0 | case odbc_call_spec: |
542 | 0 | case subquery: |
543 | 0 | case term: |
544 | 0 | case window_function: |
545 | 0 | case cast_spec: |
546 | 0 | case num_value_exp: |
547 | 0 | bSimple = false; |
548 | 0 | break; |
549 | 0 | default: |
550 | 0 | break; |
551 | 0 | } // switch ( getKnownRuleID() ) |
552 | | |
553 | 0 | if ( bHandled ) |
554 | 0 | return; |
555 | | |
556 | 0 | for (auto i = m_aChildren.begin(); i != m_aChildren.end();) |
557 | 0 | { |
558 | 0 | const OSQLParseNode* pSubTree = i->get(); |
559 | 0 | if ( !pSubTree ) |
560 | 0 | { |
561 | 0 | ++i; |
562 | 0 | continue; |
563 | 0 | } |
564 | | |
565 | 0 | SQLParseNodeParameter aNewParam(rParam); |
566 | | |
567 | | // don't replace the field for subqueries |
568 | 0 | if (rParam.xField.is() && SQL_ISRULE(pSubTree,subquery)) |
569 | 0 | aNewParam.xField = nullptr; |
570 | | |
571 | | // When we are building a criterion inside a query view, |
572 | | // simplify criterion display by removing: |
573 | | // "currentFieldName" |
574 | | // "currentFieldName" = |
575 | | // but only in simple expressions. |
576 | | // This means anything that is made of: |
577 | | // (see the rules conditionalised by inPredicateCheck() in sqlbison.y). |
578 | | // - parentheses |
579 | | // - logical operators (and, or, not) |
580 | | // - comparison operators (IS, =, >, <, BETWEEN, LIKE, ...) |
581 | | // but *not* e.g. in function arguments |
582 | 0 | if (bSimple && rParam.bPredicate && rParam.xField.is() && SQL_ISRULE(pSubTree,column_ref)) |
583 | 0 | { |
584 | 0 | if (columnMatchP(pSubTree, rParam)) |
585 | 0 | { |
586 | | // skip field |
587 | 0 | ++i; |
588 | | // if the following node is the comparison operator'=', |
589 | | // we filter it as well |
590 | 0 | if (SQL_ISRULE(this, comparison_predicate)) |
591 | 0 | { |
592 | 0 | if(i != m_aChildren.end()) |
593 | 0 | { |
594 | 0 | pSubTree = i->get(); |
595 | 0 | if (pSubTree && pSubTree->getNodeType() == SQLNodeType::Equal) |
596 | 0 | ++i; |
597 | 0 | } |
598 | 0 | } |
599 | 0 | } |
600 | 0 | else |
601 | 0 | { |
602 | 0 | pSubTree->impl_parseNodeToString_throw( rString, aNewParam, bSimple ); |
603 | 0 | ++i; |
604 | | |
605 | | // In the comma lists, put commas in-between all subtrees |
606 | 0 | if ((m_eNodeType == SQLNodeType::CommaListRule) && (i != m_aChildren.end())) |
607 | 0 | rString.append(","); |
608 | 0 | } |
609 | 0 | } |
610 | 0 | else |
611 | 0 | { |
612 | 0 | pSubTree->impl_parseNodeToString_throw( rString, aNewParam, bSimple ); |
613 | 0 | ++i; |
614 | | |
615 | | // In the comma lists, put commas in-between all subtrees |
616 | 0 | if ((m_eNodeType == SQLNodeType::CommaListRule) && (i != m_aChildren.end())) |
617 | 0 | { |
618 | 0 | if (SQL_ISRULE(this,value_exp_commalist) && rParam.bPredicate) |
619 | 0 | rString.append(";"); |
620 | 0 | else |
621 | 0 | rString.append(","); |
622 | 0 | } |
623 | 0 | } |
624 | | // The right hand-side of these operators is not simple |
625 | 0 | switch ( getKnownRuleID() ) |
626 | 0 | { |
627 | 0 | case general_set_fct: |
628 | 0 | case set_fct_spec: |
629 | 0 | case position_exp: |
630 | 0 | case extract_exp: |
631 | 0 | case length_exp: |
632 | 0 | case char_value_fct: |
633 | 0 | case odbc_call_spec: |
634 | 0 | case subquery: |
635 | 0 | case comparison_predicate: |
636 | 0 | case between_predicate: |
637 | 0 | case like_predicate: |
638 | 0 | case test_for_null: |
639 | 0 | case in_predicate: |
640 | 0 | case existence_test: |
641 | 0 | case unique_test: |
642 | 0 | case all_or_any_predicate: |
643 | 0 | case join_condition: |
644 | 0 | case comparison_predicate_part_2: |
645 | 0 | case parenthesized_boolean_value_expression: |
646 | 0 | case other_like_predicate_part_2: |
647 | 0 | case between_predicate_part_2: |
648 | 0 | bSimple=false; |
649 | 0 | break; |
650 | 0 | default: |
651 | 0 | break; |
652 | 0 | } |
653 | 0 | } |
654 | 0 | } |
655 | | |
656 | | |
657 | | bool OSQLParseNode::impl_parseTableNameNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const |
658 | 0 | { |
659 | | // is the table_name part of a table_ref? |
660 | 0 | OSL_ENSURE( getParent(), "OSQLParseNode::impl_parseTableNameNodeToString_throw: table_name without parent?" ); |
661 | 0 | if ( !getParent() || ( getParent()->getKnownRuleID() != table_ref ) ) |
662 | 0 | return false; |
663 | | |
664 | | // if it's a query, maybe we need to substitute the SQL statement ... |
665 | 0 | if ( !rParam.bParseToSDBCLevel ) |
666 | 0 | return false; |
667 | | |
668 | 0 | if ( !rParam.xQueries.is() ) |
669 | | // connection does not support queries in queries, or was no query supplier |
670 | 0 | return false; |
671 | | |
672 | 0 | try |
673 | 0 | { |
674 | 0 | OUString sTableOrQueryName( getChild(0)->getTokenValue() ); |
675 | 0 | bool bIsQuery = rParam.xQueries->hasByName( sTableOrQueryName ); |
676 | 0 | if ( !bIsQuery ) |
677 | 0 | return false; |
678 | | |
679 | | // avoid recursion (e.g. "foo" defined as "SELECT * FROM bar" and "bar" defined as "SELECT * FROM foo". |
680 | 0 | if ( rParam.pSubQueryHistory->find( sTableOrQueryName ) != rParam.pSubQueryHistory->end() ) |
681 | 0 | { |
682 | 0 | OSL_ENSURE( rParam.pParser, "OSQLParseNode::impl_parseTableNameNodeToString_throw: no parser?" ); |
683 | 0 | if ( rParam.pParser ) |
684 | 0 | { |
685 | 0 | const SQLError& rErrors( rParam.pParser->getErrorHelper() ); |
686 | 0 | rErrors.raiseException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES ); |
687 | 0 | } |
688 | 0 | else |
689 | 0 | { |
690 | 0 | SQLError aErrors; |
691 | 0 | aErrors.raiseException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES ); |
692 | 0 | } |
693 | 0 | } |
694 | 0 | rParam.pSubQueryHistory->insert( sTableOrQueryName ); |
695 | |
|
696 | 0 | Reference< XPropertySet > xQuery( rParam.xQueries->getByName( sTableOrQueryName ), UNO_QUERY_THROW ); |
697 | | |
698 | | // substitute the query name with the constituting command |
699 | 0 | OUString sCommand; |
700 | 0 | OSL_VERIFY( xQuery->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sCommand ); |
701 | |
|
702 | 0 | bool bEscapeProcessing = false; |
703 | 0 | OSL_VERIFY( xQuery->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing ); |
704 | | |
705 | | // the query we found here might itself be based on another query, so parse it recursively |
706 | 0 | OSL_ENSURE( rParam.pParser, "OSQLParseNode::impl_parseTableNameNodeToString_throw: cannot analyze sub queries without a parser!" ); |
707 | 0 | if ( bEscapeProcessing && rParam.pParser ) |
708 | 0 | { |
709 | 0 | OUString sError; |
710 | 0 | std::unique_ptr< OSQLParseNode > pSubQueryNode( rParam.pParser->parseTree( sError, sCommand ) ); |
711 | 0 | if (pSubQueryNode) |
712 | 0 | { |
713 | | // parse the sub-select to SDBC level, too |
714 | 0 | OUStringBuffer sSubSelect; |
715 | 0 | pSubQueryNode->impl_parseNodeToString_throw( sSubSelect, rParam, false ); |
716 | 0 | if ( !sSubSelect.isEmpty() ) |
717 | 0 | sCommand = sSubSelect.makeStringAndClear(); |
718 | 0 | } |
719 | 0 | } |
720 | |
|
721 | 0 | rString.append( " ( " ); |
722 | 0 | rString.append(sCommand); |
723 | 0 | rString.append( " )" ); |
724 | | |
725 | | // append the query name as table alias, since it might be referenced in other |
726 | | // parts of the statement - but only if there's no other alias name present |
727 | 0 | if ( !lcl_isAliasNamePresent( *this ) ) |
728 | 0 | { |
729 | 0 | rString.append( " AS " ); |
730 | 0 | if ( rParam.bQuote ) |
731 | 0 | rString.append(SetQuotation( sTableOrQueryName, |
732 | 0 | rParam.aMetaData.getIdentifierQuoteString(), rParam.aMetaData.getIdentifierQuoteString() )); |
733 | 0 | } |
734 | | |
735 | | // don't forget to remove the query name from the history, else multiple inclusions |
736 | | // won't work |
737 | | // #i69227# / 2006-10-10 / frank.schoenheit@sun.com |
738 | 0 | rParam.pSubQueryHistory->erase( sTableOrQueryName ); |
739 | |
|
740 | 0 | return true; |
741 | 0 | } |
742 | 0 | catch( const SQLException& ) |
743 | 0 | { |
744 | 0 | throw; |
745 | 0 | } |
746 | 0 | catch( const Exception& ) |
747 | 0 | { |
748 | 0 | DBG_UNHANDLED_EXCEPTION("connectivity.parse"); |
749 | 0 | } |
750 | 0 | return false; |
751 | 0 | } |
752 | | |
753 | | |
754 | | void OSQLParseNode::impl_parseTableRangeNodeToString_throw(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const |
755 | 0 | { |
756 | 0 | OSL_PRECOND( ( count() == 2 ) || ( count() == 3 ) || ( count() == 5 ) ,"Illegal count"); |
757 | | |
758 | | // rString += " "; |
759 | 0 | std::for_each(m_aChildren.begin(),m_aChildren.end(), |
760 | 0 | [&] (std::unique_ptr<OSQLParseNode> const & pNode) { pNode->impl_parseNodeToString_throw(rString, rParam, false); }); |
761 | 0 | } |
762 | | |
763 | | |
764 | | void OSQLParseNode::impl_parseLikeNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple ) const |
765 | 0 | { |
766 | 0 | assert(SQL_ISRULE(this,like_predicate)); |
767 | 0 | OSL_ENSURE(count() == 2,"count != 2: Prepare for GPF"); |
768 | |
|
769 | 0 | const OSQLParseNode* pEscNode = nullptr; |
770 | 0 | const OSQLParseNode* pParaNode = nullptr; |
771 | |
|
772 | 0 | const SQLParseNodeParameter& aNewParam(rParam); |
773 | | //aNewParam.bQuote = sal_True; // why setting this to true? @see https://bz.apache.org/ooo/show_bug.cgi?id=75557 |
774 | |
|
775 | 0 | if ( !(bSimple && rParam.bPredicate && rParam.xField.is() && SQL_ISRULE(m_aChildren[0],column_ref) && columnMatchP(m_aChildren[0].get(), rParam)) ) |
776 | 0 | m_aChildren[0]->impl_parseNodeToString_throw( rString, aNewParam, bSimple ); |
777 | |
|
778 | 0 | const OSQLParseNode* pPart2 = m_aChildren[1].get(); |
779 | 0 | pPart2->getChild(0)->impl_parseNodeToString_throw( rString, aNewParam, false ); |
780 | 0 | pPart2->getChild(1)->impl_parseNodeToString_throw( rString, aNewParam, false ); |
781 | 0 | pParaNode = pPart2->getChild(2); |
782 | 0 | pEscNode = pPart2->getChild(3); |
783 | |
|
784 | 0 | if (pParaNode->isToken()) |
785 | 0 | { |
786 | 0 | OUString aStr = ConvertLikeToken(pParaNode, pEscNode, rParam.bInternational); |
787 | 0 | rString.append(" "); |
788 | 0 | rString.append(SetQuotation(aStr, u"\'", u"\'\'")); |
789 | 0 | } |
790 | 0 | else |
791 | 0 | pParaNode->impl_parseNodeToString_throw( rString, aNewParam, false ); |
792 | |
|
793 | 0 | pEscNode->impl_parseNodeToString_throw( rString, aNewParam, false ); |
794 | 0 | } |
795 | | |
796 | | |
797 | | bool OSQLParseNode::getTableComponents(const OSQLParseNode* _pTableNode, |
798 | | css::uno::Any &_rCatalog, |
799 | | OUString &_rSchema, |
800 | | OUString &_rTable, |
801 | | const Reference< XDatabaseMetaData >& _xMetaData) |
802 | 0 | { |
803 | 0 | OSL_ENSURE(_pTableNode,"Wrong use of getTableComponents! _pTableNode is not allowed to be null!"); |
804 | 0 | if(_pTableNode) |
805 | 0 | { |
806 | 0 | const bool bSupportsCatalog = _xMetaData.is() && _xMetaData->supportsCatalogsInDataManipulation(); |
807 | 0 | const bool bSupportsSchema = _xMetaData.is() && _xMetaData->supportsSchemasInDataManipulation(); |
808 | 0 | const OSQLParseNode* pTableNode = _pTableNode; |
809 | | // clear the parameter given |
810 | 0 | _rCatalog = Any(); |
811 | 0 | _rSchema.clear(); |
812 | 0 | _rTable.clear(); |
813 | | // see rule catalog_name: in sqlbison.y |
814 | 0 | if (SQL_ISRULE(pTableNode,catalog_name)) |
815 | 0 | { |
816 | 0 | OSL_ENSURE(pTableNode->getChild(0) && pTableNode->getChild(0)->isToken(),"Invalid parsenode!"); |
817 | 0 | _rCatalog <<= pTableNode->getChild(0)->getTokenValue(); |
818 | 0 | pTableNode = pTableNode->getChild(2); |
819 | 0 | } |
820 | | // check if we have schema_name rule |
821 | 0 | if(SQL_ISRULE(pTableNode,schema_name)) |
822 | 0 | { |
823 | 0 | if ( bSupportsCatalog && !bSupportsSchema ) |
824 | 0 | _rCatalog <<= pTableNode->getChild(0)->getTokenValue(); |
825 | 0 | else |
826 | 0 | _rSchema = pTableNode->getChild(0)->getTokenValue(); |
827 | 0 | pTableNode = pTableNode->getChild(2); |
828 | 0 | } |
829 | | // check if we have table_name rule |
830 | 0 | if(SQL_ISRULE(pTableNode,table_name)) |
831 | 0 | { |
832 | 0 | _rTable = pTableNode->getChild(0)->getTokenValue(); |
833 | 0 | } |
834 | 0 | else |
835 | 0 | { |
836 | 0 | SAL_WARN( "connectivity.parse","Error in parse tree!"); |
837 | 0 | } |
838 | 0 | } |
839 | 0 | return !_rTable.isEmpty(); |
840 | 0 | } |
841 | | |
842 | | void OSQLParser::killThousandSeparator(OSQLParseNode* pLiteral) |
843 | 0 | { |
844 | 0 | if ( pLiteral ) |
845 | 0 | { |
846 | 0 | auto& s_xLocaleData = getLocaleData(); |
847 | 0 | if ( s_xLocaleData.get()->get()->getLocaleItem( m_pData->aLocale ).decimalSeparator.toChar() == ',' ) |
848 | 0 | { |
849 | 0 | pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace('.', sal_Unicode()); |
850 | | // and replace decimal |
851 | 0 | pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace(',', '.'); |
852 | 0 | } |
853 | 0 | else |
854 | 0 | pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace(',', sal_Unicode()); |
855 | 0 | } |
856 | 0 | } |
857 | | |
858 | | OSQLParseNode* OSQLParser::convertNode(sal_Int32 nType, OSQLParseNode* pLiteral) |
859 | 0 | { |
860 | 0 | if ( !pLiteral ) |
861 | 0 | return nullptr; |
862 | | |
863 | 0 | OSQLParseNode* pReturn = pLiteral; |
864 | |
|
865 | 0 | if ( ( pLiteral->isRule() && !SQL_ISRULE(pLiteral,value_exp) ) || SQL_ISTOKEN(pLiteral,FALSE) || SQL_ISTOKEN(pLiteral,TRUE) ) |
866 | 0 | { |
867 | 0 | switch(nType) |
868 | 0 | { |
869 | 0 | case DataType::CHAR: |
870 | 0 | case DataType::VARCHAR: |
871 | 0 | case DataType::LONGVARCHAR: |
872 | 0 | case DataType::CLOB: |
873 | 0 | if ( !SQL_ISRULE(pReturn,char_value_exp) && !buildStringNodes(pReturn) ) |
874 | 0 | pReturn = nullptr; |
875 | 0 | break; |
876 | 0 | default: |
877 | 0 | break; |
878 | 0 | } |
879 | 0 | } |
880 | 0 | else |
881 | 0 | { |
882 | 0 | switch(pLiteral->getNodeType()) |
883 | 0 | { |
884 | 0 | case SQLNodeType::String: |
885 | 0 | switch(nType) |
886 | 0 | { |
887 | 0 | case DataType::CHAR: |
888 | 0 | case DataType::VARCHAR: |
889 | 0 | case DataType::LONGVARCHAR: |
890 | 0 | case DataType::CLOB: |
891 | 0 | break; |
892 | 0 | case DataType::DATE: |
893 | 0 | case DataType::TIME: |
894 | 0 | case DataType::TIMESTAMP: |
895 | 0 | if (m_xFormatter.is()) |
896 | 0 | pReturn = buildDate( nType, pReturn); |
897 | 0 | break; |
898 | 0 | default: |
899 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidCompare); |
900 | 0 | break; |
901 | 0 | } |
902 | 0 | break; |
903 | 0 | case SQLNodeType::AccessDate: |
904 | 0 | switch(nType) |
905 | 0 | { |
906 | 0 | case DataType::DATE: |
907 | 0 | case DataType::TIME: |
908 | 0 | case DataType::TIMESTAMP: |
909 | 0 | if ( m_xFormatter.is() ) |
910 | 0 | pReturn = buildDate( nType, pReturn); |
911 | 0 | else |
912 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidDateCompare); |
913 | 0 | break; |
914 | 0 | default: |
915 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidCompare); |
916 | 0 | break; |
917 | 0 | } |
918 | 0 | break; |
919 | 0 | case SQLNodeType::IntNum: |
920 | 0 | switch(nType) |
921 | 0 | { |
922 | 0 | case DataType::BIT: |
923 | 0 | case DataType::BOOLEAN: |
924 | 0 | case DataType::DECIMAL: |
925 | 0 | case DataType::NUMERIC: |
926 | 0 | case DataType::TINYINT: |
927 | 0 | case DataType::SMALLINT: |
928 | 0 | case DataType::INTEGER: |
929 | 0 | case DataType::BIGINT: |
930 | 0 | case DataType::FLOAT: |
931 | 0 | case DataType::REAL: |
932 | 0 | case DataType::DOUBLE: |
933 | | // kill thousand separators if any |
934 | 0 | killThousandSeparator(pReturn); |
935 | 0 | break; |
936 | 0 | case DataType::CHAR: |
937 | 0 | case DataType::VARCHAR: |
938 | 0 | case DataType::LONGVARCHAR: |
939 | 0 | case DataType::CLOB: |
940 | 0 | pReturn = buildNode_STR_NUM(pReturn); |
941 | 0 | break; |
942 | 0 | default: |
943 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidIntCompare); |
944 | 0 | break; |
945 | 0 | } |
946 | 0 | break; |
947 | 0 | case SQLNodeType::ApproxNum: |
948 | 0 | switch(nType) |
949 | 0 | { |
950 | 0 | case DataType::DECIMAL: |
951 | 0 | case DataType::NUMERIC: |
952 | 0 | case DataType::FLOAT: |
953 | 0 | case DataType::REAL: |
954 | 0 | case DataType::DOUBLE: |
955 | | // kill thousand separators if any |
956 | 0 | killThousandSeparator(pReturn); |
957 | 0 | break; |
958 | 0 | case DataType::CHAR: |
959 | 0 | case DataType::VARCHAR: |
960 | 0 | case DataType::LONGVARCHAR: |
961 | 0 | case DataType::CLOB: |
962 | 0 | pReturn = buildNode_STR_NUM(pReturn); |
963 | 0 | break; |
964 | 0 | case DataType::INTEGER: |
965 | 0 | default: |
966 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidRealCompare); |
967 | 0 | break; |
968 | 0 | } |
969 | 0 | break; |
970 | 0 | default: |
971 | 0 | ; |
972 | 0 | } |
973 | 0 | } |
974 | 0 | return pReturn; |
975 | 0 | } |
976 | | |
977 | | sal_Int16 OSQLParser::buildPredicateRule(OSQLParseNode*& pAppend, OSQLParseNode* pLiteral, OSQLParseNode* pCompare, OSQLParseNode* pLiteral2) |
978 | 0 | { |
979 | 0 | OSL_ENSURE(inPredicateCheck(),"Only in predicate check allowed!"); |
980 | 0 | sal_Int16 nErg = 0; |
981 | 0 | if ( m_xField.is() ) |
982 | 0 | { |
983 | 0 | sal_Int32 nType = 0; |
984 | 0 | try |
985 | 0 | { |
986 | 0 | m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; |
987 | 0 | } |
988 | 0 | catch( Exception& ) |
989 | 0 | { |
990 | 0 | return nErg; |
991 | 0 | } |
992 | | |
993 | 0 | OSQLParseNode* pNode1 = convertNode(nType,pLiteral); |
994 | 0 | if ( pNode1 ) |
995 | 0 | { |
996 | 0 | OSQLParseNode* pNode2 = convertNode(nType,pLiteral2); |
997 | 0 | if ( m_sErrorMessage.isEmpty() ) |
998 | 0 | nErg = buildNode(pAppend,pCompare,pNode1,pNode2); |
999 | 0 | } |
1000 | 0 | } |
1001 | 0 | if (!pCompare->getParent()) // I have no parent so I was not used and I must die :-) |
1002 | 0 | delete pCompare; |
1003 | 0 | return nErg; |
1004 | 0 | } |
1005 | | |
1006 | | sal_Int16 OSQLParser::buildLikeRule(OSQLParseNode* pAppend, OSQLParseNode*& pLiteral, const OSQLParseNode* pEscape) |
1007 | 0 | { |
1008 | 0 | sal_Int16 nErg = 0; |
1009 | 0 | sal_Int32 nType = 0; |
1010 | |
|
1011 | 0 | if (!m_xField.is()) |
1012 | 0 | return nErg; |
1013 | 0 | try |
1014 | 0 | { |
1015 | 0 | Any aValue; |
1016 | 0 | { |
1017 | 0 | aValue = m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)); |
1018 | 0 | aValue >>= nType; |
1019 | 0 | } |
1020 | 0 | } |
1021 | 0 | catch( Exception& ) |
1022 | 0 | { |
1023 | 0 | return nErg; |
1024 | 0 | } |
1025 | | |
1026 | 0 | switch (nType) |
1027 | 0 | { |
1028 | 0 | case DataType::CHAR: |
1029 | 0 | case DataType::VARCHAR: |
1030 | 0 | case DataType::LONGVARCHAR: |
1031 | 0 | case DataType::CLOB: |
1032 | 0 | if(pLiteral->isRule()) |
1033 | 0 | { |
1034 | 0 | pAppend->append(pLiteral); |
1035 | 0 | nErg = 1; |
1036 | 0 | } |
1037 | 0 | else |
1038 | 0 | { |
1039 | 0 | switch(pLiteral->getNodeType()) |
1040 | 0 | { |
1041 | 0 | case SQLNodeType::String: |
1042 | 0 | pLiteral->m_aNodeValue = ConvertLikeToken(pLiteral, pEscape, false); |
1043 | 0 | pAppend->append(pLiteral); |
1044 | 0 | nErg = 1; |
1045 | 0 | break; |
1046 | 0 | case SQLNodeType::ApproxNum: |
1047 | 0 | if (m_xFormatter.is() && m_nFormatKey) |
1048 | 0 | { |
1049 | 0 | sal_Int16 nScale = 0; |
1050 | 0 | try |
1051 | 0 | { |
1052 | 0 | Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, u"Decimals"_ustr ); |
1053 | 0 | aValue >>= nScale; |
1054 | 0 | } |
1055 | 0 | catch( Exception& ) |
1056 | 0 | { |
1057 | 0 | } |
1058 | |
|
1059 | 0 | pAppend->append(new OSQLInternalNode(stringToDouble(pLiteral->getTokenValue(),nScale),SQLNodeType::String)); |
1060 | 0 | } |
1061 | 0 | else |
1062 | 0 | pAppend->append(new OSQLInternalNode(pLiteral->getTokenValue(),SQLNodeType::String)); |
1063 | |
|
1064 | 0 | delete pLiteral; |
1065 | 0 | nErg = 1; |
1066 | 0 | break; |
1067 | 0 | default: |
1068 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::ValueNoLike); |
1069 | 0 | m_sErrorMessage = m_sErrorMessage.replaceAt(m_sErrorMessage.indexOf("#1"),2,pLiteral->getTokenValue()); |
1070 | 0 | break; |
1071 | 0 | } |
1072 | 0 | } |
1073 | 0 | break; |
1074 | 0 | default: |
1075 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::FieldNoLike); |
1076 | 0 | break; |
1077 | 0 | } |
1078 | 0 | return nErg; |
1079 | 0 | } |
1080 | | |
1081 | | OSQLParseNode* OSQLParser::buildNode_Date(const double& fValue, sal_Int32 nType) |
1082 | 0 | { |
1083 | 0 | OSQLParseNode* pNewNode = new OSQLInternalNode("", SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::set_fct_spec)); |
1084 | 0 | pNewNode->append(new OSQLInternalNode("{", SQLNodeType::Punctuation)); |
1085 | 0 | OSQLParseNode* pDateNode = new OSQLInternalNode("", SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::odbc_fct_spec)); |
1086 | 0 | pNewNode->append(pDateNode); |
1087 | 0 | pNewNode->append(new OSQLInternalNode("}", SQLNodeType::Punctuation)); |
1088 | |
|
1089 | 0 | switch (nType) |
1090 | 0 | { |
1091 | 0 | case DataType::DATE: |
1092 | 0 | { |
1093 | 0 | Date aDate = DBTypeConversion::toDate(fValue,DBTypeConversion::getNULLDate(m_xFormatter->getNumberFormatsSupplier())); |
1094 | 0 | OUString aString = DBTypeConversion::toDateString(aDate); |
1095 | 0 | pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_D)); |
1096 | 0 | pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String)); |
1097 | 0 | break; |
1098 | 0 | } |
1099 | 0 | case DataType::TIME: |
1100 | 0 | { |
1101 | 0 | css::util::Time aTime = DBTypeConversion::toTime(fValue); |
1102 | 0 | std::ignore = DBTypeConversion::roundTimeFraction(aTime, m_aMetaData.getMaxDateTimeLiteralFractionDigits()); |
1103 | 0 | OUString aString = DBTypeConversion::toTimeString(aTime); |
1104 | 0 | pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_T)); |
1105 | 0 | pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String)); |
1106 | 0 | break; |
1107 | 0 | } |
1108 | 0 | case DataType::TIMESTAMP: |
1109 | 0 | { |
1110 | 0 | DateTime aDateTime = DBTypeConversion::toDateTime(fValue,DBTypeConversion::getNULLDate(m_xFormatter->getNumberFormatsSupplier())); |
1111 | 0 | DBTypeConversion::roundDateTimeFraction(aDateTime, m_aMetaData.getMaxDateTimeLiteralFractionDigits()); |
1112 | 0 | if (aDateTime.Seconds || aDateTime.Minutes || aDateTime.Hours) |
1113 | 0 | { |
1114 | 0 | OUString aString = DBTypeConversion::toDateTimeString(aDateTime); |
1115 | 0 | pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_TS)); |
1116 | 0 | pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String)); |
1117 | 0 | } |
1118 | 0 | else |
1119 | 0 | { |
1120 | 0 | Date aDate(aDateTime.Day,aDateTime.Month,aDateTime.Year); |
1121 | 0 | pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_D)); |
1122 | 0 | pDateNode->append(new OSQLInternalNode(DBTypeConversion::toDateString(aDate), SQLNodeType::String)); |
1123 | 0 | } |
1124 | 0 | break; |
1125 | 0 | } |
1126 | 0 | } |
1127 | | |
1128 | 0 | return pNewNode; |
1129 | 0 | } |
1130 | | |
1131 | | OSQLParseNode* OSQLParser::buildNode_STR_NUM(OSQLParseNode*& _pLiteral) |
1132 | 0 | { |
1133 | 0 | OSQLParseNode* pReturn = nullptr; |
1134 | 0 | if ( _pLiteral ) |
1135 | 0 | { |
1136 | 0 | if (m_nFormatKey) |
1137 | 0 | { |
1138 | 0 | sal_Int16 nScale = 0; |
1139 | 0 | try |
1140 | 0 | { |
1141 | 0 | Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, u"Decimals"_ustr ); |
1142 | 0 | aValue >>= nScale; |
1143 | 0 | } |
1144 | 0 | catch( Exception& ) |
1145 | 0 | { |
1146 | 0 | } |
1147 | |
|
1148 | 0 | pReturn = new OSQLInternalNode(stringToDouble(_pLiteral->getTokenValue(),nScale),SQLNodeType::String); |
1149 | 0 | } |
1150 | 0 | else |
1151 | 0 | pReturn = new OSQLInternalNode(_pLiteral->getTokenValue(),SQLNodeType::String); |
1152 | |
|
1153 | 0 | delete _pLiteral; |
1154 | 0 | _pLiteral = nullptr; |
1155 | 0 | } |
1156 | 0 | return pReturn; |
1157 | 0 | } |
1158 | | |
1159 | | OUString OSQLParser::stringToDouble(const OUString& _rValue,sal_Int16 _nScale) |
1160 | 0 | { |
1161 | 0 | OUString aValue; |
1162 | 0 | if(!m_xCharClass.is()) |
1163 | 0 | m_xCharClass = CharacterClassification::create( m_xContext ); |
1164 | 0 | auto& s_xLocaleData = getLocaleData(); |
1165 | 0 | if( s_xLocaleData.get() ) |
1166 | 0 | { |
1167 | 0 | try |
1168 | 0 | { |
1169 | 0 | ParseResult aResult = m_xCharClass->parsePredefinedToken(KParseType::ANY_NUMBER,_rValue,0,m_pData->aLocale,0,OUString(),KParseType::ANY_NUMBER,OUString()); |
1170 | 0 | if((aResult.TokenType & KParseType::IDENTNAME) && aResult.EndPos == _rValue.getLength()) |
1171 | 0 | { |
1172 | 0 | aValue = OUString::number(aResult.Value); |
1173 | 0 | sal_Int32 nPos = aValue.lastIndexOf('.'); |
1174 | 0 | if((nPos+_nScale) < aValue.getLength()) |
1175 | 0 | aValue = aValue.replaceAt(nPos+_nScale,aValue.getLength()-nPos-_nScale, u""); |
1176 | 0 | OUString sDecimalSeparator = s_xLocaleData.get()->get()->getLocaleItem(m_pData->aLocale).decimalSeparator; |
1177 | 0 | aValue = aValue.replaceAt(aValue.lastIndexOf('.'), 1, sDecimalSeparator); |
1178 | 0 | return aValue; |
1179 | 0 | } |
1180 | 0 | } |
1181 | 0 | catch(Exception&) |
1182 | 0 | { |
1183 | 0 | } |
1184 | 0 | } |
1185 | 0 | return aValue; |
1186 | 0 | } |
1187 | | |
1188 | | |
1189 | | std::mutex& OSQLParser::getMutex() |
1190 | 0 | { |
1191 | 0 | static std::mutex aMutex; |
1192 | 0 | return aMutex; |
1193 | 0 | } |
1194 | | |
1195 | | |
1196 | | std::unique_ptr<OSQLParseNode> OSQLParser::predicateTree(OUString& rErrorMessage, const OUString& rStatement, |
1197 | | const Reference< css::util::XNumberFormatter > & xFormatter, |
1198 | | const Reference< XPropertySet > & xField, |
1199 | | bool bUseRealName, |
1200 | | const Reference< css::sdbc::XConnection >& xConnection) |
1201 | 0 | { |
1202 | | // Guard the parsing |
1203 | 0 | std::unique_lock aGuard(getMutex()); |
1204 | | // must be reset |
1205 | 0 | setParser(this); |
1206 | | |
1207 | | |
1208 | | // reset the parser |
1209 | 0 | m_xField = xField; |
1210 | 0 | m_xFormatter = xFormatter; |
1211 | 0 | m_aMetaData = ::dbtools::DatabaseMetaData(xConnection); |
1212 | |
|
1213 | 0 | if (m_xField.is()) |
1214 | 0 | { |
1215 | 0 | sal_Int32 nType=0; |
1216 | 0 | try |
1217 | 0 | { |
1218 | | // get the field name |
1219 | 0 | OUString aString; |
1220 | | |
1221 | | // retrieve the fields name |
1222 | | // #75243# use the RealName of the column if there is any otherwise the name which could be the alias |
1223 | | // of the field |
1224 | 0 | Reference< XPropertySetInfo> xInfo = m_xField->getPropertySetInfo(); |
1225 | 0 | if ( bUseRealName && xInfo->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME))) |
1226 | 0 | m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME)) >>= aString; |
1227 | 0 | else |
1228 | 0 | m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aString; |
1229 | |
|
1230 | 0 | m_sFieldName = aString; |
1231 | | |
1232 | | // get the field format key |
1233 | 0 | if ( xInfo->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY))) |
1234 | 0 | m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) >>= m_nFormatKey; |
1235 | 0 | else |
1236 | 0 | m_nFormatKey = 0; |
1237 | | |
1238 | | // get the field type |
1239 | 0 | m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; |
1240 | 0 | } |
1241 | 0 | catch ( Exception& ) |
1242 | 0 | { |
1243 | 0 | OSL_ASSERT(false); |
1244 | 0 | } |
1245 | |
|
1246 | 0 | if (m_nFormatKey && m_xFormatter.is()) |
1247 | 0 | { |
1248 | 0 | Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_LOCALE) ); |
1249 | 0 | OSL_ENSURE(aValue.getValueType() == cppu::UnoType<css::lang::Locale>::get(), "OSQLParser::PredicateTree : invalid language property !"); |
1250 | |
|
1251 | 0 | if (aValue.getValueType() == cppu::UnoType<css::lang::Locale>::get()) |
1252 | 0 | aValue >>= m_pData->aLocale; |
1253 | 0 | } |
1254 | 0 | else |
1255 | 0 | m_pData->aLocale = m_pContext->getPreferredLocale(); |
1256 | |
|
1257 | 0 | if ( m_xFormatter.is() ) |
1258 | 0 | { |
1259 | 0 | try |
1260 | 0 | { |
1261 | 0 | Reference< css::util::XNumberFormatsSupplier > xFormatSup = m_xFormatter->getNumberFormatsSupplier(); |
1262 | 0 | if ( xFormatSup.is() ) |
1263 | 0 | { |
1264 | 0 | Reference< css::util::XNumberFormats > xFormats = xFormatSup->getNumberFormats(); |
1265 | 0 | if ( xFormats.is() ) |
1266 | 0 | { |
1267 | 0 | css::lang::Locale aLocale; |
1268 | 0 | aLocale.Language = "en"; |
1269 | 0 | aLocale.Country = "US"; |
1270 | 0 | OUString sFormat(u"YYYY-MM-DD"_ustr); |
1271 | 0 | m_nDateFormatKey = xFormats->queryKey(sFormat,aLocale,false); |
1272 | 0 | if ( m_nDateFormatKey == sal_Int32(-1) ) |
1273 | 0 | m_nDateFormatKey = xFormats->addNew(sFormat, aLocale); |
1274 | 0 | } |
1275 | 0 | } |
1276 | 0 | } |
1277 | 0 | catch ( Exception& ) |
1278 | 0 | { |
1279 | 0 | SAL_WARN( "connectivity.parse","DateFormatKey"); |
1280 | 0 | } |
1281 | 0 | } |
1282 | | |
1283 | 0 | switch (nType) |
1284 | 0 | { |
1285 | 0 | case DataType::DATE: |
1286 | 0 | case DataType::TIME: |
1287 | 0 | case DataType::TIMESTAMP: |
1288 | 0 | s_pScanner->SetRule(OSQLScanner::GetDATERule()); |
1289 | 0 | break; |
1290 | 0 | case DataType::CHAR: |
1291 | 0 | case DataType::VARCHAR: |
1292 | 0 | case DataType::LONGVARCHAR: |
1293 | 0 | case DataType::CLOB: |
1294 | 0 | s_pScanner->SetRule(OSQLScanner::GetSTRINGRule()); |
1295 | 0 | break; |
1296 | 0 | default: |
1297 | 0 | { |
1298 | 0 | auto& s_xLocaleData = getLocaleData(); |
1299 | 0 | if ( s_xLocaleData.get()->get()->getLocaleItem( m_pData->aLocale ).decimalSeparator.toChar() == ',' ) |
1300 | 0 | s_pScanner->SetRule(OSQLScanner::GetGERRule()); |
1301 | 0 | else |
1302 | 0 | s_pScanner->SetRule(OSQLScanner::GetENGRule()); |
1303 | 0 | } |
1304 | 0 | } |
1305 | |
|
1306 | 0 | } |
1307 | 0 | else |
1308 | 0 | s_pScanner->SetRule(OSQLScanner::GetSQLRule()); |
1309 | | |
1310 | 0 | s_pScanner->prepareScan(rStatement, m_pContext, true); |
1311 | |
|
1312 | 0 | SQLyylval.pParseNode = nullptr; |
1313 | | // SQLyypvt = NULL; |
1314 | 0 | m_pParseTree = nullptr; |
1315 | 0 | m_sErrorMessage.clear(); |
1316 | | |
1317 | | // Start the parser |
1318 | 0 | if (SQLyyparse() != 0) |
1319 | 0 | { |
1320 | 0 | m_sFieldName.clear(); |
1321 | 0 | m_xField.clear(); |
1322 | 0 | m_xFormatter.clear(); |
1323 | 0 | m_nFormatKey = 0; |
1324 | 0 | m_nDateFormatKey = 0; |
1325 | |
|
1326 | 0 | if (m_sErrorMessage.isEmpty()) |
1327 | 0 | m_sErrorMessage = s_pScanner->getErrorMessage(); |
1328 | 0 | if (m_sErrorMessage.isEmpty()) |
1329 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::General); |
1330 | |
|
1331 | 0 | rErrorMessage = m_sErrorMessage; |
1332 | | |
1333 | | // clear the garbage collector |
1334 | 0 | (*s_pGarbageCollector)->clearAndDelete(); |
1335 | | // coverity[leaked_storage : FALSE] - because the garbage collector deleted it |
1336 | 0 | m_pParseTree.release(); |
1337 | 0 | return nullptr; |
1338 | 0 | } |
1339 | 0 | else |
1340 | 0 | { |
1341 | 0 | (*s_pGarbageCollector)->clear(); |
1342 | |
|
1343 | 0 | m_sFieldName.clear(); |
1344 | 0 | m_xField.clear(); |
1345 | 0 | m_xFormatter.clear(); |
1346 | 0 | m_nFormatKey = 0; |
1347 | 0 | m_nDateFormatKey = 0; |
1348 | | |
1349 | | // Return the result (the root parse node): |
1350 | | |
1351 | | // Instead, the parse method sets the member pParseTree and simply returns that |
1352 | 0 | OSL_ENSURE(m_pParseTree != nullptr,"OSQLParser: Parser did not return a ParseTree!"); |
1353 | 0 | return std::move(m_pParseTree); |
1354 | 0 | } |
1355 | 0 | } |
1356 | | |
1357 | | |
1358 | | OSQLParser::OSQLParser(css::uno::Reference< css::uno::XComponentContext > xContext, |
1359 | | const IParseContext* _pContext, |
1360 | | const IParseContext* _pNeutral) |
1361 | 0 | :m_pContext(_pContext) |
1362 | 0 | ,m_pNeutral(_pNeutral) |
1363 | 0 | ,m_pData( new OSQLParser_Data ) |
1364 | 0 | ,m_nFormatKey(0) |
1365 | 0 | ,m_nDateFormatKey(0) |
1366 | 0 | ,m_xContext(std::move(xContext)) |
1367 | 0 | { |
1368 | | |
1369 | |
|
1370 | 0 | setParser(this); |
1371 | |
|
1372 | | #ifdef SQLYYDEBUG |
1373 | | #ifdef SQLYYDEBUG_ON |
1374 | | SQLyydebug = 1; |
1375 | | #endif |
1376 | | #endif |
1377 | |
|
1378 | 0 | std::unique_lock aGuard(getMutex()); |
1379 | | // Do we have to initialize the data? |
1380 | 0 | if (s_nRefCount == 0) |
1381 | 0 | { |
1382 | 0 | s_pScanner = new OSQLScanner(); |
1383 | 0 | s_pScanner->setScanner(); |
1384 | 0 | s_pGarbageCollector = new OSQLParseNodesGarbageCollector(); |
1385 | |
|
1386 | 0 | auto& s_xLocaleData = getLocaleData(); |
1387 | 0 | if(!s_xLocaleData.get()) |
1388 | 0 | s_xLocaleData.set(LocaleData::create(m_xContext)); |
1389 | | |
1390 | | // reset to UNKNOWN_RULE |
1391 | 0 | static_assert(OSQLParseNode::UNKNOWN_RULE==0, "UNKNOWN_RULE must be 0 for memset to 0 to work"); |
1392 | 0 | memset(OSQLParser::s_nRuleIDs,0,sizeof(OSQLParser::s_nRuleIDs)); |
1393 | |
|
1394 | 0 | const struct |
1395 | 0 | { |
1396 | 0 | OSQLParseNode::Rule eRule; // the parse node's ID for the rule |
1397 | 0 | OString sRuleName; // the name of the rule ("select_statement") |
1398 | 0 | } aRuleDescriptions[] = |
1399 | 0 | { |
1400 | 0 | { OSQLParseNode::select_statement, "select_statement"_ostr }, |
1401 | 0 | { OSQLParseNode::table_exp, "table_exp"_ostr }, |
1402 | 0 | { OSQLParseNode::table_ref_commalist, "table_ref_commalist"_ostr }, |
1403 | 0 | { OSQLParseNode::table_ref, "table_ref"_ostr }, |
1404 | 0 | { OSQLParseNode::catalog_name, "catalog_name"_ostr }, |
1405 | 0 | { OSQLParseNode::schema_name, "schema_name"_ostr }, |
1406 | 0 | { OSQLParseNode::table_name, "table_name"_ostr }, |
1407 | 0 | { OSQLParseNode::opt_column_commalist, "opt_column_commalist"_ostr }, |
1408 | 0 | { OSQLParseNode::column_commalist, "column_commalist"_ostr }, |
1409 | 0 | { OSQLParseNode::column_ref_commalist, "column_ref_commalist"_ostr }, |
1410 | 0 | { OSQLParseNode::column_ref, "column_ref"_ostr }, |
1411 | 0 | { OSQLParseNode::opt_order_by_clause, "opt_order_by_clause"_ostr }, |
1412 | 0 | { OSQLParseNode::ordering_spec_commalist, "ordering_spec_commalist"_ostr }, |
1413 | 0 | { OSQLParseNode::ordering_spec, "ordering_spec"_ostr }, |
1414 | 0 | { OSQLParseNode::opt_asc_desc, "opt_asc_desc"_ostr }, |
1415 | 0 | { OSQLParseNode::where_clause, "where_clause"_ostr }, |
1416 | 0 | { OSQLParseNode::opt_where_clause, "opt_where_clause"_ostr }, |
1417 | 0 | { OSQLParseNode::search_condition, "search_condition"_ostr }, |
1418 | 0 | { OSQLParseNode::comparison, "comparison"_ostr }, |
1419 | 0 | { OSQLParseNode::comparison_predicate, "comparison_predicate"_ostr }, |
1420 | 0 | { OSQLParseNode::between_predicate, "between_predicate"_ostr }, |
1421 | 0 | { OSQLParseNode::like_predicate, "like_predicate"_ostr }, |
1422 | 0 | { OSQLParseNode::opt_escape, "opt_escape"_ostr }, |
1423 | 0 | { OSQLParseNode::test_for_null, "test_for_null"_ostr }, |
1424 | 0 | { OSQLParseNode::scalar_exp_commalist, "scalar_exp_commalist"_ostr }, |
1425 | 0 | { OSQLParseNode::scalar_exp, "scalar_exp"_ostr }, |
1426 | 0 | { OSQLParseNode::parameter_ref, "parameter_ref"_ostr }, |
1427 | 0 | { OSQLParseNode::parameter, "parameter"_ostr }, |
1428 | 0 | { OSQLParseNode::general_set_fct, "general_set_fct"_ostr }, |
1429 | 0 | { OSQLParseNode::range_variable, "range_variable"_ostr }, |
1430 | 0 | { OSQLParseNode::column, "column"_ostr }, |
1431 | 0 | { OSQLParseNode::delete_statement_positioned, "delete_statement_positioned"_ostr }, |
1432 | 0 | { OSQLParseNode::delete_statement_searched, "delete_statement_searched"_ostr }, |
1433 | 0 | { OSQLParseNode::update_statement_positioned, "update_statement_positioned"_ostr }, |
1434 | 0 | { OSQLParseNode::update_statement_searched, "update_statement_searched"_ostr }, |
1435 | 0 | { OSQLParseNode::assignment_commalist, "assignment_commalist"_ostr }, |
1436 | 0 | { OSQLParseNode::assignment, "assignment"_ostr }, |
1437 | 0 | { OSQLParseNode::values_or_query_spec, "values_or_query_spec"_ostr }, |
1438 | 0 | { OSQLParseNode::insert_statement, "insert_statement"_ostr }, |
1439 | 0 | { OSQLParseNode::insert_atom_commalist, "insert_atom_commalist"_ostr }, |
1440 | 0 | { OSQLParseNode::insert_atom, "insert_atom"_ostr }, |
1441 | 0 | { OSQLParseNode::from_clause, "from_clause"_ostr }, |
1442 | 0 | { OSQLParseNode::qualified_join, "qualified_join"_ostr }, |
1443 | 0 | { OSQLParseNode::cross_union, "cross_union"_ostr }, |
1444 | 0 | { OSQLParseNode::select_sublist, "select_sublist"_ostr }, |
1445 | 0 | { OSQLParseNode::derived_column, "derived_column"_ostr }, |
1446 | 0 | { OSQLParseNode::column_val, "column_val"_ostr }, |
1447 | 0 | { OSQLParseNode::set_fct_spec, "set_fct_spec"_ostr }, |
1448 | 0 | { OSQLParseNode::boolean_term, "boolean_term"_ostr }, |
1449 | 0 | { OSQLParseNode::boolean_primary, "boolean_primary"_ostr }, |
1450 | 0 | { OSQLParseNode::num_value_exp, "num_value_exp"_ostr }, |
1451 | 0 | { OSQLParseNode::join_type, "join_type"_ostr }, |
1452 | 0 | { OSQLParseNode::position_exp, "position_exp"_ostr }, |
1453 | 0 | { OSQLParseNode::extract_exp, "extract_exp"_ostr }, |
1454 | 0 | { OSQLParseNode::length_exp, "length_exp"_ostr }, |
1455 | 0 | { OSQLParseNode::char_value_fct, "char_value_fct"_ostr }, |
1456 | 0 | { OSQLParseNode::odbc_call_spec, "odbc_call_spec"_ostr }, |
1457 | 0 | { OSQLParseNode::in_predicate, "in_predicate"_ostr }, |
1458 | 0 | { OSQLParseNode::existence_test, "existence_test"_ostr }, |
1459 | 0 | { OSQLParseNode::unique_test, "unique_test"_ostr }, |
1460 | 0 | { OSQLParseNode::all_or_any_predicate, "all_or_any_predicate"_ostr }, |
1461 | 0 | { OSQLParseNode::named_columns_join, "named_columns_join"_ostr }, |
1462 | 0 | { OSQLParseNode::join_condition, "join_condition"_ostr }, |
1463 | 0 | { OSQLParseNode::joined_table, "joined_table"_ostr }, |
1464 | 0 | { OSQLParseNode::boolean_factor, "boolean_factor"_ostr }, |
1465 | 0 | { OSQLParseNode::sql_not, "sql_not"_ostr }, |
1466 | 0 | { OSQLParseNode::manipulative_statement, "manipulative_statement"_ostr }, |
1467 | 0 | { OSQLParseNode::subquery, "subquery"_ostr }, |
1468 | 0 | { OSQLParseNode::value_exp_commalist, "value_exp_commalist"_ostr }, |
1469 | 0 | { OSQLParseNode::odbc_fct_spec, "odbc_fct_spec"_ostr }, |
1470 | 0 | { OSQLParseNode::union_statement, "union_statement"_ostr }, |
1471 | 0 | { OSQLParseNode::outer_join_type, "outer_join_type"_ostr }, |
1472 | 0 | { OSQLParseNode::char_value_exp, "char_value_exp"_ostr }, |
1473 | 0 | { OSQLParseNode::term, "term"_ostr }, |
1474 | 0 | { OSQLParseNode::value_exp_primary, "value_exp_primary"_ostr }, |
1475 | 0 | { OSQLParseNode::value_exp, "value_exp"_ostr }, |
1476 | 0 | { OSQLParseNode::selection, "selection"_ostr }, |
1477 | 0 | { OSQLParseNode::fold, "fold"_ostr }, |
1478 | 0 | { OSQLParseNode::char_substring_fct, "char_substring_fct"_ostr }, |
1479 | 0 | { OSQLParseNode::factor, "factor"_ostr }, |
1480 | 0 | { OSQLParseNode::base_table_def, "base_table_def"_ostr }, |
1481 | 0 | { OSQLParseNode::base_table_element_commalist, "base_table_element_commalist"_ostr }, |
1482 | 0 | { OSQLParseNode::data_type, "data_type"_ostr }, |
1483 | 0 | { OSQLParseNode::column_def, "column_def"_ostr }, |
1484 | 0 | { OSQLParseNode::table_node, "table_node"_ostr }, |
1485 | 0 | { OSQLParseNode::as_clause, "as_clause"_ostr }, |
1486 | 0 | { OSQLParseNode::opt_as, "opt_as"_ostr }, |
1487 | 0 | { OSQLParseNode::op_column_commalist, "op_column_commalist"_ostr }, |
1488 | 0 | { OSQLParseNode::table_primary_as_range_column, "table_primary_as_range_column"_ostr }, |
1489 | 0 | { OSQLParseNode::datetime_primary, "datetime_primary"_ostr }, |
1490 | 0 | { OSQLParseNode::concatenation, "concatenation"_ostr }, |
1491 | 0 | { OSQLParseNode::char_factor, "char_factor"_ostr }, |
1492 | 0 | { OSQLParseNode::bit_value_fct, "bit_value_fct"_ostr }, |
1493 | 0 | { OSQLParseNode::comparison_predicate_part_2, "comparison_predicate_part_2"_ostr }, |
1494 | 0 | { OSQLParseNode::parenthesized_boolean_value_expression, "parenthesized_boolean_value_expression"_ostr }, |
1495 | 0 | { OSQLParseNode::character_string_type, "character_string_type"_ostr }, |
1496 | 0 | { OSQLParseNode::other_like_predicate_part_2, "other_like_predicate_part_2"_ostr }, |
1497 | 0 | { OSQLParseNode::between_predicate_part_2, "between_predicate_part_2"_ostr }, |
1498 | 0 | { OSQLParseNode::null_predicate_part_2, "null_predicate_part_2"_ostr }, |
1499 | 0 | { OSQLParseNode::cast_spec, "cast_spec"_ostr }, |
1500 | 0 | { OSQLParseNode::window_function, "window_function"_ostr } |
1501 | 0 | }; |
1502 | 0 | const size_t nRuleMapCount = std::size( aRuleDescriptions ); |
1503 | | // added a new rule? Adjust this map! |
1504 | | // +1 for UNKNOWN_RULE |
1505 | 0 | static_assert(nRuleMapCount + 1 == static_cast<size_t>(OSQLParseNode::rule_count), "must be equal"); |
1506 | |
|
1507 | 0 | for (const auto & aRuleDescription : aRuleDescriptions) |
1508 | 0 | { |
1509 | | // look up the rule description in the our identifier map |
1510 | 0 | sal_uInt32 nParserRuleID = StrToRuleID( aRuleDescription.sRuleName ); |
1511 | | // map the parser's rule ID to the OSQLParseNode::Rule |
1512 | 0 | s_aReverseRuleIDLookup[ nParserRuleID ] = aRuleDescription.eRule; |
1513 | | // and map the OSQLParseNode::Rule to the parser's rule ID |
1514 | 0 | s_nRuleIDs[ aRuleDescription.eRule ] = nParserRuleID; |
1515 | 0 | } |
1516 | 0 | } |
1517 | 0 | ++s_nRefCount; |
1518 | |
|
1519 | 0 | if (m_pContext == nullptr) |
1520 | | // take the default context |
1521 | 0 | m_pContext = &s_aDefaultContext; |
1522 | |
|
1523 | 0 | m_pData->aLocale = m_pContext->getPreferredLocale(); |
1524 | 0 | } |
1525 | | |
1526 | | //static |
1527 | | tools::DeleteOnDeinit<css::uno::Reference< css::i18n::XLocaleData4>>& OSQLParser::getLocaleData() |
1528 | 0 | { |
1529 | 0 | static tools::DeleteOnDeinit<css::uno::Reference< css::i18n::XLocaleData4>> s_xLocaleData(tools::DeleteOnDeinitFlag::Empty); |
1530 | 0 | return s_xLocaleData; |
1531 | 0 | } |
1532 | | |
1533 | | OSQLParser::~OSQLParser() |
1534 | 0 | { |
1535 | 0 | std::unique_lock aGuard(getMutex()); |
1536 | 0 | OSL_ENSURE(s_nRefCount > 0, "OSQLParser::~OSQLParser() : suspicious call : has a refcount of 0 !"); |
1537 | 0 | if (!--s_nRefCount) |
1538 | 0 | { |
1539 | 0 | s_pScanner->setScanner(true); |
1540 | 0 | delete s_pScanner; |
1541 | 0 | s_pScanner = nullptr; |
1542 | |
|
1543 | 0 | delete s_pGarbageCollector; |
1544 | 0 | s_pGarbageCollector = nullptr; |
1545 | |
|
1546 | 0 | RuleIDMap().swap(s_aReverseRuleIDLookup); |
1547 | 0 | } |
1548 | 0 | m_pParseTree = nullptr; |
1549 | 0 | } |
1550 | | |
1551 | | void OSQLParseNode::substituteParameterNames(OSQLParseNode const * _pNode) |
1552 | 0 | { |
1553 | 0 | sal_Int32 nCount = _pNode->count(); |
1554 | 0 | for(sal_Int32 i=0;i < nCount;++i) |
1555 | 0 | { |
1556 | 0 | OSQLParseNode* pChildNode = _pNode->getChild(i); |
1557 | 0 | if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() > 1) |
1558 | 0 | { |
1559 | 0 | OSQLParseNode* pNewNode = new OSQLParseNode("?" ,SQLNodeType::Punctuation,0); |
1560 | 0 | pChildNode->replaceAndDelete(pChildNode->getChild(0), pNewNode); |
1561 | 0 | sal_Int32 nChildCount = pChildNode->count(); |
1562 | 0 | for(sal_Int32 j=1;j < nChildCount;++j) |
1563 | 0 | delete pChildNode->removeAt(1); |
1564 | 0 | } |
1565 | 0 | else |
1566 | 0 | substituteParameterNames(pChildNode); |
1567 | |
|
1568 | 0 | } |
1569 | 0 | } |
1570 | | |
1571 | | bool OSQLParser::extractDate(OSQLParseNode const * pLiteral,double& _rfValue) |
1572 | 0 | { |
1573 | 0 | Reference< XNumberFormatsSupplier > xFormatSup = m_xFormatter->getNumberFormatsSupplier(); |
1574 | 0 | Reference< XNumberFormatTypes > xFormatTypes; |
1575 | 0 | if ( xFormatSup.is() ) |
1576 | 0 | xFormatTypes.set(xFormatSup->getNumberFormats(), css::uno::UNO_QUERY); |
1577 | | |
1578 | | // if there is no format key, yet, make sure we have a feasible one for our locale |
1579 | 0 | try |
1580 | 0 | { |
1581 | 0 | if ( !m_nFormatKey && xFormatTypes.is() ) |
1582 | 0 | m_nFormatKey = ::dbtools::getDefaultNumberFormat( m_xField, xFormatTypes, m_pData->aLocale ); |
1583 | 0 | } |
1584 | 0 | catch( Exception& ) { } |
1585 | 0 | const OUString& sValue = pLiteral->getTokenValue(); |
1586 | 0 | sal_Int32 nTryFormat = m_nFormatKey; |
1587 | 0 | bool bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue ); |
1588 | | |
1589 | | // If our format key didn't do, try the default date format for our locale. |
1590 | 0 | if ( !bSuccess && xFormatTypes.is() ) |
1591 | 0 | { |
1592 | 0 | try |
1593 | 0 | { |
1594 | 0 | nTryFormat = xFormatTypes->getStandardFormat( NumberFormat::DATE, m_pData->aLocale ); |
1595 | 0 | } |
1596 | 0 | catch( Exception& ) { } |
1597 | 0 | bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue ); |
1598 | 0 | } |
1599 | | |
1600 | | // if this also didn't do, try ISO format |
1601 | 0 | if ( !bSuccess && xFormatTypes.is() ) |
1602 | 0 | { |
1603 | 0 | try |
1604 | 0 | { |
1605 | 0 | nTryFormat = xFormatTypes->getFormatIndex( NumberFormatIndex::DATE_DIN_YYYYMMDD, m_pData->aLocale ); |
1606 | 0 | } |
1607 | 0 | catch( Exception& ) { } |
1608 | 0 | bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue ); |
1609 | 0 | } |
1610 | | |
1611 | | // if this also didn't do, try fallback date format (en-US) |
1612 | 0 | if ( !bSuccess ) |
1613 | 0 | { |
1614 | 0 | nTryFormat = m_nDateFormatKey; |
1615 | 0 | bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue ); |
1616 | 0 | } |
1617 | 0 | return bSuccess; |
1618 | 0 | } |
1619 | | |
1620 | | OSQLParseNode* OSQLParser::buildDate(sal_Int32 _nType,OSQLParseNode*& pLiteral) |
1621 | 0 | { |
1622 | | // try converting the string into a date, according to our format key |
1623 | 0 | double fValue = 0.0; |
1624 | 0 | OSQLParseNode* pFCTNode = nullptr; |
1625 | |
|
1626 | 0 | if ( extractDate(pLiteral,fValue) ) |
1627 | 0 | pFCTNode = buildNode_Date( fValue, _nType); |
1628 | |
|
1629 | 0 | delete pLiteral; |
1630 | 0 | pLiteral = nullptr; |
1631 | |
|
1632 | 0 | if ( !pFCTNode ) |
1633 | 0 | m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidDateCompare); |
1634 | |
|
1635 | 0 | return pFCTNode; |
1636 | 0 | } |
1637 | | |
1638 | | |
1639 | | OSQLParseNode::OSQLParseNode(const char * pNewValue, |
1640 | | SQLNodeType eNewNodeType, |
1641 | | sal_uInt32 nNewNodeID) |
1642 | 0 | :m_pParent(nullptr) |
1643 | 0 | ,m_aNodeValue(pNewValue,strlen(pNewValue),RTL_TEXTENCODING_UTF8) |
1644 | 0 | ,m_eNodeType(eNewNodeType) |
1645 | 0 | ,m_nNodeID(nNewNodeID) |
1646 | 0 | { |
1647 | 0 | OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType"); |
1648 | 0 | } |
1649 | | |
1650 | | OSQLParseNode::OSQLParseNode(std::string_view _rNewValue, |
1651 | | SQLNodeType eNewNodeType, |
1652 | | sal_uInt32 nNewNodeID) |
1653 | 0 | :m_pParent(nullptr) |
1654 | 0 | ,m_aNodeValue(OStringToOUString(_rNewValue,RTL_TEXTENCODING_UTF8)) |
1655 | 0 | ,m_eNodeType(eNewNodeType) |
1656 | 0 | ,m_nNodeID(nNewNodeID) |
1657 | 0 | { |
1658 | 0 | OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType"); |
1659 | 0 | } |
1660 | | |
1661 | | OSQLParseNode::OSQLParseNode(OUString _aNewValue, |
1662 | | SQLNodeType eNewNodeType, |
1663 | | sal_uInt32 nNewNodeID) |
1664 | 0 | :m_pParent(nullptr) |
1665 | 0 | ,m_aNodeValue(std::move(_aNewValue)) |
1666 | 0 | ,m_eNodeType(eNewNodeType) |
1667 | 0 | ,m_nNodeID(nNewNodeID) |
1668 | 0 | { |
1669 | 0 | OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType"); |
1670 | 0 | } |
1671 | | |
1672 | | OSQLParseNode::OSQLParseNode(const OSQLParseNode& rParseNode) |
1673 | 0 | { |
1674 | | // Set the getParent to NULL |
1675 | 0 | m_pParent = nullptr; |
1676 | | |
1677 | | // Copy the members |
1678 | 0 | m_aNodeValue = rParseNode.m_aNodeValue; |
1679 | 0 | m_eNodeType = rParseNode.m_eNodeType; |
1680 | 0 | m_nNodeID = rParseNode.m_nNodeID; |
1681 | | |
1682 | | |
1683 | | // Remember that we derived from Container. According to SV-Help the Container's |
1684 | | // copy ctor creates a new Container with the same pointers for content. |
1685 | | // This means after copying the Container, for all non-NULL pointers a copy is |
1686 | | // created and reattached instead of the old pointer. |
1687 | | |
1688 | | // If not a leaf, then process SubTrees |
1689 | 0 | for (auto const& child : rParseNode.m_aChildren) |
1690 | 0 | append(new OSQLParseNode(*child)); |
1691 | 0 | } |
1692 | | |
1693 | | |
1694 | | OSQLParseNode& OSQLParseNode::operator=(const OSQLParseNode& rParseNode) |
1695 | 0 | { |
1696 | 0 | if (this != &rParseNode) |
1697 | 0 | { |
1698 | | // Copy the members - pParent remains the same |
1699 | 0 | m_aNodeValue = rParseNode.m_aNodeValue; |
1700 | 0 | m_eNodeType = rParseNode.m_eNodeType; |
1701 | 0 | m_nNodeID = rParseNode.m_nNodeID; |
1702 | |
|
1703 | 0 | m_aChildren.clear(); |
1704 | |
|
1705 | 0 | for (auto const& child : rParseNode.m_aChildren) |
1706 | 0 | append(new OSQLParseNode(*child)); |
1707 | 0 | } |
1708 | 0 | return *this; |
1709 | 0 | } |
1710 | | |
1711 | | |
1712 | | bool OSQLParseNode::operator==(OSQLParseNode const & rParseNode) const |
1713 | 0 | { |
1714 | | // The members must be equal |
1715 | 0 | bool bResult = (m_nNodeID == rParseNode.m_nNodeID) && |
1716 | 0 | (m_eNodeType == rParseNode.m_eNodeType) && |
1717 | 0 | (m_aNodeValue == rParseNode.m_aNodeValue) && |
1718 | 0 | count() == rParseNode.count(); |
1719 | | |
1720 | | // Parameters are not equal! |
1721 | 0 | bResult = bResult && !SQL_ISRULE(this, parameter); |
1722 | | |
1723 | | // compare children |
1724 | 0 | for (size_t i=0; bResult && i < count(); i++) |
1725 | 0 | bResult = *getChild(i) == *rParseNode.getChild(i); |
1726 | |
|
1727 | 0 | return bResult; |
1728 | 0 | } |
1729 | | |
1730 | | |
1731 | | OSQLParseNode::~OSQLParseNode() |
1732 | 0 | { |
1733 | 0 | } |
1734 | | |
1735 | | void OSQLParseNode::append(OSQLParseNode* pNewNode) |
1736 | 0 | { |
1737 | 0 | assert(pNewNode != nullptr && "OSQLParseNode: invalid NewSubTree"); |
1738 | 0 | OSL_ENSURE(pNewNode->getParent() == nullptr, "OSQLParseNode: Node is not an orphan"); |
1739 | 0 | OSL_ENSURE(std::none_of(m_aChildren.begin(), m_aChildren.end(), |
1740 | 0 | [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pNewNode; }), |
1741 | 0 | "OSQLParseNode::append() Node already element of parent"); |
1742 | | |
1743 | | // Create connection to getParent |
1744 | 0 | pNewNode->setParent( this ); |
1745 | | // and attach the SubTree at the end |
1746 | 0 | m_aChildren.emplace_back(pNewNode); |
1747 | 0 | } |
1748 | | |
1749 | | bool OSQLParseNode::addDateValue(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const |
1750 | 0 | { |
1751 | | // special display for date/time values |
1752 | 0 | if (!SQL_ISRULE(this,set_fct_spec) || !SQL_ISPUNCTUATION(m_aChildren[0],"{")) |
1753 | 0 | return false; |
1754 | | |
1755 | 0 | const OSQLParseNode* pODBCNode = m_aChildren[1].get(); |
1756 | 0 | const OSQLParseNode* pODBCNodeChild = pODBCNode->m_aChildren[0].get(); |
1757 | |
|
1758 | 0 | if (pODBCNodeChild->getNodeType() != SQLNodeType::Keyword || !( |
1759 | 0 | SQL_ISTOKEN(pODBCNodeChild, D) || |
1760 | 0 | SQL_ISTOKEN(pODBCNodeChild, T) || |
1761 | 0 | SQL_ISTOKEN(pODBCNodeChild, TS) )) |
1762 | 0 | return false; |
1763 | | |
1764 | 0 | OUString suQuote(u"'"_ustr); |
1765 | 0 | if (rParam.bPredicate) |
1766 | 0 | { |
1767 | 0 | if (rParam.aMetaData.shouldEscapeDateTime()) |
1768 | 0 | { |
1769 | 0 | suQuote = "#"; |
1770 | 0 | } |
1771 | 0 | } |
1772 | 0 | else |
1773 | 0 | { |
1774 | 0 | if (rParam.aMetaData.shouldEscapeDateTime()) |
1775 | 0 | { |
1776 | | // suQuote = "'"; |
1777 | 0 | return false; |
1778 | 0 | } |
1779 | 0 | } |
1780 | | |
1781 | 0 | if (!rString.isEmpty()) |
1782 | 0 | rString.append(" "); |
1783 | 0 | rString.append(suQuote); |
1784 | 0 | const OUString sTokenValue = pODBCNode->m_aChildren[1]->getTokenValue(); |
1785 | 0 | if (SQL_ISTOKEN(pODBCNodeChild, D)) |
1786 | 0 | { |
1787 | 0 | rString.append(rParam.bPredicate ? convertDateString(rParam, sTokenValue) : sTokenValue); |
1788 | 0 | } |
1789 | 0 | else if (SQL_ISTOKEN(pODBCNodeChild, T)) |
1790 | 0 | { |
1791 | 0 | rString.append(rParam.bPredicate ? convertTimeString(rParam, sTokenValue) : sTokenValue); |
1792 | 0 | } |
1793 | 0 | else |
1794 | 0 | { |
1795 | 0 | rString.append(rParam.bPredicate ? convertDateTimeString(rParam, sTokenValue) : sTokenValue); |
1796 | 0 | } |
1797 | 0 | rString.append(suQuote); |
1798 | 0 | return true; |
1799 | 0 | } |
1800 | | |
1801 | | void OSQLParseNode::replaceNodeValue(const OUString& rTableAlias, const OUString& rColumnName) |
1802 | 0 | { |
1803 | 0 | for (size_t i=0;i<count();++i) |
1804 | 0 | { |
1805 | 0 | if (SQL_ISRULE(this,column_ref) && count() == 1 && getChild(0)->getTokenValue() == rColumnName) |
1806 | 0 | { |
1807 | 0 | OSQLParseNode * pCol = removeAt(sal_uInt32(0)); |
1808 | 0 | append(new OSQLParseNode(rTableAlias,SQLNodeType::Name)); |
1809 | 0 | append(new OSQLParseNode(".",SQLNodeType::Punctuation)); |
1810 | 0 | append(pCol); |
1811 | 0 | } |
1812 | 0 | else |
1813 | 0 | getChild(i)->replaceNodeValue(rTableAlias,rColumnName); |
1814 | 0 | } |
1815 | 0 | } |
1816 | | |
1817 | | OSQLParseNode* OSQLParseNode::getByRule(OSQLParseNode::Rule eRule) const |
1818 | 0 | { |
1819 | 0 | OSQLParseNode* pRetNode = nullptr; |
1820 | 0 | if (isRule() && OSQLParser::RuleID(eRule) == getRuleID()) |
1821 | 0 | pRetNode = const_cast<OSQLParseNode*>(this); |
1822 | 0 | else |
1823 | 0 | { |
1824 | 0 | for (auto const& child : m_aChildren) |
1825 | 0 | { |
1826 | 0 | pRetNode = child->getByRule(eRule); |
1827 | 0 | if (pRetNode) |
1828 | 0 | break; |
1829 | 0 | } |
1830 | 0 | } |
1831 | 0 | return pRetNode; |
1832 | 0 | } |
1833 | | |
1834 | | static OSQLParseNode* MakeANDNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf) |
1835 | 0 | { |
1836 | 0 | OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_term)); |
1837 | 0 | pNewNode->append(pLeftLeaf); |
1838 | 0 | pNewNode->append(new OSQLParseNode("AND",SQLNodeType::Keyword,SQL_TOKEN_AND)); |
1839 | 0 | pNewNode->append(pRightLeaf); |
1840 | 0 | return pNewNode; |
1841 | 0 | } |
1842 | | |
1843 | | static OSQLParseNode* MakeORNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf) |
1844 | 0 | { |
1845 | 0 | OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::search_condition)); |
1846 | 0 | pNewNode->append(pLeftLeaf); |
1847 | 0 | pNewNode->append(new OSQLParseNode("OR",SQLNodeType::Keyword,SQL_TOKEN_OR)); |
1848 | 0 | pNewNode->append(pRightLeaf); |
1849 | 0 | return pNewNode; |
1850 | 0 | } |
1851 | | |
1852 | | void OSQLParseNode::disjunctiveNormalForm(OSQLParseNode*& pSearchCondition) |
1853 | 0 | { |
1854 | 0 | if(!pSearchCondition) // no where condition at entry point |
1855 | 0 | return; |
1856 | | |
1857 | 0 | OSQLParseNode::absorptions(pSearchCondition); |
1858 | | // '(' search_condition ')' |
1859 | 0 | if (SQL_ISRULE(pSearchCondition,boolean_primary)) |
1860 | 0 | { |
1861 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(1); |
1862 | 0 | disjunctiveNormalForm(pLeft); |
1863 | 0 | } |
1864 | | // search_condition SQL_TOKEN_OR boolean_term |
1865 | 0 | else if (SQL_ISRULE(pSearchCondition,search_condition)) |
1866 | 0 | { |
1867 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
1868 | 0 | disjunctiveNormalForm(pLeft); |
1869 | |
|
1870 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
1871 | 0 | disjunctiveNormalForm(pRight); |
1872 | 0 | } |
1873 | | // boolean_term SQL_TOKEN_AND boolean_factor |
1874 | 0 | else if (SQL_ISRULE(pSearchCondition,boolean_term)) |
1875 | 0 | { |
1876 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
1877 | 0 | disjunctiveNormalForm(pLeft); |
1878 | |
|
1879 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
1880 | 0 | disjunctiveNormalForm(pRight); |
1881 | |
|
1882 | 0 | OSQLParseNode* pNewNode = nullptr; |
1883 | | // '(' search_condition ')' on left side |
1884 | 0 | if(pLeft->count() == 3 && SQL_ISRULE(pLeft,boolean_primary) && SQL_ISRULE(pLeft->getChild(1),search_condition)) |
1885 | 0 | { |
1886 | | // and-or tree on left side |
1887 | 0 | OSQLParseNode* pOr = pLeft->getChild(1); |
1888 | 0 | OSQLParseNode* pNewLeft = nullptr; |
1889 | 0 | OSQLParseNode* pNewRight = nullptr; |
1890 | | |
1891 | | // cut right from parent |
1892 | 0 | OSQLParseNode* pOldRight = pSearchCondition->removeAt(2); |
1893 | 0 | assert(pOldRight == pRight); |
1894 | |
|
1895 | 0 | pNewRight = MakeANDNode(pOr->removeAt(2), pOldRight); |
1896 | 0 | pNewLeft = MakeANDNode(pOr->removeAt(sal_uInt32(0)), new OSQLParseNode(*pOldRight)); |
1897 | 0 | pNewNode = MakeORNode(pNewLeft,pNewRight); |
1898 | | // and append new Node |
1899 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
1900 | |
|
1901 | 0 | disjunctiveNormalForm(pSearchCondition); |
1902 | 0 | } |
1903 | 0 | else if(pRight->count() == 3 && SQL_ISRULE(pRight,boolean_primary) && SQL_ISRULE(pRight->getChild(1),search_condition)) |
1904 | 0 | { // '(' search_condition ')' on right side |
1905 | | // and-or tree on right side |
1906 | | // a and (b or c) |
1907 | 0 | OSQLParseNode* pOr = pRight->getChild(1); |
1908 | 0 | OSQLParseNode* pNewLeft = nullptr; |
1909 | 0 | OSQLParseNode* pNewRight = nullptr; |
1910 | | |
1911 | | // cut left from parent |
1912 | 0 | OSQLParseNode* pOldLeft = pSearchCondition->removeAt(sal_uInt32(0)); |
1913 | 0 | assert(pOldLeft == pLeft); |
1914 | |
|
1915 | 0 | pNewRight = MakeANDNode(pOldLeft, pOr->removeAt(2)); |
1916 | 0 | pNewLeft = MakeANDNode(new OSQLParseNode(*pOldLeft), pOr->removeAt(sal_uInt32(0))); |
1917 | 0 | pNewNode = MakeORNode(pNewLeft,pNewRight); |
1918 | | |
1919 | | // and append new Node |
1920 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
1921 | 0 | disjunctiveNormalForm(pSearchCondition); |
1922 | 0 | } |
1923 | 0 | else if(SQL_ISRULE(pLeft,boolean_primary) && (!SQL_ISRULE(pLeft->getChild(1),search_condition) || !SQL_ISRULE(pLeft->getChild(1),boolean_term))) |
1924 | 0 | pSearchCondition->replaceAndDelete(pLeft, pLeft->removeAt(1)); |
1925 | 0 | else if(SQL_ISRULE(pRight,boolean_primary) && (!SQL_ISRULE(pRight->getChild(1),search_condition) || !SQL_ISRULE(pRight->getChild(1),boolean_term))) |
1926 | 0 | pSearchCondition->replaceAndDelete(pRight, pRight->removeAt(1)); |
1927 | 0 | } |
1928 | 0 | } |
1929 | | |
1930 | | void OSQLParseNode::negateSearchCondition(OSQLParseNode*& pSearchCondition, bool bNegate) |
1931 | 0 | { |
1932 | 0 | if(!pSearchCondition) // no where condition at entry point |
1933 | 0 | return; |
1934 | | // '(' search_condition ')' |
1935 | 0 | if (pSearchCondition->count() == 3 && SQL_ISRULE(pSearchCondition,boolean_primary)) |
1936 | 0 | { |
1937 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(1); |
1938 | 0 | negateSearchCondition(pRight,bNegate); |
1939 | 0 | } |
1940 | | // search_condition SQL_TOKEN_OR boolean_term |
1941 | 0 | else if (SQL_ISRULE(pSearchCondition,search_condition)) |
1942 | 0 | { |
1943 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
1944 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
1945 | 0 | if(bNegate) |
1946 | 0 | { |
1947 | 0 | OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_term)); |
1948 | 0 | pNewNode->append(pSearchCondition->removeAt(sal_uInt32(0))); |
1949 | 0 | pNewNode->append(new OSQLParseNode("AND",SQLNodeType::Keyword,SQL_TOKEN_AND)); |
1950 | 0 | pNewNode->append(pSearchCondition->removeAt(sal_uInt32(1))); |
1951 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
1952 | |
|
1953 | 0 | pLeft = pNewNode->getChild(0); |
1954 | 0 | pRight = pNewNode->getChild(2); |
1955 | 0 | } |
1956 | |
|
1957 | 0 | negateSearchCondition(pLeft,bNegate); |
1958 | 0 | negateSearchCondition(pRight,bNegate); |
1959 | 0 | } |
1960 | | // boolean_term SQL_TOKEN_AND boolean_factor |
1961 | 0 | else if (SQL_ISRULE(pSearchCondition,boolean_term)) |
1962 | 0 | { |
1963 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
1964 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
1965 | 0 | if(bNegate) |
1966 | 0 | { |
1967 | 0 | OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::search_condition)); |
1968 | 0 | pNewNode->append(pSearchCondition->removeAt(sal_uInt32(0))); |
1969 | 0 | pNewNode->append(new OSQLParseNode("OR",SQLNodeType::Keyword,SQL_TOKEN_OR)); |
1970 | 0 | pNewNode->append(pSearchCondition->removeAt(sal_uInt32(1))); |
1971 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
1972 | |
|
1973 | 0 | pLeft = pNewNode->getChild(0); |
1974 | 0 | pRight = pNewNode->getChild(2); |
1975 | 0 | } |
1976 | |
|
1977 | 0 | negateSearchCondition(pLeft,bNegate); |
1978 | 0 | negateSearchCondition(pRight,bNegate); |
1979 | 0 | } |
1980 | | // SQL_TOKEN_NOT ( boolean_primary ) |
1981 | 0 | else if (SQL_ISRULE(pSearchCondition,boolean_factor)) |
1982 | 0 | { |
1983 | 0 | OSQLParseNode *pNot = pSearchCondition->removeAt(sal_uInt32(0)); |
1984 | 0 | delete pNot; |
1985 | 0 | OSQLParseNode *pBooleanTest = pSearchCondition->removeAt(sal_uInt32(0)); |
1986 | | // TODO is this needed // pBooleanTest->setParent(NULL); |
1987 | 0 | replaceAndReset(pSearchCondition,pBooleanTest); |
1988 | |
|
1989 | 0 | if (!bNegate) |
1990 | 0 | negateSearchCondition(pSearchCondition, true); // negate all deeper values |
1991 | 0 | } |
1992 | | // row_value_constructor comparison row_value_constructor |
1993 | | // row_value_constructor comparison any_all_some subquery |
1994 | 0 | else if(bNegate && (SQL_ISRULE(pSearchCondition,comparison_predicate) || SQL_ISRULE(pSearchCondition,all_or_any_predicate))) |
1995 | 0 | { |
1996 | 0 | assert(pSearchCondition->count() == 3); |
1997 | 0 | OSQLParseNode* pComparison = pSearchCondition->getChild(1); |
1998 | 0 | if(SQL_ISRULE(pComparison, comparison)) |
1999 | 0 | { |
2000 | 0 | assert(pComparison->count() == 2 || |
2001 | 0 | pComparison->count() == 4); |
2002 | 0 | assert(SQL_ISTOKEN(pComparison->getChild(0), IS)); |
2003 | |
|
2004 | 0 | OSQLParseNode* pNot = pComparison->getChild(1); |
2005 | 0 | OSQLParseNode* pNotNot = nullptr; |
2006 | 0 | if(pNot->isRule()) // no NOT token (empty rule) |
2007 | 0 | pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT); |
2008 | 0 | else |
2009 | 0 | { |
2010 | 0 | assert(SQL_ISTOKEN(pNot,NOT)); |
2011 | 0 | pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not)); |
2012 | 0 | } |
2013 | 0 | pComparison->replaceAndDelete(pNot, pNotNot); |
2014 | 0 | } |
2015 | 0 | else |
2016 | 0 | { |
2017 | 0 | OSQLParseNode* pNewComparison; |
2018 | 0 | switch(pComparison->getNodeType()) |
2019 | 0 | { |
2020 | 0 | default: |
2021 | 0 | case SQLNodeType::Equal: |
2022 | 0 | assert(pComparison->getNodeType() == SQLNodeType::Equal && |
2023 | 0 | "OSQLParseNode::negateSearchCondition: unexpected node type!"); |
2024 | 0 | pNewComparison = new OSQLParseNode("<>",SQLNodeType::NotEqual,SQL_NOTEQUAL); |
2025 | 0 | break; |
2026 | 0 | case SQLNodeType::Less: |
2027 | 0 | pNewComparison = new OSQLParseNode(">=",SQLNodeType::GreatEq,SQL_GREATEQ); |
2028 | 0 | break; |
2029 | 0 | case SQLNodeType::Great: |
2030 | 0 | pNewComparison = new OSQLParseNode("<=",SQLNodeType::LessEq,SQL_LESSEQ); |
2031 | 0 | break; |
2032 | 0 | case SQLNodeType::LessEq: |
2033 | 0 | pNewComparison = new OSQLParseNode(">",SQLNodeType::Great,SQL_GREAT); |
2034 | 0 | break; |
2035 | 0 | case SQLNodeType::GreatEq: |
2036 | 0 | pNewComparison = new OSQLParseNode("<",SQLNodeType::Less,SQL_LESS); |
2037 | 0 | break; |
2038 | 0 | case SQLNodeType::NotEqual: |
2039 | 0 | pNewComparison = new OSQLParseNode("=",SQLNodeType::Equal,SQL_EQUAL); |
2040 | 0 | break; |
2041 | 0 | } |
2042 | 0 | pSearchCondition->replaceAndDelete(pComparison, pNewComparison); |
2043 | 0 | } |
2044 | 0 | } |
2045 | | |
2046 | 0 | else if(bNegate && (SQL_ISRULE(pSearchCondition,test_for_null) || |
2047 | 0 | SQL_ISRULE(pSearchCondition,in_predicate) || |
2048 | 0 | SQL_ISRULE(pSearchCondition,between_predicate) )) |
2049 | 0 | { |
2050 | 0 | OSQLParseNode* pPart2 = pSearchCondition->getChild(1); |
2051 | 0 | sal_uInt32 nNotPos = 0; |
2052 | 0 | if ( SQL_ISRULE( pSearchCondition, test_for_null ) ) |
2053 | 0 | nNotPos = 1; |
2054 | |
|
2055 | 0 | OSQLParseNode* pNot = pPart2->getChild(nNotPos); |
2056 | 0 | OSQLParseNode* pNotNot = nullptr; |
2057 | 0 | if(pNot->isRule()) // no NOT token (empty rule) |
2058 | 0 | pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT); |
2059 | 0 | else |
2060 | 0 | { |
2061 | 0 | assert(SQL_ISTOKEN(pNot,NOT)); |
2062 | 0 | pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not)); |
2063 | 0 | } |
2064 | 0 | pPart2->replaceAndDelete(pNot, pNotNot); |
2065 | 0 | } |
2066 | 0 | else if(bNegate && SQL_ISRULE(pSearchCondition,like_predicate)) |
2067 | 0 | { |
2068 | 0 | OSQLParseNode* pNot = pSearchCondition->getChild( 1 )->getChild( 0 ); |
2069 | 0 | OSQLParseNode* pNotNot = nullptr; |
2070 | 0 | if(pNot->isRule()) |
2071 | 0 | pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT); |
2072 | 0 | else |
2073 | 0 | pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not)); |
2074 | 0 | pSearchCondition->getChild( 1 )->replaceAndDelete(pNot, pNotNot); |
2075 | 0 | } |
2076 | 0 | } |
2077 | | |
2078 | | void OSQLParseNode::eraseBraces(OSQLParseNode*& pSearchCondition) |
2079 | 0 | { |
2080 | 0 | if (!(pSearchCondition && (SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && |
2081 | 0 | SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")"))))) |
2082 | 0 | return; |
2083 | | |
2084 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(1); |
2085 | 0 | absorptions(pRight); |
2086 | | // if child is not an or and tree then delete () around child |
2087 | 0 | if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) || |
2088 | 0 | SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || // and can always stand without () |
2089 | 0 | (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition))) |
2090 | 0 | { |
2091 | 0 | OSQLParseNode* pNode = pSearchCondition->removeAt(1); |
2092 | 0 | replaceAndReset(pSearchCondition,pNode); |
2093 | 0 | } |
2094 | 0 | } |
2095 | | |
2096 | | void OSQLParseNode::absorptions(OSQLParseNode*& pSearchCondition) |
2097 | 0 | { |
2098 | 0 | if(!pSearchCondition) // no where condition at entry point |
2099 | 0 | return; |
2100 | | |
2101 | 0 | eraseBraces(pSearchCondition); |
2102 | |
|
2103 | 0 | if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) |
2104 | 0 | { |
2105 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
2106 | 0 | absorptions(pLeft); |
2107 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
2108 | 0 | absorptions(pRight); |
2109 | 0 | } |
2110 | |
|
2111 | 0 | sal_uInt32 nPos = 0; |
2112 | | // a and a || a or a |
2113 | 0 | OSQLParseNode* pNewNode = nullptr; |
2114 | 0 | if(( SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) |
2115 | 0 | && *pSearchCondition->getChild(0) == *pSearchCondition->getChild(2)) |
2116 | 0 | { |
2117 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(0)); |
2118 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2119 | 0 | } |
2120 | | // ( a or b ) and a || ( b or c ) and a |
2121 | | // a and ( a or b ) || a and ( b or c ) |
2122 | 0 | else if ( SQL_ISRULE(pSearchCondition,boolean_term) |
2123 | 0 | && ( |
2124 | 0 | ( SQL_ISRULE(pSearchCondition->getChild(nPos = 0),boolean_primary) |
2125 | 0 | || SQL_ISRULE(pSearchCondition->getChild(nPos),search_condition) |
2126 | 0 | ) |
2127 | 0 | || ( SQL_ISRULE(pSearchCondition->getChild(nPos = 2),boolean_primary) |
2128 | 0 | || SQL_ISRULE(pSearchCondition->getChild(nPos),search_condition) |
2129 | 0 | ) |
2130 | 0 | ) |
2131 | 0 | ) |
2132 | 0 | { |
2133 | 0 | OSQLParseNode* p2ndSearch = pSearchCondition->getChild(nPos); |
2134 | 0 | if ( SQL_ISRULE(p2ndSearch,boolean_primary) ) |
2135 | 0 | p2ndSearch = p2ndSearch->getChild(1); |
2136 | |
|
2137 | 0 | if ( *p2ndSearch->getChild(0) == *pSearchCondition->getChild(2-nPos) ) // a and ( a or b) -> a or b |
2138 | 0 | { |
2139 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(0)); |
2140 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2141 | |
|
2142 | 0 | } |
2143 | 0 | else if ( *p2ndSearch->getChild(2) == *pSearchCondition->getChild(2-nPos) ) // a and ( b or a) -> a or b |
2144 | 0 | { |
2145 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(2)); |
2146 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2147 | 0 | } |
2148 | 0 | else if ( p2ndSearch->getByRule(OSQLParseNode::search_condition) ) |
2149 | 0 | { |
2150 | | // a and ( b or c ) -> ( a and b ) or ( a and c ) |
2151 | | // ( b or c ) and a -> ( a and b ) or ( a and c ) |
2152 | 0 | OSQLParseNode* pC = p2ndSearch->removeAt(sal_uInt32(2)); |
2153 | 0 | OSQLParseNode* pB = p2ndSearch->removeAt(sal_uInt32(0)); |
2154 | 0 | OSQLParseNode* pA = pSearchCondition->removeAt(sal_uInt32(2)-nPos); |
2155 | |
|
2156 | 0 | OSQLParseNode* p1stAnd = MakeANDNode(pA,pB); |
2157 | 0 | OSQLParseNode* p2ndAnd = MakeANDNode(new OSQLParseNode(*pA),pC); |
2158 | 0 | pNewNode = MakeORNode(p1stAnd,p2ndAnd); |
2159 | 0 | OSQLParseNode* pNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); |
2160 | 0 | pNode->append(new OSQLParseNode("(",SQLNodeType::Punctuation)); |
2161 | 0 | pNode->append(pNewNode); |
2162 | 0 | pNode->append(new OSQLParseNode(")",SQLNodeType::Punctuation)); |
2163 | 0 | OSQLParseNode::eraseBraces(p1stAnd); |
2164 | 0 | OSQLParseNode::eraseBraces(p2ndAnd); |
2165 | 0 | replaceAndReset(pSearchCondition,pNode); |
2166 | 0 | } |
2167 | 0 | } |
2168 | | // a or a and b || a or b and a |
2169 | 0 | else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term)) |
2170 | 0 | { |
2171 | 0 | if(*pSearchCondition->getChild(2)->getChild(0) == *pSearchCondition->getChild(0)) |
2172 | 0 | { |
2173 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(0)); |
2174 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2175 | 0 | } |
2176 | 0 | else if(*pSearchCondition->getChild(2)->getChild(2) == *pSearchCondition->getChild(0)) |
2177 | 0 | { |
2178 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(0)); |
2179 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2180 | 0 | } |
2181 | 0 | } |
2182 | | // a and b or a || b and a or a |
2183 | 0 | else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term)) |
2184 | 0 | { |
2185 | 0 | if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)) |
2186 | 0 | { |
2187 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(2)); |
2188 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2189 | 0 | } |
2190 | 0 | else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)) |
2191 | 0 | { |
2192 | 0 | pNewNode = pSearchCondition->removeAt(sal_uInt32(2)); |
2193 | 0 | replaceAndReset(pSearchCondition,pNewNode); |
2194 | 0 | } |
2195 | 0 | } |
2196 | 0 | eraseBraces(pSearchCondition); |
2197 | 0 | } |
2198 | | |
2199 | | void OSQLParseNode::compress(OSQLParseNode *&pSearchCondition) |
2200 | 0 | { |
2201 | 0 | if(!pSearchCondition) // no WHERE condition at entry point |
2202 | 0 | return; |
2203 | | |
2204 | 0 | OSQLParseNode::eraseBraces(pSearchCondition); |
2205 | |
|
2206 | 0 | if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) |
2207 | 0 | { |
2208 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0); |
2209 | 0 | compress(pLeft); |
2210 | |
|
2211 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2); |
2212 | 0 | compress(pRight); |
2213 | 0 | } |
2214 | 0 | else if( SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && |
2215 | 0 | SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")"))) |
2216 | 0 | { |
2217 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(1); |
2218 | 0 | compress(pRight); |
2219 | | // if child is not an or and tree then delete () around child |
2220 | 0 | if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) || |
2221 | 0 | (SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) && SQL_ISRULE(pSearchCondition->getParent(),boolean_term)) || |
2222 | 0 | (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition))) |
2223 | 0 | { |
2224 | 0 | OSQLParseNode* pNode = pSearchCondition->removeAt(1); |
2225 | 0 | replaceAndReset(pSearchCondition,pNode); |
2226 | 0 | } |
2227 | 0 | } |
2228 | | |
2229 | | // or with two and trees where one element of the and trees are equal |
2230 | 0 | if(!(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term))) |
2231 | 0 | return; |
2232 | | |
2233 | 0 | if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(0)) |
2234 | 0 | { |
2235 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(2); |
2236 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2); |
2237 | 0 | OSQLParseNode* pNode = MakeORNode(pLeft,pRight); |
2238 | |
|
2239 | 0 | OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); |
2240 | 0 | pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation)); |
2241 | 0 | pNewRule->append(pNode); |
2242 | 0 | pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation)); |
2243 | |
|
2244 | 0 | OSQLParseNode::eraseBraces(pLeft); |
2245 | 0 | OSQLParseNode::eraseBraces(pRight); |
2246 | |
|
2247 | 0 | pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)),pNewRule); |
2248 | 0 | replaceAndReset(pSearchCondition,pNode); |
2249 | 0 | } |
2250 | 0 | else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(0)) |
2251 | 0 | { |
2252 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)); |
2253 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2); |
2254 | 0 | OSQLParseNode* pNode = MakeORNode(pLeft,pRight); |
2255 | |
|
2256 | 0 | OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); |
2257 | 0 | pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation)); |
2258 | 0 | pNewRule->append(pNode); |
2259 | 0 | pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation)); |
2260 | |
|
2261 | 0 | OSQLParseNode::eraseBraces(pLeft); |
2262 | 0 | OSQLParseNode::eraseBraces(pRight); |
2263 | |
|
2264 | 0 | pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule); |
2265 | 0 | replaceAndReset(pSearchCondition,pNode); |
2266 | 0 | } |
2267 | 0 | else if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(2)) |
2268 | 0 | { |
2269 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(2); |
2270 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(sal_uInt32(0)); |
2271 | 0 | OSQLParseNode* pNode = MakeORNode(pLeft,pRight); |
2272 | |
|
2273 | 0 | OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); |
2274 | 0 | pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation)); |
2275 | 0 | pNewRule->append(pNode); |
2276 | 0 | pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation)); |
2277 | |
|
2278 | 0 | OSQLParseNode::eraseBraces(pLeft); |
2279 | 0 | OSQLParseNode::eraseBraces(pRight); |
2280 | |
|
2281 | 0 | pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)),pNewRule); |
2282 | 0 | replaceAndReset(pSearchCondition,pNode); |
2283 | 0 | } |
2284 | 0 | else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(2)) |
2285 | 0 | { |
2286 | 0 | OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)); |
2287 | 0 | OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(sal_uInt32(0)); |
2288 | 0 | OSQLParseNode* pNode = MakeORNode(pLeft,pRight); |
2289 | |
|
2290 | 0 | OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); |
2291 | 0 | pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation)); |
2292 | 0 | pNewRule->append(pNode); |
2293 | 0 | pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation)); |
2294 | |
|
2295 | 0 | OSQLParseNode::eraseBraces(pLeft); |
2296 | 0 | OSQLParseNode::eraseBraces(pRight); |
2297 | |
|
2298 | 0 | pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule); |
2299 | 0 | replaceAndReset(pSearchCondition,pNode); |
2300 | 0 | } |
2301 | 0 | } |
2302 | | #if OSL_DEBUG_LEVEL > 1 |
2303 | | |
2304 | | void OSQLParseNode::showParseTree( OUString& rString ) const |
2305 | | { |
2306 | | OUStringBuffer aBuf; |
2307 | | showParseTree( aBuf, 0 ); |
2308 | | rString = aBuf.makeStringAndClear(); |
2309 | | } |
2310 | | |
2311 | | |
2312 | | void OSQLParseNode::showParseTree( OUStringBuffer& _inout_rBuffer, sal_uInt32 nLevel ) const |
2313 | | { |
2314 | | for ( sal_uInt32 j=0; j<nLevel; ++j) |
2315 | | _inout_rBuffer.appendAscii( " " ); |
2316 | | |
2317 | | if ( !isToken() ) |
2318 | | { |
2319 | | // Rule name as rule |
2320 | | _inout_rBuffer.appendAscii( "RULE_ID: " ); |
2321 | | _inout_rBuffer.append( (sal_Int32)getRuleID() ); |
2322 | | _inout_rBuffer.append( '(' ); |
2323 | | _inout_rBuffer.append( OSQLParser::RuleIDToStr( getRuleID() ) ); |
2324 | | _inout_rBuffer.append( ')' ); |
2325 | | _inout_rBuffer.append( '\n' ); |
2326 | | |
2327 | | // Get the first sub tree |
2328 | | for (auto const& child : m_aChildren) |
2329 | | child->showParseTree( _inout_rBuffer, nLevel+1 ); |
2330 | | } |
2331 | | else |
2332 | | { |
2333 | | // Found a token |
2334 | | switch (m_eNodeType) |
2335 | | { |
2336 | | |
2337 | | case SQLNodeType::Keyword: |
2338 | | _inout_rBuffer.appendAscii( "SQL_KEYWORD: " ); |
2339 | | _inout_rBuffer.append( OStringToOUString( OSQLParser::TokenIDToStr( getTokenID() ), RTL_TEXTENCODING_UTF8 ) ); |
2340 | | _inout_rBuffer.append( '\n' ); |
2341 | | break; |
2342 | | |
2343 | | case SQLNodeType::Name: |
2344 | | _inout_rBuffer.appendAscii( "SQL_NAME: " ); |
2345 | | _inout_rBuffer.append( '"' ); |
2346 | | _inout_rBuffer.append( m_aNodeValue ); |
2347 | | _inout_rBuffer.append( '"' ); |
2348 | | _inout_rBuffer.append( '\n' ); |
2349 | | break; |
2350 | | |
2351 | | case SQLNodeType::String: |
2352 | | _inout_rBuffer.appendAscii( "SQL_STRING: " ); |
2353 | | _inout_rBuffer.append( '\'' ); |
2354 | | _inout_rBuffer.append( m_aNodeValue ); |
2355 | | _inout_rBuffer.append( '\'' ); |
2356 | | _inout_rBuffer.append( '\n' ); |
2357 | | break; |
2358 | | |
2359 | | case SQLNodeType::IntNum: |
2360 | | _inout_rBuffer.appendAscii( "SQL_INTNUM: " ); |
2361 | | _inout_rBuffer.append( m_aNodeValue ); |
2362 | | _inout_rBuffer.append( '\n' ); |
2363 | | break; |
2364 | | |
2365 | | case SQLNodeType::ApproxNum: |
2366 | | _inout_rBuffer.appendAscii( "SQL_APPROXNUM: " ); |
2367 | | _inout_rBuffer.append( m_aNodeValue ); |
2368 | | _inout_rBuffer.append( '\n' ); |
2369 | | break; |
2370 | | |
2371 | | case SQLNodeType::Punctuation: |
2372 | | _inout_rBuffer.appendAscii( "SQL_PUNCTUATION: " ); |
2373 | | _inout_rBuffer.append( m_aNodeValue ); |
2374 | | _inout_rBuffer.append( '\n' ); |
2375 | | break; |
2376 | | |
2377 | | case SQLNodeType::Equal: |
2378 | | case SQLNodeType::Less: |
2379 | | case SQLNodeType::Great: |
2380 | | case SQLNodeType::LessEq: |
2381 | | case SQLNodeType::GreatEq: |
2382 | | case SQLNodeType::NotEqual: |
2383 | | _inout_rBuffer.append( m_aNodeValue ); |
2384 | | _inout_rBuffer.append( '\n' ); |
2385 | | break; |
2386 | | |
2387 | | case SQLNodeType::AccessDate: |
2388 | | _inout_rBuffer.appendAscii( "SQL_ACCESS_DATE: " ); |
2389 | | _inout_rBuffer.append( m_aNodeValue ); |
2390 | | _inout_rBuffer.append( '\n' ); |
2391 | | break; |
2392 | | |
2393 | | case SQLNodeType::Concat: |
2394 | | _inout_rBuffer.appendAscii( "||" ); |
2395 | | _inout_rBuffer.append( '\n' ); |
2396 | | break; |
2397 | | |
2398 | | default: |
2399 | | SAL_INFO( "connectivity.parse", "-- " << int( m_eNodeType ) ); |
2400 | | SAL_WARN( "connectivity.parse", "OSQLParser::ShowParseTree: unzulaessiger NodeType" ); |
2401 | | } |
2402 | | } |
2403 | | } |
2404 | | #endif // OSL_DEBUG_LEVEL > 0 |
2405 | | |
2406 | | // Insert methods |
2407 | | |
2408 | | void OSQLParseNode::insert(sal_uInt32 nPos, OSQLParseNode* pNewSubTree) |
2409 | 0 | { |
2410 | 0 | assert(pNewSubTree != nullptr && "OSQLParseNode: invalid NewSubTree"); |
2411 | 0 | OSL_ENSURE(pNewSubTree->getParent() == nullptr, "OSQLParseNode: Node is not an orphan"); |
2412 | | |
2413 | | // Create connection to getParent |
2414 | 0 | pNewSubTree->setParent( this ); |
2415 | 0 | m_aChildren.emplace(m_aChildren.begin() + nPos, pNewSubTree); |
2416 | 0 | } |
2417 | | |
2418 | | // removeAt methods |
2419 | | |
2420 | | OSQLParseNode* OSQLParseNode::removeAt(sal_uInt32 nPos) |
2421 | 0 | { |
2422 | 0 | assert(nPos < m_aChildren.size() && "Illegal position for removeAt"); |
2423 | 0 | auto aPos(m_aChildren.begin() + nPos); |
2424 | 0 | auto pNode = std::move(*aPos); |
2425 | | |
2426 | | // Set the getParent of the removed node to NULL |
2427 | 0 | pNode->setParent( nullptr ); |
2428 | |
|
2429 | 0 | m_aChildren.erase(aPos); |
2430 | 0 | return pNode.release(); |
2431 | 0 | } |
2432 | | |
2433 | | // Replace methods |
2434 | | |
2435 | | void OSQLParseNode::replaceAndDelete(OSQLParseNode* pOldSubNode, OSQLParseNode* pNewSubNode ) |
2436 | 0 | { |
2437 | 0 | assert(pOldSubNode != nullptr && pNewSubNode != nullptr && "OSQLParseNode: invalid nodes"); |
2438 | 0 | assert(pOldSubNode != pNewSubNode && "OSQLParseNode: same node"); |
2439 | 0 | assert(pNewSubNode->getParent() == nullptr && "OSQLParseNode: node already has getParent"); |
2440 | 0 | assert(std::any_of(m_aChildren.begin(), m_aChildren.end(), |
2441 | 0 | [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pOldSubNode; }) |
2442 | 0 | && "OSQLParseNode::Replace() Node not element of parent"); |
2443 | 0 | assert(std::none_of(m_aChildren.begin(), m_aChildren.end(), |
2444 | 0 | [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pNewSubNode; }) |
2445 | 0 | && "OSQLParseNode::Replace() Node already element of parent"); |
2446 | |
|
2447 | 0 | pOldSubNode->setParent( nullptr ); |
2448 | 0 | pNewSubNode->setParent( this ); |
2449 | 0 | auto it = std::find_if(m_aChildren.begin(), m_aChildren.end(), |
2450 | 0 | [&pOldSubNode](const std::unique_ptr<OSQLParseNode>& rxChild) { return rxChild.get() == pOldSubNode; }); |
2451 | 0 | assert(it != m_aChildren.end()); |
2452 | 0 | it->reset(pNewSubNode); |
2453 | 0 | } |
2454 | | |
2455 | | void OSQLParseNode::parseLeaf(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const |
2456 | 0 | { |
2457 | | // Found a leaf |
2458 | | // Append content to the output string |
2459 | 0 | switch (m_eNodeType) |
2460 | 0 | { |
2461 | 0 | case SQLNodeType::Keyword: |
2462 | 0 | { |
2463 | 0 | if (!rString.isEmpty()) |
2464 | 0 | rString.append(" "); |
2465 | |
|
2466 | 0 | const OString sT = OSQLParser::TokenIDToStr(m_nNodeID, rParam.bInternational ? &rParam.m_rContext : nullptr); |
2467 | 0 | rString.append(OStringToOUString(sT,RTL_TEXTENCODING_UTF8)); |
2468 | 0 | } break; |
2469 | 0 | case SQLNodeType::String: |
2470 | 0 | if (!rString.isEmpty()) |
2471 | 0 | rString.append(" "); |
2472 | 0 | rString.append(SetQuotation(m_aNodeValue, u"\'", u"\'\'")); |
2473 | 0 | break; |
2474 | 0 | case SQLNodeType::Name: |
2475 | 0 | if (!rString.isEmpty()) |
2476 | 0 | { |
2477 | 0 | switch(rString[rString.getLength()-1]) |
2478 | 0 | { |
2479 | 0 | case ' ' : |
2480 | 0 | case '.' : break; |
2481 | 0 | default : |
2482 | 0 | if ( rParam.aMetaData.getCatalogSeparator().isEmpty() |
2483 | 0 | || rString[rString.getLength() - 1] != rParam.aMetaData.getCatalogSeparator().toChar() |
2484 | 0 | ) |
2485 | 0 | rString.append(" "); |
2486 | 0 | break; |
2487 | 0 | } |
2488 | 0 | } |
2489 | 0 | if (rParam.bQuote) |
2490 | 0 | { |
2491 | 0 | if (rParam.bPredicate) |
2492 | 0 | { |
2493 | 0 | rString.append("["); |
2494 | 0 | rString.append(m_aNodeValue); |
2495 | 0 | rString.append("]"); |
2496 | 0 | } |
2497 | 0 | else |
2498 | 0 | rString.append(SetQuotation(m_aNodeValue, |
2499 | 0 | rParam.aMetaData.getIdentifierQuoteString(), rParam.aMetaData.getIdentifierQuoteString() )); |
2500 | 0 | } |
2501 | 0 | else |
2502 | 0 | rString.append(m_aNodeValue); |
2503 | 0 | break; |
2504 | 0 | case SQLNodeType::AccessDate: |
2505 | 0 | if (!rString.isEmpty()) |
2506 | 0 | rString.append(" "); |
2507 | 0 | rString.append("#"); |
2508 | 0 | rString.append(m_aNodeValue); |
2509 | 0 | rString.append("#"); |
2510 | 0 | break; |
2511 | | |
2512 | 0 | case SQLNodeType::IntNum: |
2513 | 0 | case SQLNodeType::ApproxNum: |
2514 | 0 | { |
2515 | 0 | OUString aTmp = m_aNodeValue; |
2516 | 0 | static constexpr OUString strPoint(u"."_ustr); |
2517 | 0 | if (rParam.bInternational && rParam.bPredicate && rParam.sDecSep != strPoint) |
2518 | 0 | aTmp = aTmp.replaceAll(strPoint, rParam.sDecSep); |
2519 | |
|
2520 | 0 | if (!rString.isEmpty()) |
2521 | 0 | rString.append(" "); |
2522 | 0 | rString.append(aTmp); |
2523 | |
|
2524 | 0 | } break; |
2525 | 0 | case SQLNodeType::Punctuation: |
2526 | 0 | if ( getParent() && SQL_ISRULE(getParent(),cast_spec) && m_aNodeValue.toChar() == '(' ) // no spaces in front of '(' |
2527 | 0 | { |
2528 | 0 | rString.append(m_aNodeValue); |
2529 | 0 | break; |
2530 | 0 | } |
2531 | 0 | [[fallthrough]]; |
2532 | 0 | default: |
2533 | 0 | if (!rString.isEmpty() && m_aNodeValue.toChar() != '.' && m_aNodeValue.toChar() != ':' ) |
2534 | 0 | { |
2535 | 0 | switch( rString[rString.getLength() - 1] ) |
2536 | 0 | { |
2537 | 0 | case ' ' : |
2538 | 0 | case '.' : break; |
2539 | 0 | default : |
2540 | 0 | if ( rParam.aMetaData.getCatalogSeparator().isEmpty() |
2541 | 0 | || rString[rString.getLength() - 1] != rParam.aMetaData.getCatalogSeparator().toChar() |
2542 | 0 | ) |
2543 | 0 | rString.append(" "); |
2544 | 0 | break; |
2545 | 0 | } |
2546 | 0 | } |
2547 | 0 | rString.append(m_aNodeValue); |
2548 | 0 | } |
2549 | 0 | } |
2550 | | |
2551 | | |
2552 | | sal_Int32 OSQLParser::getFunctionReturnType(std::u16string_view _sFunctionName, const IParseContext* pContext) |
2553 | 0 | { |
2554 | 0 | sal_Int32 nType = DataType::SQLNULL; |
2555 | 0 | OString sFunctionName(OUStringToOString(_sFunctionName,RTL_TEXTENCODING_UTF8)); |
2556 | |
|
2557 | 0 | if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ASCII,pContext))) nType = DataType::INTEGER; |
2558 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_BIT_LENGTH,pContext))) nType = DataType::INTEGER; |
2559 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CHAR,pContext))) nType = DataType::VARCHAR; |
2560 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CHAR_LENGTH,pContext))) nType = DataType::INTEGER; |
2561 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CONCAT,pContext))) nType = DataType::VARCHAR; |
2562 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DIFFERENCE,pContext))) nType = DataType::VARCHAR; |
2563 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_INSERT,pContext))) nType = DataType::VARCHAR; |
2564 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LCASE,pContext))) nType = DataType::VARCHAR; |
2565 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LEFT,pContext))) nType = DataType::VARCHAR; |
2566 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LENGTH,pContext))) nType = DataType::INTEGER; |
2567 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOCATE,pContext))) nType = DataType::VARCHAR; |
2568 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOCATE_2,pContext))) nType = DataType::VARCHAR; |
2569 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LTRIM,pContext))) nType = DataType::VARCHAR; |
2570 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_OCTET_LENGTH,pContext))) nType = DataType::INTEGER; |
2571 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_POSITION,pContext))) nType = DataType::INTEGER; |
2572 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_REPEAT,pContext))) nType = DataType::VARCHAR; |
2573 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_REPLACE,pContext))) nType = DataType::VARCHAR; |
2574 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RIGHT,pContext))) nType = DataType::VARCHAR; |
2575 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RTRIM,pContext))) nType = DataType::VARCHAR; |
2576 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SOUNDEX,pContext))) nType = DataType::VARCHAR; |
2577 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SPACE,pContext))) nType = DataType::VARCHAR; |
2578 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SUBSTRING,pContext))) nType = DataType::VARCHAR; |
2579 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_UCASE,pContext))) nType = DataType::VARCHAR; |
2580 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_DATE,pContext))) nType = DataType::DATE; |
2581 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_TIME,pContext))) nType = DataType::TIME; |
2582 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_TIMESTAMP,pContext))) nType = DataType::TIMESTAMP; |
2583 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURDATE,pContext))) nType = DataType::DATE; |
2584 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DATEDIFF,pContext))) nType = DataType::INTEGER; |
2585 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DATEVALUE,pContext))) nType = DataType::DATE; |
2586 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURTIME,pContext))) nType = DataType::TIME; |
2587 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYNAME,pContext))) nType = DataType::VARCHAR; |
2588 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFMONTH,pContext))) nType = DataType::INTEGER; |
2589 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFWEEK,pContext))) nType = DataType::INTEGER; |
2590 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFYEAR,pContext))) nType = DataType::INTEGER; |
2591 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_EXTRACT,pContext))) nType = DataType::VARCHAR; |
2592 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_HOUR,pContext))) nType = DataType::INTEGER; |
2593 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MINUTE,pContext))) nType = DataType::INTEGER; |
2594 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MONTH,pContext))) nType = DataType::INTEGER; |
2595 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MONTHNAME,pContext))) nType = DataType::VARCHAR; |
2596 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_NOW,pContext))) nType = DataType::TIMESTAMP; |
2597 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_QUARTER,pContext))) nType = DataType::INTEGER; |
2598 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SECOND,pContext))) nType = DataType::INTEGER; |
2599 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMESTAMPADD,pContext))) nType = DataType::TIMESTAMP; |
2600 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMESTAMPDIFF,pContext))) nType = DataType::TIMESTAMP; |
2601 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMEVALUE,pContext))) nType = DataType::TIMESTAMP; |
2602 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_WEEK,pContext))) nType = DataType::INTEGER; |
2603 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_YEAR,pContext))) nType = DataType::INTEGER; |
2604 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ABS,pContext))) nType = DataType::DOUBLE; |
2605 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ACOS,pContext))) nType = DataType::DOUBLE; |
2606 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ASIN,pContext))) nType = DataType::DOUBLE; |
2607 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ATAN,pContext))) nType = DataType::DOUBLE; |
2608 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ATAN2,pContext))) nType = DataType::DOUBLE; |
2609 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CEILING,pContext))) nType = DataType::DOUBLE; |
2610 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COS,pContext))) nType = DataType::DOUBLE; |
2611 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COT,pContext))) nType = DataType::DOUBLE; |
2612 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DEGREES,pContext))) nType = DataType::DOUBLE; |
2613 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_EXP,pContext))) nType = DataType::DOUBLE; |
2614 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_FLOOR,pContext))) nType = DataType::DOUBLE; |
2615 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOGF,pContext))) nType = DataType::DOUBLE; |
2616 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOG,pContext))) nType = DataType::DOUBLE; |
2617 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOG10,pContext))) nType = DataType::DOUBLE; |
2618 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LN,pContext))) nType = DataType::DOUBLE; |
2619 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MOD,pContext))) nType = DataType::DOUBLE; |
2620 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_PI,pContext))) nType = DataType::DOUBLE; |
2621 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_POWER,pContext))) nType = DataType::DOUBLE; |
2622 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RADIANS,pContext))) nType = DataType::DOUBLE; |
2623 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RAND,pContext))) nType = DataType::DOUBLE; |
2624 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ROUND,pContext))) nType = DataType::DOUBLE; |
2625 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ROUNDMAGIC,pContext))) nType = DataType::DOUBLE; |
2626 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SIGN,pContext))) nType = DataType::DOUBLE; |
2627 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SIN,pContext))) nType = DataType::DOUBLE; |
2628 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SQRT,pContext))) nType = DataType::DOUBLE; |
2629 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TAN,pContext))) nType = DataType::DOUBLE; |
2630 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TRUNCATE,pContext))) nType = DataType::DOUBLE; |
2631 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COUNT,pContext))) nType = DataType::INTEGER; |
2632 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MAX,pContext))) nType = DataType::DOUBLE; |
2633 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MIN,pContext))) nType = DataType::DOUBLE; |
2634 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_AVG,pContext))) nType = DataType::DOUBLE; |
2635 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SUM,pContext))) nType = DataType::DOUBLE; |
2636 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOWER,pContext))) nType = DataType::VARCHAR; |
2637 | 0 | else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_UPPER,pContext))) nType = DataType::VARCHAR; |
2638 | |
|
2639 | 0 | return nType; |
2640 | 0 | } |
2641 | | |
2642 | | sal_Int32 OSQLParser::getFunctionParameterType(sal_uInt32 _nTokenId, sal_uInt32 _nPos) |
2643 | 0 | { |
2644 | 0 | sal_Int32 nType = DataType::VARCHAR; |
2645 | |
|
2646 | 0 | if(_nTokenId == SQL_TOKEN_CHAR) nType = DataType::INTEGER; |
2647 | 0 | else if(_nTokenId == SQL_TOKEN_INSERT) |
2648 | 0 | { |
2649 | 0 | if ( _nPos == 2 || _nPos == 3 ) |
2650 | 0 | nType = DataType::INTEGER; |
2651 | 0 | } |
2652 | 0 | else if(_nTokenId == SQL_TOKEN_LEFT) |
2653 | 0 | { |
2654 | 0 | if ( _nPos == 2 ) |
2655 | 0 | nType = DataType::INTEGER; |
2656 | 0 | } |
2657 | 0 | else if(_nTokenId == SQL_TOKEN_LOCATE) |
2658 | 0 | { |
2659 | 0 | if ( _nPos == 3 ) |
2660 | 0 | nType = DataType::INTEGER; |
2661 | 0 | } |
2662 | 0 | else if(_nTokenId == SQL_TOKEN_LOCATE_2) |
2663 | 0 | { |
2664 | 0 | if ( _nPos == 3 ) |
2665 | 0 | nType = DataType::INTEGER; |
2666 | 0 | } |
2667 | 0 | else if( _nTokenId == SQL_TOKEN_REPEAT || _nTokenId == SQL_TOKEN_RIGHT ) |
2668 | 0 | { |
2669 | 0 | if ( _nPos == 2 ) |
2670 | 0 | nType = DataType::INTEGER; |
2671 | 0 | } |
2672 | 0 | else if(_nTokenId == SQL_TOKEN_SPACE ) |
2673 | 0 | { |
2674 | 0 | nType = DataType::INTEGER; |
2675 | 0 | } |
2676 | 0 | else if(_nTokenId == SQL_TOKEN_SUBSTRING) |
2677 | 0 | { |
2678 | 0 | if ( _nPos != 1 ) |
2679 | 0 | nType = DataType::INTEGER; |
2680 | 0 | } |
2681 | 0 | else if(_nTokenId == SQL_TOKEN_DATEDIFF) |
2682 | 0 | { |
2683 | 0 | if ( _nPos != 1 ) |
2684 | 0 | nType = DataType::TIMESTAMP; |
2685 | 0 | } |
2686 | 0 | else if(_nTokenId == SQL_TOKEN_DATEVALUE) |
2687 | 0 | nType = DataType::DATE; |
2688 | 0 | else if(_nTokenId == SQL_TOKEN_DAYNAME) |
2689 | 0 | nType = DataType::DATE; |
2690 | 0 | else if(_nTokenId == SQL_TOKEN_DAYOFMONTH) |
2691 | 0 | nType = DataType::DATE; |
2692 | 0 | else if(_nTokenId == SQL_TOKEN_DAYOFWEEK) |
2693 | 0 | nType = DataType::DATE; |
2694 | 0 | else if(_nTokenId == SQL_TOKEN_DAYOFYEAR) |
2695 | 0 | nType = DataType::DATE; |
2696 | 0 | else if(_nTokenId == SQL_TOKEN_EXTRACT) nType = DataType::VARCHAR; |
2697 | 0 | else if(_nTokenId == SQL_TOKEN_HOUR) nType = DataType::TIME; |
2698 | 0 | else if(_nTokenId == SQL_TOKEN_MINUTE) nType = DataType::TIME; |
2699 | 0 | else if(_nTokenId == SQL_TOKEN_MONTH) nType = DataType::DATE; |
2700 | 0 | else if(_nTokenId == SQL_TOKEN_MONTHNAME) nType = DataType::DATE; |
2701 | 0 | else if(_nTokenId == SQL_TOKEN_NOW) nType = DataType::TIMESTAMP; |
2702 | 0 | else if(_nTokenId == SQL_TOKEN_QUARTER) nType = DataType::DATE; |
2703 | 0 | else if(_nTokenId == SQL_TOKEN_SECOND) nType = DataType::TIME; |
2704 | 0 | else if(_nTokenId == SQL_TOKEN_TIMESTAMPADD) nType = DataType::TIMESTAMP; |
2705 | 0 | else if(_nTokenId == SQL_TOKEN_TIMESTAMPDIFF) nType = DataType::TIMESTAMP; |
2706 | 0 | else if(_nTokenId == SQL_TOKEN_TIMEVALUE) nType = DataType::TIMESTAMP; |
2707 | 0 | else if(_nTokenId == SQL_TOKEN_WEEK) nType = DataType::DATE; |
2708 | 0 | else if(_nTokenId == SQL_TOKEN_YEAR) nType = DataType::DATE; |
2709 | | |
2710 | 0 | else if(_nTokenId == SQL_TOKEN_ABS) nType = DataType::DOUBLE; |
2711 | 0 | else if(_nTokenId == SQL_TOKEN_ACOS) nType = DataType::DOUBLE; |
2712 | 0 | else if(_nTokenId == SQL_TOKEN_ASIN) nType = DataType::DOUBLE; |
2713 | 0 | else if(_nTokenId == SQL_TOKEN_ATAN) nType = DataType::DOUBLE; |
2714 | 0 | else if(_nTokenId == SQL_TOKEN_ATAN2) nType = DataType::DOUBLE; |
2715 | 0 | else if(_nTokenId == SQL_TOKEN_CEILING) nType = DataType::DOUBLE; |
2716 | 0 | else if(_nTokenId == SQL_TOKEN_COS) nType = DataType::DOUBLE; |
2717 | 0 | else if(_nTokenId == SQL_TOKEN_COT) nType = DataType::DOUBLE; |
2718 | 0 | else if(_nTokenId == SQL_TOKEN_DEGREES) nType = DataType::DOUBLE; |
2719 | 0 | else if(_nTokenId == SQL_TOKEN_EXP) nType = DataType::DOUBLE; |
2720 | 0 | else if(_nTokenId == SQL_TOKEN_FLOOR) nType = DataType::DOUBLE; |
2721 | 0 | else if(_nTokenId == SQL_TOKEN_LOGF) nType = DataType::DOUBLE; |
2722 | 0 | else if(_nTokenId == SQL_TOKEN_LOG) nType = DataType::DOUBLE; |
2723 | 0 | else if(_nTokenId == SQL_TOKEN_LOG10) nType = DataType::DOUBLE; |
2724 | 0 | else if(_nTokenId == SQL_TOKEN_LN) nType = DataType::DOUBLE; |
2725 | 0 | else if(_nTokenId == SQL_TOKEN_MOD) nType = DataType::DOUBLE; |
2726 | 0 | else if(_nTokenId == SQL_TOKEN_PI) nType = DataType::DOUBLE; |
2727 | 0 | else if(_nTokenId == SQL_TOKEN_POWER) nType = DataType::DOUBLE; |
2728 | 0 | else if(_nTokenId == SQL_TOKEN_RADIANS) nType = DataType::DOUBLE; |
2729 | 0 | else if(_nTokenId == SQL_TOKEN_RAND) nType = DataType::DOUBLE; |
2730 | 0 | else if(_nTokenId == SQL_TOKEN_ROUND) nType = DataType::DOUBLE; |
2731 | 0 | else if(_nTokenId == SQL_TOKEN_ROUNDMAGIC) nType = DataType::DOUBLE; |
2732 | 0 | else if(_nTokenId == SQL_TOKEN_SIGN) nType = DataType::DOUBLE; |
2733 | 0 | else if(_nTokenId == SQL_TOKEN_SIN) nType = DataType::DOUBLE; |
2734 | 0 | else if(_nTokenId == SQL_TOKEN_SQRT) nType = DataType::DOUBLE; |
2735 | 0 | else if(_nTokenId == SQL_TOKEN_TAN) nType = DataType::DOUBLE; |
2736 | 0 | else if(_nTokenId == SQL_TOKEN_TRUNCATE) nType = DataType::DOUBLE; |
2737 | 0 | else if(_nTokenId == SQL_TOKEN_COUNT) nType = DataType::INTEGER; |
2738 | 0 | else if(_nTokenId == SQL_TOKEN_MAX) nType = DataType::DOUBLE; |
2739 | 0 | else if(_nTokenId == SQL_TOKEN_MIN) nType = DataType::DOUBLE; |
2740 | 0 | else if(_nTokenId == SQL_TOKEN_AVG) nType = DataType::DOUBLE; |
2741 | 0 | else if(_nTokenId == SQL_TOKEN_SUM) nType = DataType::DOUBLE; |
2742 | | |
2743 | 0 | else if(_nTokenId == SQL_TOKEN_LOWER) nType = DataType::VARCHAR; |
2744 | 0 | else if(_nTokenId == SQL_TOKEN_UPPER) nType = DataType::VARCHAR; |
2745 | |
|
2746 | 0 | return nType; |
2747 | 0 | } |
2748 | | |
2749 | | |
2750 | | const SQLError& OSQLParser::getErrorHelper() const |
2751 | 0 | { |
2752 | 0 | return m_pData->aErrors; |
2753 | 0 | } |
2754 | | |
2755 | | |
2756 | | OSQLParseNode::Rule OSQLParseNode::getKnownRuleID() const |
2757 | 0 | { |
2758 | 0 | if ( !isRule() ) |
2759 | 0 | return UNKNOWN_RULE; |
2760 | 0 | return OSQLParser::RuleIDToRule( getRuleID() ); |
2761 | 0 | } |
2762 | | |
2763 | | OUString OSQLParseNode::getTableRange(const OSQLParseNode* _pTableRef) |
2764 | 0 | { |
2765 | 0 | assert(_pTableRef); |
2766 | 0 | OSL_ENSURE(_pTableRef->count() > 1 && _pTableRef->getKnownRuleID() == OSQLParseNode::table_ref,"Invalid node give, only table ref is allowed!"); |
2767 | 0 | const sal_uInt32 nCount = _pTableRef->count(); |
2768 | 0 | OUString sTableRange; |
2769 | 0 | if ( nCount == 2 || (nCount == 3 && !_pTableRef->getChild(0)->isToken()) ) |
2770 | 0 | { |
2771 | 0 | const OSQLParseNode* pNode = _pTableRef->getChild(nCount - (nCount == 2 ? 1 : 2)); |
2772 | 0 | assert(pNode); |
2773 | 0 | OSL_ENSURE(pNode->getKnownRuleID() == OSQLParseNode::table_primary_as_range_column || |
2774 | 0 | pNode->getKnownRuleID() == OSQLParseNode::range_variable, "SQL grammar changed!"); |
2775 | 0 | if ( !pNode->isLeaf() ) |
2776 | 0 | sTableRange = pNode->getChild(1)->getTokenValue(); |
2777 | 0 | } // if ( nCount == 2 || nCount == 3 ) |
2778 | |
|
2779 | 0 | return sTableRange; |
2780 | 0 | } |
2781 | | |
2782 | | OSQLParseNodesContainer::OSQLParseNodesContainer() |
2783 | 0 | { |
2784 | 0 | } |
2785 | | |
2786 | | OSQLParseNodesContainer::~OSQLParseNodesContainer() |
2787 | 0 | { |
2788 | 0 | } |
2789 | | |
2790 | | void OSQLParseNodesContainer::push_back(OSQLParseNode* _pNode) |
2791 | 0 | { |
2792 | 0 | std::unique_lock aGuard(m_aMutex); |
2793 | 0 | m_aNodes.push_back(_pNode); |
2794 | 0 | } |
2795 | | |
2796 | | void OSQLParseNodesContainer::erase(OSQLParseNode* _pNode) |
2797 | 0 | { |
2798 | 0 | std::unique_lock aGuard(m_aMutex); |
2799 | 0 | if ( !m_aNodes.empty() ) |
2800 | 0 | { |
2801 | 0 | std::vector< OSQLParseNode* >::iterator aFind = std::find(m_aNodes.begin(), m_aNodes.end(),_pNode); |
2802 | 0 | if ( aFind != m_aNodes.end() ) |
2803 | 0 | m_aNodes.erase(aFind); |
2804 | 0 | } |
2805 | 0 | } |
2806 | | |
2807 | | void OSQLParseNodesContainer::clear() |
2808 | 0 | { |
2809 | 0 | std::unique_lock aGuard(m_aMutex); |
2810 | 0 | m_aNodes.clear(); |
2811 | 0 | } |
2812 | | |
2813 | | void OSQLParseNodesContainer::clearAndDelete() |
2814 | 0 | { |
2815 | 0 | std::unique_lock aGuard(m_aMutex); |
2816 | | // clear the garbage collector |
2817 | 0 | while ( !m_aNodes.empty() ) |
2818 | 0 | { |
2819 | 0 | OSQLParseNode* pNode = m_aNodes[0]; |
2820 | 0 | while ( pNode->getParent() ) |
2821 | 0 | { |
2822 | 0 | pNode = pNode->getParent(); |
2823 | 0 | } |
2824 | 0 | aGuard.unlock(); // can call back into this object during destruction |
2825 | 0 | delete pNode; |
2826 | 0 | aGuard.lock(); |
2827 | 0 | } |
2828 | 0 | } |
2829 | | } // namespace connectivity |
2830 | | |
2831 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |