1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef _CONNECTIVITY_SQLPARSE_HXX
24 #define _CONNECTIVITY_SQLPARSE_HXX
25 
26 #include <com/sun/star/uno/Reference.h>
27 #include <osl/mutex.hxx>
28 #include <connectivity/sqlnode.hxx>
29 #ifndef YYBISON
30 #ifndef FLEX_SCANNER
31 #ifndef BISON_INCLUDED
32 #define BISON_INCLUDED
33 #include "sqlbison.hxx"
34 #endif
35 #endif
36 #endif
37 #include <com/sun/star/i18n/XCharacterClassification.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/i18n/XLocaleData.hpp>
40 #include <com/sun/star/lang/Locale.hpp>
41 #include "connectivity/IParseContext.hxx"
42 #include "connectivity/dbtoolsdllapi.hxx"
43 #include "connectivity/sqlerror.hxx"
44 #include <salhelper/singletonref.hxx>
45 #include <osl/mutex.hxx>
46 
47 #include <map>
48 
49 // forward declarations
50 namespace com
51 {
52 	namespace sun
53 	{
54 		namespace star
55 		{
56 			namespace beans
57 			{
58 				class XPropertySet;
59 			}
60 			namespace util
61 			{
62 				class XNumberFormatter;
63 			}
64 			namespace lang
65 			{
66 				struct Locale;
67 			}
68 		}
69 	}
70 }
71 namespace connectivity
72 {
73 	class OSQLScanner;
74     class SQLError;
75 
76 	//==========================================================================
77 	//= OParseContext
78 	//==========================================================================
79 	class OOO_DLLPUBLIC_DBTOOLS OParseContext : public IParseContext
80 	{
81 	public:
82 		OParseContext();
83 
84 		virtual ~OParseContext();
85 		// retrieves language specific error messages
86 		virtual ::rtl::OUString getErrorMessage(ErrorCode _eCodes) const;
87 
88 		// retrieves language specific keyword strings (only ASCII allowed)
89 		virtual ::rtl::OString getIntlKeywordAscii(InternationalKeyCode _eKey) const;
90 
91 		// finds out, if we have an international keyword (only ASCII allowed)
92 		virtual InternationalKeyCode getIntlKeyCode(const ::rtl::OString& rToken) const;
93 
94 		// determines the default international setting
95 		static const ::com::sun::star::lang::Locale& getDefaultLocale();
96 
97 		/** set's the default locale which should be used when analyzing strings
98 			<p>If no locale is set, and any method which needs a locale is called, a default
99 			(en-US) is used.</p>
100 			<p>If, while parsing, the locale can be obtained from other sources (such as the number format
101 			set for a table column), the preferred locale is ignored.</p>
102 		*/
103 		static void setDefaultLocale( const ::com::sun::star::lang::Locale& _rLocale );
104 
105 		/** get's a locale instance which should be used when parsing in the context specified by this instance
106 			<p>if this is not overridden by derived classes, it returns the static default locale.</p>
107 		*/
108 		virtual ::com::sun::star::lang::Locale getPreferredLocale( ) const;
109 	};
110 
111     //==========================================================================
112     // OSQLParseNodesContainer
113     // grabage collection of nodes
114     //==========================================================================
115     class OSQLParseNodesContainer
116     {
117         ::osl::Mutex m_aMutex;
118         ::std::vector< OSQLParseNode* > m_aNodes;
119     public:
120         OSQLParseNodesContainer();
121         ~OSQLParseNodesContainer();
122 
123         void push_back(OSQLParseNode* _pNode);
124         void erase(OSQLParseNode* _pNode);
125         bool empty() const;
126         void clear();
127         void clearAndDelete();
128     };
129 
130     typedef salhelper::SingletonRef<OSQLParseNodesContainer> OSQLParseNodesGarbageCollector;
131 
132 	//==========================================================================
133 	//= OSQLParser
134 	//==========================================================================
135     struct OSQLParser_Data
136     {
137         ::com::sun::star::lang::Locale  aLocale;
138         ::connectivity::SQLError        aErrors;
139 
140         OSQLParser_Data( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xServiceFactory );
141 
142     };
143 	/** Parser for SQL92
144 	*/
145 	class OOO_DLLPUBLIC_DBTOOLS OSQLParser
146 	{
147 		friend class OSQLParseNode;
148 		friend class OSQLInternalNode;
149 		friend struct SQLParseNodeParameter;
150 
151 	private:
152         typedef ::std::map< sal_uInt32, OSQLParseNode::Rule >   RuleIDMap;
153 	//	static parts for parsers
154 		static sal_uInt32			s_nRuleIDs[OSQLParseNode::rule_count + 1];
155         static RuleIDMap            s_aReverseRuleIDLookup;
156 		static OParseContext		s_aDefaultContext;
157 
158 		static OSQLScanner*			            s_pScanner;
159         static OSQLParseNodesGarbageCollector*  s_pGarbageCollector;
160 		static sal_Int32			            s_nRefCount;
161 
162 	// informations on the current parse action
163 		const IParseContext*		m_pContext;
164 		OSQLParseNode*				m_pParseTree;	// result from parsing
165         ::std::auto_ptr< OSQLParser_Data >
166                                     m_pData;
167 		::rtl::OUString						m_sFieldName;	// current field name for a predicate
168 		::rtl::OUString						m_sErrorMessage;// current error msg
169 
170 		::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
171 									m_xField;		// current field
172 		::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >
173 									m_xFormatter;	// current number formatter
174 		sal_Int32					m_nFormatKey;	// numberformat, which should be used
175 		sal_Int32					m_nDateFormatKey;
176 		::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >	m_xServiceFactory;
177 		::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCharacterClassification> m_xCharClass;
178 		static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData>		s_xLocaleData;
179 		::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData>		xDummy; // can be deleted after 627
180 
181 		// convert a string into double trim it to scale of _nscale and than transform it back to string
182 		::rtl::OUString stringToDouble(const ::rtl::OUString& _rValue,sal_Int16 _nScale);
183 		OSQLParseNode*  buildDate(sal_Int32 _nType,OSQLParseNode*& pLiteral);
184         bool            extractDate(OSQLParseNode* pLiteral,double& _rfValue);
185         void            killThousandSeparator(OSQLParseNode* pLiteral);
186         OSQLParseNode*  convertNode(sal_Int32 nType,OSQLParseNode*& pLiteral);
187         // makes a string out of a number, pLiteral will be deleted
188 		OSQLParseNode*  buildNode_STR_NUM(OSQLParseNode*& pLiteral);
189         OSQLParseNode*  buildNode_Date(const double& fValue, sal_Int32 nType);
190 
191 		static ::osl::Mutex& getMutex();
192 
193 	public:
194 		// if NULL, a default context will be used
195 		// the context must live as long as the parser
196 		OSQLParser(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xServiceFactory,const IParseContext* _pContext = NULL);
197 		~OSQLParser();
198 
199 		// Parsing an SQLStatement
200 		OSQLParseNode* parseTree(::rtl::OUString& rErrorMessage,
201 					   const ::rtl::OUString& rStatement,
202 					   sal_Bool bInternational = sal_False);
203 
204 		// Check a Predicate
205 		OSQLParseNode* predicateTree(::rtl::OUString& rErrorMessage, const ::rtl::OUString& rStatement,
206 					   const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter,
207 					   const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & xField);
208 
209 		// Access to the context
getContext() const210 		const IParseContext& getContext() const {return *m_pContext;}
211 
212         /// access to the SQLError instance owned by this parser
213         const SQLError& getErrorHelper() const;
214 
215 		// TokenIDToStr: Token-Name zu einer Token-Nr.
216 		static ::rtl::OString TokenIDToStr(sal_uInt32 nTokenID, const IParseContext* pContext = NULL);
217 
218 		// StrToTokenID: Token-Nr. zu einem Token-Namen.
219 		// static sal_uInt32 StrToTokenID(const ::rtl::OString & rName);
220 
221 		// RuleIDToStr gibt den zu einer RuleID gehoerenden ::rtl::OUString zurueck
222 		// (Leerstring, falls nicht gefunden)
223 		static ::rtl::OUString RuleIDToStr(sal_uInt32 nRuleID);
224 
225 		// StrToRuleID berechnet zu einem ::rtl::OUString die RuleID (d.h. ::com::sun::star::sdbcx::Index in yytname)
226 		// (0, falls nicht gefunden). Die Suche nach der ID aufgrund eines Strings ist
227 		// extrem ineffizient (sequentielle Suche nach ::rtl::OUString)!
228 		static sal_uInt32 StrToRuleID(const ::rtl::OString & rValue);
229 
230         static OSQLParseNode::Rule RuleIDToRule( sal_uInt32 _nRule );
231 
232 		// RuleId mit enum, wesentlich effizienter
233 		static sal_uInt32 RuleID(OSQLParseNode::Rule eRule);
234 		// compares the _sFunctionName with all known function names and return the DataType of the return value
235 		static sal_Int32 getFunctionReturnType(const ::rtl::OUString& _sFunctionName, const IParseContext* pContext = NULL);
236 
237         // returns the type for a parameter in a given function name
238         static sal_Int32 getFunctionParameterType(sal_uInt32 _nTokenId,sal_uInt32 _nPos);
239 
240 		void error( const sal_Char* pFormat);
241 		int SQLlex();
242 #ifdef YYBISON
243 		void setParseTree(OSQLParseNode * pNewParseTree);
244 
245 		// Is the parse in a special mode?
246 		// Predicate chack is used to check a condition for a field
inPredicateCheck() const247 		sal_Bool inPredicateCheck() const {return m_xField.is();}
getFieldName() const248 		const ::rtl::OUString& getFieldName() const {return m_sFieldName;}
249 
250 		void reduceLiteral(OSQLParseNode*& pLiteral, sal_Bool bAppendBlank);
251 		 // does not change the pLiteral argument
252 		sal_Int16 buildNode(OSQLParseNode*& pAppend,OSQLParseNode* pCompare,OSQLParseNode* pLiteral,OSQLParseNode* pLiteral2);
253 
254 		sal_Int16 buildComparsionRule(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral);
255 		// pCompre will be deleted if it is not used
256 		sal_Int16 buildPredicateRule(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral,OSQLParseNode*& pCompare,OSQLParseNode* pLiteral2 = NULL);
257 
258 		sal_Int16 buildLikeRule(OSQLParseNode*& pAppend,OSQLParseNode*& pLiteral,const OSQLParseNode* pEscape);
259 		sal_Int16 buildStringNodes(OSQLParseNode*& pLiteral);
260 #else
261 #endif
262 	};
263 }
264 
265 
266 #endif //_CONNECTIVITY_SQLPARSE_HXX
267