2019-05-19 05:27:00 +00:00
|
|
|
#include <DataStreams/CheckConstraintsBlockOutputStream.h>
|
2019-06-05 08:05:46 +00:00
|
|
|
#include <Functions/FunctionHelpers.h>
|
|
|
|
#include <common/find_symbols.h>
|
2019-06-05 07:33:34 +00:00
|
|
|
#include <Parsers/formatAST.h>
|
2019-06-05 08:05:46 +00:00
|
|
|
#include <Columns/ColumnsCommon.h>
|
2019-05-19 05:27:00 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
void CheckConstraintsBlockOutputStream::write(const Block & block)
|
|
|
|
{
|
2019-06-05 07:33:34 +00:00
|
|
|
for (size_t i = 0; i < expressions.size(); ++i)
|
|
|
|
{
|
2019-08-11 09:28:15 +00:00
|
|
|
Block res = block;
|
2019-06-05 07:33:34 +00:00
|
|
|
auto constraint_expr = expressions[i];
|
2019-08-11 09:28:15 +00:00
|
|
|
auto res_column_uint8 = executeOnBlock(res, constraint_expr);
|
2019-07-28 12:33:40 +00:00
|
|
|
if (!memoryIsByte(res_column_uint8->getRawDataBegin<1>(), res_column_uint8->byteSize(), 0x1))
|
|
|
|
{
|
|
|
|
auto indices_wrong = findAllWrong(res_column_uint8->getRawDataBegin<1>(), res_column_uint8->byteSize());
|
|
|
|
std::string indices_str = "{";
|
2019-07-29 10:05:43 +00:00
|
|
|
for (size_t j = 0; j < indices_wrong.size(); ++j)
|
|
|
|
{
|
2019-07-28 12:33:40 +00:00
|
|
|
indices_str += std::to_string(indices_wrong[j]);
|
|
|
|
indices_str += (j != indices_wrong.size() - 1) ? ", " : "}";
|
|
|
|
}
|
|
|
|
|
|
|
|
throw Exception{"Violated constraint " + constraints.constraints[i]->name +
|
|
|
|
" in table " + table + " at indices " + indices_str + ", constraint expression: " +
|
2019-08-14 19:51:03 +00:00
|
|
|
serializeAST(*(constraints.constraints[i]->expr), true), DB::ErrorCodes::VIOLATED_CONSTRAINT};
|
2019-07-28 12:33:40 +00:00
|
|
|
}
|
2019-06-05 07:33:34 +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();
|
|
|
|
}
|
|
|
|
|
2019-07-28 12:33:40 +00:00
|
|
|
const ColumnUInt8 *CheckConstraintsBlockOutputStream::executeOnBlock(
|
2019-08-11 09:28:15 +00:00
|
|
|
Block & block,
|
2019-07-28 12:33:40 +00:00
|
|
|
const ExpressionActionsPtr & constraint)
|
2019-06-05 08:05:46 +00:00
|
|
|
{
|
2019-08-11 09:28:15 +00:00
|
|
|
constraint->execute(block);
|
|
|
|
ColumnWithTypeAndName res_column = block.safeGetByPosition(block.columns() - 1);
|
2019-07-28 12:33:40 +00:00
|
|
|
return checkAndGetColumn<ColumnUInt8>(res_column.column.get());
|
2019-06-05 08:05:46 +00:00
|
|
|
}
|
|
|
|
|
2019-07-28 12:33:40 +00:00
|
|
|
std::vector<size_t> CheckConstraintsBlockOutputStream::findAllWrong(const void *data, size_t size)
|
2019-06-05 08:05:46 +00:00
|
|
|
{
|
2019-07-28 12:33:40 +00:00
|
|
|
std::vector<size_t> res;
|
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
auto ptr = reinterpret_cast<const uint8_t *>(data);
|
2019-06-05 08:05:46 +00:00
|
|
|
|
2019-07-28 12:33:40 +00:00
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
if (*(ptr + i) == 0x0)
|
|
|
|
{
|
|
|
|
res.push_back(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2019-05-19 05:27:00 +00:00
|
|
|
}
|