bump product version to 4.2.0.1
[LibreOffice.git] / include / connectivity / sqlnode.hxx
blobd1c4cf759b26a32a8f545ad127d19dac7b246eb6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #ifndef INCLUDED_CONNECTIVITY_SQLNODE_HXX
20 #define INCLUDED_CONNECTIVITY_SQLNODE_HXX
22 #include <connectivity/dbtoolsdllapi.hxx>
23 #include <connectivity/dbmetadata.hxx>
24 #include <com/sun/star/uno/Reference.hxx>
25 #include <com/sun/star/util/XNumberFormatTypes.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <vector>
28 #include <functional>
29 #include <set>
30 #include <boost/shared_ptr.hpp>
31 #include <rtl/ustrbuf.hxx>
33 // forward declarations
34 namespace com
36 namespace sun
38 namespace star
40 namespace beans
42 class XPropertySet;
44 namespace util
46 class XNumberFormatter;
48 namespace container
50 class XNameAccess;
56 #define ORDER_BY_CHILD_POS 5
57 #define TABLE_EXPRESSION_CHILD_COUNT 9
59 namespace connectivity
61 class OSQLParser;
62 class OSQLParseNode;
63 class IParseContext;
65 typedef ::std::vector< OSQLParseNode* > OSQLParseNodes;
67 enum SQLNodeType {SQL_NODE_RULE, SQL_NODE_LISTRULE, SQL_NODE_COMMALISTRULE,
68 SQL_NODE_KEYWORD, SQL_NODE_COMPARISON, SQL_NODE_NAME,
69 SQL_NODE_STRING, SQL_NODE_INTNUM, SQL_NODE_APPROXNUM,
70 SQL_NODE_EQUAL,SQL_NODE_LESS,SQL_NODE_GREAT,SQL_NODE_LESSEQ,SQL_NODE_GREATEQ,SQL_NODE_NOTEQUAL,
71 SQL_NODE_PUNCTUATION, SQL_NODE_AMMSC, SQL_NODE_ACCESS_DATE,SQL_NODE_DATE,SQL_NODE_CONCAT};
73 typedef ::std::set< OUString > QueryNameSet;
74 //==================================================================
75 //= SQLParseNodeParameter
76 //==================================================================
77 struct OOO_DLLPUBLIC_DBTOOLS SQLParseNodeParameter
79 const ::com::sun::star::lang::Locale& rLocale;
80 ::dbtools::DatabaseMetaData aMetaData;
81 OSQLParser* pParser;
82 ::boost::shared_ptr< QueryNameSet > pSubQueryHistory;
83 ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > xFormatter;
84 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xField;
85 OUString sPredicateTableAlias;
86 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xQueries; // see bParseToSDBCLevel
87 const IParseContext& m_rContext;
88 sal_Char cDecSep;
89 bool bQuote : 1; /// should we quote identifiers?
90 bool bInternational : 1; /// should we internationalize keywords and placeholders?
91 bool bPredicate : 1; /// are we going to parse a mere predicate?
92 bool bParseToSDBCLevel : 1; /// should we create an SDBC-level statement (e.g. with substituted sub queries)?
94 SQLParseNodeParameter(
95 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
96 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _xFormatter,
97 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xField,
98 const OUString &_sPredicateTableAlias,
99 const ::com::sun::star::lang::Locale& _rLocale,
100 const IParseContext* _pContext,
101 bool _bIntl,
102 bool _bQuote,
103 sal_Char _cDecSep,
104 bool _bPredicate,
105 bool _bParseToSDBC
107 ~SQLParseNodeParameter();
110 //==========================================================================
111 //= OSQLParseNode
112 //==========================================================================
113 class OOO_DLLPUBLIC_DBTOOLS OSQLParseNode
115 friend class OSQLParser;
117 OSQLParseNodes m_aChildren;
118 OSQLParseNode* m_pParent; // pParent for reverse linkage in the tree
119 OUString m_aNodeValue; // token name, or empty in case of rules,
120 // or OUString in case of
121 // OUString, INT, etc.
122 SQLNodeType m_eNodeType; // see above
123 sal_uInt32 m_nNodeID; // ::com::sun::star::chaos::Rule ID (if IsRule())
124 // or Token ID (if !IsRule())
125 // ::com::sun::star::chaos::Rule IDs and Token IDs can't
126 // be distinguished by their values,
127 // IsRule has to be used for that!
128 public:
129 enum Rule
131 UNKNOWN_RULE = 0, // ID indicating that a node is no rule with a matching Rule-enum value (see getKnownRuleID)
132 // we make sure it is 0 so that it is the default-constructor value of this enum
133 // and std::map<foo,Rule>::operator[](bar) default-inserts UNKNOWN_RULE rather than select_statement (!)
134 select_statement,
135 table_exp,
136 table_ref_commalist,
137 table_ref,
138 catalog_name,
139 schema_name,
140 table_name,
141 opt_column_commalist,
142 column_commalist,
143 column_ref_commalist,
144 column_ref,
145 opt_order_by_clause,
146 ordering_spec_commalist,
147 ordering_spec,
148 opt_asc_desc,
149 where_clause,
150 opt_where_clause,
151 search_condition,
152 comparison,
153 comparison_predicate,
154 between_predicate,
155 like_predicate,
156 opt_escape,
157 test_for_null,
158 scalar_exp_commalist,
159 scalar_exp,
160 parameter_ref,
161 parameter,
162 general_set_fct,
163 range_variable,
164 column,
165 delete_statement_positioned,
166 delete_statement_searched,
167 update_statement_positioned,
168 update_statement_searched,
169 assignment_commalist,
170 assignment,
171 values_or_query_spec,
172 insert_statement,
173 insert_atom_commalist,
174 insert_atom,
175 from_clause,
176 qualified_join,
177 cross_union,
178 select_sublist,
179 derived_column,
180 column_val,
181 set_fct_spec,
182 boolean_term,
183 boolean_primary,
184 num_value_exp,
185 join_type,
186 position_exp,
187 extract_exp,
188 length_exp,
189 char_value_fct,
190 odbc_call_spec,
191 in_predicate,
192 existence_test,
193 unique_test,
194 all_or_any_predicate,
195 named_columns_join,
196 join_condition,
197 joined_table,
198 boolean_factor,
199 sql_not,
200 manipulative_statement,
201 subquery,
202 value_exp_commalist,
203 odbc_fct_spec,
204 union_statement,
205 outer_join_type,
206 char_value_exp,
207 term,
208 value_exp_primary,
209 value_exp,
210 selection,
211 fold,
212 char_substring_fct,
213 factor,
214 base_table_def,
215 base_table_element_commalist,
216 data_type,
217 column_def,
218 table_node,
219 as_clause,
220 opt_as,
221 op_column_commalist,
222 table_primary_as_range_column,
223 datetime_primary,
224 concatenation,
225 char_factor,
226 bit_value_fct,
227 comparison_predicate_part_2,
228 parenthesized_boolean_value_expression,
229 character_string_type,
230 other_like_predicate_part_2,
231 between_predicate_part_2,
232 cast_spec,
233 window_function,
234 rule_count // last value
237 // must be ascii encoding for the value
238 OSQLParseNode(const sal_Char* _pValueStr,
239 SQLNodeType _eNodeType,
240 sal_uInt32 _nNodeID = 0);
242 OSQLParseNode(const OString& _rValue,
243 SQLNodeType eNewNodeType,
244 sal_uInt32 nNewNodeID=0);
246 OSQLParseNode(const OUString& _rValue,
247 SQLNodeType _eNodeType,
248 sal_uInt32 _nNodeID = 0);
250 // copies the respective ParseNode
251 OSQLParseNode(const OSQLParseNode& rParseNode);
252 OSQLParseNode& operator=(const OSQLParseNode& rParseNode);
254 sal_Bool operator==(OSQLParseNode& rParseNode) const;
256 // destructor destructs the tree recursively
257 virtual ~OSQLParseNode();
259 OSQLParseNode* getParent() const {return m_pParent;};
261 void setParent(OSQLParseNode* pParseNode) {m_pParent = pParseNode;};
263 size_t count() const {return m_aChildren.size();};
264 inline OSQLParseNode* getChild(sal_uInt32 nPos) const;
266 void append(OSQLParseNode* pNewSubTree);
267 void insert(sal_uInt32 nPos, OSQLParseNode* pNewSubTree);
269 OSQLParseNode* replace(OSQLParseNode* pOldSubTree, OSQLParseNode* pNewSubTree);
271 OSQLParseNode* removeAt(sal_uInt32 nPos);
273 void replaceNodeValue(const OUString& rTableAlias,const OUString& rColumnName);
275 /** parses the node to a string which can be passed to a driver's connection for execution
277 Any particles of the parse tree which represent application-level features - such
278 as queries appearing in the FROM part - are substituted, so that the resulting statement can
279 be executed at an SDBC-level connection.
281 @param _out_rString
282 is an output parameter taking the resulting SQL statement
284 @param _rxConnection
285 the connection relative to which to parse. This must be an SDB-level connection (e.g.
286 support the XQueriesSupplier interface) for the method to be able to do all necessary
287 substitutions.
289 @param _rParser
290 the SQLParser used to create the node. This is needed in case we need to parse
291 sub queries which are present in the SQL statement - those sub queries need to be parsed,
292 too, to check whether they contain nested sub queries.
294 @param _pErrorHolder
295 takes the error which occurred while generating the statement, if any. Might be <NULL/>,
296 in this case the error is not reported back, and can only be recognized by examing the
297 return value.
299 @return
300 <TRUE/> if and only if the parsing was successful.<br/>
302 Currently, there's only one condition how this method can fail: If it contains a nested
303 query which causes a cycle. E.g., consider a statement <code>SELECT * from "foo"</code>,
304 where <code>foo</code> is a query defined as <code>SELECT * FROM "bar"</code>, where
305 <code>bar</code> is defined as <code>SELECT * FROM "foo"</code>. This statement obviously
306 cannot be parsed to an executable statement.
308 If this method returns <FALSE/>, you're encouraged to check and handle the error in
309 <arg>_pErrorHolder</arg>.
311 bool parseNodeToExecutableStatement( OUString& _out_rString,
312 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
313 OSQLParser& _rParser,
314 ::com::sun::star::sdbc::SQLException* _pErrorHolder ) const;
316 void parseNodeToStr(OUString& rString,
317 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
318 const IParseContext* pContext = NULL,
319 bool _bIntl = sal_False,
320 bool _bQuote= sal_True) const;
322 // quoted and internationalised
323 void parseNodeToPredicateStr(OUString& rString,
324 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
325 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
326 const ::com::sun::star::lang::Locale& rIntl,
327 sal_Char _cDec,
328 const IParseContext* pContext = NULL ) const;
330 void parseNodeToPredicateStr(OUString& rString,
331 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
332 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
333 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _xField,
334 const OUString &_sTableAlias,
335 const ::com::sun::star::lang::Locale& rIntl,
336 sal_Char _cDec,
337 const IParseContext* pContext = NULL ) const;
339 OSQLParseNode* getByRule(OSQLParseNode::Rule eRule) const;
341 #if OSL_DEBUG_LEVEL > 1
342 // shows the ParseTree with tabs and linefeeds
343 void showParseTree( OUString& rString ) const;
344 void showParseTree( OUStringBuffer& _inout_rBuf, sal_uInt32 nLevel ) const;
345 #endif
347 SQLNodeType getNodeType() const {return m_eNodeType;};
349 // RuleId returns the RuleID of the node's rule (only if IsRule())
350 sal_uInt32 getRuleID() const {return m_nNodeID;}
352 /** returns the ID of the rule represented by the node
353 If the node does not represent a rule, UNKNOWN_RULE is returned
355 Rule getKnownRuleID() const;
357 // returns the TokenId of the node's token (only if !isRule())
358 sal_uInt32 getTokenID() const {return m_nNodeID;}
360 // IsRule tests whether a node is a rule (NonTerminal)
361 // ATTENTION: rules can be leaves, for example empty lists
362 sal_Bool isRule() const
363 { return (m_eNodeType == SQL_NODE_RULE) || (m_eNodeType == SQL_NODE_LISTRULE)
364 || (m_eNodeType == SQL_NODE_COMMALISTRULE);}
366 // IsToken tests whether a Node is a Token (Terminal but not a rule)
367 sal_Bool isToken() const {return !isRule();}
369 const OUString& getTokenValue() const {return m_aNodeValue;}
371 void setTokenValue(const OUString& rString) { if (isToken()) m_aNodeValue = rString;}
373 sal_Bool isLeaf() const {return m_aChildren.empty();}
375 // negate only a searchcondition, any other rule could cause a gpf
376 static void negateSearchCondition(OSQLParseNode*& pSearchCondition,sal_Bool bNegate=sal_False);
378 // normalize a logic form
379 // e.q. (a or b) and (c or d) <=> a and c or a and d or b and c or b and d
380 static void disjunctiveNormalForm(OSQLParseNode*& pSearchCondition);
382 // Simplifies logic expressions
383 // a and a = a
384 // a or a = a
385 // a and ( a + b) = a
386 // a or a and b = a
387 static void absorptions(OSQLParseNode*& pSearchCondition);
389 // erase unnecessary braces
390 static void eraseBraces(OSQLParseNode*& pSearchCondition);
392 // makes the logic formula a little smaller
393 static void compress(OSQLParseNode*& pSearchCondition);
394 // return the catalog, schema and tablename form this node
395 // _pTableNode must be a rule of that above or a SQL_TOKEN_NAME
396 static sal_Bool getTableComponents(const OSQLParseNode* _pTableNode,
397 ::com::sun::star::uno::Any &_rCatalog,
398 OUString &_rSchema,
399 OUString &_rTable
400 ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _xMetaData);
402 // substitute all occurrences of :var or [name] into the dynamic parameter ?
403 // _pNode will be modified if parameters exists
404 static void substituteParameterNames(OSQLParseNode* _pNode);
406 /** return a table range when it exists.
408 static OUString getTableRange(const OSQLParseNode* _pTableRef);
410 protected:
411 // ParseNodeToStr concatenates all Tokens (leaves) of the ParseNodes.
412 void parseNodeToStr(OUString& rString,
413 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
414 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
415 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _xField,
416 const OUString &_sPredicateTableAlias,
417 const ::com::sun::star::lang::Locale& rIntl,
418 const IParseContext* pContext,
419 bool _bIntl,
420 bool _bQuote,
421 sal_Char _cDecSep,
422 bool _bPredicate,
423 bool _bSubstitute) const;
425 private:
426 void impl_parseNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple=true ) const;
427 void impl_parseLikeNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple=true ) const;
428 void impl_parseTableRangeNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const;
430 /** parses a table_name node into a SQL statement particle.
431 @return
432 <TRUE/> if and only if parsing was successful, <FALSE/> if default handling should
433 be applied.
435 bool impl_parseTableNameNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const;
437 sal_Bool addDateValue(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const;
438 OUString convertDateTimeString(const SQLParseNodeParameter& rParam, const OUString& rString) const;
439 OUString convertDateString(const SQLParseNodeParameter& rParam, const OUString& rString) const;
440 OUString convertTimeString(const SQLParseNodeParameter& rParam, const OUString& rString) const;
441 void parseLeaf(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const;
444 //-----------------------------------------------------------------------------
445 inline OSQLParseNode* OSQLParseNode::getChild(sal_uInt32 nPos) const
447 OSL_ENSURE(nPos < m_aChildren.size(), "Invalid Position");
449 // return m_aChildren[nPos];
450 return m_aChildren.at(nPos);
453 // utilities to query for a specific rule, token or punctuation
454 #define SQL_ISRULE(pParseNode, eRule) ((pParseNode)->isRule() && (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::eRule))
455 #define SQL_ISRULEOR2(pParseNode, e1, e2) ((pParseNode)->isRule() && ( \
456 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
457 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
458 #define SQL_ISRULEOR3(pParseNode, e1, e2, e3) ((pParseNode)->isRule() && ( \
459 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
460 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2) || \
461 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e3)))
462 #define SQL_ISTOKEN(pParseNode, token) ((pParseNode)->isToken() && (pParseNode)->getTokenID() == SQL_TOKEN_##token)
463 #define SQL_ISTOKENOR2(pParseNode, tok0, tok1) ((pParseNode)->isToken() && ( (pParseNode)->getTokenID() == SQL_TOKEN_##tok0 || (pParseNode)->getTokenID() == SQL_TOKEN_##tok1 ))
464 #define SQL_ISTOKENOR3(pParseNode, tok0, tok1, tok2) ((pParseNode)->isToken() && ( (pParseNode)->getTokenID() == SQL_TOKEN_##tok0 || (pParseNode)->getTokenID() == SQL_TOKEN_##tok1 || (pParseNode)->getTokenID() == SQL_TOKEN_##tok2 ))
465 #define SQL_ISPUNCTUATION(pParseNode, aString) ((pParseNode)->getNodeType() == SQL_NODE_PUNCTUATION && !(pParseNode)->getTokenValue().compareToAscii(aString))
468 #endif // INCLUDED_CONNECTIVITY_SQLNODE_HXX
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */