diff options
Diffstat (limited to 'include/connectivity/sqlparse.hxx')
-rw-r--r-- | include/connectivity/sqlparse.hxx | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/include/connectivity/sqlparse.hxx b/include/connectivity/sqlparse.hxx new file mode 100644 index 0000000000..4ccd5ebbea --- /dev/null +++ b/include/connectivity/sqlparse.hxx @@ -0,0 +1,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: */ |