decimal scalar ops and comparision

This commit is contained in:
wangjiaming0909 2025-01-17 08:31:02 +08:00
parent f18e5879f4
commit 494a16713e
19 changed files with 453 additions and 223 deletions

View File

@ -365,6 +365,13 @@ typedef struct tDataTypeCompress {
extern tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX];
extern tDataTypeCompress tDataCompress[TSDB_DATA_TYPE_MAX];
typedef struct SDataType {
uint8_t type;
uint8_t precision;
uint8_t scale;
int32_t bytes;
} SDataType;
bool isValidDataType(int32_t type);
int32_t operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type);
@ -373,7 +380,9 @@ void *getDataMin(int32_t type, void *value);
void *getDataMax(int32_t type, void *value);
#define STypeMod int32_t
uint8_t decimalTypeFromPrecision(uint8_t precision);
uint8_t decimalTypeFromPrecision(uint8_t precision);
STypeMod decimalCalcTypeMod(uint8_t prec, uint8_t scale);
void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale);
#ifdef __cplusplus
}

View File

@ -22,7 +22,6 @@ extern "C" {
#include "tdef.h"
#include "ttypes.h"
typedef struct SDataType SDataType;
typedef struct SValue SValue;
typedef void DecimalType;
@ -50,7 +49,6 @@ void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low);
#define DECIMAL_WORD_NUM(TYPE) sizeof(TYPE) / sizeof(DecimalWord)
int32_t decimalCalcTypeMod(const SDataType* pType);
void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale);
int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, Decimal64* result);

View File

@ -25,6 +25,7 @@ extern "C" {
#include "tmsg.h"
#include "tsimplehash.h"
#include "tvariant.h"
#include "ttypes.h"
#define TABLE_TOTAL_COL_NUM(pMeta) ((pMeta)->tableInfo.numOfColumns + (pMeta)->tableInfo.numOfTags)
#define TABLE_META_SIZE(pMeta) \
@ -45,13 +46,6 @@ typedef struct SRawExprNode {
bool isPseudoColumn;
} SRawExprNode;
typedef struct SDataType {
uint8_t type;
uint8_t precision;
uint8_t scale;
int32_t bytes;
} SDataType;
typedef struct SExprNode {
ENodeType type;
SDataType resType;

View File

@ -86,6 +86,9 @@ int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight);
int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight);
int32_t compareLenBinaryVal(const void *pLeft, const void *pRight);
int32_t compareDecimal64(const void* pleft, const void* pright);
int32_t compareDecimal128(const void* pleft, const void* pright);
int32_t comparestrRegexMatch(const void *pLeft, const void *pRight);
int32_t comparestrRegexNMatch(const void *pLeft, const void *pRight);

View File

