summaryrefslogtreecommitdiffstats
path: root/connectivity/source/drivers/file/fcode.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /connectivity/source/drivers/file/fcode.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--connectivity/source/drivers/file/fcode.cxx391
1 files changed, 391 insertions, 0 deletions
diff --git a/connectivity/source/drivers/file/fcode.cxx b/connectivity/source/drivers/file/fcode.cxx
new file mode 100644
index 000000000..36cba4a73
--- /dev/null
+++ b/connectivity/source/drivers/file/fcode.cxx
@@ -0,0 +1,391 @@
+/* -*- 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 .
+ */
+
+#include <file/fcode.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <connectivity/sqlparse.hxx>
+#include <sqlbison.hxx>
+#include <com/sun/star/sdb/SQLFilterOperator.hpp>
+
+using namespace ::comphelper;
+using namespace connectivity;
+using namespace connectivity::file;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+
+OCode::~OCode() = default;
+
+OOperandRow::OOperandRow(sal_uInt16 _nPos, sal_Int32 _rType)
+ : OOperand(_rType)
+ , m_nRowPos(_nPos)
+{}
+
+void OOperandRow::bindValue(const OValueRefRow& _pRow)
+{
+ OSL_ENSURE(_pRow.is(),"NO EMPTY row allowed!");
+ m_pRow = _pRow;
+ OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
+ (*m_pRow)[m_nRowPos]->setBound(true);
+}
+
+void OOperandRow::setValue(const ORowSetValue& _rVal)
+{
+ OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
+ (*(*m_pRow)[m_nRowPos]) = _rVal;
+}
+
+const ORowSetValue& OOperandRow::getValue() const
+{
+ OSL_ENSURE(m_pRow.is() && m_nRowPos < m_pRow->size(),"Invalid RowPos is >= vector.size()");
+ return (*m_pRow)[m_nRowPos]->getValue();
+}
+
+
+void OOperandValue::setValue(const ORowSetValue& _rVal)
+{
+ m_aValue = _rVal;
+}
+
+OOperandParam::OOperandParam(OSQLParseNode const * pNode, sal_Int32 _nPos)
+ : OOperandRow(static_cast<sal_uInt16>(_nPos), DataType::VARCHAR) // Standard-Type
+{
+ OSL_ENSURE(SQL_ISRULE(pNode,parameter),"Argument is not a parameter");
+ OSL_ENSURE(pNode->count() > 0,"Error in Parse Tree");
+ OSQLParseNode *pMark = pNode->getChild(0);
+
+ OUString aParameterName;
+ if (SQL_ISPUNCTUATION(pMark, "?"))
+ aParameterName = "?";
+ else if (SQL_ISPUNCTUATION(pMark, ":"))
+ aParameterName = pNode->getChild(1)->getTokenValue();
+ else
+ {
+ SAL_WARN( "connectivity.drivers","Error in Parse Tree");
+ }
+
+ // set up Parameter-Column with default type, can be specified more precisely later using Describe-Parameter
+
+ // save Identity (not especially necessary here, just for the sake of symmetry)
+
+ // todo
+ // OColumn* pColumn = new OFILEColumn(aParameterName,eDBType,255,0,SQL_FLAGS_NULLALLOWED);
+ // rParamColumns->AddColumn(pColumn);
+
+ // the value will be set just before the evaluation
+}
+
+
+const ORowSetValue& OOperandValue::getValue() const
+{
+ return m_aValue;
+}
+
+
+OOperandConst::OOperandConst(const OSQLParseNode& rColumnRef, const OUString& aStrValue)
+{
+ switch (rColumnRef.getNodeType())
+ {
+ case SQLNodeType::String:
+ m_aValue = aStrValue;
+ m_eDBType = DataType::VARCHAR;
+ m_aValue.setBound(true);
+ return;
+ case SQLNodeType::IntNum:
+ case SQLNodeType::ApproxNum:
+ m_aValue = aStrValue.toDouble();
+ m_eDBType = DataType::DOUBLE;
+ m_aValue.setBound(true);
+ return;
+ default:
+ break;
+ }
+
+ if (SQL_ISTOKEN(&rColumnRef, TRUE))
+ {
+ m_aValue = 1.0;
+ m_eDBType = DataType::BIT;
+ }
+ else if (SQL_ISTOKEN(&rColumnRef, FALSE))
+ {
+ m_aValue = 0.0;
+ m_eDBType = DataType::BIT;
+ }
+ else
+ {
+ SAL_WARN( "connectivity.drivers", "Parse Error");
+ }
+ m_aValue.setBound(true);
+}
+
+
+// Implementation of the operators
+
+
+bool OBoolOperator::operate(const OOperand*, const OOperand*) const
+{
+ return false;
+}
+
+
+void OBoolOperator::Exec(OCodeStack& rCodeStack)
+{
+ OOperand *pRight = rCodeStack.top();
+ rCodeStack.pop();
+ OOperand *pLeft = rCodeStack.top();
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResultBOOL(operate(pLeft, pRight)));
+ if( typeid(OOperandResult) == typeid(*pLeft))
+ delete pLeft;
+ if( typeid(OOperandResult) == typeid(*pRight))
+ delete pRight;
+}
+
+bool OOp_NOT::operate(const OOperand* pLeft, const OOperand* ) const
+{
+ return !pLeft->isValid();
+}
+
+void OOp_NOT::Exec(OCodeStack& rCodeStack)
+{
+ OOperand* pOperand = rCodeStack.top();
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResultBOOL(operate(pOperand, nullptr)));
+
+ if( typeid(OOperandResult) == typeid(*pOperand))
+ delete pOperand;
+}
+
+bool OOp_AND::operate(const OOperand* pLeft, const OOperand* pRight) const
+{
+ return pLeft->isValid() && pRight->isValid();
+}
+
+
+bool OOp_OR::operate(const OOperand* pLeft, const OOperand* pRight) const
+{
+ return pLeft->isValid() || pRight->isValid();
+}
+
+
+void OOp_ISNULL::Exec(OCodeStack& rCodeStack)
+{
+ OOperand* pOperand = rCodeStack.top();
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResultBOOL(operate(pOperand, nullptr)));
+ if( typeid(OOperandResult) == typeid(*pOperand))
+ delete pOperand;
+}
+
+
+bool OOp_ISNULL::operate(const OOperand* pOperand, const OOperand*) const
+{
+ return pOperand->getValue().isNull();
+}
+
+
+bool OOp_ISNOTNULL::operate(const OOperand* pOperand, const OOperand*) const
+{
+ return !OOp_ISNULL::operate(pOperand, nullptr);
+}
+
+
+bool OOp_LIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
+{
+ bool bMatch;
+ const ORowSetValue& aLH(pLeft->getValue());
+ const ORowSetValue& aRH(pRight->getValue());
+
+ if (aLH.isNull() || aRH.isNull())
+ bMatch = false;
+ else
+ {
+ bMatch = match(aRH.getString(), aLH.getString(), cEscape);
+ }
+ return bMatch;
+}
+
+
+bool OOp_NOTLIKE::operate(const OOperand* pLeft, const OOperand* pRight) const
+{
+ return !OOp_LIKE::operate(pLeft, pRight);
+}
+
+
+bool OOp_COMPARE::operate(const OOperand* pLeft, const OOperand* pRight) const
+{
+ const ORowSetValue& aLH(pLeft->getValue());
+ const ORowSetValue& aRH(pRight->getValue());
+
+ if (aLH.isNull() || aRH.isNull()) // if (!aLH.getValue() || !aRH.getValue())
+ return false;
+
+ bool bResult = false;
+ sal_Int32 eDBType = pLeft->getDBType();
+
+ // Comparison (depending on Data-type):
+ switch (eDBType)
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ {
+ OUString sLH = aLH, sRH = aRH;
+ sal_Int32 nRes = sLH.compareToIgnoreAsciiCase(sRH);
+ switch(aPredicateType)
+ {
+ case SQLFilterOperator::EQUAL: bResult = (nRes == 0); break;
+ case SQLFilterOperator::NOT_EQUAL: bResult = (nRes != 0); break;
+ case SQLFilterOperator::LESS: bResult = (nRes < 0); break;
+ case SQLFilterOperator::LESS_EQUAL: bResult = (nRes <= 0); break;
+ case SQLFilterOperator::GREATER: bResult = (nRes > 0); break;
+ case SQLFilterOperator::GREATER_EQUAL: bResult = (nRes >= 0); break;
+ default: bResult = false;
+ }
+ } break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::BIT:
+ case DataType::TIMESTAMP:
+ case DataType::DATE:
+ case DataType::TIME:
+ {
+ double n = aLH ,m = aRH;
+
+ switch (aPredicateType)
+ {
+ case SQLFilterOperator::EQUAL: bResult = (n == m); break;
+ case SQLFilterOperator::LIKE: bResult = (n == m); break;
+ case SQLFilterOperator::NOT_EQUAL: bResult = (n != m); break;
+ case SQLFilterOperator::NOT_LIKE: bResult = (n != m); break;
+ case SQLFilterOperator::LESS: bResult = (n < m); break;
+ case SQLFilterOperator::LESS_EQUAL: bResult = (n <= m); break;
+ case SQLFilterOperator::GREATER: bResult = (n > m); break;
+ case SQLFilterOperator::GREATER_EQUAL: bResult = (n >= m); break;
+ default: bResult = false;
+ }
+ } break;
+ default:
+ bResult = aLH == aRH;
+ }
+ return bResult;
+}
+
+
+void ONumOperator::Exec(OCodeStack& rCodeStack)
+{
+ OOperand *pRight = rCodeStack.top();
+ rCodeStack.pop();
+ OOperand *pLeft = rCodeStack.top();
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResultNUM(operate(pLeft->getValue(), pRight->getValue())));
+ if( typeid(OOperandResult) == typeid(*pLeft))
+ delete pLeft;
+ if( typeid(OOperandResult) == typeid(*pRight))
+ delete pRight;
+}
+
+double OOp_ADD::operate(const double& fLeft,const double& fRight) const
+{
+ return fLeft + fRight;
+}
+
+
+double OOp_SUB::operate(const double& fLeft,const double& fRight) const
+{
+ return fLeft - fRight;
+}
+
+
+double OOp_MUL::operate(const double& fLeft,const double& fRight) const
+{
+ return fLeft * fRight;
+}
+
+
+double OOp_DIV::operate(const double& fLeft,const double& fRight) const
+{
+ return fLeft / fRight;
+}
+
+void ONthOperator::Exec(OCodeStack& rCodeStack)
+{
+ std::vector<ORowSetValue> aValues;
+ std::vector<OOperand*> aOperands;
+ OOperand* pOperand;
+ do
+ {
+ OSL_ENSURE(!rCodeStack.empty(),"Stack must be none empty!");
+ pOperand = rCodeStack.top();
+ rCodeStack.pop();
+ assert(pOperand);
+ if (pOperand && typeid(OStopOperand) != typeid(*pOperand))
+ aValues.push_back( pOperand->getValue() );
+ aOperands.push_back( pOperand );
+ }
+ while (pOperand && typeid(OStopOperand) != typeid(*pOperand));
+
+ rCodeStack.push(new OOperandResult(operate(aValues)));
+
+ for (const auto& rpOperand : aOperands)
+ {
+ if (typeid(OOperandResult) == typeid(*rpOperand))
+ delete rpOperand;
+ }
+}
+
+void OBinaryOperator::Exec(OCodeStack& rCodeStack)
+{
+ OOperand *pRight = rCodeStack.top();
+ rCodeStack.pop();
+ OOperand *pLeft = rCodeStack.top();
+ rCodeStack.pop();
+
+ if ( !rCodeStack.empty() && typeid(OStopOperand) == typeid(*rCodeStack.top()) )
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResult(operate(pLeft->getValue(),pRight->getValue())));
+ if(typeid(OOperandResult) == typeid(*pRight))
+ delete pRight;
+ if(typeid(OOperandResult) == typeid(*pLeft))
+ delete pLeft;
+}
+
+void OUnaryOperator::Exec(OCodeStack& rCodeStack)
+{
+ OSL_ENSURE(!rCodeStack.empty(),"Stack is empty!");
+ OOperand* pOperand = rCodeStack.top();
+ rCodeStack.pop();
+
+ rCodeStack.push(new OOperandResult(operate(pOperand->getValue())));
+ if (typeid(OOperandResult) == typeid(*pOperand))
+ delete pOperand;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */