ClickHouse/dbms/src/DataStreams/CheckConstraintsBlockOutputStream.cpp

107 lines
3.2 KiB
C++
Raw Normal View History

#include <DataStreams/ExpressionBlockInputStream.h>
2019-05-19 05:27:00 +00:00
#include <DataStreams/CheckConstraintsBlockOutputStream.h>
#include <Parsers/formatAST.h>
#include <Columns/ColumnsCommon.h>
#include <Common/assert_cast.h>
2019-08-24 21:35:07 +00:00
#include <Common/FieldVisitors.h>
2019-05-19 05:27:00 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int VIOLATED_CONSTRAINT;
}
CheckConstraintsBlockOutputStream::CheckConstraintsBlockOutputStream(
const String & table_,
const BlockOutputStreamPtr & output_,
const Block & header_,
const ConstraintsDescription & constraints_,
const Context & context_)
: table(table_),
output(output_),
header(header_),
constraints(constraints_),
expressions(constraints_.getExpressions(context_, header.getNamesAndTypesList()))
{
}
2019-05-19 05:27:00 +00:00
void CheckConstraintsBlockOutputStream::write(const Block & block)
{
if (block.rows() > 0)
{
2019-08-24 21:20:20 +00:00
std::cerr << "Checking " << expressions.size() << " constraints\n";
for (size_t i = 0; i < expressions.size(); ++i)
2019-07-28 12:33:40 +00:00
{
2019-08-24 21:20:20 +00:00
std::cerr << serializeAST(*(constraints.constraints[i]->expr), true) << "\n";
Block block_to_calculate = block;
auto constraint_expr = expressions[i];
constraint_expr->execute(block_to_calculate);
ColumnWithTypeAndName res_column = block_to_calculate.getByPosition(block_to_calculate.columns() - 1);
const ColumnUInt8 & res_column_uint8 = assert_cast<const ColumnUInt8 &>(*res_column.column);
const UInt8 * data = res_column_uint8.getData().data();
size_t size = res_column_uint8.size();
/// Is violated.
if (!memoryIsByte(data, size, 1))
2019-07-29 10:05:43 +00:00
{
size_t row_idx = 0;
for (; row_idx < size; ++row_idx)
if (data[row_idx] != 1)
break;
2019-07-28 12:33:40 +00:00
2019-08-24 21:35:07 +00:00
Names related_columns = constraint_expr->getRequiredColumns();
std::stringstream exception_message;
exception_message << "Constraint " << backQuote(constraints.constraints[i]->name)
<< " for table " << backQuote(table)
<< " is violated at row " << (rows_written + row_idx + 1)
<< ". Expression: (" << serializeAST(*(constraints.constraints[i]->expr), true) << ")"
<< ". Column values";
bool first = true;
for (const auto & name : related_columns)
{
const IColumn & column = *block.getByName(name).column;
assert(row_idx < column.size());
exception_message << (first ? ": " : ", ")
<< backQuoteIfNeed(name) << " = " << applyVisitor(FieldVisitorToString(), column[row_idx]);
first = false;
}
throw Exception{exception_message.str(), ErrorCodes::VIOLATED_CONSTRAINT};
}
2019-07-28 12:33:40 +00:00
}
}
2019-05-19 05:27:00 +00:00
output->write(block);
2019-07-28 12:33:40 +00:00
rows_written += block.rows();
2019-05-19 05:27:00 +00:00
}
void CheckConstraintsBlockOutputStream::flush()
{
output->flush();
}
void CheckConstraintsBlockOutputStream::writePrefix()
{
output->writePrefix();
}
void CheckConstraintsBlockOutputStream::writeSuffix()
{
output->writeSuffix();
}
}