1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_CONNECTIVITY_SQLPARSE_HXX
#define INCLUDED_CONNECTIVITY_SQLPARSE_HXX
#include <com/sun/star/uno/Reference.h>
#include <connectivity/sqlnode.hxx>
#include <connectivity/IParseContext.hxx>
#include <connectivity/dbtoolsdllapi.hxx>
#include <connectivity/sqlerror.hxx>
#include <comphelper/singletonref.hxx>
#include <vcl/lazydelete.hxx>
#include <map>
#include <memory>
#include <mutex>
#include <string_view>
namespace com::sun::star::i18n { class XCharacterClassification; }
namespace com::sun::star::i18n { class XLocaleData4; }
namespace com::sun::star
{
namespace beans
{
class XPropertySet;
}
namespace util
{
class XNumberFormatter;
}
}
namespace connectivity
{
class OSQLScanner;
//= OParseContext
class OParseContext final : public IParseContext
{
public:
OParseContext();
virtual ~OParseContext();
// retrieves language specific error messages
virtual OUString getErrorMessage(ErrorCode _eCodes) const override;
// retrieves language specific keyword strings (only ASCII allowed)
virtual OString getIntlKeywordAscii(InternationalKeyCode _eKey) const override;
// finds out, if we have an international keyword (only ASCII allowed)
virtual InternationalKeyCode getIntlKeyCode(const OString& rToken) const override;
// determines the default international setting
static const css::lang::Locale& getDefaultLocale();
/** gets a locale instance which should be used when parsing in the context specified by this instance
<p>if this is not overridden by derived classes, it returns the static default locale.</p>
*/
virtual css::lang::Locale getPreferredLocale( ) const override;
};
// OSQLParseNodesContainer
// garbage collection of nodes
class OSQLParseNodesContainer
{
std::mutex m_aMutex;
::std::vector< OSQLParseNode* > m_aNodes;
public:
OSQLParseNodesContainer();
~OSQLParseNodesContainer();
void push_back(OSQLParseNode* _pNode);
void erase(OSQLParseNode* _pNode);
void clear();
void clearAndDelete();
};
typedef comphelper::SingletonRef<OSQLParseNodesContainer> OSQLParseNodesGarbageCollector;
//= OSQLParser
struct OSQLParser_Data
{
css::lang::Locale aLocale;
::connectivity::SQLError aErrors;
};
/** Parser for SQL92
*/
class OOO_DLLPUBLIC_DBTOOLS OSQLParser
{
friend class OSQLParseNode;
friend class OSQLInternalNode;
friend struct SQLParseNodeParameter;
private:
typedef ::std::map< sal_uInt32, OSQLParseNode::Rule > RuleIDMap;
// static parts for parsers
static sal_uInt32 s_nRuleIDs[OSQLParseNode::rule_count + 1];
static RuleIDMap s_aReverseRuleIDLookup;
static OParseContext s_aDefaultContext;
static OSQLScanner* s_pScanner;
static OSQLParseNodesGarbageCollector* s_pGarbageCollector;
static sal_Int32 s_nRefCount;
// information on the current parse action
const IParseContext* m_pContext;
const IParseContext* m_pNeutral;
std::unique_ptr<OSQLParseNode> m_pParseTree; // result from parsing
::std::unique_ptr< OSQLParser_Data >
m_pData;
OUString m_sFieldName; // current field name for a predicate
OUString m_sErrorMessage;// current error msg
css::uno::Reference< css::beans::XPropertySet >
m_xField; // current field
css::uno::Reference< css::util::XNumberFormatter >
m_xFormatter; // current number formatter
sal_Int32 m_nFormatKey; // numberformat, which should be used
sal_Int32 m_nDateFormatKey;
css::uno::Reference< css::uno::XComponentContext > m_xContext;
css::uno::Reference< css::i18n::XCharacterClassification> m_xCharClass;
static vcl::DeleteOnDeinit<css::uno::Reference< css::i18n::XLocaleData4>> s_xLocaleData;
// convert a string into double trim it to scale of _nscale and then transform it back to string
OUString stringToDouble(const OUString& _rValue,sal_Int16 _nScale);
OSQLParseNode* buildDate(sal_Int32 _nType,OSQLParseNode*& pLiteral);
bool extractDate(OSQLParseNode const * pLiteral,double& _rfValue);
void killThousandSeparator(OSQLParseNode* pLiteral);
OSQLParseNode* convertNode(sal_Int32 nType, OSQLParseNode* pLiteral);
// makes a string out of a number, pLiteral will be deleted
OSQLParseNode* buildNode_STR_NUM(OSQLParseNode*& pLiteral);
OSQLParseNode* buildNode_Date(const double& fValue, sal_Int32 nType);
static std::mutex& getMutex();
public:
// if NULL, a default context will be used
// the context must live as long as the parser
OSQLParser(css::uno::Reference< css::uno::XComponentContext > xContext,
const IParseContext* _pContext = nullptr,
const IParseContext* _pNeutral = nullptr);
~OSQLParser();
// Parsing an SQLStatement
std::unique_ptr<OSQLParseNode> parseTree(OUString& rErrorMessage,
const OUString& rStatement,
bool bInternational = false);
// Check a Predicate
// set bUseRealName to false if you pass a xField that comes from where you got that field,
// as opposed from to from yourself.
std::unique_ptr<OSQLParseNode> predicateTree(OUString& rErrorMessage, const OUString& rStatement,
const css::uno::Reference< css::util::XNumberFormatter > & xFormatter,
const css::uno::Reference< css::beans::XPropertySet > & xField,
bool bUseRealName = true);
// Access to the context
const IParseContext& getContext() const { return *m_pContext; }
const IParseContext* getNeutral() const { return m_pNeutral; }
/// access to the SQLError instance owned by this parser
const SQLError& getErrorHelper() const;
// TokenIDToStr: token name belonging to a token number.
static OString TokenIDToStr(sal_uInt32 nTokenID, const IParseContext* pContext = nullptr);
#if OSL_DEBUG_LEVEL > 0
// (empty string if not found)
static OUString RuleIDToStr(sal_uInt32 nRuleID);
#endif
// StrToRuleID calculates the RuleID for an OUString (that is, css::sdbcx::Index in yytname)
// (0 if not found). The search for an ID based on a String is
// extremely inefficient (sequential search for OUString)!
static sal_uInt32 StrToRuleID(const OString & rValue);
static OSQLParseNode::Rule RuleIDToRule( sal_uInt32 _nRule );
// RuleId with enum, far more efficient
static sal_uInt32 RuleID(OSQLParseNode::Rule eRule);
// compares the _sFunctionName with all known function names and return the DataType of the return value
static sal_Int32 getFunctionReturnType(std::u16string_view _sFunctionName, const IParseContext* pContext);
// returns the type for a parameter in a given function name
static sal_Int32 getFunctionParameterType(sal_uInt32 _nTokenId,sal_uInt32 _nPos);
void error(const char *fmt);
static int SQLlex();
#ifdef YYBISON
void setParseTree(OSQLParseNode * pNewParseTree);
// Is the parse in a special mode?
// Predicate check is used to check a condition for a field
bool inPredicateCheck() const {return m_xField.is();}
const OUString& getFieldName() const {return m_sFieldName;}
static void reduceLiteral(OSQLParseNode*& pLiteral, bool bAppendBlank);
// does not change the pLiteral argument
sal_Int16 buildNode(OSQLParseNode*& pAppend,OSQLParseNode* pCompare,OSQLParseNode* pLiteral,OSQLParseNode* pLiteral2);
sal_Int16 buildComparisonRule(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral);
// pCompre will be deleted if it is not used
sal_Int16 buildPredicateRule(OSQLParseNode*& pAppend,OSQLParseNode* const pLiteral,OSQLParseNode* pCompare,OSQLParseNode* pLiteral2 = nullptr);
sal_Int16 buildLikeRule(OSQLParseNode* pAppend, OSQLParseNode*& pLiteral, const OSQLParseNode* pEscape);
sal_Int16 buildStringNodes(OSQLParseNode*& pLiteral);
#endif
};
}
#endif // INCLUDED_CONNECTIVITY_SQLPARSE_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|