@ -198,6 +198,14 @@ int32_t tsCompressBigint2(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int3
int32_t nBuf);
int32_t tsDecompressBigint2(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf);
int32_t tsCompressDecimal64(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf);
int32_t tsDecompressDecimal64(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf);
int32_t tsCompressDecimal128(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf);
int32_t tsDecompressDecimal128(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf);
/*************************************************************************
* STREAM COMPRESSION

View File

@ -2508,7 +2508,7 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4) {
if (convertUcs4) {
code = doConvertUCS4(pResultInfo, colLength);
}
if (TSDB_CODE_SUCCESS == code) {
if (TSDB_CODE_SUCCESS == code && convertUcs4) {
code = convertDecimalType(pResultInfo);
}
return code;

View File

@ -64,7 +64,7 @@ uint8_t getDefaultEncode(uint8_t type) {
return TSDB_COLVAL_ENCODE_DISABLED;
case TSDB_DATA_TYPE_DECIMAL64:
case TSDB_DATA_TYPE_DECIMAL:
return TSDB_COLVAL_ENCODE_SIMPLE8B;
return TSDB_COLVAL_ENCODE_DISABLED;
case TSDB_DATA_TYPE_BLOB:
return TSDB_COLVAL_ENCODE_SIMPLE8B;
case TSDB_DATA_TYPE_MEDIUMBLOB:
@ -416,7 +416,7 @@ int8_t validColEncode(uint8_t type, uint8_t l1) {
} else if (type == TSDB_DATA_TYPE_GEOMETRY) {
return 1;
} else if (type == TSDB_DATA_TYPE_DECIMAL64 || type == TSDB_DATA_TYPE_DECIMAL) {
return 1;
return l1 == TSDB_COLVAL_ENCODE_DISABLED ? 1 : 0;
}
return 0;
}

View File

@ -3196,7 +3196,15 @@ int32_t blockEncode(const SSDataBlock* pBlock, char* data, size_t dataBuflen, in
*((int8_t*)data) = pColInfoData->info.type;
data += sizeof(int8_t);
*((int32_t*)data) = pColInfoData->info.bytes;
int32_t bytes = pColInfoData->info.bytes;
*((int32_t*)data) = bytes;
if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
bytes <<= 16;
bytes |= pColInfoData->info.precision;
bytes <<= 8;
bytes |= pColInfoData->info.scale;
*(int32_t*)data = bytes;
}
data += sizeof(int32_t);
}
@ -3334,6 +3342,11 @@ int32_t blockDecode(SSDataBlock* pBlock, const char* pData, const char** pEndPos
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
pBlock->info.hasVarCol = true;
}
if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
pColInfoData->info.scale = pColInfoData->info.bytes & 0xFF;
pColInfoData->info.precision = pColInfoData->info.precision = (pColInfoData->info.bytes & 0xFF00) >> 8;
pColInfoData->info.bytes >>= 24;
}
}
int32_t code = blockDataEnsureCapacity(pBlock, numOfRows);

View File

@ -94,10 +94,11 @@ tDataTypeCompress tDataCompress[TSDB_DATA_TYPE_MAX] = {
{TSDB_DATA_TYPE_JSON, 4, TSDB_MAX_JSON_TAG_LEN, "JSON", 0, 0, tsCompressString2, tsDecompressString2},
{TSDB_DATA_TYPE_VARBINARY, 9, 1, "VARBINARY", 0, 0, tsCompressString2,
tsDecompressString2}, // placeholder, not implemented
{TSDB_DATA_TYPE_DECIMAL, 7, 1, "DECIMAL", 0, 0, NULL, NULL}, // placeholder, not implemented
{TSDB_DATA_TYPE_DECIMAL, 7, DECIMAL128_BYTES, "DECIMAL", 0, 0, tsCompressDecimal128, tsDecompressDecimal128}, // placeholder, not implemented
{TSDB_DATA_TYPE_BLOB, 4, 1, "BLOB", 0, 0, NULL, NULL}, // placeholder, not implemented
{TSDB_DATA_TYPE_MEDIUMBLOB, 10, 1, "MEDIUMBLOB", 0, 0, NULL, NULL}, // placeholder, not implemented
{TSDB_DATA_TYPE_GEOMETRY, 8, 1, "GEOMETRY", 0, 0, tsCompressString2, tsDecompressString2},
{TSDB_DATA_TYPE_DECIMAL64, 9, DECIMAL64_BYTES, "DECIMAL64", 0, 0, tsCompressDecimal64, tsDecompressDecimal64}, // placeholder, not implemented
// TODO wjm decimal compress
};
@ -236,3 +237,13 @@ int32_t operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type) {
uint8_t decimalTypeFromPrecision(uint8_t precision) {
return precision > TSDB_DECIMAL64_MAX_PRECISION ? TSDB_DATA_TYPE_DECIMAL : TSDB_DATA_TYPE_DECIMAL64;
}
STypeMod decimalCalcTypeMod(uint8_t prec, uint8_t scale) {
return ((STypeMod)prec << 8) + scale;
}
void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale) {
*precision = (uint8_t)((typeMod >> 8) & 0xFF);
*scale = (uint8_t)(typeMod & 0xFF);
}

View File

@ -9,7 +9,7 @@ target_include_directories(
)
target_link_libraries(
decimal
PRIVATE os util common qcom nodes
PRIVATE os common
)
if(${BUILD_TEST})

View File

@ -15,8 +15,8 @@
*/
#include "decimal.h"
#include "querynodes.h"
#include "wideInteger.h"
#include "tdataformat.h"
typedef enum DecimalInternalType {
DECIMAL_64 = 0,
@ -50,6 +50,10 @@ static uint8_t maxPrecision(DecimalInternalType type) {
}
}
static const uint8_t typeConvertDecimalPrec[] = {
0, 1, 3, 5, 10, 19, TSDB_DECIMAL128_MAX_PRECISION, TSDB_DECIMAL_MAX_PRECISION, 0, 19, 10, 3, 5, 10, 20, 0,
0, 0, 0, 0, 0, 0};
int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOperatorType opType,
SDataType* pOutType) {
if (IS_FLOAT_TYPE(pLeftT->type) || IS_FLOAT_TYPE(pRightT->type) || IS_VAR_DATA_TYPE(pLeftT->type) ||
@ -69,12 +73,12 @@ int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOp
uint8_t p1 = pLeftT->precision, s1 = pLeftT->scale, p2 = pRightT->precision, s2 = pRightT->scale;
if (!IS_DECIMAL_TYPE(pLeftT->type)) {
p1 = TSDB_DECIMAL_MAX_PRECISION;
s1 = s2; // TODO wjm take which scale? Maybe use default DecimalMax
p1 = typeConvertDecimalPrec[pLeftT->type];
s1 = 0;
}
if (!IS_DECIMAL_TYPE(pRightT->type)) {
p1 = TSDB_DECIMAL_MAX_PRECISION;
s2 = s1;
p2 = typeConvertDecimalPrec[pRightT->type];
s2 = 0;
}
switch (opType) {
@ -104,26 +108,13 @@ int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOp
pOutType->precision = TSDB_DECIMAL_MAX_PRECISION;
pOutType->scale = TMAX(minScale, (int8_t)(pOutType->scale) - delta);
}
pOutType->type =
pOutType->precision > TSDB_DECIMAL64_MAX_PRECISION ? TSDB_DATA_TYPE_DECIMAL : TSDB_DATA_TYPE_DECIMAL64;
pOutType->type = TSDB_DATA_TYPE_DECIMAL;
pOutType->bytes = tDataTypes[pOutType->type].bytes;
return 0;
}
static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* result);
int32_t decimalCalcTypeMod(const SDataType* pType) {
if (IS_DECIMAL_TYPE(pType->type)) {
return (pType->precision << 8) + pType->scale;
}
return 0;
}
void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale) {
*precision = (uint8_t)((typeMod >> 8) & 0xFF);
*scale = (uint8_t)(typeMod & 0xFF);
}
static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* result) {
int32_t code = 0, pos = 0;
result->precision = 0;
@ -675,6 +666,8 @@ static int32_t decimal128ToStr(const DecimalType* pInt, uint8_t scale, char* pBu
int32_t wholeLen = len - scale;
if (wholeLen > 0) {
TAOS_STRNCAT(pBuf, buf, wholeLen);
} else {
TAOS_STRNCAT(pBuf, "0", 2);
}
if (scale > 0) {
TAOS_STRNCAT(pBuf, ".", 2);
@ -698,20 +691,6 @@ int32_t decimalToStr(const DecimalType* pDec, int8_t dataType, int8_t precision,
return 0;
}
static bool needScaleToOutScale(EOperatorType op) {
switch (op) {
case OP_TYPE_ADD:
case OP_TYPE_SUB:
return true; // convert precision and scale
case OP_TYPE_MULTI:
case OP_TYPE_DIV:
return false;
break;
default:
return false;
}
}
static void decimalAddLargePositive(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT,
const SDataType* pOT) {
Decimal wholeX = *pX, wholeY = *pY, fracX = {0}, fracY = {0};

View File

@ -1,9 +1,11 @@
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include "decimal.h"
#include "libs/nodes/querynodes.h"
#include "tcommon.h"
#include "tdatablock.h"
#include "wideInteger.h"
using namespace std;
@ -133,6 +135,30 @@ struct NumericType<128> {
static constexpr int8_t maxPrec = TSDB_DECIMAL_MAX_PRECISION;
};
template <typename T>
struct TrivialTypeInfo {
using TrivialType = T;
};
#define DEFINE_TRIVIAL_TYPE_HELPER(type, tsdb_type) \
template <> \
struct TrivialTypeInfo<type> { \
static constexpr type dataType = tsdb_type; \
static constexpr int32_t bytes = sizeof(type); \
}
DEFINE_TRIVIAL_TYPE_HELPER(int8_t, TSDB_DATA_TYPE_TINYINT);
DEFINE_TRIVIAL_TYPE_HELPER(uint8_t, TSDB_DATA_TYPE_UTINYINT);
DEFINE_TRIVIAL_TYPE_HELPER(int16_t, TSDB_DATA_TYPE_SMALLINT);
DEFINE_TRIVIAL_TYPE_HELPER(uint16_t, TSDB_DATA_TYPE_USMALLINT);
DEFINE_TRIVIAL_TYPE_HELPER(int32_t, TSDB_DATA_TYPE_INT);
DEFINE_TRIVIAL_TYPE_HELPER(uint32_t, TSDB_DATA_TYPE_UINT);
DEFINE_TRIVIAL_TYPE_HELPER(int64_t, TSDB_DATA_TYPE_BIGINT);
DEFINE_TRIVIAL_TYPE_HELPER(uint64_t, TSDB_DATA_TYPE_UBIGINT);
DEFINE_TRIVIAL_TYPE_HELPER(float, TSDB_DATA_TYPE_FLOAT);
DEFINE_TRIVIAL_TYPE_HELPER(double, TSDB_DATA_TYPE_DOUBLE);
DEFINE_TRIVIAL_TYPE_HELPER(bool, TSDB_DATA_TYPE_BOOL);
template <int ByteNum>
class Numeric {
using Type = typename NumericType<ByteNum>::Type;
@ -178,25 +204,43 @@ class Numeric {
return out;
}
template <int ByteNum2, int ByteNumO = 128>
Numeric<ByteNumO> operator+(const Numeric<ByteNum2>& r) {
return binaryOp<ByteNum2, ByteNumO>(r, OP_TYPE_ADD);
template <int ByteNumO, typename T>
Numeric<ByteNumO> binaryOp(const T& r, EOperatorType op) {
using TypeInfo = TrivialTypeInfo<T>;
SDataType lt{.type = NumericType<ByteNum>::dataType, .precision = prec_, .scale = scale_, .bytes = ByteNum};
SDataType rt{.type = TypeInfo::dataType, .precision = 0, .scale = 0, .bytes = TypeInfo::bytes};
SDataType ot = getRetType(op, lt, rt);
Numeric<ByteNumO> out{ot.precision, ot.scale, "0"};
int32_t code = decimalOp(op, &lt, &rt, &ot, &dec_, &r, &out);
if (code != 0) throw std::overflow_error(tstrerror(code));
return out;
}
#define DEFINE_OPERATOR(op, op_type) \
template <int ByteNum2, int ByteNumO = 128> \
Numeric<ByteNumO> operator op(const Numeric<ByteNum2>& r) { \
cout << *this << " " #op " " << r << " = "; \
auto res = binaryOp<ByteNum2, ByteNumO>(r, op_type); \
cout << res << endl; \
return res; \
}
template <int ByteNum2, int ByteNumO = 128>
Numeric<ByteNumO> operator-(const Numeric<ByteNum2>& r) {
return binaryOp<ByteNum2, ByteNumO>(r, OP_TYPE_SUB);
}
DEFINE_OPERATOR(+, OP_TYPE_ADD);
DEFINE_OPERATOR(-, OP_TYPE_SUB);
DEFINE_OPERATOR(*, OP_TYPE_MULTI);
DEFINE_OPERATOR(/, OP_TYPE_DIV);
template <int ByteNum2, int ByteNumO = 128>
Numeric<ByteNumO> operator*(const Numeric<ByteNum2>& r) {
return binaryOp<ByteNum2, ByteNumO>(r, OP_TYPE_MULTI);
}
template <int ByteNum2, int ByteNumO = 128>
Numeric<ByteNumO> operator/(const Numeric<ByteNum2>& r) {
return binaryOp<ByteNum2, ByteNumO>(r, OP_TYPE_DIV);
#define DEFINE_OPERATOR_T(op, op_type) \
template <typename T, int ByteNumO = 128> \
Numeric<ByteNumO> operator op(const T & r) { \
cout << *this << " " #op " " << r << " = "; \
auto res = binaryOp<ByteNumO, T>(r, op_type); \
cout << res << endl; \
return res; \
}
DEFINE_OPERATOR_T(+, OP_TYPE_ADD);
DEFINE_OPERATOR_T(-, OP_TYPE_SUB);
DEFINE_OPERATOR_T(*, OP_TYPE_MULTI);
DEFINE_OPERATOR_T(/, OP_TYPE_DIV);
template <int ByteNum2>
Numeric& operator+=(const Numeric<ByteNum2>& r) {
@ -240,12 +284,10 @@ TEST(decimal, numeric) {
Numeric<64> dec{10, 4, "123.456"};
Numeric<64> dec2{18, 10, "123456.123123"};
auto o = dec + dec2;
cout << dec << " + " << dec2 << " = " << o << endl;
ASSERT_EQ(o.toString(), "123579.5791230000");
Numeric<128> dec128{37, 10, "123456789012300.09876543"};
o = dec + dec128;
cout << dec << " + " << dec128 << " = " << o << endl;
ASSERT_EQ(o.toStringTrimTailingZeros(), "123456789012423.55476543");
ASSERT_EQ(o.toString(), "123456789012423.5547654300");
@ -256,25 +298,52 @@ TEST(decimal, numeric) {
ASSERT_EQ(os2.toStringTrimTailingZeros(), dec.toStringTrimTailingZeros());
os = dec * dec2;
cout << dec << " * " << dec2 << " = " << os << endl;
ASSERT_EQ(os.toStringTrimTailingZeros(), "15241399.136273088");
ASSERT_EQ(os.toString(), "15241399.13627308800000");
os = dec * dec128;
cout << dec << " * " << dec128 << " = " << os << endl;
ASSERT_EQ(os.toStringTrimTailingZeros(), "15241481344302520.993184");
ASSERT_EQ(os.toString(), "15241481344302520.993184");
os2 = os / dec128;
cout << os << " / " << dec128 << " = " << os2 << endl;
ASSERT_EQ(os2.toStringTrimTailingZeros(), "123.456");
ASSERT_EQ(os2.toString(), "123.456000");
os = dec2 / dec;
cout << dec2 << " / " << dec << " = " << os;
ASSERT_EQ(os.toString(), "1000.000997302682737169518");
int32_t a = 123;
os = dec + a;
ASSERT_EQ(os.toString(), "246.4560");
os = dec * a;
ASSERT_EQ(os.toString(), "15185.0880");
os = dec / 2;
ASSERT_EQ(os.toStringTrimTailingZeros(), "61.728");
os = dec2 / 2;
ASSERT_EQ(os.toStringTrimTailingZeros(), "61728.0615615");
os = dec128 / 2;
ASSERT_EQ(os.toStringTrimTailingZeros(), "61728394506150.049382715");
auto dec3 = Numeric<64>(10, 2, "171154.38");
os = dec3 / 2;
ASSERT_EQ(os.toStringTrimTailingZeros(), "85577.19");
auto dec4 = Numeric<64>(10, 5, "1.23456");
os = dec4 / 2;
ASSERT_EQ(os.toStringTrimTailingZeros(), "0.61728");
os = dec4 / 123123123;
ASSERT_EQ(os.toStringTrimTailingZeros(), "0.0000000100270361075880117");
}
// TEST where decimal column in (...)
// TEST same decimal type with different scale doing comparing or operations
// TEST case when select common type
TEST(decimal, a) {
__int128 a = generate_big_int128(37);
extractWideInteger<9>(a);
@ -326,20 +395,28 @@ TEST(decimal128, divide) {
}
TEST(decimal, cpi_taos_fetch_rows) {
//GTEST_SKIP();
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
const char* db = "test";
const char* sql = "select c1, c2 from nt";
const char* db = "test_api";
const char* create_tb = "create table if not exists test_api.nt(ts timestamp, c1 decimal(10, 2), c2 decimal(38, 10))";
const char* sql = "select c1, c2 from test_api.nt";
const char* sql_insert = "insert into test_api.nt values(now, 123456.123, 98472981092.1209111)";
TAOS* pTaos = taos_connect(host, user, passwd, db, 0);
TAOS* pTaos = taos_connect(host, user, passwd, NULL, 0);
if (!pTaos) {
cout << "taos connect failed: " << host << " " << taos_errstr(NULL);
FAIL();
}
auto* res = taos_query(pTaos, sql);
auto* res = taos_query(pTaos, (std::string("create database if not exists ") + db).c_str());
taos_free_result(res);
res = taos_query(pTaos, create_tb);
taos_free_result(res);
res = taos_query(pTaos, sql_insert);
taos_free_result(res);
res = taos_query(pTaos, sql);
int32_t code = taos_errno(res);
if (code != 0) {
cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res);
@ -359,6 +436,7 @@ TEST(decimal, cpi_taos_fetch_rows) {
code = taos_errno(res);
if (code != 0) {
cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res);
taos_free_result(res);
FAIL();
}
@ -369,8 +447,35 @@ TEST(decimal, cpi_taos_fetch_rows) {
cout << "taos_query with sql: " << sql << " failed: " << taos_errstr(res);
FAIL();
}
if (numOfRows > 0) {
int32_t version = *(int32_t*)pData;
ASSERT_EQ(version, BLOCK_VERSION_1);
int32_t rows = *(int32_t*)((char*)pData + 4 + 4);
int32_t colNum = *(int32_t*)((char*)pData + 4 + 4 + 4);
int32_t bytes_skip = 4 + 4 + 4 + 4 + 4 + 8;
char* p = (char*)pData + bytes_skip;
// col1
int8_t t = *(int8_t*)p;
int32_t type_mod = *(int32_t*)(p + 1);
SSDataBlock* pBlock;
ASSERT_EQ(t, TSDB_DATA_TYPE_DECIMAL64);
auto check_type_mod = [](int32_t type_mod, uint8_t prec, uint8_t scale, int32_t bytes) {
ASSERT_EQ(type_mod & 0xFF, scale);
ASSERT_EQ((type_mod & 0xFF00) >> 8, prec);
ASSERT_EQ(type_mod >> 24, bytes);
};
check_type_mod(type_mod, 10, 2, 8);
// col2
p += 5;
t = *(int8_t*)p;
type_mod = *(int32_t*)(p + 1);
check_type_mod(type_mod, 38, 10, 16);
p = p + 5 + BitmapLen(numOfRows) + colNum * 4;
int64_t row1Val = *(int64_t*)p;
ASSERT_EQ(row1Val, 12345612);
}
taos_free_result(res);
taos_close(pTaos);
@ -466,8 +571,8 @@ TEST(decimal, decimalOpRetType) {
EOperatorType op = OP_TYPE_ADD;
auto ta = getDecimalType(10, 2);
auto tb = getDecimalType(10, 2);
SDataType tc{}, tExpect = {.type = TSDB_DATA_TYPE_DECIMAL64, .precision = 11, .scale = 2, .bytes = sizeof(Decimal64)};
int32_t code = decimalGetRetType(&ta, &tb, op, &tc);
SDataType tc{}, tExpect = {.type = TSDB_DATA_TYPE_DECIMAL, .precision = 11, .scale = 2, .bytes = sizeof(Decimal)};
int32_t code = decimalGetRetType(&ta, &tb, op, &tc);
ASSERT_EQ(code, 0);
ASSERT_EQ(tExpect, tc);
@ -477,7 +582,7 @@ TEST(decimal, decimalOpRetType) {
code = decimalGetRetType(&ta, &tb, op, &tc);
ASSERT_EQ(code, 0);
tExpect.type = TSDB_DATA_TYPE_DECIMAL;
tExpect.precision = TSDB_DECIMAL_MAX_PRECISION;
tExpect.precision = 22;
tExpect.scale = 2;
tExpect.bytes = sizeof(Decimal);
ASSERT_EQ(tExpect, tc);
@ -492,6 +597,15 @@ TEST(decimal, decimalOpRetType) {
tExpect.scale = 0;
tExpect.bytes = 8;
ASSERT_EQ(tExpect, tc);
op = OP_TYPE_DIV;
ta = getDecimalType(10, 2);
tb = getDecimalType(10, 2);
tExpect.type = TSDB_DATA_TYPE_DECIMAL;
tExpect.precision = 23;
tExpect.scale = 13;
tExpect.bytes = sizeof(Decimal);
code = decimalGetRetType(&ta, &tb, op, &tc);
}
TEST(decimal, op) {
@ -507,15 +621,15 @@ TEST(decimal, op) {
code = decimal64FromStr(strb, strlen(strb), tb.precision, tb.scale, &b);
ASSERT_EQ(code, 0);
SDataType tc{}, tExpect{.type = TSDB_DATA_TYPE_DECIMAL64, .precision = 11, .scale = 2, .bytes = sizeof(Decimal64)};
SDataType tc{}, tExpect{.type = TSDB_DATA_TYPE_DECIMAL, .precision = 11, .scale = 2, .bytes = sizeof(Decimal)};
code = decimalGetRetType(&ta, &tb, op, &tc);
ASSERT_EQ(code, 0);
ASSERT_EQ(tc, tExpect);
Decimal64 res{};
Decimal res{};
code = decimalOp(op, &ta, &tb, &tc, &a, &b, &res);
ASSERT_EQ(code, 0);
checkDecimal(&res, TSDB_DATA_TYPE_DECIMAL64, tc.precision, tc.scale, "580.11");
checkDecimal(&res, TSDB_DATA_TYPE_DECIMAL, tc.precision, tc.scale, "580.11");
a = {1234567890};
b = {9876543210};

View File

@ -1509,7 +1509,7 @@ int64_t int64SafeSub(int64_t a, int64_t b) {
STypeMod calcTypeMod(const SDataType* pType) {
if (IS_DECIMAL_TYPE(pType->type)) {
return decimalCalcTypeMod(pType);
return decimalCalcTypeMod(pType->precision, pType->scale);
}
return 0;
}

View File

@ -136,7 +136,8 @@ __compar_fn_t gDataCompare[] = {
setChkInBytes2, setChkInBytes4, setChkInBytes8, comparestrRegexMatch,
comparestrRegexNMatch, setChkNotInBytes1, setChkNotInBytes2, setChkNotInBytes4,
setChkNotInBytes8, compareChkNotInString, comparestrPatternNMatch, comparewcsPatternNMatch,
comparewcsRegexMatch, comparewcsRegexNMatch, compareLenBinaryVal
comparewcsRegexMatch, comparewcsRegexNMatch, compareLenBinaryVal, compareDecimal64,
compareDecimal128,
};
__compar_fn_t gInt8SignCompare[] = {compareInt8Val, compareInt8Int16, compareInt8Int32,
@ -350,6 +351,11 @@ int32_t filterGetCompFuncIdx(int32_t type, int32_t optr, int8_t *comparFn, bool
case TSDB_DATA_TYPE_UBIGINT:
*comparFn = 14;
break;
case TSDB_DATA_TYPE_DECIMAL64:
*comparFn = 31;
break;
case TSDB_DATA_TYPE_DECIMAL:
*comparFn = 32;
default:
*comparFn = 0;
@ -362,7 +368,7 @@ int32_t filterGetCompFuncIdx(int32_t type, int32_t optr, int8_t *comparFn, bool
int32_t filterGetCompFunc(__compar_fn_t *func, int32_t type, int32_t optr) {
int8_t compFuncIdx = 0;
int32_t code = filterGetCompFuncIdx(type, optr, &compFuncIdx, true);
*func = gDataCompare[compFuncIdx];
if (TSDB_CODE_SUCCESS == code) *func = gDataCompare[compFuncIdx];
return code;
}

View File

@ -43,10 +43,12 @@
{ .type = (col).type, .precision = (col).precision, .bytes = (col).bytes, .scale = (col).scale }
bool noConvertBeforeCompare(int32_t leftType, int32_t rightType, int32_t optr) {
return IS_NUMERIC_TYPE(leftType) && IS_NUMERIC_TYPE(rightType) &&
(optr >= OP_TYPE_GREATER_THAN && optr <= OP_TYPE_NOT_EQUAL);
return !IS_DECIMAL_TYPE(leftType) && !IS_DECIMAL_TYPE(rightType) && IS_NUMERIC_TYPE(leftType) &&
IS_NUMERIC_TYPE(rightType) && (optr >= OP_TYPE_GREATER_THAN && optr <= OP_TYPE_NOT_EQUAL);
}
static int32_t vectorMathOpForDecimal(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t step, int32_t i, EOperatorType op);
int32_t convertNumberToNumber(const void *inData, void *outData, int8_t inType, int8_t outType) {
switch (outType) {
case TSDB_DATA_TYPE_BOOL: {
@ -1027,53 +1029,55 @@ int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut,
}
int8_t gConvertTypes[TSDB_DATA_TYPE_MAX][TSDB_DATA_TYPE_MAX] = {
/* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB MEDB GEOM*/
/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*BOOL*/ 0, 0, 2, 3, 4, 5, 6, 7, 5, 9, 5, 11, 12, 13, 14, 0, -1, 0, 0, 0, -1,
/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 5, 9, 5, 3, 4, 5, 7, 0, -1, 0, 0, 0, -1,
/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 5, 9, 5, 3, 4, 5, 7, 0, -1, 0, 0, 0, -1,
/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 5, 9, 5, 4, 4, 5, 7, 0, -1, 0, 0, 0, -1,
/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 5, 9, 5, 5, 5, 5, 7, 0, -1, 0, 0, 0, -1,
/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 6, 6, 6, 6, 6, 6, 6, 0, -1, 0, 0, 0, -1,
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 0, -1, 0, 0, 0, -1,
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 7, 7, 7, 0, 16, 0, 0, 0, 20,
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 7, 0, -1, 0, 0, 0, -1,
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 16, 0, 0, 0, -1,
/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, -1, 0, 0, 0, -1,
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 0, -1, 0, 0, 0, -1,
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, -1, 0, 0, 0, -1,
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1,
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1,
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1,
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1,
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1,
/*MEDB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1,
/*GEOM*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0
/*NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB MEDB GEOM DEC64*/
/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*BOOL*/ 0, 0, 2, 3, 4, 5, 6, 7, 5, 9, 5, 11, 12, 13, 14, 0, -1, 17, 0, 0, -1, 17,
/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 5, 9, 5, 3, 4, 5, 7, 0, -1, 17, 0, 0, -1, 17,
/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 5, 9, 5, 3, 4, 5, 7, 0, -1, 17, 0, 0, -1, 17,
/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 5, 9, 5, 4, 4, 5, 7, 0, -1, 17, 0, 0, -1, 17,
/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 5, 9, 5, 5, 5, 5, 7, 0, -1, 17, 0, 0, -1, 17,
/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 6, 6, 6, 6, 6, 6, 6, 0, -1, 7, 0, 0, -1, 7,
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 0, -1, 7, 0, 0, -1, 7,
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 7, 7, 7, 0, 16, 7, 0, 0, 20, 7,
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 7, 0, -1, 17, 0, 0, -1, 17,
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 16, 7, 0, 0, -1, 7,
/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, -1, 17, 0, 0, -1, 17,
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 0, -1, 17, 0, 0, -1, 17,
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, -1, 17, 0, 0, -1, 17,
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 17, 0, 0, -1, 17,
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, -1,
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 7,
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, -1, 17,
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, -1,
/*MEDB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, -1,
/*GEOM*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1,
/*DEC64*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
};
int8_t gDisplyTypes[TSDB_DATA_TYPE_MAX][TSDB_DATA_TYPE_MAX] = {
/* NULL BOOL TINY SMAL INT BIGI FLOA DOUB VARC TIM NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB MEDB GEOM*/
/*NULL*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, -1, -1, 20,
/*BOOL*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1,
/*TINY*/ 0, 0, 2, 3, 4, 5, 8, 8, 8, 5, 10, 3, 4, 5, 8, -1, -1, -1, -1, -1, -1,
/*SMAL*/ 0, 0, 0, 3, 4, 5, 8, 8, 8, 5, 10, 3, 4, 5, 8, -1, -1, -1, -1, -1, -1,
/*INT */ 0, 0, 0, 0, 4, 5, 8, 8, 8, 5, 10, 4, 4, 5, 8, -1, -1, -1, -1, -1, -1,
/*BIGI*/ 0, 0, 0, 0, 0, 5, 8, 8, 8, 5, 10, 5, 5, 5, 8, -1, -1, -1, -1, -1, -1,
/*FLOA*/ 0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 10, 8, 8, 8, 8, -1, -1, -1, -1, -1, -1,
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 10, 8, 8, 8, 8, -1, -1, -1, -1, -1, -1,
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 10, 8, 8, 8, 8, -1, 16, -1, -1, -1, -1,
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 5, 5, 5, 8, -1, -1, -1, -1, -1, -1,
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, -1, -1, -1, -1, -1, -1,
/*UTINY*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1,
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, -1, -1, -1, -1, -1, -1,
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, -1, -1, -1, -1, -1, -1,
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, -1, -1, -1,
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, -1, -1, -1, -1, -1,
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, -1, -1, -1, -1,
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1,
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
/*MEDB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1,
/*GEOM*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20
/*NULL BOOL TINY SMAL INT BIGI FLOA DOUB VARC TIM NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB MEDB GEOM DEC64*/
/*NULL*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, -1, 20, 21,
/*BOOL*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 10, 11, 12, 13, 14, -1, -1, 17, -1, -1, -1, 17,
/*TINY*/ 0, 0, 2, 3, 4, 5, 8, 8, 8, 5, 10, 3, 4, 5, 8, -1, -1, 17, -1, -1, -1, 17,
/*SMAL*/ 0, 0, 0, 3, 4, 5, 8, 8, 8, 5, 10, 3, 4, 5, 8, -1, -1, 17, -1, -1, -1, 17,
/*INT */ 0, 0, 0, 0, 4, 5, 8, 8, 8, 5, 10, 4, 4, 5, 8, -1, -1, 17, -1, -1, -1, 17,
/*BIGI*/ 0, 0, 0, 0, 0, 5, 8, 8, 8, 5, 10, 5, 5, 5, 8, -1, -1, 17, -1, -1, -1, 17,
/*FLOA*/ 0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 10, 8, 8, 8, 8, -1, -1, 7, -1, -1, -1, 7,
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 10, 8, 8, 8, 8, -1, -1, 7, -1, -1, -1, 7,
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 10, 8, 8, 8, 8, -1, 16, 7, -1, -1, -1, 7,
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 5, 5, 5, 8, -1, -1, 17, -1, -1, -1, 17,
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, -1, -1, 7, -1, -1, -1, 7,
/*UTINY*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, -1, -1, 17, -1, -1, -1, 17,
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, -1, -1, 17, -1, -1, -1, 17,
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, -1, -1, 17, -1, -1, -1, 17,
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, -1, -1, 17, -1, -1, -1, 17,
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, -1, -1, -1, -1, -1, -1,
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, -1, -1, -1, -1, -1,
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 17,
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1,
/*MEDB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
/*GEOM*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, -1,
/*DEC64*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0,
};
int32_t vectorGetConvertType(int32_t type1, int32_t type2) {
@ -1117,6 +1121,9 @@ int32_t vectorConvertCols(SScalarParam *pLeft, SScalarParam *pRight, SScalarPara
int32_t leftType = GET_PARAM_TYPE(pLeft);
int32_t rightType = GET_PARAM_TYPE(pRight);
if (leftType == rightType) {
if (IS_DECIMAL_TYPE(leftType)) {
//TODO wjm force do conversion for decimal type
}
return TSDB_CODE_SUCCESS;
}
@ -1309,23 +1316,7 @@ int32_t vectorMathAdd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p
SCL_ERR_JRET(vectorMathAddHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i));
}
} else if (IS_DECIMAL_TYPE(pOutputCol->info.type)) {
Decimal *output = (Decimal *)pOutputCol->pData;
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) {
colDataSetNULL(pOutputCol, i);
continue;
}
SDataType leftType = GET_COL_DATA_TYPE(pLeft->columnData->info),
rightType = GET_COL_DATA_TYPE(pRight->columnData->info),
outType = GET_COL_DATA_TYPE(pOutputCol->info);
SCL_ERR_JRET(decimalOp(OP_TYPE_ADD, &leftType, &rightType, &outType, colDataGetData(pLeftCol, i),
colDataGetData(pRightCol, i), output));
}
} else if (pLeft->numOfRows == 1) {
// TODO wjm
} else if (pRight->numOfRows == 1) {
}
SCL_ERR_JRET(vectorMathOpForDecimal(pLeft, pRight, pOut, step, i, OP_TYPE_ADD));
}
_return:
@ -1402,10 +1393,8 @@ int32_t vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p
int32_t leftConvert = 0, rightConvert = 0;
SColumnInfoData *pLeftCol = NULL;
SColumnInfoData *pRightCol = NULL;
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
if (checkOperatorRestypeIsTimestamp(OP_TYPE_SUB, GET_PARAM_TYPE(pLeft), GET_PARAM_TYPE(pRight))) { // timestamp minus duration
if (pOutputCol->info.type == TSDB_DATA_TYPE_TIMESTAMP) { // timestamp minus duration
int64_t *output = (int64_t *)pOutputCol->pData;
_getBigintValue_fn_t getVectorBigintValueFnLeft;
_getBigintValue_fn_t getVectorBigintValueFnRight;
@ -1431,7 +1420,9 @@ int32_t vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p
*output = leftRes - rightRes;
}
}
} else {
} else if (pOutputCol->info.type == TSDB_DATA_TYPE_DOUBLE) {
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
double *output = (double *)pOutputCol->pData;
_getDoubleValue_fn_t getVectorDoubleValueFnLeft;
_getDoubleValue_fn_t getVectorDoubleValueFnRight;
@ -1455,6 +1446,8 @@ int32_t vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p
} else if (pRight->numOfRows == 1) {
SCL_ERR_JRET(vectorMathSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i));
}
} else if (pOutputCol->info.type == TSDB_DATA_TYPE_DECIMAL) {
SCL_ERR_JRET(vectorMathOpForDecimal(pLeft, pRight, pOut, step, i, OP_TYPE_SUB));
}
_return:
@ -1502,31 +1495,35 @@ int32_t vectorMathMultiply(SScalarParam *pLeft, SScalarParam *pRight, SScalarPar
int32_t leftConvert = 0, rightConvert = 0;
SColumnInfoData *pLeftCol = NULL;
SColumnInfoData *pRightCol = NULL;
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
if (pOutputCol->info.type == TSDB_DATA_TYPE_DECIMAL) {
SCL_ERR_JRET(vectorMathOpForDecimal(pLeft, pRight, pOut, step, i, OP_TYPE_MULTI));
} else {
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
_getDoubleValue_fn_t getVectorDoubleValueFnLeft;
_getDoubleValue_fn_t getVectorDoubleValueFnRight;
SCL_ERR_JRET(getVectorDoubleValueFn(pLeftCol->info.type, &getVectorDoubleValueFnLeft));
SCL_ERR_JRET(getVectorDoubleValueFn(pRightCol->info.type, &getVectorDoubleValueFnRight));
_getDoubleValue_fn_t getVectorDoubleValueFnLeft;
_getDoubleValue_fn_t getVectorDoubleValueFnRight;
SCL_ERR_JRET(getVectorDoubleValueFn(pLeftCol->info.type, &getVectorDoubleValueFnLeft));
SCL_ERR_JRET(getVectorDoubleValueFn(pRightCol->info.type, &getVectorDoubleValueFnRight));
double *output = (double *)pOutputCol->pData;
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) {
colDataSetNULL(pOutputCol, i);
continue; // TODO set null or ignore
double *output = (double *)pOutputCol->pData;
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) {
colDataSetNULL(pOutputCol, i);
continue; // TODO set null or ignore
}
double leftRes = 0;
double rightRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
SCL_ERR_JRET(getVectorDoubleValueFnRight(RIGHT_COL, i, &rightRes));
*output = leftRes * rightRes;
}
double leftRes = 0;
double rightRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
SCL_ERR_JRET(getVectorDoubleValueFnRight(RIGHT_COL, i, &rightRes));
*output = leftRes * rightRes;
} else if (pLeft->numOfRows == 1) {
SCL_ERR_JRET(vectorMathMultiplyHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i));
} else if (pRight->numOfRows == 1) {
SCL_ERR_JRET(vectorMathMultiplyHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i));
}
} else if (pLeft->numOfRows == 1) {
SCL_ERR_JRET(vectorMathMultiplyHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i));
} else if (pRight->numOfRows == 1) {
SCL_ERR_JRET(vectorMathMultiplyHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i));
}
_return:
@ -1546,37 +1543,21 @@ int32_t vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam
int32_t leftConvert = 0, rightConvert = 0;
SColumnInfoData *pLeftCol = NULL;
SColumnInfoData *pRightCol = NULL;
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
if (pOutputCol->info.type == TSDB_DATA_TYPE_DECIMAL) {
SCL_ERR_JRET(vectorMathOpForDecimal(pLeft, pRight, pOut, step, i, OP_TYPE_DIV));
} else {
SCL_ERR_JRET(vectorConvertVarToDouble(pLeft, &leftConvert, &pLeftCol));
SCL_ERR_JRET(vectorConvertVarToDouble(pRight, &rightConvert, &pRightCol));
_getDoubleValue_fn_t getVectorDoubleValueFnLeft;
_getDoubleValue_fn_t getVectorDoubleValueFnRight;
SCL_ERR_JRET(getVectorDoubleValueFn(pLeftCol->info.type, &getVectorDoubleValueFnLeft));
SCL_ERR_JRET(getVectorDoubleValueFn(pRightCol->info.type, &getVectorDoubleValueFnRight));
_getDoubleValue_fn_t getVectorDoubleValueFnLeft;
_getDoubleValue_fn_t getVectorDoubleValueFnRight;
SCL_ERR_JRET(getVectorDoubleValueFn(pLeftCol->info.type, &getVectorDoubleValueFnLeft));
SCL_ERR_JRET(getVectorDoubleValueFn(pRightCol->info.type, &getVectorDoubleValueFnRight));
double *output = (double *)pOutputCol->pData;
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) { // divide by 0 check
colDataSetNULL(pOutputCol, i);
continue;
}
double rightRes = 0;
SCL_ERR_JRET((getVectorDoubleValueFnRight(RIGHT_COL, i, &rightRes)));
if (rightRes == 0) {
colDataSetNULL(pOutputCol, i);
continue;
}
double leftRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
*output = leftRes / rightRes;
}
} else if (pLeft->numOfRows == 1) {
if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value
colDataSetNNULL(pOutputCol, 0, pRight->numOfRows);
} else {
for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) {
if (IS_HELPER_NULL(pRightCol, i)) { // divide by 0 check
double *output = (double *)pOutputCol->pData;
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) {
if (IS_NULL) { // divide by 0 check
colDataSetNULL(pOutputCol, i);
continue;
}
@ -1587,29 +1568,49 @@ int32_t vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam
continue;
}
double leftRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, 0, &leftRes));
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
*output = leftRes / rightRes;
}
}
} else if (pRight->numOfRows == 1) {
if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value (divde by 0 check)
colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows);
} else {
double rightRes = 0;
SCL_ERR_JRET((getVectorDoubleValueFnRight(RIGHT_COL, 0, &rightRes)));
if (rightRes == 0) {
colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows);
} else if (pLeft->numOfRows == 1) {
if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value
colDataSetNNULL(pOutputCol, 0, pRight->numOfRows);
} else {
for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) {
if (IS_HELPER_NULL(pLeftCol, i)) {
for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) {
if (IS_HELPER_NULL(pRightCol, i)) { // divide by 0 check
colDataSetNULL(pOutputCol, i);
continue;
}
double rightRes = 0;
SCL_ERR_JRET((getVectorDoubleValueFnRight(RIGHT_COL, i, &rightRes)));
if (rightRes == 0) {
colDataSetNULL(pOutputCol, i);
continue;
}
double leftRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, 0, &leftRes));
*output = leftRes / rightRes;
}
}
} else if (pRight->numOfRows == 1) {
if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value (divde by 0 check)
colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows);
} else {
double rightRes = 0;
SCL_ERR_JRET((getVectorDoubleValueFnRight(RIGHT_COL, 0, &rightRes)));
if (rightRes == 0) {
colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows);
} else {
for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) {
if (IS_HELPER_NULL(pLeftCol, i)) {
colDataSetNULL(pOutputCol, i);
continue;
}
double leftRes = 0;
SCL_ERR_JRET(getVectorDoubleValueFnLeft(LEFT_COL, i, &leftRes));
*output = leftRes / rightRes;
}
}
}
}
}
@ -1908,6 +1909,10 @@ int32_t doVectorCompare(SScalarParam *pLeft, SScalarParam *pLeftVar, SScalarPara
} else {
fp = filterGetCompFuncEx(lType, rType, optr);
}
if (!fp) {
qError("doVecotrCompare failed with fp is NULL, op: %d, lType: %d, rType: %d", optr, lType, rType);
return TSDB_CODE_INTERNAL_ERROR;
}
if (pLeftVar != NULL) {
SCL_ERR_RET(filterGetCompFunc(&fpVar, GET_PARAM_TYPE(pLeftVar), optr));
@ -2241,3 +2246,50 @@ bool checkOperatorRestypeIsTimestamp(EOperatorType opType, int32_t lType, int32_
}
return false;
}
static int32_t vectorMathOpOneRowForDecimal(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t step,
int32_t i, EOperatorType op, SScalarParam *pOneRowParam) {
SScalarParam *pNotOneRowParam = pLeft == pOneRowParam ? pRight : pLeft;
Decimal *output = (Decimal *)pOut->columnData->pData;
int32_t code = 0;
SDataType leftType = GET_COL_DATA_TYPE(pLeft->columnData->info),
rightType = GET_COL_DATA_TYPE(pRight->columnData->info),
outType = GET_COL_DATA_TYPE(pOut->columnData->info);
if (IS_HELPER_NULL(pOneRowParam->columnData, 0)) {
colDataSetNNULL(pOut->columnData, 0, pNotOneRowParam->numOfRows);
} else {
for (; i < pNotOneRowParam->numOfRows && i >= 0 && TSDB_CODE_SUCCESS == code; i += step, output += 1) {
if (IS_HELPER_NULL(pNotOneRowParam->columnData, i)) {
colDataSetNULL(pOut->columnData, i);
continue;
}
code = decimalOp(op, &leftType, &rightType, &outType,
colDataGetData(pLeft->columnData, pLeft == pOneRowParam ? 0 : i),
colDataGetData(pRight->columnData, pRight == pOneRowParam ? 0 : i), output);
}
}
return code;
}
static int32_t vectorMathOpForDecimal(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t step, int32_t i, EOperatorType op) {
Decimal *output = (Decimal *)pOut->columnData->pData;
int32_t code = 0;
SDataType leftType = GET_COL_DATA_TYPE(pLeft->columnData->info),
rightType = GET_COL_DATA_TYPE(pRight->columnData->info),
outType = GET_COL_DATA_TYPE(pOut->columnData->info);
if (pLeft->numOfRows == pRight->numOfRows) {
for (; i < pRight->numOfRows && i >= 0 && TSDB_CODE_SUCCESS == code; i += step, output += 1) {
if (IS_NULL) {
colDataSetNULL(pOut->columnData, i);
continue;
}
code = decimalOp(op, &leftType, &rightType, &outType, colDataGetData(pLeft->columnData, i),
colDataGetData(pRight->columnData, i), output);
}
} else if (pLeft->numOfRows == 1) {
code = vectorMathOpOneRowForDecimal(pLeft, pRight, pOut, step, i, op, pLeft);
} else if (pRight->numOfRows == 1) {
code = vectorMathOpOneRowForDecimal(pLeft, pRight, pOut, step, i, op, pRight);
}
return code;
}

View File

@ -40,7 +40,7 @@ if(TD_LINUX)
util
PUBLIC os common
PUBLIC lz4_static fast-lzma2 pcre2-8
PUBLIC api cjson geos_c TSZ
PUBLIC api cjson geos_c TSZ decimal
)
else()
target_link_libraries(

View File

@ -25,6 +25,7 @@
#include "types.h"
#include "osString.h"
#include "ttimer.h"
#include "decimal.h"
int32_t setChkInBytes1(const void *pLeft, const void *pRight) {
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0;
@ -1034,6 +1035,21 @@ int32_t compareUint64Uint32(const void *pLeft, const void *pRight) {
return 0;
}
int32_t compareDecimal64(const void* pleft, const void* pright) {
SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
if (pOps->gt(pleft, pright, WORD_NUM(Decimal64))) return 1;
if (pOps->lt(pleft, pright, WORD_NUM(Decimal64))) return -1;
return 0;
}
int32_t compareDecimal128(const void* pleft, const void* pright) {
SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
if (pOps->gt(pleft, pright, WORD_NUM(Decimal128))) return 1;
if (pOps->lt(pleft,pright, WORD_NUM(Decimal128))) return -1;
return 0;
}
int32_t compareJsonValDesc(const void *pLeft, const void *pRight) { return compareJsonVal(pRight, pLeft); }
/*

View File

@ -1637,7 +1637,7 @@ int32_t tsDecompressBigint(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int
int8_t alvl = tsGetCompressL2Level(l2, lvl); \
return compressL2Dict[l2].comprFn(pIn, nIn, pOut, nOut, type, alvl); \
} else { \
uTrace("dencode:%s, decompress:%s, level:%d, type:%s", "disabled", compressL2Dict[l1].name, lvl, \
uTrace("dencode:%s, decompress:%s, level:%d, type:%s", "disabled", compressL2Dict[l2].name, lvl, \
tDataTypes[type].name); \
return compressL2Dict[l2].decomprFn(pIn, nIn, pOut, nOut, type); \
} \
@ -1831,6 +1831,25 @@ int32_t tsDecompressBigint2(void *pIn, int32_t nIn, int32_t nEle, void *pOut, in
FUNC_COMPRESS_IMPL(pIn, nIn, nEle, pOut, nOut, cmprAlg, pBuf, nBuf, TSDB_DATA_TYPE_BIGINT, 0);
}
int32_t tsCompressDecimal64(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf) {
FUNC_COMPRESS_IMPL(pIn, nIn, nEle, pOut, nOut, cmprAlg, pBuf, nBuf, TSDB_DATA_TYPE_DECIMAL64, 1);
}
int32_t tsDecompressDecimal64(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf) {
FUNC_COMPRESS_IMPL(pIn, nIn, nEle, pOut, nOut, cmprAlg, pBuf, nBuf, TSDB_DATA_TYPE_DECIMAL64, 0);
}
int32_t tsCompressDecimal128(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf) {
FUNC_COMPRESS_IMPL(pIn, nIn, nEle, pOut, nOut, cmprAlg, pBuf, nBuf, TSDB_DATA_TYPE_DECIMAL, 1);
}
int32_t tsDecompressDecimal128(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int32_t nOut, uint32_t cmprAlg,
void *pBuf, int32_t nBuf) {
FUNC_COMPRESS_IMPL(pIn, nIn, nEle, pOut, nOut, cmprAlg, pBuf, nBuf, TSDB_DATA_TYPE_DECIMAL, 0);
}
void tcompressDebug(uint32_t cmprAlg, uint8_t *l1Alg, uint8_t *l2Alg, uint8_t *level) {
DEFINE_VAR(cmprAlg)
*l1Alg = l1;
@ -1903,6 +1922,12 @@ int32_t getWordLength(char type) {
case TSDB_DATA_TYPE_TINYINT:
wordLength = CHAR_BYTES;
break;
case TSDB_DATA_TYPE_DECIMAL64:
wordLength = DECIMAL64_BYTES;
break;
case TSDB_DATA_TYPE_DECIMAL:
wordLength = DECIMAL128_BYTES;
break;
default:
uError("Invalid decompress integer type:%d", type);
return TSDB_CODE_INVALID_PARA;

View File

@ -32,13 +32,13 @@ class DecimalType:
if allow_weight_overflow:
weight = secrets.randbelow(40)
else:
weight = secrets.randbelow(self.precision + 1)
weight = secrets.randbelow(self.precision - self.scale)
if allow_scale_overflow:
dscale = secrets.randbelow(40 - weight + 1)
else:
dscale = secrets.randbelow(self.precision - weight + 1)
digits :str = ''
for i in range(dscale):
for _ in range(weight):
digits += str(secrets.randbelow(10))
if dscale > 0:
digits += '.'
@ -411,9 +411,9 @@ class TDTestCase:
tdLog.printNoPrefix("-------- test create decimal column")
self.columns = [
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(10, 2))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(20, 2))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(30, 2))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(38, 2))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(20, 4))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(30, 8))),
DataType(TypeEnum.DECIMAL, type_mod=DataType.get_decimal_type_mod(DecimalType(38, 10))),
DataType(TypeEnum.TINYINT),
DataType(TypeEnum.INT),
DataType(TypeEnum.BIGINT),
@ -453,13 +453,15 @@ class TDTestCase:
## drop index from stb
### These ops will override the previous stbobjs and meta entries, so test it
## TODO test encode and compress for decimal type
def test_insert_decimal_values(self):
for i in range(self.c_table_num):
pass
#TableInserter(tdSql, self.db_name, f"{self.c_table_prefix}{i}", self.columns, self.tags).insert(1, 1537146000000, 500)
TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(1, 1537146000000, 500)
TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(100, 1537146000000, 500)
## insert null/None for decimal type