summaryrefslogtreecommitdiffstats
path: root/include/connectivity/sqlparse.hxx
blob: 814615aef5b4d6d96fa3680e85c583833483e52e (plain)
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
235
/* -*- 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 <memory>

#include <com/sun/star/uno/Reference.h>
#include <osl/mutex.hxx>
#include <connectivity/sqlnode.hxx>
#include <connectivity/IParseContext.hxx>
#include <connectivity/dbtoolsdllapi.hxx>
#include <connectivity/sqlerror.hxx>
#include <salhelper/singletonref.hxx>

#include <map>

namespace com::sun::star::i18n { class XCharacterClassification; }
namespace com::sun::star::i18n { class XLocaleData4; }

namespace com
{
    namespace sun
    {
        namespace 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
    {
        ::osl::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 salhelper::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;
        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 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 ::osl::Mutex& getMutex();

    public:
        // if NULL, a default context will be used
        // the context must live as long as the parser
        OSQLParser(const css::uno::Reference< css::uno::XComponentContext >& rxContext, const IParseContext* _pContext = 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;}

        /// 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(const OUString& _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: */