office-gobmx/include/connectivity/sqlparse.hxx
Henry Castro 3d910abdaa connectivity: add neutral context parser
Signed-off-by: Henry Castro <hcastro@collabora.com>
Change-Id: I12b0fe811d141873aaa64af5b6c457051c3356b0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156297
Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156424
Tested-by: Jenkins
2023-09-01 21:39:46 +02:00

234 lines
9.5 KiB
C++

/* -*- 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: */