44#include < Interpreters/ExpressionActions.h>
55#include < Columns/ColumnsCommon.h>
66#include < Columns/ColumnsNumber.h>
7+ #include < Columns/ColumnConst.h>
78#include < Common/assert_cast.h>
89#include < Common/quoteString.h>
910#include < Common/FieldVisitors.h>
@@ -15,6 +16,7 @@ namespace DB
1516namespace ErrorCodes
1617{
1718 extern const int VIOLATED_CONSTRAINT;
19+ extern const int LOGICAL_ERROR;
1820}
1921
2022
@@ -41,45 +43,72 @@ void CheckConstraintsBlockOutputStream::write(const Block & block)
4143 for (size_t i = 0 ; i < expressions.size (); ++i)
4244 {
4345 auto constraint_expr = expressions[i];
44-
4546 constraint_expr->execute (block_to_calculate);
47+
48+ auto * constraint_ptr = constraints.constraints [i]->as <ASTConstraintDeclaration>();
49+
4650 ColumnWithTypeAndName res_column = block_to_calculate.getByPosition (block_to_calculate.columns () - 1 );
47- const ColumnUInt8 & res_column_uint8 = assert_cast<const ColumnUInt8 &>(*res_column.column );
4851
49- const UInt8 * data = res_column_uint8.getData ().data ();
50- size_t size = res_column_uint8.size ();
52+ if (!isUInt8 (res_column.type ))
53+ throw Exception (ErrorCodes::LOGICAL_ERROR, " Constraint {} does not return a value of type UInt8" ,
54+ backQuote (constraint_ptr->name ));
5155
52- // / Is violated.
53- if (!memoryIsByte (data, size, 1 ))
56+ if (const ColumnConst * res_const = typeid_cast<const ColumnConst *>(res_column.column .get ()))
5457 {
55- size_t row_idx = 0 ;
56- for (; row_idx < size; ++row_idx)
57- if (data[row_idx] != 1 )
58- break ;
58+ UInt8 value = res_const->getValue <UInt64>();
5959
60- Names related_columns = constraint_expr->getRequiredColumns ();
60+ // / Is violated.
61+ if (!value)
62+ {
63+ std::stringstream exception_message;
6164
62- std::stringstream exception_message;
65+ exception_message << " Constraint " << backQuote (constraint_ptr->name )
66+ << " for table " << table_id.getNameForLogs ()
67+ << " is violated, because it is a constant expression returning 0."
68+ << " It is most likely an error in table definition." ;
69+
70+ throw Exception{exception_message.str (), ErrorCodes::VIOLATED_CONSTRAINT};
71+ }
72+ }
73+ else
74+ {
75+ const ColumnUInt8 & res_column_uint8 = assert_cast<const ColumnUInt8 &>(*res_column.column );
6376
64- exception_message << " Constraint " << backQuote (constraints.constraints [i]->name )
65- << " for table " << backQuote (table)
66- << " is violated at row " << (rows_written + row_idx + 1 )
67- << " . Expression: (" << serializeAST (*(constraints.constraints [i]->expr ), true ) << " )"
68- << " . Column values" ;
77+ const UInt8 * data = res_column_uint8.getData ().data ();
78+ size_t size = res_column_uint8.size ();
6979
70- bool first = true ;
71- for ( const auto & name : related_columns )
80+ // / Is violated.
81+ if (! memoryIsByte (data, size, 1 ) )
7282 {
73- const IColumn & column = *block.getByName (name).column ;
74- assert (row_idx < column.size ());
83+ size_t row_idx = 0 ;
84+ for (; row_idx < size; ++row_idx)
85+ if (data[row_idx] != 1 )
86+ break ;
7587
76- exception_message << (first ? " : " : " , " )
77- << backQuoteIfNeed (name) << " = " << applyVisitor (FieldVisitorToString (), column[row_idx]);
88+ Names related_columns = constraint_expr->getRequiredColumns ();
7889
79- first = false ;
80- }
90+ std::stringstream exception_message;
91+
92+ exception_message << " Constraint " << backQuote (constraint_ptr->name )
93+ << " for table " << table_id.getNameForLogs ()
94+ << " is violated at row " << (rows_written + row_idx + 1 )
95+ << " . Expression: (" << serializeAST (*(constraint_ptr->expr ), true ) << " )"
96+ << " . Column values" ;
97+
98+ bool first = true ;
99+ for (const auto & name : related_columns)
100+ {
101+ const IColumn & column = *block.getByName (name).column ;
102+ assert (row_idx < column.size ());
81103
82- throw Exception{exception_message.str (), ErrorCodes::VIOLATED_CONSTRAINT};
104+ exception_message << (first ? " : " : " , " )
105+ << backQuoteIfNeed (name) << " = " << applyVisitor (FieldVisitorToString (), column[row_idx]);
106+
107+ first = false ;
108+ }
109+
110+ throw Exception{exception_message.str (), ErrorCodes::VIOLATED_CONSTRAINT};
111+ }
83112 }
84113 }
85114 }
0 commit comments