1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski #ifndef _CONNECTIVITY_SQLNODE_HXX
24*b1cdbd2cSJim Jagielski #define _CONNECTIVITY_SQLNODE_HXX
25*b1cdbd2cSJim Jagielski 
26*b1cdbd2cSJim Jagielski #include "connectivity/dbtoolsdllapi.hxx"
27*b1cdbd2cSJim Jagielski #include "connectivity/dbmetadata.hxx"
28*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/Reference.hxx>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XNumberFormatTypes.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/XPropertySet.hpp>
31*b1cdbd2cSJim Jagielski #include <vector>
32*b1cdbd2cSJim Jagielski #include <functional>
33*b1cdbd2cSJim Jagielski #include <set>
34*b1cdbd2cSJim Jagielski #include <boost/shared_ptr.hpp>
35*b1cdbd2cSJim Jagielski #include <rtl/ustrbuf.hxx>
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski // forward declarations
38*b1cdbd2cSJim Jagielski namespace com
39*b1cdbd2cSJim Jagielski {
40*b1cdbd2cSJim Jagielski 	namespace sun
41*b1cdbd2cSJim Jagielski 	{
42*b1cdbd2cSJim Jagielski 		namespace star
43*b1cdbd2cSJim Jagielski 		{
44*b1cdbd2cSJim Jagielski 			namespace beans
45*b1cdbd2cSJim Jagielski 			{
46*b1cdbd2cSJim Jagielski 				class XPropertySet;
47*b1cdbd2cSJim Jagielski 			}
48*b1cdbd2cSJim Jagielski 			namespace util
49*b1cdbd2cSJim Jagielski 			{
50*b1cdbd2cSJim Jagielski 				class XNumberFormatter;
51*b1cdbd2cSJim Jagielski 			}
52*b1cdbd2cSJim Jagielski             namespace container
53*b1cdbd2cSJim Jagielski             {
54*b1cdbd2cSJim Jagielski                 class XNameAccess;
55*b1cdbd2cSJim Jagielski             }
56*b1cdbd2cSJim Jagielski 		}
57*b1cdbd2cSJim Jagielski 	}
58*b1cdbd2cSJim Jagielski }
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski namespace rtl
61*b1cdbd2cSJim Jagielski {
62*b1cdbd2cSJim Jagielski     class OUStringBuffer;
63*b1cdbd2cSJim Jagielski }
64*b1cdbd2cSJim Jagielski #define ORDER_BY_CHILD_POS  5
65*b1cdbd2cSJim Jagielski #define TABLE_EXPRESSION_CHILD_COUNT    9
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski namespace connectivity
68*b1cdbd2cSJim Jagielski {
69*b1cdbd2cSJim Jagielski     class OSQLParser;
70*b1cdbd2cSJim Jagielski 	class OSQLParseNode;
71*b1cdbd2cSJim Jagielski 	class IParseContext;
72*b1cdbd2cSJim Jagielski 
73*b1cdbd2cSJim Jagielski     typedef ::std::vector< OSQLParseNode* >                  OSQLParseNodes;
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski 	enum SQLNodeType	{SQL_NODE_RULE, SQL_NODE_LISTRULE, SQL_NODE_COMMALISTRULE,
76*b1cdbd2cSJim Jagielski 						 SQL_NODE_KEYWORD, SQL_NODE_COMPARISON, SQL_NODE_NAME,
77*b1cdbd2cSJim Jagielski 						 SQL_NODE_STRING,	SQL_NODE_INTNUM, SQL_NODE_APPROXNUM,
78*b1cdbd2cSJim Jagielski 						 SQL_NODE_EQUAL,SQL_NODE_LESS,SQL_NODE_GREAT,SQL_NODE_LESSEQ,SQL_NODE_GREATEQ,SQL_NODE_NOTEQUAL,
79*b1cdbd2cSJim Jagielski 						 SQL_NODE_PUNCTUATION, SQL_NODE_AMMSC, SQL_NODE_ACCESS_DATE,SQL_NODE_DATE,SQL_NODE_CONCAT};
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski     typedef ::std::set< ::rtl::OUString >   QueryNameSet;
82*b1cdbd2cSJim Jagielski     //==================================================================
83*b1cdbd2cSJim Jagielski     //= SQLParseNodeParameter
84*b1cdbd2cSJim Jagielski     //==================================================================
85*b1cdbd2cSJim Jagielski     struct OOO_DLLPUBLIC_DBTOOLS SQLParseNodeParameter
86*b1cdbd2cSJim Jagielski     {
87*b1cdbd2cSJim Jagielski 	    const ::com::sun::star::lang::Locale&	rLocale;
88*b1cdbd2cSJim Jagielski         ::dbtools::DatabaseMetaData             aMetaData;
89*b1cdbd2cSJim Jagielski         OSQLParser*                             pParser;
90*b1cdbd2cSJim Jagielski         ::boost::shared_ptr< QueryNameSet >     pSubQueryHistory;
91*b1cdbd2cSJim Jagielski 	    ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >    xFormatter;
92*b1cdbd2cSJim Jagielski 	    ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >       xField;
93*b1cdbd2cSJim Jagielski 	    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    xQueries;  // see bParseToSDBCLevel
94*b1cdbd2cSJim Jagielski 	    const IParseContext& m_rContext;
95*b1cdbd2cSJim Jagielski 	    sal_Char			cDecSep;
96*b1cdbd2cSJim Jagielski 	    bool                bQuote                      : 1;    /// should we quote identifiers?
97*b1cdbd2cSJim Jagielski 	    bool                bInternational              : 1;    /// should we internationalize keywords and placeholders?
98*b1cdbd2cSJim Jagielski 	    bool                bPredicate                  : 1;    /// are we going to parse a mere predicate?
99*b1cdbd2cSJim Jagielski         bool                bParseToSDBCLevel           : 1;    /// should we create an SDBC-level statement (e.g. with substituted sub queries)?
100*b1cdbd2cSJim Jagielski 
101*b1cdbd2cSJim Jagielski 	    SQLParseNodeParameter(
102*b1cdbd2cSJim Jagielski             const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
103*b1cdbd2cSJim Jagielski 		    const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _xFormatter,
104*b1cdbd2cSJim Jagielski             const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xField,
105*b1cdbd2cSJim Jagielski 		    const ::com::sun::star::lang::Locale& _rLocale,
106*b1cdbd2cSJim Jagielski             const IParseContext* _pContext,
107*b1cdbd2cSJim Jagielski 		    bool _bIntl,
108*b1cdbd2cSJim Jagielski             bool _bQuote,
109*b1cdbd2cSJim Jagielski             sal_Char _cDecSep,
110*b1cdbd2cSJim Jagielski             bool _bPredicate,
111*b1cdbd2cSJim Jagielski             bool _bParseToSDBC
112*b1cdbd2cSJim Jagielski         );
113*b1cdbd2cSJim Jagielski         ~SQLParseNodeParameter();
114*b1cdbd2cSJim Jagielski     };
115*b1cdbd2cSJim Jagielski 
116*b1cdbd2cSJim Jagielski 	//==========================================================================
117*b1cdbd2cSJim Jagielski 	//= OSQLParseNode
118*b1cdbd2cSJim Jagielski 	//==========================================================================
119*b1cdbd2cSJim Jagielski 	class OOO_DLLPUBLIC_DBTOOLS OSQLParseNode
120*b1cdbd2cSJim Jagielski 	{
121*b1cdbd2cSJim Jagielski 		friend class OSQLParser;
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski 		OSQLParseNodes					m_aChildren;
124*b1cdbd2cSJim Jagielski 		OSQLParseNode*	 				m_pParent;		// pParent fuer Reuckverkettung im Baum
125*b1cdbd2cSJim Jagielski 		::rtl::OUString 				m_aNodeValue;	// Token-Name oder leer bei Regeln oder ::rtl::OUString bei
126*b1cdbd2cSJim Jagielski 														// ::rtl::OUString, INT, usw. -Werten
127*b1cdbd2cSJim Jagielski 		SQLNodeType 					m_eNodeType;	// s. o.
128*b1cdbd2cSJim Jagielski 		sal_uInt32						m_nNodeID; 		// ::com::sun::star::chaos::Rule ID (bei IsRule()) oder Token ID (bei !IsRule())
129*b1cdbd2cSJim Jagielski 											// ::com::sun::star::chaos::Rule IDs und Token IDs koennen nicht anhand des Wertes
130*b1cdbd2cSJim Jagielski 											// unterschieden werden, dafuer ist IsRule() abzufragen!
131*b1cdbd2cSJim Jagielski 	public:
132*b1cdbd2cSJim Jagielski 		enum Rule
133*b1cdbd2cSJim Jagielski 		{
134*b1cdbd2cSJim Jagielski 			select_statement = 0,
135*b1cdbd2cSJim Jagielski 			table_exp,
136*b1cdbd2cSJim Jagielski 			table_ref_commalist,
137*b1cdbd2cSJim Jagielski 			table_ref,
138*b1cdbd2cSJim Jagielski 			catalog_name,
139*b1cdbd2cSJim Jagielski 			schema_name,
140*b1cdbd2cSJim Jagielski 			table_name,
141*b1cdbd2cSJim Jagielski 			opt_column_commalist,
142*b1cdbd2cSJim Jagielski 			column_commalist,
143*b1cdbd2cSJim Jagielski 			column_ref_commalist,
144*b1cdbd2cSJim Jagielski 			column_ref,
145*b1cdbd2cSJim Jagielski 			opt_order_by_clause,
146*b1cdbd2cSJim Jagielski 			ordering_spec_commalist,
147*b1cdbd2cSJim Jagielski 			ordering_spec,
148*b1cdbd2cSJim Jagielski 			opt_asc_desc,
149*b1cdbd2cSJim Jagielski 			where_clause,
150*b1cdbd2cSJim Jagielski 			opt_where_clause,
151*b1cdbd2cSJim Jagielski 			search_condition,
152*b1cdbd2cSJim Jagielski 			comparison_predicate,
153*b1cdbd2cSJim Jagielski 			between_predicate,
154*b1cdbd2cSJim Jagielski 			like_predicate,
155*b1cdbd2cSJim Jagielski 			opt_escape,
156*b1cdbd2cSJim Jagielski 			test_for_null,
157*b1cdbd2cSJim Jagielski 			scalar_exp_commalist,
158*b1cdbd2cSJim Jagielski 			scalar_exp,
159*b1cdbd2cSJim Jagielski 			parameter_ref,
160*b1cdbd2cSJim Jagielski 			parameter,
161*b1cdbd2cSJim Jagielski 			general_set_fct,
162*b1cdbd2cSJim Jagielski 			range_variable,
163*b1cdbd2cSJim Jagielski 			column,
164*b1cdbd2cSJim Jagielski 			delete_statement_positioned,
165*b1cdbd2cSJim Jagielski 			delete_statement_searched,
166*b1cdbd2cSJim Jagielski 			update_statement_positioned,
167*b1cdbd2cSJim Jagielski 			update_statement_searched,
168*b1cdbd2cSJim Jagielski 			assignment_commalist,
169*b1cdbd2cSJim Jagielski 			assignment,
170*b1cdbd2cSJim Jagielski 			values_or_query_spec,
171*b1cdbd2cSJim Jagielski 			insert_statement,
172*b1cdbd2cSJim Jagielski 			insert_atom_commalist,
173*b1cdbd2cSJim Jagielski 			insert_atom,
174*b1cdbd2cSJim Jagielski 			predicate_check,
175*b1cdbd2cSJim Jagielski 			from_clause,
176*b1cdbd2cSJim Jagielski 			qualified_join,
177*b1cdbd2cSJim Jagielski 			cross_union,
178*b1cdbd2cSJim Jagielski 			select_sublist,
179*b1cdbd2cSJim Jagielski 			derived_column,
180*b1cdbd2cSJim Jagielski 			column_val,
181*b1cdbd2cSJim Jagielski 			set_fct_spec,
182*b1cdbd2cSJim Jagielski 			boolean_term,
183*b1cdbd2cSJim Jagielski 			boolean_primary,
184*b1cdbd2cSJim Jagielski 			num_value_exp,
185*b1cdbd2cSJim Jagielski 			join_type,
186*b1cdbd2cSJim Jagielski 			position_exp,
187*b1cdbd2cSJim Jagielski 			extract_exp,
188*b1cdbd2cSJim Jagielski 			length_exp,
189*b1cdbd2cSJim Jagielski 			char_value_fct,
190*b1cdbd2cSJim Jagielski 			odbc_call_spec,
191*b1cdbd2cSJim Jagielski 			in_predicate,
192*b1cdbd2cSJim Jagielski 			existence_test,
193*b1cdbd2cSJim Jagielski 			unique_test,
194*b1cdbd2cSJim Jagielski 			all_or_any_predicate,
195*b1cdbd2cSJim Jagielski 			named_columns_join,
196*b1cdbd2cSJim Jagielski 			join_condition,
197*b1cdbd2cSJim Jagielski             joined_table,
198*b1cdbd2cSJim Jagielski 			boolean_factor,
199*b1cdbd2cSJim Jagielski 			sql_not,
200*b1cdbd2cSJim Jagielski 			boolean_test,
201*b1cdbd2cSJim Jagielski 			manipulative_statement,
202*b1cdbd2cSJim Jagielski 			subquery,
203*b1cdbd2cSJim Jagielski 			value_exp_commalist,
204*b1cdbd2cSJim Jagielski 			odbc_fct_spec,
205*b1cdbd2cSJim Jagielski 			union_statement,
206*b1cdbd2cSJim Jagielski 			outer_join_type,
207*b1cdbd2cSJim Jagielski 			char_value_exp,
208*b1cdbd2cSJim Jagielski 			term,
209*b1cdbd2cSJim Jagielski 			value_exp_primary,
210*b1cdbd2cSJim Jagielski 			value_exp,
211*b1cdbd2cSJim Jagielski 			selection,
212*b1cdbd2cSJim Jagielski 			fold,
213*b1cdbd2cSJim Jagielski 			char_substring_fct,
214*b1cdbd2cSJim Jagielski 			factor,
215*b1cdbd2cSJim Jagielski             base_table_def,
216*b1cdbd2cSJim Jagielski             base_table_element_commalist,
217*b1cdbd2cSJim Jagielski             data_type,
218*b1cdbd2cSJim Jagielski             column_def,
219*b1cdbd2cSJim Jagielski             table_node,
220*b1cdbd2cSJim Jagielski             as,
221*b1cdbd2cSJim Jagielski             op_column_commalist,
222*b1cdbd2cSJim Jagielski             table_primary_as_range_column,
223*b1cdbd2cSJim Jagielski             datetime_primary,
224*b1cdbd2cSJim Jagielski             concatenation,
225*b1cdbd2cSJim Jagielski             char_factor,
226*b1cdbd2cSJim Jagielski             bit_value_fct,
227*b1cdbd2cSJim Jagielski             comparison_predicate_part_2,
228*b1cdbd2cSJim Jagielski             parenthesized_boolean_value_expression,
229*b1cdbd2cSJim Jagielski             character_string_type,
230*b1cdbd2cSJim Jagielski             other_like_predicate_part_2,
231*b1cdbd2cSJim Jagielski             between_predicate_part_2,
232*b1cdbd2cSJim Jagielski             cast_spec,
233*b1cdbd2cSJim Jagielski             rule_count,             // letzter_wert
234*b1cdbd2cSJim Jagielski             UNKNOWN_RULE            // ID indicating that a node is no rule with a matching Rule-enum value (see getKnownRuleID)
235*b1cdbd2cSJim Jagielski 		};
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski 		// must be ascii encoding for the value
238*b1cdbd2cSJim Jagielski 		OSQLParseNode(const sal_Char* _pValueStr,
239*b1cdbd2cSJim Jagielski 					  SQLNodeType _eNodeType,
240*b1cdbd2cSJim Jagielski 					  sal_uInt32 _nNodeID = 0);
241*b1cdbd2cSJim Jagielski 
242*b1cdbd2cSJim Jagielski 		OSQLParseNode(const ::rtl::OString& _rValue,
243*b1cdbd2cSJim Jagielski 					  SQLNodeType eNewNodeType,
244*b1cdbd2cSJim Jagielski 					  sal_uInt32 nNewNodeID=0);
245*b1cdbd2cSJim Jagielski 
246*b1cdbd2cSJim Jagielski 		OSQLParseNode(const sal_Unicode* _pValue,
247*b1cdbd2cSJim Jagielski 					  SQLNodeType _eNodeType,
248*b1cdbd2cSJim Jagielski 					  sal_uInt32 _nNodeID = 0);
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski 		OSQLParseNode(const ::rtl::OUString& _rValue,
251*b1cdbd2cSJim Jagielski 					  SQLNodeType _eNodeType,
252*b1cdbd2cSJim Jagielski 					  sal_uInt32 _nNodeID = 0);
253*b1cdbd2cSJim Jagielski 
254*b1cdbd2cSJim Jagielski 			// Kopiert den entsprechenden ParseNode
255*b1cdbd2cSJim Jagielski 		OSQLParseNode(const OSQLParseNode& rParseNode);
256*b1cdbd2cSJim Jagielski 		OSQLParseNode& operator=(const OSQLParseNode& rParseNode);
257*b1cdbd2cSJim Jagielski 
258*b1cdbd2cSJim Jagielski 		sal_Bool operator==(OSQLParseNode& rParseNode) const;
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski 		// Destruktor raeumt rekursiv den Baum ab
261*b1cdbd2cSJim Jagielski 		virtual ~OSQLParseNode();
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski 		// Parent gibt den Zeiger auf den Parent zurueck
getParent() const264*b1cdbd2cSJim Jagielski 		OSQLParseNode* getParent() const {return m_pParent;};
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski 		// SetParent setzt den Parent-Zeiger eines ParseNodes
setParent(OSQLParseNode * pParseNode)267*b1cdbd2cSJim Jagielski 		void setParent(OSQLParseNode* pParseNode) {m_pParent = pParseNode;};
268*b1cdbd2cSJim Jagielski 
269*b1cdbd2cSJim Jagielski 		// ChildCount liefert die Anzahl der Kinder eines Knotens
count() const270*b1cdbd2cSJim Jagielski 		sal_uInt32 count() const {return m_aChildren.size();};
271*b1cdbd2cSJim Jagielski 		inline OSQLParseNode* getChild(sal_uInt32 nPos) const;
272*b1cdbd2cSJim Jagielski 
273*b1cdbd2cSJim Jagielski 		void append(OSQLParseNode* pNewSubTree);
274*b1cdbd2cSJim Jagielski 		void insert(sal_uInt32 nPos, OSQLParseNode* pNewSubTree);
275*b1cdbd2cSJim Jagielski 
276*b1cdbd2cSJim Jagielski 		OSQLParseNode* replaceAt(sal_uInt32 nPos, OSQLParseNode* pNewSubTree);
277*b1cdbd2cSJim Jagielski 		OSQLParseNode* replace(OSQLParseNode* pOldSubTree, OSQLParseNode* pNewSubTree);
278*b1cdbd2cSJim Jagielski 
279*b1cdbd2cSJim Jagielski 		OSQLParseNode* removeAt(sal_uInt32 nPos);
280*b1cdbd2cSJim Jagielski 		OSQLParseNode* remove(OSQLParseNode* pSubTree);
281*b1cdbd2cSJim Jagielski 
282*b1cdbd2cSJim Jagielski 		void replaceNodeValue(const ::rtl::OUString& rTableAlias,const ::rtl::OUString& rColumnName);
283*b1cdbd2cSJim Jagielski 
284*b1cdbd2cSJim Jagielski         /** parses the node to a string which can be passed to a driver's connection for execution
285*b1cdbd2cSJim Jagielski 
286*b1cdbd2cSJim Jagielski             Any particles of the parse tree which represent application-level features - such
287*b1cdbd2cSJim Jagielski             as queries appearing in the FROM part - are subsituted, so that the resulting statement can
288*b1cdbd2cSJim Jagielski             be executed at an SDBC-level connection.
289*b1cdbd2cSJim Jagielski 
290*b1cdbd2cSJim Jagielski             @param  _out_rString
291*b1cdbd2cSJim Jagielski                 is an output parameter taking the resulting SQL statement
292*b1cdbd2cSJim Jagielski 
293*b1cdbd2cSJim Jagielski             @param  _rxConnection
294*b1cdbd2cSJim Jagielski                 the connection relative to which to parse. This must be an SDB-level connection (e.g.
295*b1cdbd2cSJim Jagielski                 support the XQueriesSupplier interface) for the method to be able to do all necessary
296*b1cdbd2cSJim Jagielski                 substitutions.
297*b1cdbd2cSJim Jagielski 
298*b1cdbd2cSJim Jagielski             @param _rParser
299*b1cdbd2cSJim Jagielski                 the SQLParser used to create the node. This is needed in case we need to parse
300*b1cdbd2cSJim Jagielski                 sub queries which are present in the SQL statement - those sub queries need to be parsed,
301*b1cdbd2cSJim Jagielski                 too, to check whether they contain nested sub queries.
302*b1cdbd2cSJim Jagielski 
303*b1cdbd2cSJim Jagielski             @param _pErrorHolder
304*b1cdbd2cSJim Jagielski                 takes the error which occured while generating the statement, if any. Might be <NULL/>,
305*b1cdbd2cSJim Jagielski                 in this case the error is not reported back, and can only be recognized by examing the
306*b1cdbd2cSJim Jagielski                 return value.
307*b1cdbd2cSJim Jagielski 
308*b1cdbd2cSJim Jagielski             @return
309*b1cdbd2cSJim Jagielski                 <TRUE/> if and only if the parsing was successful.<br/>
310*b1cdbd2cSJim Jagielski 
311*b1cdbd2cSJim Jagielski                 Currently, there's only one condition how this method can fail: If it contains a nested
312*b1cdbd2cSJim Jagielski                 query which causes a cycle. E.g., consider a statement <code>SELECT * from "foo"</code>,
313*b1cdbd2cSJim Jagielski                 where <code>bar </code> is a query defined as <code>SELECT * FROM "bar"</code>, where
314*b1cdbd2cSJim Jagielski                 <code>bar</code> is defined as <code>SELECT * FROM "foo"</code>. This statement obviously
315*b1cdbd2cSJim Jagielski                 cannot be parsed to an executable statement.
316*b1cdbd2cSJim Jagielski 
317*b1cdbd2cSJim Jagielski                 If this method returns <FALSE/>, you're encouraged to check and handle the error in
318*b1cdbd2cSJim Jagielski                 <arg>_pErrorHolder</arg>.
319*b1cdbd2cSJim Jagielski         */
320*b1cdbd2cSJim Jagielski         bool parseNodeToExecutableStatement( ::rtl::OUString& _out_rString,
321*b1cdbd2cSJim Jagielski             const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
322*b1cdbd2cSJim Jagielski             OSQLParser& _rParser,
323*b1cdbd2cSJim Jagielski             ::com::sun::star::sdbc::SQLException* _pErrorHolder ) const;
324*b1cdbd2cSJim Jagielski 
325*b1cdbd2cSJim Jagielski 		void parseNodeToStr(::rtl::OUString& rString,
326*b1cdbd2cSJim Jagielski 							const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
327*b1cdbd2cSJim Jagielski 							const IParseContext* pContext = NULL,
328*b1cdbd2cSJim Jagielski 							sal_Bool _bIntl = sal_False,
329*b1cdbd2cSJim Jagielski 							sal_Bool _bQuote= sal_True) const;
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski 		// quoted und internationalisert
332*b1cdbd2cSJim Jagielski 		void parseNodeToPredicateStr(::rtl::OUString& rString,
333*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
334*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
335*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::lang::Locale& rIntl,
336*b1cdbd2cSJim Jagielski 									 sal_Char _cDec,
337*b1cdbd2cSJim Jagielski 									 const IParseContext* pContext = NULL ) const;
338*b1cdbd2cSJim Jagielski 
339*b1cdbd2cSJim Jagielski 		void parseNodeToPredicateStr(::rtl::OUString& rString,
340*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
341*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
342*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _xField,
343*b1cdbd2cSJim Jagielski 									 const ::com::sun::star::lang::Locale& rIntl,
344*b1cdbd2cSJim Jagielski 									 sal_Char _cDec,
345*b1cdbd2cSJim Jagielski 									 const IParseContext* pContext = NULL ) const;
346*b1cdbd2cSJim Jagielski 
347*b1cdbd2cSJim Jagielski 		OSQLParseNode* getByRule(OSQLParseNode::Rule eRule) const;
348*b1cdbd2cSJim Jagielski 
349*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 0
350*b1cdbd2cSJim Jagielski 			// zeigt den ParseTree mit tabs und linefeeds
351*b1cdbd2cSJim Jagielski 		void showParseTree( ::rtl::OUString& rString ) const;
352*b1cdbd2cSJim Jagielski 		void showParseTree( ::rtl::OUStringBuffer& _inout_rBuf, sal_uInt32 nLevel ) const;
353*b1cdbd2cSJim Jagielski #endif
354*b1cdbd2cSJim Jagielski 
355*b1cdbd2cSJim Jagielski 			// GetNodeType gibt den Knotentyp zurueck
getNodeType() const356*b1cdbd2cSJim Jagielski 		SQLNodeType getNodeType() const {return m_eNodeType;};
357*b1cdbd2cSJim Jagielski 
358*b1cdbd2cSJim Jagielski 			// RuleId liefert die RuleId der Regel des Knotens (nur bei IsRule())
getRuleID() const359*b1cdbd2cSJim Jagielski 		sal_uInt32 getRuleID() const {return m_nNodeID;}
360*b1cdbd2cSJim Jagielski 
361*b1cdbd2cSJim Jagielski         /** returns the ID of the rule represented by the node
362*b1cdbd2cSJim Jagielski 
363*b1cdbd2cSJim Jagielski             If the node does not represent a rule, UNKNOWN_RULE is returned
364*b1cdbd2cSJim Jagielski         */
365*b1cdbd2cSJim Jagielski         Rule getKnownRuleID() const;
366*b1cdbd2cSJim Jagielski 
367*b1cdbd2cSJim Jagielski 			// RuleId liefert die TokenId des Tokens des Knotens (nur bei ! IsRule())
getTokenID() const368*b1cdbd2cSJim Jagielski 		sal_uInt32 getTokenID() const {return m_nNodeID;}
369*b1cdbd2cSJim Jagielski 
370*b1cdbd2cSJim Jagielski 			// IsRule testet ob ein Node eine Regel (NonTerminal) ist
371*b1cdbd2cSJim Jagielski 			// Achtung : Regeln koenne auch Blaetter sein, z.B. leere Listen
isRule() const372*b1cdbd2cSJim Jagielski 		sal_Bool isRule() const
373*b1cdbd2cSJim Jagielski 			{ return (m_eNodeType == SQL_NODE_RULE) || (m_eNodeType == SQL_NODE_LISTRULE)
374*b1cdbd2cSJim Jagielski 				|| (m_eNodeType == SQL_NODE_COMMALISTRULE);}
375*b1cdbd2cSJim Jagielski 
376*b1cdbd2cSJim Jagielski 			// IsToken testet ob ein Node ein Token (Terminal) ist
isToken() const377*b1cdbd2cSJim Jagielski 		sal_Bool isToken() const {return !isRule();} // ein Token ist keine Regel
378*b1cdbd2cSJim Jagielski 
379*b1cdbd2cSJim Jagielski 				// TokenValue liefert den NodeValue eines Tokens
getTokenValue() const380*b1cdbd2cSJim Jagielski 		const ::rtl::OUString& getTokenValue() const {return m_aNodeValue;}
381*b1cdbd2cSJim Jagielski 
382*b1cdbd2cSJim Jagielski 			// SetTokenValue setzt den NodeValue
setTokenValue(const::rtl::OUString & rString)383*b1cdbd2cSJim Jagielski 		void setTokenValue(const ::rtl::OUString& rString) {	if (isToken()) m_aNodeValue = rString;}
384*b1cdbd2cSJim Jagielski 
385*b1cdbd2cSJim Jagielski 			// IsLeaf testet ob ein Node ein Blatt ist
isLeaf() const386*b1cdbd2cSJim Jagielski 		sal_Bool isLeaf() const {return m_aChildren.empty();}
387*b1cdbd2cSJim Jagielski 
388*b1cdbd2cSJim Jagielski 		// negate only a searchcondition, any other rule could cause a gpf
389*b1cdbd2cSJim Jagielski 		static void negateSearchCondition(OSQLParseNode*& pSearchCondition,sal_Bool bNegate=sal_False);
390*b1cdbd2cSJim Jagielski 
391*b1cdbd2cSJim Jagielski 		// normalize a logic form
392*b1cdbd2cSJim Jagielski 		// e.q. (a or b) and (c or d) <=> a and c or a and d or b and c or b and d
393*b1cdbd2cSJim Jagielski 		static void disjunctiveNormalForm(OSQLParseNode*& pSearchCondition);
394*b1cdbd2cSJim Jagielski 
395*b1cdbd2cSJim Jagielski 		//	 Simplies logic expressions
396*b1cdbd2cSJim Jagielski 		// a * a		= a
397*b1cdbd2cSJim Jagielski 		// a + a		= a
398*b1cdbd2cSJim Jagielski 		// a * ( a + b) = a
399*b1cdbd2cSJim Jagielski 		// a + a * b	= a
400*b1cdbd2cSJim Jagielski 		static void absorptions(OSQLParseNode*& pSearchCondition);
401*b1cdbd2cSJim Jagielski 
402*b1cdbd2cSJim Jagielski 		// erase not nessary braces
403*b1cdbd2cSJim Jagielski 		static void eraseBraces(OSQLParseNode*& pSearchCondition);
404*b1cdbd2cSJim Jagielski 
405*b1cdbd2cSJim Jagielski 		// makes the logic formula a little more smaller
406*b1cdbd2cSJim Jagielski 		static void compress(OSQLParseNode*& pSearchCondition);
407*b1cdbd2cSJim Jagielski 		// return the catalog, schema and tablename form this node
408*b1cdbd2cSJim Jagielski 		// _pTableNode must be a rule of that above or a SQL_TOKEN_NAME
409*b1cdbd2cSJim Jagielski 		static sal_Bool getTableComponents(const OSQLParseNode* _pTableNode,
410*b1cdbd2cSJim Jagielski 											::com::sun::star::uno::Any &_rCatalog,
411*b1cdbd2cSJim Jagielski 											::rtl::OUString &_rSchema,
412*b1cdbd2cSJim Jagielski 											::rtl::OUString &_rTable
413*b1cdbd2cSJim Jagielski                                             ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _xMetaData);
414*b1cdbd2cSJim Jagielski 
415*b1cdbd2cSJim Jagielski 		// susbtitute all occurences of :var or [name] into the dynamic parameter ?
416*b1cdbd2cSJim Jagielski 		// _pNode will be modified if parameters exists
417*b1cdbd2cSJim Jagielski 		static void substituteParameterNames(OSQLParseNode* _pNode);
418*b1cdbd2cSJim Jagielski 
419*b1cdbd2cSJim Jagielski         /** return a table range when it exists.
420*b1cdbd2cSJim Jagielski         */
421*b1cdbd2cSJim Jagielski         static ::rtl::OUString getTableRange(const OSQLParseNode* _pTableRef);
422*b1cdbd2cSJim Jagielski 
423*b1cdbd2cSJim Jagielski 	protected:
424*b1cdbd2cSJim Jagielski 		// ParseNodeToStr konkateniert alle Token (Blaetter) des ParseNodes
425*b1cdbd2cSJim Jagielski 		void parseNodeToStr(::rtl::OUString& rString,
426*b1cdbd2cSJim Jagielski 							const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
427*b1cdbd2cSJim Jagielski 							const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
428*b1cdbd2cSJim Jagielski 							const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & _xField,
429*b1cdbd2cSJim Jagielski 							const ::com::sun::star::lang::Locale& rIntl,
430*b1cdbd2cSJim Jagielski 							const IParseContext* pContext,
431*b1cdbd2cSJim Jagielski 							bool _bIntl,
432*b1cdbd2cSJim Jagielski 							bool _bQuote,
433*b1cdbd2cSJim Jagielski 							sal_Char _cDecSep,
434*b1cdbd2cSJim Jagielski 							bool _bPredicate,
435*b1cdbd2cSJim Jagielski                             bool _bSubstitute) const;
436*b1cdbd2cSJim Jagielski 
437*b1cdbd2cSJim Jagielski 	private:
438*b1cdbd2cSJim Jagielski 		void impl_parseNodeToString_throw( ::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const;
439*b1cdbd2cSJim Jagielski 		void impl_parseLikeNodeToString_throw( ::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const;
440*b1cdbd2cSJim Jagielski         void impl_parseTableRangeNodeToString_throw( ::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const;
441*b1cdbd2cSJim Jagielski 
442*b1cdbd2cSJim Jagielski         /** parses a table_name node into a SQL statement particle.
443*b1cdbd2cSJim Jagielski             @return
444*b1cdbd2cSJim Jagielski                 <TRUE/> if and only if parsing was successful, <FALSE/> if default handling should
445*b1cdbd2cSJim Jagielski                 be applied.
446*b1cdbd2cSJim Jagielski         */
447*b1cdbd2cSJim Jagielski 		bool impl_parseTableNameNodeToString_throw( ::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const;
448*b1cdbd2cSJim Jagielski 
449*b1cdbd2cSJim Jagielski         sal_Bool addDateValue(::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const;
450*b1cdbd2cSJim Jagielski 		::rtl::OUString convertDateTimeString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const;
451*b1cdbd2cSJim Jagielski 		::rtl::OUString convertDateString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const;
452*b1cdbd2cSJim Jagielski 		::rtl::OUString convertTimeString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const;
453*b1cdbd2cSJim Jagielski 		void parseLeaf(::rtl::OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const;
454*b1cdbd2cSJim Jagielski 	};
455*b1cdbd2cSJim Jagielski 
456*b1cdbd2cSJim Jagielski 	//-----------------------------------------------------------------------------
getChild(sal_uInt32 nPos) const457*b1cdbd2cSJim Jagielski 	inline OSQLParseNode* OSQLParseNode::getChild(sal_uInt32 nPos) const
458*b1cdbd2cSJim Jagielski 	{
459*b1cdbd2cSJim Jagielski 		OSL_ENSURE(nPos < m_aChildren.size(), "Invalid Position");
460*b1cdbd2cSJim Jagielski 
461*b1cdbd2cSJim Jagielski 		//	return m_aChildren[nPos];
462*b1cdbd2cSJim Jagielski 		return m_aChildren.at(nPos);
463*b1cdbd2cSJim Jagielski 	}
464*b1cdbd2cSJim Jagielski 
465*b1cdbd2cSJim Jagielski 	// Utility-Methoden zum Abfragen auf bestimmte Rules, Token oder Punctuation:
466*b1cdbd2cSJim Jagielski 	#define SQL_ISRULE(pParseNode, eRule) 	((pParseNode)->isRule() && (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::eRule))
467*b1cdbd2cSJim Jagielski 	#define SQL_ISTOKEN(pParseNode, token) ((pParseNode)->isToken() && (pParseNode)->getTokenID() == SQL_TOKEN_##token)
468*b1cdbd2cSJim Jagielski 	#define SQL_ISPUNCTUATION(pParseNode, aString) ((pParseNode)->getNodeType() == SQL_NODE_PUNCTUATION && !(pParseNode)->getTokenValue().compareToAscii(aString))
469*b1cdbd2cSJim Jagielski }
470*b1cdbd2cSJim Jagielski 
471*b1cdbd2cSJim Jagielski #endif	//_CONNECTIVITY_SQLNODE_HXX
472