Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#3922
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
guo-shaoge authored and ti-chi-bot committed Feb 21, 2022
1 parent 0c9c1ff commit f55cd5e
Show file tree
Hide file tree
Showing 5 changed files with 863 additions and 71 deletions.
77 changes: 10 additions & 67 deletions dbms/src/Flash/Coprocessor/DAGContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,76 +11,19 @@ extern const int DIVIDED_BY_ZERO;
extern const int INVALID_TIME;
} // namespace ErrorCodes

namespace
{
enum Flag
{
IGNORE_TRUNCATE = 1,
TRUNCATE_AS_WARNING = 1u << 1u,
PAD_CHAR_TO_FULL_LENGTH = 1u << 2u,
IN_INSERT_STMT = 1u << 3u,
IN_UPDATE_OR_DELETE_STMT = 1u << 4u,
IN_SELECT_STMT = 1u << 5u,
OVERFLOW_AS_WARNING = 1u << 6u,
IGNORE_ZERO_IN_DATE = 1u << 7u,
DIVIDED_BY_ZERO_AS_WARNING = 1u << 8u,
IN_LOAD_DATA_STMT = 1u << 10u,
};

enum SqlMode
{
REAL_AS_FLOAT = 1ul,
PIPES_AS_CONCAT = 1ul << 1ul,
ANSI_QUOTES = 1ul << 2ul,
IGNORE_SPACE = 1ul << 3ul,
NOT_USED = 1ul << 4ul,
ONLY_FULL_GROUP_BY = 1ul << 5ul,
NO_UNSIGNED_SUBTRACTION = 1ul << 6ul,
NO_DIR_IN_CREATE = 1ul << 7ul,
POSTGRESQL = 1ul << 8ul,
ORACLE = 1ul << 9ul,
MSSQL = 1ul << 10ul,
DB2 = 1ul << 11ul,
MAXDB = 1ul << 12ul,
NO_KEY_OPTIONS = 1ul << 13ul,
NO_TABLE_OPTIONS = 1ul << 14ul,
NO_FIELD_OPTIONS = 1ul << 15ul,
MYSQL323 = 1ul << 16ul,
MYSQL40 = 1ul << 17ul,
ANSI = 1ul << 18ul,
NO_AUTO_VALUE_ON_ZERO = 1ul << 19ul,
NO_BACK_SLASH_ESCAPES = 1ul << 20ul,
STRICT_TRANS_TABLES = 1ul << 21ul,
STRICT_ALL_TABLES = 1ul << 22ul,
NO_ZERO_IN_DATE = 1ul << 23ul,
NO_ZERO_DATE = 1ul << 24ul,
INVALID_DATES = 1ul << 25ul,
ERROR_FOR_DIVISION_BY_ZERO = 1ul << 26ul,
TRADITIONAL = 1ul << 27ul,
NO_AUTO_CREATE_USER = 1ul << 28ul,
HIGH_NOT_PRECEDENCE = 1ul << 29ul,
NO_ENGINE_SUBSTITUTION = 1ul << 30ul,

// Duplicated with Flag::PAD_CHAR_TO_FULL_LENGTH
// PAD_CHAR_TO_FULL_LENGTH = 1ul << 31ul,

ALLOW_INVALID_DATES = 1ul << 32ul,
};
} // namespace

bool strictSqlMode(UInt64 sql_mode)
{
return sql_mode & SqlMode::STRICT_ALL_TABLES || sql_mode & SqlMode::STRICT_TRANS_TABLES;
return sql_mode & TiDBSQLMode::STRICT_ALL_TABLES || sql_mode & TiDBSQLMode::STRICT_TRANS_TABLES;
}

bool DAGContext::allowZeroInDate() const
{
return flags & Flag::IGNORE_ZERO_IN_DATE;
return flags & TiDBSQLFlags::IGNORE_ZERO_IN_DATE;
}

