2020-01-28 16:08:30 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include <Columns/ColumnsNumber.h>
|
|
|
|
#include <DataStreams/IBlockOutputStream.h>
|
|
|
|
#include <DataStreams/LimitBlockInputStream.h>
|
|
|
|
#include <DataStreams/copyData.h>
|
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
2020-01-28 16:09:24 +00:00
|
|
|
#include <Disks/tests/gtest_disk.h>
|
2020-01-28 16:08:30 +00:00
|
|
|
#include <Formats/FormatFactory.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteBufferFromOStream.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Storages/StorageLog.h>
|
|
|
|
#include <Common/typeid_cast.h>
|
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
#include <memory>
|
|
|
|
|
2020-01-28 16:08:30 +00:00
|
|
|
#if !__clang__
|
|
|
|
# pragma GCC diagnostic push
|
|
|
|
# pragma GCC diagnostic ignored "-Wsuggest-override"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DB::Context createContext()
|
|
|
|
{
|
|
|
|
auto context = DB::Context::createGlobal();
|
|
|
|
context.makeGlobalContext();
|
|
|
|
context.setPath("./");
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
DB::StoragePtr createStorage(DB::DiskPtr & disk)
|
|
|
|
{
|
|
|
|
using namespace DB;
|
|
|
|
|
|
|
|
NamesAndTypesList names_and_types;
|
|
|
|
names_and_types.emplace_back("a", std::make_shared<DataTypeUInt64>());
|
|
|
|
|
|
|
|
StoragePtr table = StorageLog::create(
|
2020-01-30 19:29:30 +00:00
|
|
|
disk, "table/", StorageID("test", "test"), ColumnsDescription{names_and_types}, ConstraintsDescription{}, 1048576);
|
2020-01-28 16:08:30 +00:00
|
|
|
|
|
|
|
table->startup();
|
|
|
|
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
std::unique_ptr<DB::Context> context;
|
|
|
|
|
2020-01-28 16:08:30 +00:00
|
|
|
template <typename T>
|
|
|
|
class StorageLogTest : public testing::Test
|
|
|
|
{
|
|
|
|
public:
|
2020-01-30 19:29:30 +00:00
|
|
|
static void SetUpTestSuite()
|
|
|
|
{
|
|
|
|
// Create context only once.
|
|
|
|
if (!context)
|
|
|
|
context = std::make_unique<DB::Context>(createContext());
|
|
|
|
}
|
|
|
|
|
2020-01-28 16:08:30 +00:00
|
|
|
void SetUp() override
|
|
|
|
{
|
|
|
|
disk_ = createDisk<T>();
|
|
|
|
table_ = createStorage(disk_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TearDown() override
|
|
|
|
{
|
|
|
|
table_->shutdown();
|
|
|
|
destroyDisk<T>(disk_);
|
|
|
|
}
|
|
|
|
|
|
|
|
const DB::DiskPtr & getDisk() { return disk_; }
|
2020-01-30 19:29:30 +00:00
|
|
|
DB::StoragePtr & getTable() { return table_; }
|
2020-01-28 16:08:30 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
DB::DiskPtr disk_;
|
|
|
|
DB::StoragePtr table_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef testing::Types<DB::DiskMemory, DB::DiskLocal> DiskImplementations;
|
|
|
|
TYPED_TEST_SUITE(StorageLogTest, DiskImplementations);
|
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
// Returns data written to table in Values format.
|
|
|
|
std::string writeData(int rows, DB::StoragePtr & table)
|
2020-01-28 16:08:30 +00:00
|
|
|
{
|
|
|
|
using namespace DB;
|
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
std::string data;
|
2020-01-28 16:08:30 +00:00
|
|
|
|
|
|
|
Block block;
|
|
|
|
|
|
|
|
{
|
|
|
|
ColumnWithTypeAndName column;
|
|
|
|
column.name = "a";
|
2020-01-30 19:29:30 +00:00
|
|
|
column.type = table->getColumn("a").type;
|
2020-01-28 16:08:30 +00:00
|
|
|
auto col = column.type->createColumn();
|
|
|
|
ColumnUInt64::Container & vec = typeid_cast<ColumnUInt64 &>(*col).getData();
|
|
|
|
|
|
|
|
vec.resize(rows);
|
|
|
|
for (size_t i = 0; i < rows; ++i)
|
2020-01-30 19:29:30 +00:00
|
|
|
{
|
2020-01-28 16:08:30 +00:00
|
|
|
vec[i] = i;
|
2020-01-30 19:29:30 +00:00
|
|
|
if (i > 0)
|
|
|
|
data += ",";
|
|
|
|
data += "(" + std::to_string(i) + ")";
|
|
|
|
}
|
2020-01-28 16:08:30 +00:00
|
|
|
|
|
|
|
column.column = std::move(col);
|
|
|
|
block.insert(column);
|
|
|
|
}
|
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
BlockOutputStreamPtr out = table->write({}, *context);
|
|
|
|
out->write(block);
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
return data;
|
|
|
|
}
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
// Returns all table data in Values format.
|
|
|
|
std::string readData(DB::StoragePtr & table)
|
|
|
|
{
|
|
|
|
using namespace DB;
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
Names column_names;
|
|
|
|
column_names.push_back("a");
|
|
|
|
|
|
|
|
QueryProcessingStage::Enum stage = table->getQueryProcessingStage(*context);
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
BlockInputStreamPtr in = table->read(column_names, {}, *context, stage, 8192, 1)[0];
|
|
|
|
|
|
|
|
Block sample;
|
2020-01-28 16:08:30 +00:00
|
|
|
{
|
2020-01-30 19:29:30 +00:00
|
|
|
ColumnWithTypeAndName col;
|
|
|
|
col.type = std::make_shared<DataTypeUInt64>();
|
|
|
|
sample.insert(std::move(col));
|
|
|
|
}
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
std::ostringstream ss;
|
|
|
|
WriteBufferFromOStream out_buf(ss);
|
|
|
|
BlockOutputStreamPtr output = FormatFactory::instance().getOutput("Values", out_buf, sample, *context);
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
copyData(*in, *output);
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
output->flush();
|
|
|
|
|
|
|
|
return ss.str();
|
|
|
|
}
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
TYPED_TEST(StorageLogTest, testReadWrite)
|
|
|
|
{
|
|
|
|
using namespace DB;
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
std::string data;
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
// Write several chunks of data.
|
|
|
|
data += writeData(10, this->getTable());
|
|
|
|
data += ",";
|
|
|
|
data += writeData(20, this->getTable());
|
|
|
|
data += ",";
|
|
|
|
data += writeData(10, this->getTable());
|
2020-01-28 16:08:30 +00:00
|
|
|
|
2020-01-30 19:29:30 +00:00
|
|
|
ASSERT_EQ(data, readData(this->getTable()));
|
2020-01-28 16:08:30 +00:00
|
|
|
}
|