ClickHouse/dbms/include/DB/Core/SortDescription.h
2013-05-03 10:20:53 +00:00

120 lines
3.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <vector>
#include <DB/Core/Types.h>
#include <DB/Core/Block.h>
#include <DB/Columns/IColumn.h>
namespace DB
{
/// Описание правила сортировки по одному столбцу.
struct SortColumnDescription
{
String column_name; /// Имя столбца.
size_t column_number; /// Номер столбца (используется, если не задано имя).
int direction; /// 1 - по возрастанию, -1 - по убыванию.
SortColumnDescription(size_t column_number_, int direction_)
: column_number(column_number_), direction(direction_) {}
SortColumnDescription(String column_name_, int direction_)
: column_name(column_name_), column_number(0), direction(direction_) {}
/// Для IBlockInputStream.
String getID() const
{
std::stringstream res;
res << column_name << ", " << column_number << ", " << direction;
return res.str();
}
};
/// Описание правила сортировки по нескольким столбцам.
typedef std::vector<SortColumnDescription> SortDescription;
/** Курсор, позволяющий сравнивать соответствующие строки в разных блоках.
* Курсор двигается по одному блоку.
* Для использования в priority queue.
*/
struct SortCursorImpl
{
ConstColumnPlainPtrs all_columns;
ConstColumnPlainPtrs sort_columns;
SortDescription desc;
size_t sort_columns_size;
size_t pos;
size_t rows;
/** Порядок (что сравнивается), если сравниваемые столбцы равны.
* Даёт возможность предпочитать строки из нужного курсора.
*/
size_t order;
SortCursorImpl() {}
SortCursorImpl(const Block & block, const SortDescription & desc_, size_t order_ = 0)
: desc(desc_), sort_columns_size(desc.size()), order(order_)
{
reset(block);
}
/// Установить курсор в начало нового блока.
void reset(const Block & block)
{
all_columns.clear();
sort_columns.clear();
size_t num_columns = block.columns();
for (size_t j = 0; j < num_columns; ++j)
all_columns.push_back(&*block.getByPosition(j).column);
for (size_t j = 0, size = desc.size(); j < size; ++j)
{
size_t column_number = !desc[j].column_name.empty()
? block.getPositionByName(desc[j].column_name)
: desc[j].column_number;
sort_columns.push_back(&*block.getByPosition(column_number).column);
}
pos = 0;
rows = all_columns[0]->size();
}
bool isLast() const { return pos + 1 >= rows; }
void next() { ++pos; }
};
/// Для лёгкости копирования.
struct SortCursor
{
SortCursorImpl * impl;
SortCursor(SortCursorImpl * impl_) : impl(impl_) {}
SortCursorImpl * operator-> () { return impl; }
const SortCursorImpl * operator-> () const { return impl; }
/// Инвертировано, чтобы из priority queue элементы вынимались в нужном порядке.
bool operator< (const SortCursor & rhs) const
{
for (size_t i = 0; i < impl->sort_columns_size; ++i)
{
int res = impl->desc[i].direction * impl->sort_columns[i]->compareAt(impl->pos, rhs.impl->pos, *(rhs.impl->sort_columns[i]));
if (res > 0)
return true;
if (res < 0)
return false;
}
return impl->order > rhs.impl->order;
}
};
}