bool DAGContext::allowInvalidDate() const
{
return sql_mode & SqlMode::ALLOW_INVALID_DATES;
return sql_mode & TiDBSQLMode::ALLOW_INVALID_DATES;
}

std::map<String, ProfileStreamsInfo> & DAGContext::getProfileStreamsMap()
Expand All @@ -100,7 +43,7 @@ std::unordered_map<UInt32, std::vector<String>> & DAGContext::getQBIdToJoinAlias

void DAGContext::handleTruncateError(const String & msg)
{
if (!(flags & Flag::IGNORE_TRUNCATE || flags & Flag::TRUNCATE_AS_WARNING))
if (!(flags & TiDBSQLFlags::IGNORE_TRUNCATE || flags & TiDBSQLFlags::TRUNCATE_AS_WARNING))
{
throw TiFlashException("Truncate error " + msg, Errors::Types::Truncated);
}
Expand All @@ -109,7 +52,7 @@ void DAGContext::handleTruncateError(const String & msg)

void DAGContext::handleOverflowError(const String & msg, const TiFlashError & error)
{
if (!(flags & Flag::OVERFLOW_AS_WARNING))
if (!(flags & TiDBSQLFlags::OVERFLOW_AS_WARNING))
{
throw TiFlashException("Overflow error: " + msg, error);
}
Expand All @@ -118,11 +61,11 @@ void DAGContext::handleOverflowError(const String & msg, const TiFlashError & er

void DAGContext::handleDivisionByZero()
{
if (flags & Flag::IN_INSERT_STMT || flags & Flag::IN_UPDATE_OR_DELETE_STMT)
if (flags & TiDBSQLFlags::IN_INSERT_STMT || flags & TiDBSQLFlags::IN_UPDATE_OR_DELETE_STMT)
{
if (!(sql_mode & SqlMode::ERROR_FOR_DIVISION_BY_ZERO))
if (!(sql_mode & TiDBSQLMode::ERROR_FOR_DIVISION_BY_ZERO))
return;
if (strictSqlMode(sql_mode) && !(flags & Flag::DIVIDED_BY_ZERO_AS_WARNING))
if (strictSqlMode(sql_mode) && !(flags & TiDBSQLFlags::DIVIDED_BY_ZERO_AS_WARNING))
{
throw TiFlashException("Division by 0", Errors::Expression::DivisionByZero);
}
Expand All @@ -137,7 +80,7 @@ void DAGContext::handleInvalidTime(const String & msg, const TiFlashError & erro
throw TiFlashException(msg, error);
}
handleTruncateError(msg);
if (strictSqlMode(sql_mode) && (flags & Flag::IN_INSERT_STMT || flags & Flag::IN_UPDATE_OR_DELETE_STMT))
if (strictSqlMode(sql_mode) && (flags & TiDBSQLFlags::IN_INSERT_STMT || flags & TiDBSQLFlags::IN_UPDATE_OR_DELETE_STMT))
{
throw TiFlashException(msg, error);
}
Expand All @@ -153,7 +96,7 @@ void DAGContext::appendWarning(const String & msg, int32_t code)

bool DAGContext::shouldClipToZero()
{
return flags & Flag::IN_INSERT_STMT || flags & Flag::IN_LOAD_DATA_STMT;
return flags & TiDBSQLFlags::IN_INSERT_STMT || flags & TiDBSQLFlags::IN_LOAD_DATA_STMT;
}

std::pair<bool, double> DAGContext::getTableScanThroughput()
Expand Down
84 changes: 84 additions & 0 deletions dbms/src/Flash/Coprocessor/DAGContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,64 @@ UInt64 inline getMaxErrorCount(const tipb::DAGRequest &)
/// todo max_error_count is a system variable in mysql, TiDB should put it into dag request, now use the default value instead
return 1024;
}
<<<<<<< HEAD
=======

namespace TiDBSQLFlags
{
constexpr UInt64 IGNORE_TRUNCATE = 1;
constexpr UInt64 TRUNCATE_AS_WARNING = 1u << 1u;
constexpr UInt64 PAD_CHAR_TO_FULL_LENGTH = 1u << 2u;
constexpr UInt64 IN_INSERT_STMT = 1u << 3u;
constexpr UInt64 IN_UPDATE_OR_DELETE_STMT = 1u << 4u;
constexpr UInt64 IN_SELECT_STMT = 1u << 5u;
constexpr UInt64 OVERFLOW_AS_WARNING = 1u << 6u;
constexpr UInt64 IGNORE_ZERO_IN_DATE = 1u << 7u;
constexpr UInt64 DIVIDED_BY_ZERO_AS_WARNING = 1u << 8u;
constexpr UInt64 IN_LOAD_DATA_STMT = 1u << 10u;
} // namespace TiDBSQLFlags

namespace TiDBSQLMode
{
constexpr UInt64 REAL_AS_FLOAT = 1ul;
constexpr UInt64 PIPES_AS_CONCAT = 1ul << 1ul;
constexpr UInt64 ANSI_QUOTES = 1ul << 2ul;
constexpr UInt64 IGNORE_SPACE = 1ul << 3ul;
constexpr UInt64 NOT_USED = 1ul << 4ul;
constexpr UInt64 ONLY_FULL_GROUP_BY = 1ul << 5ul;
constexpr UInt64 NO_UNSIGNED_SUBTRACTION = 1ul << 6ul;
constexpr UInt64 NO_DIR_IN_CREATE = 1ul << 7ul;
constexpr UInt64 POSTGRESQL = 1ul << 8ul;
constexpr UInt64 ORACLE = 1ul << 9ul;
constexpr UInt64 MSSQL = 1ul << 10ul;
constexpr UInt64 DB2 = 1ul << 11ul;
constexpr UInt64 MAXDB = 1ul << 12ul;
constexpr UInt64 NO_KEY_OPTIONS = 1ul << 13ul;
constexpr UInt64 NO_TABLE_OPTIONS = 1ul << 14ul;
constexpr UInt64 NO_FIELD_OPTIONS = 1ul << 15ul;
constexpr UInt64 MYSQL323 = 1ul << 16ul;
constexpr UInt64 MYSQL40 = 1ul << 17ul;
constexpr UInt64 ANSI = 1ul << 18ul;
constexpr UInt64 NO_AUTO_VALUE_ON_ZERO = 1ul << 19ul;
constexpr UInt64 NO_BACK_SLASH_ESCAPES = 1ul << 20ul;
constexpr UInt64 STRICT_TRANS_TABLES = 1ul << 21ul;
constexpr UInt64 STRICT_ALL_TABLES = 1ul << 22ul;
constexpr UInt64 NO_ZERO_IN_DATE = 1ul << 23ul;
constexpr UInt64 NO_ZERO_DATE = 1ul << 24ul;
constexpr UInt64 INVALID_DATES = 1ul << 25ul;
constexpr UInt64 ERROR_FOR_DIVISION_BY_ZERO = 1ul << 26ul;
constexpr UInt64 TRADITIONAL = 1ul << 27ul;
constexpr UInt64 NO_AUTO_CREATE_USER = 1ul << 28ul;
constexpr UInt64 HIGH_NOT_PRECEDENCE = 1ul << 29ul;
constexpr UInt64 NO_ENGINE_SUBSTITUTION = 1ul << 30ul;

// Duplicated with Flag::PAD_CHAR_TO_FULL_LENGTH
// PAD_CHAR_TO_FULL_LENGTH = 1ul << 31ul;

constexpr UInt64 ALLOW_INVALID_DATES = 1ul << 32ul;
} // namespace TiDBSQLMode

>>>>>>> 6ea6c80198 (Fix cast to decimal overflow bug (#3922))
/// A context used to track the information that needs to be passed around during DAG planning.
class DAGContext
{
Expand Down Expand Up @@ -125,7 +183,33 @@ class DAGContext

BlockInputStreams & getRemoteInputStreams() { return remote_block_input_streams; }

<<<<<<< HEAD
std::pair<bool, double> getTableScanThroughput();
=======
UInt64 getFlags() const
{
return flags;
}
void setFlags(UInt64 f)
{
flags = f;
}
void addFlag(UInt64 f)
{
flags |= f;
}
void delFlag(UInt64 f)
{
flags &= (~f);
}
bool hasFlag(UInt64 f) const
{
return (flags & f);
}

void initExchangeReceiverIfMPP(Context & context, size_t max_streams);
const std::unordered_map<String, std::shared_ptr<ExchangeReceiver>> & getMPPExchangeReceiverMap() const;
>>>>>>> 6ea6c80198 (Fix cast to decimal overflow bug (#3922))

size_t final_concurrency = 1;
Int64 compile_time_ns;
Expand Down
27 changes: 27 additions & 0 deletions dbms/src/Flash/Coprocessor/tests/gtest_dag_context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <Flash/Coprocessor/DAGContext.h>
#include <gtest/gtest.h>

namespace DB
{
namespace tests
{
TEST(DAGContextTest, FlagsTest)
{
DAGContext context(1024);

ASSERT_EQ(context.getFlags(), static_cast<UInt64>(0));

UInt64 f = TiDBSQLFlags::TRUNCATE_AS_WARNING | TiDBSQLFlags::IN_LOAD_DATA_STMT;
context.setFlags(f);
ASSERT_EQ(context.getFlags(), f);

UInt64 f1 = f | TiDBSQLFlags::OVERFLOW_AS_WARNING;
context.addFlag(TiDBSQLFlags::OVERFLOW_AS_WARNING);
ASSERT_EQ(context.getFlags(), f1);

context.delFlag(TiDBSQLFlags::OVERFLOW_AS_WARNING);
ASSERT_EQ(context.getFlags(), f);
}

} // namespace tests
} // namespace DB
25 changes: 21 additions & 4 deletions dbms/src/Functions/FunctionsTiDBConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -811,9 +811,13 @@ struct TiDBConvertToDecimal
using FromFieldType = typename FromDataType::FieldType;

template <typename T, typename U>
static U toTiDBDecimalInternal(T value, PrecType prec, ScaleType scale, const Context & context)
static U toTiDBDecimalInternal(T int_value, PrecType prec, ScaleType scale, const Context & context)
{
// int_value is the value that exposes to user. Such as cast(val to decimal), val is the int_value which used by user.
// And val * scale_mul is the scaled_value, which is stored in ColumnDecimal internally.
static_assert(std::is_integral_v<T>);
using UType = typename U::NativeType;
<<<<<<< HEAD
auto maxValue = DecimalMaxValue::get(prec);
if (value > maxValue || value < -maxValue)
{
Expand All @@ -822,10 +826,23 @@ struct TiDBConvertToDecimal
return static_cast<UType>(maxValue);
else
return static_cast<UType>(-maxValue);
}
=======
UType scale_mul = getScaleMultiplier<U>(scale);
U result = static_cast<UType>(value) * scale_mul;
return result;

Int256 scaled_value = static_cast<Int256>(int_value) * static_cast<Int256>(scale_mul);
Int256 scaled_max_value = DecimalMaxValue::get(prec);

if (scaled_value > scaled_max_value || scaled_value < -scaled_max_value)
{
context.getDAGContext()->handleOverflowError("cast to decimal", Errors::Types::Truncated);
if (int_value > 0)
return static_cast<UType>(scaled_max_value);
else
return static_cast<UType>(-scaled_max_value);
>>>>>>> 6ea6c80198 (Fix cast to decimal overflow bug (#3922))
}

return static_cast<UType>(scaled_value);
}

template <typename U>
Expand Down
Loading

0 comments on commit f55cd5e

Please sign in to comment.