blob: f559f1250ea01a5d1bbf99db96979bedb8ee58a8 [file] [log] [blame]
/**
*
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <regex>
#include <map>
#include <vector>
#include <algorithm>
#include <memory>
#include <string>
#include "data/DatabaseConnectors.h"
#include "utils/StringUtils.h"
namespace org::apache::nifi::minifi::sql {
class MockRow : public Row {
public:
MockRow(std::vector<std::string>* column_names, std::vector<DataType>* column_types, const std::vector<std::string>& column_values)
: column_names_(column_names), column_types_(column_types), column_values_(column_values) {
}
std::size_t size() const override;
std::string getColumnName(std::size_t index) const override;
bool isNull(std::size_t index) const override;
DataType getDataType(std::size_t index) const override;
std::string getString(std::size_t index) const override;
double getDouble(std::size_t index) const override;
int getInteger(std::size_t index) const override;
long long getLongLong(std::size_t index) const override; // NOLINT Return type comes from SOCI interface
unsigned long long getUnsignedLongLong(std::size_t index) const override; // NOLINT Return type comes from SOCI interface
std::tm getDate(std::size_t /*index*/) const override;
std::vector<std::string> getValues() const;
std::string getValue(const std::string& col_name) const;
DataType getDataType(const std::string& col_name) const;
private:
std::vector<std::string>* column_names_;
std::vector<DataType>* column_types_;
std::vector<std::string> column_values_;
};
class MockRowset : public Rowset {
public:
MockRowset(const std::vector<std::string>& column_names, const std::vector<DataType>& column_types)
: column_names_(column_names), column_types_(column_types) {
}
void addRow(const std::vector<std::string>& column_values);
void reset() override;
bool is_done() override;
Row& getCurrent() override;
void next() override;
std::vector<std::string> getColumnNames() const;
std::vector<DataType> getColumnTypes() const;
std::vector<MockRow> getRows() const;
std::size_t getColumnIndex(const std::string& col_name) const;
void sort(const std::string& order_by_col, bool order_ascending = true);
std::unique_ptr<MockRowset> select(const std::vector<std::string>& cols, const std::function<bool(const MockRow&)>& condition, const std::string& order_by_col, bool order_ascending = true);
private:
std::vector<std::string> column_names_;
std::vector<DataType> column_types_;
std::vector<MockRow> rows_;
std::vector<MockRow>::iterator current_row_;
};
class MockDB {
public:
explicit MockDB(const std::string& file_path) : file_path_(file_path) {
readDb();
}
~MockDB() {
storeDb();
}
std::unique_ptr<Rowset> execute(const std::string& query, const std::vector<std::string>& args);
private:
enum class ParsePhase {
NEW_TABLE,
COLUMN_NAMES,
COLUMN_TYPES,
ROW_VALUES
};
void createTable(const std::string& query);
void insertInto(const std::string& query, const std::vector<std::string>& args);
std::unique_ptr<Rowset> select(const std::string& query, const std::vector<std::string>& args);
void readDb();
void storeDb();
/**
* This function parses an and-separated list of conditions in the format of <column_name> [<>=] <value>
* @param condition_str SQL WHERE condition string with only AND logical operators
* @return Function object evaluating MockRow according to the condition parameter
*/
static std::function<bool(const MockRow&)> parseWhereCondition(const std::string& condition_str);
static DataType stringToDataType(const std::string& type_str);
static std::string dataTypeToString(DataType data_type);
std::string file_path_;
std::map<std::string, MockRowset> tables_;
};
class MockStatement : public Statement {
public:
explicit MockStatement(const std::string& query, const std::string& file_path)
: Statement(query), file_path_(file_path) {
}
std::unique_ptr<Rowset> execute(const std::vector<std::string>& args = {}) override;
private:
std::string file_path_;
};
class MockSession : public Session {
public:
void begin() override {
}
void commit() override {
}
void rollback() override {
}
void execute(const std::string& /*statement*/) override {
}
};
class MockODBCConnection : public Connection {
public:
explicit MockODBCConnection(std::string connectionString);
bool connected(std::string& exception) const override;
std::unique_ptr<sql::Statement> prepareStatement(const std::string& query) const override;
std::unique_ptr<Session> getSession() const override;
private:
std::string connection_string_;
std::string file_path_;
};
} // namespace org::apache::nifi::minifi::sql