/src/libreoffice/connectivity/source/drivers/file/fcomp.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 <file/fcomp.hxx> |
21 | | #include <tools/debug.hxx> |
22 | | #include <connectivity/sqlparse.hxx> |
23 | | #include <file/fanalyzer.hxx> |
24 | | #include <com/sun/star/util/Date.hpp> |
25 | | #include <com/sun/star/util/DateTime.hpp> |
26 | | #include <com/sun/star/util/Time.hpp> |
27 | | #include <com/sun/star/sdbc/XColumnLocate.hpp> |
28 | | #include <connectivity/dbexception.hxx> |
29 | | #include <connectivity/dbconversion.hxx> |
30 | | #include <com/sun/star/sdb/SQLFilterOperator.hpp> |
31 | | #include <file/FStringFunctions.hxx> |
32 | | #include <file/FDateFunctions.hxx> |
33 | | #include <file/FNumericFunctions.hxx> |
34 | | #include <file/FConnection.hxx> |
35 | | #include <comphelper/diagnose_ex.hxx> |
36 | | #include <sqlbison.hxx> |
37 | | #include <strings.hrc> |
38 | | |
39 | | using namespace connectivity; |
40 | | using namespace connectivity::file; |
41 | | using namespace com::sun::star::uno; |
42 | | using namespace com::sun::star::sdbc; |
43 | | using namespace com::sun::star::sdb; |
44 | | using namespace ::com::sun::star::container; |
45 | | using namespace com::sun::star; |
46 | | |
47 | | OPredicateCompiler::OPredicateCompiler(OSQLAnalyzer* pAnalyzer)//,OCursor& rCurs) |
48 | 28.6k | : m_pAnalyzer(pAnalyzer) |
49 | 28.6k | , m_nParamCounter(0) |
50 | 28.6k | { |
51 | 28.6k | } |
52 | | |
53 | | |
54 | | OPredicateCompiler::~OPredicateCompiler() |
55 | 28.6k | { |
56 | 28.6k | Clean(); |
57 | 28.6k | } |
58 | | |
59 | | void OPredicateCompiler::dispose() |
60 | 28.6k | { |
61 | 28.6k | Clean(); |
62 | 28.6k | m_orgColumns = nullptr; |
63 | 28.6k | } |
64 | | |
65 | | void OPredicateCompiler::start(OSQLParseNode const * pSQLParseNode) |
66 | 28.6k | { |
67 | 28.6k | if (!pSQLParseNode) |
68 | 0 | return; |
69 | | |
70 | 28.6k | m_nParamCounter = 0; |
71 | | // analyse Parse Tree (depending on Statement-type) |
72 | | // and set pointer on WHERE-clause: |
73 | 28.6k | OSQLParseNode * pWhereClause = nullptr; |
74 | | |
75 | 28.6k | if (SQL_ISRULE(pSQLParseNode,select_statement)) |
76 | 28.6k | { |
77 | 28.6k | OSQLParseNode * pOrderbyClause = nullptr; |
78 | 28.6k | DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Error in Parse Tree"); |
79 | | |
80 | 28.6k | OSQLParseNode * pTableExp = pSQLParseNode->getChild(3); |
81 | 28.6k | assert(pTableExp && "Error in Parse Tree"); |
82 | 28.6k | DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp)," Error in Parse Tree"); |
83 | 28.6k | DBG_ASSERT(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"Error in Parse Tree"); |
84 | | |
85 | | // check that we don't use anything other than count(*) as function |
86 | 28.6k | OSQLParseNode* pSelection = pSQLParseNode->getChild(2); |
87 | 28.6k | if ( SQL_ISRULE(pSelection,scalar_exp_commalist) ) |
88 | 0 | { |
89 | 0 | for (size_t i = 0; i < pSelection->count(); i++) |
90 | 0 | { |
91 | 0 | OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0); |
92 | 0 | if ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 ) |
93 | 0 | { |
94 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,nullptr); |
95 | 0 | } |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | |
100 | 28.6k | pWhereClause = pTableExp->getChild(1); |
101 | 28.6k | pOrderbyClause = pTableExp->getChild(ORDER_BY_CHILD_POS); |
102 | 28.6k | (void)pOrderbyClause; |
103 | 28.6k | } |
104 | 0 | else if (SQL_ISRULE(pSQLParseNode,update_statement_searched)) |
105 | 0 | { |
106 | 0 | DBG_ASSERT(pSQLParseNode->count() == 5,"OFILECursor: Error in Parse Tree"); |
107 | 0 | pWhereClause = pSQLParseNode->getChild(4); |
108 | 0 | } |
109 | 0 | else if (SQL_ISRULE(pSQLParseNode,delete_statement_searched)) |
110 | 0 | { |
111 | 0 | DBG_ASSERT(pSQLParseNode->count() == 4,"Error in Parse Tree"); |
112 | 0 | pWhereClause = pSQLParseNode->getChild(3); |
113 | 0 | } |
114 | 0 | else |
115 | | // Other Statement. no selection-criteria |
116 | 0 | return; |
117 | | |
118 | 28.6k | if (SQL_ISRULE(pWhereClause,where_clause)) |
119 | 19.1k | { |
120 | | // a where-clause is not allowed to be empty: |
121 | 19.1k | DBG_ASSERT(pWhereClause->count() == 2,"OFILECursor: Error in Parse Tree"); |
122 | | |
123 | 19.1k | OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1); |
124 | 19.1k | DBG_ASSERT(pComparisonPredicate != nullptr,"OFILECursor: Error in Parse Tree"); |
125 | | |
126 | 19.1k | execute( pComparisonPredicate ); |
127 | 19.1k | } |
128 | 9.55k | else |
129 | 9.55k | { |
130 | | // The where-clause is optionally in the majority of cases, i.e. it might be an "optional-where-clause". |
131 | 9.55k | DBG_ASSERT(SQL_ISRULE(pWhereClause,opt_where_clause),"OPredicateCompiler: Error in Parse Tree"); |
132 | 9.55k | } |
133 | 28.6k | } |
134 | | |
135 | | |
136 | | OOperand* OPredicateCompiler::execute(OSQLParseNode const * pPredicateNode) |
137 | 66.8k | { |
138 | 66.8k | OOperand* pOperand = nullptr; |
139 | 66.8k | if (pPredicateNode->count() == 3 && // Expression is bracketed |
140 | 28.6k | SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"(") && |
141 | 9.55k | SQL_ISPUNCTUATION(pPredicateNode->getChild(2),")")) |
142 | 9.55k | { |
143 | 9.55k | execute(pPredicateNode->getChild(1)); |
144 | 9.55k | } |
145 | 57.3k | else if ((SQL_ISRULE(pPredicateNode,search_condition) || SQL_ISRULE(pPredicateNode,boolean_term)) |
146 | 0 | && // AND/OR-linkage: |
147 | 0 | pPredicateNode->count() == 3) |
148 | 0 | { |
149 | 0 | execute(pPredicateNode->getChild(0)); // process the left branch |
150 | 0 | execute(pPredicateNode->getChild(2)); // process the right branch |
151 | |
|
152 | 0 | if (SQL_ISTOKEN(pPredicateNode->getChild(1),OR)) // OR-Operator |
153 | 0 | { |
154 | 0 | m_aCodeList.emplace_back(new OOp_OR); |
155 | 0 | } |
156 | 0 | else if (SQL_ISTOKEN(pPredicateNode->getChild(1),AND)) // AND-Operator |
157 | 0 | m_aCodeList.emplace_back(new OOp_AND); |
158 | 0 | else |
159 | 0 | { |
160 | 0 | OSL_FAIL("OPredicateCompiler: Error in Parse Tree"); |
161 | 0 | } |
162 | 0 | } |
163 | 57.3k | else if (SQL_ISRULE(pPredicateNode,boolean_factor)) |
164 | 0 | { |
165 | 0 | execute(pPredicateNode->getChild(1)); |
166 | 0 | m_aCodeList.emplace_back(new OOp_NOT); |
167 | 0 | } |
168 | 57.3k | else if (SQL_ISRULE(pPredicateNode,comparison_predicate)) |
169 | 19.1k | { |
170 | 19.1k | execute_COMPARE(pPredicateNode); |
171 | 19.1k | } |
172 | 38.2k | else if (SQL_ISRULE(pPredicateNode,like_predicate)) |
173 | 0 | { |
174 | 0 | execute_LIKE(pPredicateNode); |
175 | 0 | } |
176 | 38.2k | else if (SQL_ISRULE(pPredicateNode,between_predicate)) |
177 | 0 | { |
178 | 0 | execute_BETWEEN(pPredicateNode); |
179 | 0 | } |
180 | 38.2k | else if (SQL_ISRULE(pPredicateNode,test_for_null)) |
181 | 0 | { |
182 | 0 | execute_ISNULL(pPredicateNode); |
183 | 0 | } |
184 | 38.2k | else if(SQL_ISRULE(pPredicateNode,num_value_exp)) |
185 | 0 | { |
186 | 0 | execute(pPredicateNode->getChild(0)); // process the left branch |
187 | 0 | execute(pPredicateNode->getChild(2)); // process the right branch |
188 | 0 | if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"+")) |
189 | 0 | { |
190 | 0 | m_aCodeList.emplace_back(new OOp_ADD); |
191 | 0 | } |
192 | 0 | else if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"-")) |
193 | 0 | m_aCodeList.emplace_back(new OOp_SUB); |
194 | 0 | else |
195 | 0 | { |
196 | 0 | OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp"); |
197 | 0 | } |
198 | 0 | } |
199 | 38.2k | else if(SQL_ISRULE(pPredicateNode,term)) |
200 | 0 | { |
201 | 0 | execute(pPredicateNode->getChild(0)); // process the left branch |
202 | 0 | execute(pPredicateNode->getChild(2)); // process the right branch |
203 | 0 | if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"*")) |
204 | 0 | { |
205 | 0 | m_aCodeList.emplace_back(new OOp_MUL); |
206 | 0 | } |
207 | 0 | else if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"/")) |
208 | 0 | m_aCodeList.emplace_back(new OOp_DIV); |
209 | 0 | else |
210 | 0 | { |
211 | 0 | OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp"); |
212 | 0 | } |
213 | 0 | } |
214 | 38.2k | else |
215 | 38.2k | pOperand = execute_Operand(pPredicateNode); // now only simple operands will be processed |
216 | | |
217 | 66.8k | return pOperand; |
218 | 66.8k | } |
219 | | |
220 | | |
221 | | void OPredicateCompiler::execute_COMPARE(OSQLParseNode const * pPredicateNode) |
222 | 19.1k | { |
223 | 19.1k | DBG_ASSERT(pPredicateNode->count() == 3,"OFILECursor: Error in Parse Tree"); |
224 | | |
225 | 19.1k | if ( !(SQL_ISRULE(pPredicateNode->getChild(0),column_ref) || |
226 | 19.1k | pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::String || |
227 | 19.1k | pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::IntNum || |
228 | 0 | pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::ApproxNum || |
229 | 0 | SQL_ISTOKEN(pPredicateNode->getChild(2),TRUE) || |
230 | 0 | SQL_ISTOKEN(pPredicateNode->getChild(2),FALSE) || |
231 | 0 | SQL_ISRULE(pPredicateNode->getChild(2),parameter) || |
232 | | // odbc date |
233 | 0 | SQL_ISRULE(pPredicateNode->getChild(2),set_fct_spec) || |
234 | 0 | SQL_ISRULE(pPredicateNode->getChild(2),position_exp) || |
235 | 0 | SQL_ISRULE(pPredicateNode->getChild(2),char_substring_fct) || |
236 | | // upper, lower etc. |
237 | 0 | SQL_ISRULE(pPredicateNode->getChild(2),fold)) ) |
238 | 0 | { |
239 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr); |
240 | 0 | return; |
241 | 0 | } |
242 | | |
243 | 19.1k | sal_Int32 ePredicateType( SQLFilterOperator::EQUAL ); |
244 | 19.1k | OSQLParseNode *pPrec = pPredicateNode->getChild(1); |
245 | | |
246 | 19.1k | if (pPrec->getNodeType() == SQLNodeType::Equal) |
247 | 19.1k | ePredicateType = SQLFilterOperator::EQUAL; |
248 | 0 | else if (pPrec->getNodeType() == SQLNodeType::NotEqual) |
249 | 0 | ePredicateType = SQLFilterOperator::NOT_EQUAL; |
250 | 0 | else if (pPrec->getNodeType() == SQLNodeType::Less) |
251 | 0 | ePredicateType = SQLFilterOperator::LESS; |
252 | 0 | else if (pPrec->getNodeType() == SQLNodeType::LessEq) |
253 | 0 | ePredicateType = SQLFilterOperator::LESS_EQUAL; |
254 | 0 | else if (pPrec->getNodeType() == SQLNodeType::GreatEq) |
255 | 0 | ePredicateType = SQLFilterOperator::GREATER_EQUAL; |
256 | 0 | else if (pPrec->getNodeType() == SQLNodeType::Great) |
257 | 0 | ePredicateType = SQLFilterOperator::GREATER; |
258 | 0 | else |
259 | 0 | OSL_FAIL( "OPredicateCompiler::execute_COMPARE: unexpected node type!" ); |
260 | | |
261 | 19.1k | execute(pPredicateNode->getChild(0)); |
262 | 19.1k | execute(pPredicateNode->getChild(2)); |
263 | 19.1k | m_aCodeList.emplace_back( new OOp_COMPARE(ePredicateType) ); |
264 | 19.1k | } |
265 | | |
266 | | |
267 | | void OPredicateCompiler::execute_LIKE(OSQLParseNode const * pPredicateNode) |
268 | 0 | { |
269 | 0 | DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree"); |
270 | 0 | const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); |
271 | |
|
272 | 0 | sal_Unicode cEscape = L'\0'; |
273 | 0 | const bool bNotLike = pPart2->getChild(0)->isToken(); |
274 | |
|
275 | 0 | OSQLParseNode* pAtom = pPart2->getChild(pPart2->count()-2); |
276 | 0 | OSQLParseNode* pOptEscape = pPart2->getChild(pPart2->count()-1); |
277 | |
|
278 | 0 | if (!(pAtom->getNodeType() == SQLNodeType::String || |
279 | 0 | SQL_ISRULE(pAtom,parameter) || |
280 | | // odbc date |
281 | 0 | SQL_ISRULE(pAtom,set_fct_spec) || |
282 | 0 | SQL_ISRULE(pAtom,position_exp) || |
283 | 0 | SQL_ISRULE(pAtom,char_substring_fct) || |
284 | | // upper, lower etc. |
285 | 0 | SQL_ISRULE(pAtom,fold)) ) |
286 | 0 | { |
287 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr); |
288 | 0 | return; |
289 | 0 | } |
290 | | |
291 | 0 | if (pOptEscape->count() != 0) |
292 | 0 | { |
293 | 0 | if (pOptEscape->count() != 2) |
294 | 0 | { |
295 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,nullptr); |
296 | 0 | } |
297 | 0 | OSQLParseNode *pEscNode = pOptEscape->getChild(1); |
298 | 0 | if (pEscNode->getNodeType() != SQLNodeType::String) |
299 | 0 | { |
300 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,nullptr); |
301 | 0 | } |
302 | 0 | else |
303 | 0 | cEscape = pEscNode->getTokenValue().toChar(); |
304 | 0 | } |
305 | |
|
306 | 0 | execute(pPredicateNode->getChild(0)); |
307 | 0 | execute(pAtom); |
308 | |
|
309 | 0 | OBoolOperator* pOperator = bNotLike |
310 | 0 | ? new OOp_NOTLIKE(cEscape) |
311 | 0 | : new OOp_LIKE(cEscape); |
312 | 0 | m_aCodeList.emplace_back(pOperator); |
313 | 0 | } |
314 | | |
315 | | void OPredicateCompiler::execute_BETWEEN(OSQLParseNode const * pPredicateNode) |
316 | 0 | { |
317 | 0 | DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree"); |
318 | |
|
319 | 0 | OSQLParseNode* pColumn = pPredicateNode->getChild(0); |
320 | 0 | const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); |
321 | 0 | OSQLParseNode* p1stValue = pPart2->getChild(2); |
322 | 0 | OSQLParseNode* p2ndtValue = pPart2->getChild(4); |
323 | |
|
324 | 0 | if ( |
325 | 0 | !(p1stValue->getNodeType() == SQLNodeType::String || SQL_ISRULE(p1stValue,parameter)) |
326 | 0 | && !(p2ndtValue->getNodeType() == SQLNodeType::String || SQL_ISRULE(p2ndtValue,parameter)) |
327 | 0 | ) |
328 | 0 | { |
329 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_BETWEEN,nullptr); |
330 | 0 | } |
331 | |
|
332 | 0 | bool bNot = SQL_ISTOKEN(pPart2->getChild(0),NOT); |
333 | |
|
334 | 0 | OOperand* pColumnOp = execute(pColumn); |
335 | 0 | OOperand* pOb1 = execute(p1stValue); |
336 | 0 | OBoolOperator* pOperator = new OOp_COMPARE(bNot ? SQLFilterOperator::LESS : SQLFilterOperator::GREATER_EQUAL); |
337 | 0 | m_aCodeList.emplace_back(pOperator); |
338 | |
|
339 | 0 | execute(pColumn); |
340 | 0 | OOperand* pOb2 = execute(p2ndtValue); |
341 | 0 | pOperator = new OOp_COMPARE(bNot ? SQLFilterOperator::GREATER : SQLFilterOperator::LESS_EQUAL); |
342 | 0 | m_aCodeList.emplace_back(pOperator); |
343 | |
|
344 | 0 | if ( pColumnOp && pOb1 && pOb2 ) |
345 | 0 | { |
346 | 0 | switch(pColumnOp->getDBType()) |
347 | 0 | { |
348 | 0 | case DataType::CHAR: |
349 | 0 | case DataType::VARCHAR: |
350 | 0 | case DataType::LONGVARCHAR: |
351 | 0 | pOb1->setValue(pOb1->getValue().getString()); |
352 | 0 | pOb2->setValue(pOb2->getValue().getString()); |
353 | 0 | break; |
354 | 0 | case DataType::DECIMAL: |
355 | 0 | case DataType::NUMERIC: |
356 | 0 | case DataType::DOUBLE: |
357 | 0 | case DataType::REAL: |
358 | 0 | pOb1->setValue(pOb1->getValue().getDouble()); |
359 | 0 | pOb2->setValue(pOb2->getValue().getDouble()); |
360 | 0 | break; |
361 | 0 | case DataType::FLOAT: |
362 | 0 | pOb1->setValue(pOb1->getValue().getFloat()); |
363 | 0 | pOb2->setValue(pOb2->getValue().getFloat()); |
364 | 0 | break; |
365 | 0 | case DataType::DATE: |
366 | 0 | pOb1->setValue(pOb1->getValue().getDate()); |
367 | 0 | pOb2->setValue(pOb2->getValue().getDate()); |
368 | 0 | break; |
369 | 0 | case DataType::TIME: |
370 | 0 | pOb1->setValue(pOb1->getValue().getTime()); |
371 | 0 | pOb2->setValue(pOb2->getValue().getTime()); |
372 | 0 | break; |
373 | 0 | case DataType::TIMESTAMP: |
374 | 0 | pOb1->setValue(pOb1->getValue().getDateTime()); |
375 | 0 | pOb2->setValue(pOb2->getValue().getDateTime()); |
376 | 0 | break; |
377 | 0 | } |
378 | 0 | } |
379 | | |
380 | | |
381 | 0 | OBoolOperator* pBoolOp = nullptr; |
382 | 0 | if ( bNot ) |
383 | 0 | pBoolOp = new OOp_OR; |
384 | 0 | else |
385 | 0 | pBoolOp = new OOp_AND; |
386 | 0 | m_aCodeList.emplace_back(pBoolOp); |
387 | 0 | } |
388 | | |
389 | | void OPredicateCompiler::execute_ISNULL(OSQLParseNode const * pPredicateNode) |
390 | 0 | { |
391 | 0 | DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree"); |
392 | 0 | const OSQLParseNode* pPart2 = pPredicateNode->getChild(1); |
393 | 0 | DBG_ASSERT(SQL_ISTOKEN(pPart2->getChild(0),IS),"OFILECursor: Error in Parse Tree"); |
394 | |
|
395 | 0 | sal_Int32 ePredicateType; |
396 | 0 | if (SQL_ISTOKEN(pPart2->getChild(1),NOT)) |
397 | 0 | ePredicateType = SQLFilterOperator::NOT_SQLNULL; |
398 | 0 | else |
399 | 0 | ePredicateType = SQLFilterOperator::SQLNULL; |
400 | |
|
401 | 0 | execute(pPredicateNode->getChild(0)); |
402 | 0 | OBoolOperator* pOperator = (ePredicateType == SQLFilterOperator::SQLNULL) ? |
403 | 0 | new OOp_ISNULL : new OOp_ISNOTNULL; |
404 | 0 | m_aCodeList.emplace_back(pOperator); |
405 | 0 | } |
406 | | |
407 | | OOperand* OPredicateCompiler::execute_Operand(OSQLParseNode const * pPredicateNode) |
408 | 38.2k | { |
409 | 38.2k | OOperand* pOperand = nullptr; |
410 | | |
411 | 38.2k | if (SQL_ISRULE(pPredicateNode,column_ref)) |
412 | 0 | { |
413 | 0 | OUString aColumnName; |
414 | 0 | if (pPredicateNode->count() == 1) |
415 | 0 | { |
416 | 0 | aColumnName = pPredicateNode->getChild(0)->getTokenValue(); |
417 | 0 | } |
418 | 0 | else if (pPredicateNode->count() == 3) |
419 | 0 | { |
420 | 0 | if(SQL_ISRULE(pPredicateNode->getChild(2),column_val)) |
421 | 0 | aColumnName = pPredicateNode->getChild(2)->getChild(0)->getTokenValue(); |
422 | 0 | else |
423 | 0 | aColumnName = pPredicateNode->getChild(2)->getTokenValue(); |
424 | 0 | } |
425 | |
|
426 | 0 | if(!m_orgColumns->hasByName(aColumnName)) |
427 | 0 | { |
428 | 0 | const OUString sError( m_pAnalyzer->getConnection()->getResources().getResourceStringWithSubstitution( |
429 | 0 | STR_INVALID_COLUMNNAME, |
430 | 0 | "$columnname$", aColumnName |
431 | 0 | ) ); |
432 | 0 | ::dbtools::throwGenericSQLException( sError, nullptr ); |
433 | 0 | } |
434 | 0 | css::uno::Reference< css::beans::XPropertySet> xCol; |
435 | 0 | try |
436 | 0 | { |
437 | 0 | if (m_orgColumns->getByName(aColumnName) >>= xCol) |
438 | 0 | { |
439 | 0 | pOperand = OSQLAnalyzer::createOperandAttr(Reference< XColumnLocate>(m_orgColumns,UNO_QUERY_THROW)->findColumn(aColumnName),xCol); |
440 | 0 | } |
441 | 0 | else |
442 | 0 | {// Column doesn't exist in the Result-set |
443 | 0 | const OUString sError( m_pAnalyzer->getConnection()->getResources().getResourceStringWithSubstitution( |
444 | 0 | STR_INVALID_COLUMNNAME, |
445 | 0 | "$columnname$", aColumnName |
446 | 0 | ) ); |
447 | 0 | ::dbtools::throwGenericSQLException( sError, nullptr ); |
448 | 0 | } |
449 | 0 | } |
450 | 0 | catch(Exception &) |
451 | 0 | { |
452 | 0 | TOOLS_WARN_EXCEPTION( "connectivity.drivers", "OPredicateCompiler::execute_Operand Exception"); |
453 | 0 | } |
454 | 0 | } |
455 | 38.2k | else if (SQL_ISRULE(pPredicateNode,parameter)) |
456 | 0 | { |
457 | 0 | pOperand = new OOperandParam(++m_nParamCounter); |
458 | 0 | } |
459 | 38.2k | else if (pPredicateNode->getNodeType() == SQLNodeType::String || |
460 | 38.2k | pPredicateNode->getNodeType() == SQLNodeType::IntNum || |
461 | 0 | pPredicateNode->getNodeType() == SQLNodeType::ApproxNum || |
462 | 0 | pPredicateNode->getNodeType() == SQLNodeType::Name || |
463 | 0 | SQL_ISTOKEN(pPredicateNode,TRUE) || |
464 | 0 | SQL_ISTOKEN(pPredicateNode,FALSE) || |
465 | 0 | SQL_ISRULE(pPredicateNode,parameter)) |
466 | 38.2k | { |
467 | 38.2k | pOperand = new OOperandConst(*pPredicateNode, pPredicateNode->getTokenValue()); |
468 | 38.2k | } |
469 | 0 | else if((pPredicateNode->count() == 2) && |
470 | 0 | (SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"+") || SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"-")) && |
471 | 0 | pPredicateNode->getChild(1)->getNodeType() == SQLNodeType::IntNum) |
472 | 0 | { // if -1 or +1 is there |
473 | 0 | OUString aValue = pPredicateNode->getChild(0)->getTokenValue() + pPredicateNode->getChild(1)->getTokenValue(); |
474 | 0 | pOperand = new OOperandConst(*pPredicateNode->getChild(1), aValue); |
475 | 0 | } |
476 | 0 | else if( SQL_ISRULE(pPredicateNode,set_fct_spec) && SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"{") ) |
477 | 0 | { |
478 | 0 | const OSQLParseNode* pODBCNode = pPredicateNode->getChild(1); |
479 | 0 | const OSQLParseNode* pODBCNodeChild = pODBCNode->getChild(0); |
480 | | |
481 | | // Odbc Date or time |
482 | 0 | if (pODBCNodeChild->getNodeType() == SQLNodeType::Keyword && ( |
483 | 0 | SQL_ISTOKEN(pODBCNodeChild,D) || |
484 | 0 | SQL_ISTOKEN(pODBCNodeChild,T) || |
485 | 0 | SQL_ISTOKEN(pODBCNodeChild,TS) )) |
486 | 0 | { |
487 | 0 | OUString sDateTime = pODBCNode->getChild(1)->getTokenValue(); |
488 | 0 | pOperand = new OOperandConst(*pODBCNode->getChild(1), sDateTime); |
489 | 0 | if(SQL_ISTOKEN(pODBCNodeChild,D)) |
490 | 0 | { |
491 | 0 | pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(sDateTime))); |
492 | 0 | } |
493 | 0 | else if(SQL_ISTOKEN(pODBCNodeChild,T)) |
494 | 0 | { |
495 | 0 | pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(sDateTime))); |
496 | 0 | } |
497 | 0 | else if(SQL_ISTOKEN(pODBCNodeChild,TS)) |
498 | 0 | { |
499 | 0 | pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(sDateTime))); |
500 | 0 | } |
501 | 0 | } |
502 | 0 | else |
503 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr); |
504 | |
|
505 | 0 | } |
506 | 0 | else if( SQL_ISRULE(pPredicateNode,fold) ) |
507 | 0 | { |
508 | 0 | execute_Fold(pPredicateNode); |
509 | 0 | } |
510 | 0 | else if( SQL_ISRULE(pPredicateNode,set_fct_spec) |
511 | 0 | || SQL_ISRULE(pPredicateNode,position_exp) |
512 | 0 | || SQL_ISRULE(pPredicateNode,char_substring_fct) |
513 | 0 | ) |
514 | 0 | { |
515 | 0 | executeFunction(pPredicateNode); |
516 | 0 | } |
517 | 0 | else if( SQL_ISRULE(pPredicateNode,length_exp) ) |
518 | 0 | { |
519 | 0 | executeFunction(pPredicateNode->getChild(0)); |
520 | 0 | } |
521 | 0 | else |
522 | 0 | { |
523 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr); |
524 | 0 | } |
525 | 38.2k | if (pOperand) |
526 | 38.2k | m_aCodeList.emplace_back(pOperand); |
527 | 38.2k | return pOperand; |
528 | 38.2k | } |
529 | | |
530 | | |
531 | | bool OPredicateInterpreter::evaluate(OCodeList& rCodeList) |
532 | 0 | { |
533 | 0 | if (!(rCodeList[0])) |
534 | 0 | return true; // no Predicate |
535 | | |
536 | 0 | for (auto const& code : rCodeList) |
537 | 0 | { |
538 | 0 | OOperand* pOperand = dynamic_cast<OOperand* >(code.get()); |
539 | 0 | if (pOperand) |
540 | 0 | m_aStack.push(pOperand); |
541 | 0 | else |
542 | 0 | static_cast<OOperator *>(code.get())->Exec(m_aStack); |
543 | 0 | } |
544 | |
|
545 | 0 | OOperand* pOperand = m_aStack.top(); |
546 | 0 | m_aStack.pop(); |
547 | |
|
548 | 0 | DBG_ASSERT(m_aStack.empty(), "Stack error"); |
549 | 0 | assert(pOperand && "Stack error"); |
550 | |
|
551 | 0 | const bool bResult = pOperand->isValid(); |
552 | 0 | if (typeid(OOperandResult) == typeid(*pOperand)) |
553 | 0 | delete pOperand; |
554 | 0 | return bResult; |
555 | 0 | } |
556 | | |
557 | | void OPredicateInterpreter::evaluateSelection(OCodeList& rCodeList, ORowSetValueDecoratorRef const & _rVal) |
558 | 0 | { |
559 | 0 | if (!(rCodeList[0])) |
560 | 0 | return ; // no Predicate |
561 | | |
562 | 0 | for (auto const& code : rCodeList) |
563 | 0 | { |
564 | 0 | OOperand* pOperand = dynamic_cast<OOperand* >(code.get()); |
565 | 0 | if (pOperand) |
566 | 0 | m_aStack.push(pOperand); |
567 | 0 | else |
568 | 0 | static_cast<OOperator *>(code.get())->Exec(m_aStack); |
569 | 0 | } |
570 | |
|
571 | 0 | OOperand* pOperand = m_aStack.top(); |
572 | 0 | m_aStack.pop(); |
573 | |
|
574 | 0 | DBG_ASSERT(m_aStack.empty(), "Stack error"); |
575 | 0 | assert(pOperand && "Stack error"); |
576 | |
|
577 | 0 | (*_rVal) = pOperand->getValue(); |
578 | 0 | if (typeid(OOperandResult) == typeid(*pOperand)) |
579 | 0 | delete pOperand; |
580 | 0 | } |
581 | | |
582 | | void OPredicateCompiler::execute_Fold(OSQLParseNode const * pPredicateNode) |
583 | 0 | { |
584 | 0 | DBG_ASSERT(pPredicateNode->count() >= 4,"OFILECursor: Error in Parse Tree"); |
585 | |
|
586 | 0 | bool bUpper = SQL_ISTOKEN(pPredicateNode->getChild(0),UPPER); |
587 | |
|
588 | 0 | execute(pPredicateNode->getChild(2)); |
589 | 0 | OOperator* pOperator = nullptr; |
590 | 0 | if ( bUpper ) |
591 | 0 | pOperator = new OOp_Upper; |
592 | 0 | else |
593 | 0 | pOperator = new OOp_Lower; |
594 | |
|
595 | 0 | m_aCodeList.emplace_back(pOperator); |
596 | 0 | } |
597 | | |
598 | | void OPredicateCompiler::executeFunction(OSQLParseNode const * pPredicateNode) |
599 | 0 | { |
600 | 0 | OOperator* pOperator = nullptr; |
601 | |
|
602 | 0 | OSL_ENSURE(pPredicateNode->getChild(0)->isToken(),"The first one must be the name of the function!"); |
603 | 0 | sal_Int32 nTokenId = pPredicateNode->getChild(0)->getTokenID(); |
604 | 0 | switch ( nTokenId ) |
605 | 0 | { |
606 | 0 | case SQL_TOKEN_CHAR_LENGTH: |
607 | 0 | case SQL_TOKEN_LENGTH: |
608 | 0 | case SQL_TOKEN_OCTET_LENGTH: |
609 | 0 | case SQL_TOKEN_ASCII: |
610 | 0 | case SQL_TOKEN_LCASE: |
611 | 0 | case SQL_TOKEN_LTRIM: |
612 | 0 | case SQL_TOKEN_RTRIM: |
613 | 0 | case SQL_TOKEN_SPACE: |
614 | 0 | case SQL_TOKEN_UCASE: |
615 | 0 | case SQL_TOKEN_ABS: |
616 | 0 | case SQL_TOKEN_ACOS: |
617 | 0 | case SQL_TOKEN_ASIN: |
618 | 0 | case SQL_TOKEN_ATAN: |
619 | 0 | case SQL_TOKEN_CEILING: |
620 | 0 | case SQL_TOKEN_COS: |
621 | 0 | case SQL_TOKEN_DEGREES: |
622 | 0 | case SQL_TOKEN_EXP: |
623 | 0 | case SQL_TOKEN_FLOOR: |
624 | 0 | case SQL_TOKEN_LOG10: |
625 | 0 | case SQL_TOKEN_LN: |
626 | 0 | case SQL_TOKEN_RADIANS: |
627 | 0 | case SQL_TOKEN_SIGN: |
628 | 0 | case SQL_TOKEN_SIN: |
629 | 0 | case SQL_TOKEN_SQRT: |
630 | 0 | case SQL_TOKEN_TAN: |
631 | 0 | case SQL_TOKEN_DAYNAME: |
632 | 0 | case SQL_TOKEN_DAYOFMONTH: |
633 | 0 | case SQL_TOKEN_DAYOFWEEK: |
634 | 0 | case SQL_TOKEN_DAYOFYEAR: |
635 | 0 | case SQL_TOKEN_HOUR: |
636 | 0 | case SQL_TOKEN_MINUTE: |
637 | 0 | case SQL_TOKEN_MONTH: |
638 | 0 | case SQL_TOKEN_MONTHNAME: |
639 | 0 | case SQL_TOKEN_QUARTER: |
640 | 0 | case SQL_TOKEN_SECOND: |
641 | 0 | case SQL_TOKEN_YEAR: |
642 | |
|
643 | 0 | execute(pPredicateNode->getChild(2)); |
644 | |
|
645 | 0 | switch( nTokenId ) |
646 | 0 | { |
647 | 0 | case SQL_TOKEN_CHAR_LENGTH: |
648 | 0 | case SQL_TOKEN_LENGTH: |
649 | 0 | case SQL_TOKEN_OCTET_LENGTH: |
650 | 0 | pOperator = new OOp_CharLength; |
651 | 0 | break; |
652 | 0 | case SQL_TOKEN_ASCII: |
653 | 0 | pOperator = new OOp_Ascii; |
654 | 0 | break; |
655 | 0 | case SQL_TOKEN_LCASE: |
656 | 0 | pOperator = new OOp_Lower; |
657 | 0 | break; |
658 | | |
659 | 0 | case SQL_TOKEN_LTRIM: |
660 | 0 | pOperator = new OOp_LTrim; |
661 | 0 | break; |
662 | 0 | case SQL_TOKEN_RTRIM: |
663 | 0 | pOperator = new OOp_RTrim; |
664 | 0 | break; |
665 | 0 | case SQL_TOKEN_SPACE: |
666 | 0 | pOperator = new OOp_Space; |
667 | 0 | break; |
668 | 0 | case SQL_TOKEN_UCASE: |
669 | 0 | pOperator = new OOp_Upper; |
670 | 0 | break; |
671 | 0 | case SQL_TOKEN_ABS: |
672 | 0 | pOperator = new OOp_Abs; |
673 | 0 | break; |
674 | 0 | case SQL_TOKEN_ACOS: |
675 | 0 | pOperator = new OOp_ACos; |
676 | 0 | break; |
677 | 0 | case SQL_TOKEN_ASIN: |
678 | 0 | pOperator = new OOp_ASin; |
679 | 0 | break; |
680 | 0 | case SQL_TOKEN_ATAN: |
681 | 0 | pOperator = new OOp_ATan; |
682 | 0 | break; |
683 | 0 | case SQL_TOKEN_CEILING: |
684 | 0 | pOperator = new OOp_Ceiling; |
685 | 0 | break; |
686 | 0 | case SQL_TOKEN_COS: |
687 | 0 | pOperator = new OOp_Cos; |
688 | 0 | break; |
689 | 0 | case SQL_TOKEN_DEGREES: |
690 | 0 | pOperator = new OOp_Degrees; |
691 | 0 | break; |
692 | 0 | case SQL_TOKEN_EXP: |
693 | 0 | pOperator = new OOp_Exp; |
694 | 0 | break; |
695 | 0 | case SQL_TOKEN_FLOOR: |
696 | 0 | pOperator = new OOp_Floor; |
697 | 0 | break; |
698 | 0 | case SQL_TOKEN_LOG10: |
699 | 0 | pOperator = new OOp_Log10; |
700 | 0 | break; |
701 | 0 | case SQL_TOKEN_LN: |
702 | 0 | pOperator = new OOp_Ln; |
703 | 0 | break; |
704 | 0 | case SQL_TOKEN_RADIANS: |
705 | 0 | pOperator = new OOp_Radians; |
706 | 0 | break; |
707 | 0 | case SQL_TOKEN_SIGN: |
708 | 0 | pOperator = new OOp_Sign; |
709 | 0 | break; |
710 | 0 | case SQL_TOKEN_SIN: |
711 | 0 | pOperator = new OOp_Sin; |
712 | 0 | break; |
713 | 0 | case SQL_TOKEN_SQRT: |
714 | 0 | pOperator = new OOp_Sqrt; |
715 | 0 | break; |
716 | 0 | case SQL_TOKEN_TAN: |
717 | 0 | pOperator = new OOp_Tan; |
718 | 0 | break; |
719 | 0 | case SQL_TOKEN_DAYOFWEEK: |
720 | 0 | pOperator = new OOp_DayOfWeek; |
721 | 0 | break; |
722 | 0 | case SQL_TOKEN_DAYOFMONTH: |
723 | 0 | pOperator = new OOp_DayOfMonth; |
724 | 0 | break; |
725 | 0 | case SQL_TOKEN_DAYOFYEAR: |
726 | 0 | pOperator = new OOp_DayOfYear; |
727 | 0 | break; |
728 | 0 | case SQL_TOKEN_MONTH: |
729 | 0 | pOperator = new OOp_Month; |
730 | 0 | break; |
731 | 0 | case SQL_TOKEN_DAYNAME: |
732 | 0 | pOperator = new OOp_DayName; |
733 | 0 | break; |
734 | 0 | case SQL_TOKEN_MONTHNAME: |
735 | 0 | pOperator = new OOp_MonthName; |
736 | 0 | break; |
737 | 0 | case SQL_TOKEN_QUARTER: |
738 | 0 | pOperator = new OOp_Quarter; |
739 | 0 | break; |
740 | 0 | case SQL_TOKEN_YEAR: |
741 | 0 | pOperator = new OOp_Year; |
742 | 0 | break; |
743 | 0 | case SQL_TOKEN_HOUR: |
744 | 0 | pOperator = new OOp_Hour; |
745 | 0 | break; |
746 | 0 | case SQL_TOKEN_MINUTE: |
747 | 0 | pOperator = new OOp_Minute; |
748 | 0 | break; |
749 | 0 | case SQL_TOKEN_SECOND: |
750 | 0 | pOperator = new OOp_Second; |
751 | 0 | break; |
752 | 0 | default: |
753 | 0 | OSL_FAIL("Error in switch!"); |
754 | 0 | } |
755 | 0 | break; |
756 | 0 | case SQL_TOKEN_CHAR: |
757 | 0 | case SQL_TOKEN_CONCAT: |
758 | 0 | case SQL_TOKEN_INSERT: |
759 | 0 | case SQL_TOKEN_LEFT: |
760 | 0 | case SQL_TOKEN_LOCATE: |
761 | 0 | case SQL_TOKEN_LOCATE_2: |
762 | 0 | case SQL_TOKEN_REPEAT: |
763 | 0 | case SQL_TOKEN_REPLACE: |
764 | 0 | case SQL_TOKEN_RIGHT: |
765 | 0 | case SQL_TOKEN_MOD: |
766 | 0 | case SQL_TOKEN_ROUND: |
767 | 0 | case SQL_TOKEN_LOGF: |
768 | 0 | case SQL_TOKEN_LOG: |
769 | 0 | case SQL_TOKEN_POWER: |
770 | 0 | case SQL_TOKEN_ATAN2: |
771 | 0 | case SQL_TOKEN_PI: |
772 | 0 | case SQL_TOKEN_CURDATE: |
773 | 0 | case SQL_TOKEN_CURTIME: |
774 | 0 | case SQL_TOKEN_NOW: |
775 | 0 | case SQL_TOKEN_WEEK: |
776 | 0 | { |
777 | 0 | m_aCodeList.emplace_back(new OStopOperand); |
778 | 0 | OSQLParseNode* pList = pPredicateNode->getChild(2); |
779 | 0 | for (size_t i=0; i < pList->count(); ++i) |
780 | 0 | execute(pList->getChild(i)); |
781 | |
|
782 | 0 | switch( nTokenId ) |
783 | 0 | { |
784 | 0 | case SQL_TOKEN_CHAR: |
785 | 0 | pOperator = new OOp_Char; |
786 | 0 | break; |
787 | 0 | case SQL_TOKEN_CONCAT: |
788 | 0 | pOperator = new OOp_Concat; |
789 | 0 | break; |
790 | 0 | case SQL_TOKEN_INSERT: |
791 | 0 | pOperator = new OOp_Insert; |
792 | 0 | break; |
793 | 0 | case SQL_TOKEN_LEFT: |
794 | 0 | pOperator = new OOp_Left; |
795 | 0 | break; |
796 | 0 | case SQL_TOKEN_LOCATE: |
797 | 0 | case SQL_TOKEN_LOCATE_2: |
798 | 0 | pOperator = new OOp_Locate; |
799 | 0 | break; |
800 | 0 | case SQL_TOKEN_REPEAT: |
801 | 0 | pOperator = new OOp_Repeat; |
802 | 0 | break; |
803 | 0 | case SQL_TOKEN_REPLACE: |
804 | 0 | pOperator = new OOp_Replace; |
805 | 0 | break; |
806 | 0 | case SQL_TOKEN_RIGHT: |
807 | 0 | pOperator = new OOp_Right; |
808 | 0 | break; |
809 | 0 | case SQL_TOKEN_MOD: |
810 | 0 | pOperator = new OOp_Mod; |
811 | 0 | break; |
812 | 0 | case SQL_TOKEN_ROUND: |
813 | 0 | pOperator = new OOp_Round; |
814 | 0 | break; |
815 | 0 | case SQL_TOKEN_LOGF: |
816 | 0 | case SQL_TOKEN_LOG: |
817 | 0 | pOperator = new OOp_Log; |
818 | 0 | break; |
819 | 0 | case SQL_TOKEN_POWER: |
820 | 0 | pOperator = new OOp_Pow; |
821 | 0 | break; |
822 | 0 | case SQL_TOKEN_ATAN2: |
823 | 0 | pOperator = new OOp_ATan2; |
824 | 0 | break; |
825 | 0 | case SQL_TOKEN_PI: |
826 | 0 | pOperator = new OOp_Pi; |
827 | 0 | break; |
828 | 0 | case SQL_TOKEN_CURDATE: |
829 | 0 | pOperator = new OOp_CurDate; |
830 | 0 | break; |
831 | 0 | case SQL_TOKEN_CURTIME: |
832 | 0 | pOperator = new OOp_CurTime; |
833 | 0 | break; |
834 | 0 | case SQL_TOKEN_NOW: |
835 | 0 | pOperator = new OOp_Now; |
836 | 0 | break; |
837 | 0 | case SQL_TOKEN_WEEK: |
838 | 0 | pOperator = new OOp_Week; |
839 | 0 | break; |
840 | 0 | default: |
841 | 0 | OSL_FAIL("Error in switch!"); |
842 | 0 | } |
843 | 0 | } |
844 | 0 | break; |
845 | | |
846 | 0 | case SQL_TOKEN_SUBSTRING: |
847 | 0 | m_aCodeList.emplace_back(new OStopOperand); |
848 | 0 | if ( pPredicateNode->count() == 4 ) //char_substring_fct |
849 | 0 | { |
850 | 0 | OSQLParseNode* pList = pPredicateNode->getChild(2); |
851 | 0 | for (size_t i=0; i < pList->count(); ++i) |
852 | 0 | execute(pList->getChild(i)); |
853 | 0 | } |
854 | 0 | else |
855 | 0 | { |
856 | 0 | execute(pPredicateNode->getChild(2)); |
857 | 0 | execute(pPredicateNode->getChild(4)); |
858 | 0 | execute(pPredicateNode->getChild(5)->getChild(1)); |
859 | 0 | } |
860 | 0 | pOperator = new OOp_SubString; |
861 | 0 | break; |
862 | | |
863 | 0 | case SQL_TOKEN_POSITION: |
864 | 0 | m_aCodeList.emplace_back(new OStopOperand); |
865 | 0 | if ( pPredicateNode->count() == 4 ) //position_exp |
866 | 0 | { |
867 | 0 | OSQLParseNode* pList = pPredicateNode->getChild(2); |
868 | 0 | for (size_t i=0; i < pList->count(); ++i) |
869 | 0 | execute(pList->getChild(i)); |
870 | 0 | } |
871 | 0 | else |
872 | 0 | { |
873 | 0 | execute(pPredicateNode->getChild(2)); |
874 | 0 | execute(pPredicateNode->getChild(4)); |
875 | 0 | } |
876 | 0 | pOperator = new OOp_Locate; |
877 | 0 | break; |
878 | 0 | default: |
879 | 0 | m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_FUNCTION_NOT_SUPPORTED,nullptr); |
880 | 0 | } |
881 | | |
882 | 0 | m_aCodeList.emplace_back(pOperator); |
883 | 0 | } |
884 | | |
885 | | |
886 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |