build fix [#METR-10498]

This commit is contained in:
Pavel Kartavyy 2014-03-26 22:19:25 +04:00
parent 14168120f1
commit a737895eb4
5 changed files with 79 additions and 51 deletions

View File

@ -74,6 +74,14 @@ namespace DB
{
return strcmp(lhs.data, rhs.data) < 0 ? true : false;
}
inline std::ostream & operator<<(std::ostream & os, const StringRef & str)
{
if (str.data)
return os << str.toString();
else
return os;
}
}
namespace std

View File

@ -20,8 +20,7 @@
#include <DB/Columns/ColumnConst.h>
#include <DB/Columns/ColumnArray.h>
#include <DB/Storages/MergeTree/PKCondition.h>
#include <DB/Storages/MergeTree/BoolMask.h>
namespace DB
{
@ -64,16 +63,18 @@ public:
*/
void execute(Block & block, const ColumnNumbers & arguments, size_t result, bool negative) const;
std::string toString()
std::string descibe()
{
if (type == KEY_64)
return setToString(key64);
else if (type == KEY_STRING)
return setToString(key_string);
else if (type == HASHED)
return setToString(hashed);
return "{hashed values}";
else if (type == EMPTY)
return "{}";
else
throw DB::Exception("Unknown type");
}
void createOrderedSet()
@ -87,14 +88,17 @@ public:
std::sort(ordered_string.begin(), ordered_string.end());
}
BoolMask mayBeTrueInRange(const Range & key_range)
BoolMask mayBeTrueInRange(const Field & left, const Field & right)
{
if (type == KEY_64)
return mayBeTrueInRangeImpl(key_range, ordered_key64);
return mayBeTrueInRangeImpl(left, right, ordered_key64);
else if (type == KEY_STRING)
return mayBeTrueInRangeImpl(key_range, ordered_string);
else
throw DB::Exception("Unsupported set of type " << type);
return mayBeTrueInRangeImpl(left, right, ordered_string);
else{
std::stringstream ss;
ss << "Unsupported set of type " << type;
throw DB::Exception(ss.str());
}
}
private:
/** Разные структуры данных, которые могут использоваться для проверки принадлежности
@ -166,16 +170,17 @@ private:
{
std::stringstream ss;
bool first = false;
for (auto & n : set)
for (auto it = set.begin(); it != set.end(); ++it)
{
if (first)
{
ss << n;
ss << *it;
first = false;
}
else
{
ss << ", " << n;
ss << ", " << *it;
}
}
@ -187,34 +192,42 @@ private:
std::vector<UInt64> ordered_key64;
std::vector<StringRef> ordered_string;
template <class Set>
BoolMask mayBeTrueInRangeImpl(const Range & key_range, const Set & set)
template <class T>
BoolMask mayBeTrueInRangeImpl(const Field & field_left, const Field & field_right, const std::vector<T> & v)
{
T left = field_left.get<T>();
T right = field_right.get<T>();
bool can_be_true;
bool can_be_false = true;
/// Если во всем диапазоне одинаковый ключ и он есть в Set, то выбираем блок для in и не выбираем для notIn
if (key_range.left == key_range.right)
if (left == right)
{
if (set.find(key_range.left) != set.end())
if (std::find(v.begin(), v.end(), left) != v.end())
{
can_be_false = false;
can_be_true = true;
}
else
{
can_be_true = false;
can_be_false = true;
}
}
else
{
auto left_it = set.lower_boud(key_range.left);
auto left_it = std::lower_bound(v.begin(), v.end(), left);
/// если весь диапазон, правее in
if (left_it == set.end())
if (left_it == v.end())
{
can_be_true = false;
}
else
{
auto right_it = set.upper_bound(key_range.right);
auto right_it = std::upper_bound(v.begin(), v.end(), right);
/// весь диапазон, левее in
if (right_it == set.begin())
if (right_it == v.begin())
{
can_be_true = false;
}
@ -239,7 +252,7 @@ private:
};
typedef SharedPtr<Set> SetPtr;
typedef Poco::SharedPtr<Set> SetPtr;
typedef std::vector<SetPtr> Sets;

View File

@ -0,0 +1,24 @@
#pragma once
/// Множество значений булевой переменной. То есть два булевых значения: может ли быть true, может ли быть false.
struct BoolMask
{
bool can_be_true;
bool can_be_false;
BoolMask() {}
BoolMask(bool can_be_true_, bool can_be_false_) : can_be_true(can_be_true_), can_be_false(can_be_false_) {}
BoolMask operator &(const BoolMask & m)
{
return BoolMask(can_be_true && m.can_be_true, can_be_false || m.can_be_false);
}
BoolMask operator |(const BoolMask & m)
{
return BoolMask(can_be_true || m.can_be_true, can_be_false && m.can_be_false);
}
BoolMask operator !()
{
return BoolMask(can_be_false, can_be_true);
}
};

View File

@ -9,6 +9,7 @@
#include <DB/Parsers/ASTFunction.h>
#include <DB/Parsers/ASTLiteral.h>
#include <DB/Columns/ColumnSet.h>
#include <DB/Storages/MergeTree/BoolMask.h>
namespace DB
@ -115,29 +116,6 @@ public:
bool operator() (const Array & l, const Array & r) const { return l < r; }
};
/// Множество значений булевой переменной. То есть два булевых значения: может ли быть true, может ли быть false.
struct BoolMask
{
bool can_be_true;
bool can_be_false;
BoolMask() {}
BoolMask(bool can_be_true_, bool can_be_false_) : can_be_true(can_be_true_), can_be_false(can_be_false_) {}
BoolMask operator &(const BoolMask & m)
{
return BoolMask(can_be_true && m.can_be_true, can_be_false || m.can_be_false);
}
BoolMask operator |(const BoolMask & m)
{
return BoolMask(can_be_true || m.can_be_true, can_be_false && m.can_be_false);
}
BoolMask operator !()
{
return BoolMask(can_be_false, can_be_true);
}
};
#pragma GCC diagnostic pop
/** Диапазон с открытыми или закрытыми концами; возможно, неограниченный.
@ -335,6 +313,7 @@ private:
String toString()
{
std::ostringstream ss;
switch (function)
{
case FUNCTION_AND:
@ -345,14 +324,15 @@ private:
return "not";
case FUNCTION_UNKNOWN:
return "unknown";
case FUNCTION_NOT_IN_SET:
case FUNCTION_IN_SET:
std::ostringstream ss;
ss << "(column " << key_column << " in " << set->toString() << ")";
{
ss << "(column " << key_column << (function == FUNCTION_IN_SET ? " in " : " notIn ") << set->descibe() << ")";
return ss.str();
}
case FUNCTION_IN_RANGE:
case FUNCTION_NOT_IN_RANGE:
{
std::ostringstream ss;
ss << "(column " << key_column << (function == FUNCTION_NOT_IN_RANGE ? " not" : "") << " in " << range.toString() << ")";
return ss.str();
}

View File

@ -2,6 +2,7 @@
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <DB/Columns/ColumnSet.h>
#include <DB/Columns/ColumnTuple.h>
namespace DB
{
@ -139,10 +140,12 @@ bool PKCondition::atomFromAST(ASTPtr & node, Block & block_with_constants, RPNEl
column = pk_columns[args[1]->getColumnName()];
}
/// для In, notIn
else if (pk_columns.count(args[0]->getColumnName()) && dynamic_cast<DB::ColumnSet *>(args[1]))
else if (pk_columns.count(args[0]->getColumnName()) && dynamic_cast<DB::ColumnSet *>(args[1].get()))
{
/// для in не бывает inverted
inverted = false;
/// не поддерживаем Primary Key, если аргумент функции in tuple
if (dynamic_cast<DB::ColumnTuple*>(args[0]))
if (dynamic_cast<DB::ColumnTuple*>(args[0].get()))
return false;
column = pk_columns[args[0]->getColumnName()];
}
@ -185,7 +188,7 @@ bool PKCondition::atomFromAST(ASTPtr & node, Block & block_with_constants, RPNEl
else if (func->name == "in" || func->name == "notIn")
{
out.function = func->name == "in" ? RPNElement::FUNCTION_IN_SET : RPNElement::FUNCTION_NOT_IN_SET;
out.set = (dynamic_cast<DB::ColumnSet *>(args[1])->getData();
out.set = (dynamic_cast<DB::ColumnSet *>(args[1].get())->getData());
out.set->createOrderedSet();
}
else
@ -281,7 +284,7 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
{
const Range & key_range = key_ranges[element.key_column];
rpn_stack.push_back(element.set->mayBeTrueInRange(key_range));
rpn_stack.push_back(element.set->mayBeTrueInRange(key_range.left, key_range.right));
if (element.function == RPNElement::FUNCTION_NOT_IN_SET)
rpn_stack.back() = !rpn_stack.back();
}