feat(decimal): support decimal data type (#30060)
* decimal: create table * decimal: add test case decimal.py * decimal: add decimal.c * support input decimal * decimal test * refactor svalue * fix test cases * add decimal unit test * add decimal test cmake * support insert and query decimal type * define wide integer, support decimal128 * support decimal128 divide * set decimal type expr res types * scalar decimal * convert to decimal * fix decimal64/128 from str and to str * fix decimal from str and decimal to str * decimal simple conversion * unit test for decimal * decimal conversion and unit tests * decimal + - * / * decimal scalar ops and comparision * start to refactor GET_TYPED_DATA * support decimal max func, cast func * refactor GET_TYPED_DATA interface * decimal scalar comparision * start to implement sum for decimal * support sum and avg for decimal type * decimal tests * add decimal test * decimal add test cases * decimal use int256/int128 * decimal testing * fix decimal table meta and add tests for decimal col streams * fix create stream and create tsma * test insert decimal values * decimal from str * test decimal input * test parse decimal from string * add taos_fetch_field_e api * decimal insert tests * test decimal operators * decimal operator test * feat:support decimal in raw block * decimal operator tests * decimal test * feat:support decimal in raw block * feat:support decimal in raw block * feat:add schemaExt to SMqDataRsp * feat:remove add schemaExt to SMqDataRsp * feat:remove add schemaExt to SMqDataRsp * feat:remove add schemaExt to SMqDataRsp * decimal test operators * decimal operator test * test decimal operators * test decimal compare operators * decimal unary operator test * decimal col with decimal col oper test * test decimal col filtering * fix decimal float operator test * decimal test where filtering * fix decimal filtering * fix decimal order by * fix decimal op test * test decimal agg funcs * test decimal functions * remove assert * fix ci build for ret check * fix decimal windows build * fix ci ret check * skip decimal ret check * skip decimal ret check * fix decimal tests * fix decimal ci test * decimal test * fix(tmq): heap user after free * fix(tmq): double free * fix(tmq): double free * fix decimal tests * fix(decimal): decimal test ci build * fix(decimal): windows build * fix(decimal): decimal test build * fix(decimal): fix decimal build and tests * fix(decimal): fix decimal tests * fix(decimal): fix taos_fetch_fields_e api * fix(decimal): fix decimal taos_fetch_fields_e api * fix(decimal): rebase 3.0 * fix(decimal): fix decimal functions * fix(decimal): fix decimal test case memory leak * fix(decimal): fix decimal tests * fix(decimal): fix decimal test case * fix(decimal): fix decimal tests * feat(decimal): fix unit tests * feat(decimal): fix deicmal unit test --------- Co-authored-by: wangmm0220 <wangmm0220@gmail.com> Co-authored-by: yihaoDeng <yhdeng@taosdata.com>
This commit is contained in:
parent
73d4e5f850
commit
f50fcb85b8
|
@ -73,6 +73,8 @@ This document details the server error codes that may be encountered when using
|
|||
| 0x80000134 | Invalid value | Invalid value | Preserve the scene and logs, report issue on github |
|
||||
| 0x80000135 | Invalid fqdn | Invalid FQDN | Check if the configured or input FQDN value is correct |
|
||||
| 0x8000013C | Invalid disk id | Invalid disk id | Check users whether the mounted disk is invalid or use the parameter diskIDCheckEnabled to skip the disk check. |
|
||||
| 0x8000013D | Decimal value overflow | Decimal value overflow | Check query expression and decimal values |
|
||||
| 0x8000013E | Division by zero error | Division by zero | Check division expression |
|
||||
|
||||
|
||||
## tsc
|
||||
|
|
|
@ -76,6 +76,8 @@ description: TDengine 服务端的错误码列表和详细说明
|
|||
| 0x80000134 | Invalid value | 无效值 | 保留现场和日志,github 上报 issue |
|
||||
| 0x80000135 | Invalid fqdn | 无效 FQDN | 检查配置或输入的 FQDN 值是否正确 |
|
||||
| 0x8000013C | Invalid disk id | 不合法的 disk id | 建议用户检查挂载磁盘是否失效或者使用参数 diskIDCheckEnabled 来跳过磁盘检查 |
|
||||
| 0x8000013D | Decimal value overflow | Decimal 计算溢出 | 检查计算表达式和参数值是否计算结果导致类型溢出 |
|
||||
| 0x8000013E | Division by zero error | Division by zero | 检查除法操作是否除以0 |
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ typedef void TAOS_SUB;
|
|||
#define TSDB_DATA_TYPE_MEDIUMBLOB 19
|
||||
#define TSDB_DATA_TYPE_BINARY TSDB_DATA_TYPE_VARCHAR // string
|
||||
#define TSDB_DATA_TYPE_GEOMETRY 20 // geometry
|
||||
#define TSDB_DATA_TYPE_MAX 21
|
||||
#define TSDB_DATA_TYPE_DECIMAL64 21 // decimal64
|
||||
#define TSDB_DATA_TYPE_MAX 22
|
||||
|
||||
typedef enum {
|
||||
TSDB_OPTION_LOCALE,
|
||||
|
@ -270,6 +271,7 @@ DLL_EXPORT int taos_affected_rows(TAOS_RES *res);
|
|||
DLL_EXPORT int64_t taos_affected_rows64(TAOS_RES *res);
|
||||
|
||||
DLL_EXPORT TAOS_FIELD *taos_fetch_fields(TAOS_RES *res);
|
||||
DLL_EXPORT TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res);
|
||||
DLL_EXPORT int taos_select_db(TAOS *taos, const char *db);
|
||||
DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields);
|
||||
DLL_EXPORT int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields);
|
||||
|
|
|
@ -79,7 +79,7 @@ uint8_t columnLevelVal(const char* level);
|
|||
uint8_t columnEncodeVal(const char* encode);
|
||||
uint16_t columnCompressVal(const char* compress);
|
||||
|
||||
bool useCompress(uint8_t tableType);
|
||||
bool withExtSchema(uint8_t tableType);
|
||||
bool checkColumnEncode(char encode[TSDB_CL_COMPRESS_OPTION_LEN]);
|
||||
bool checkColumnEncodeOrSetDefault(uint8_t type, char encode[TSDB_CL_COMPRESS_OPTION_LEN]);
|
||||
bool checkColumnCompress(char compress[TSDB_CL_COMPRESS_OPTION_LEN]);
|
||||
|
|
|
@ -166,14 +166,35 @@ typedef enum EStreamType {
|
|||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct SColumnDataAgg {
|
||||
int16_t colId;
|
||||
int32_t colId;
|
||||
int16_t numOfNull;
|
||||
int64_t sum;
|
||||
int64_t max;
|
||||
int64_t min;
|
||||
union {
|
||||
struct {
|
||||
int64_t sum;
|
||||
int64_t max;
|
||||
int64_t min;
|
||||
};
|
||||
struct {
|
||||
uint64_t decimal128Sum[2];
|
||||
uint64_t decimal128Max[2];
|
||||
uint64_t decimal128Min[2];
|
||||
uint8_t overflow;
|
||||
};
|
||||
};
|
||||
} SColumnDataAgg;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define DECIMAL_AGG_FLAG 0x80000000
|
||||
|
||||
#define COL_AGG_GET_SUM_PTR(pAggs, dataType) \
|
||||
(!IS_DECIMAL_TYPE(dataType) ? (void*)&pAggs->sum : (void*)pAggs->decimal128Sum)
|
||||
|
||||
#define COL_AGG_GET_MAX_PTR(pAggs, dataType) \
|
||||
(!IS_DECIMAL_TYPE(dataType) ? (void*)&pAggs->max : (void*)pAggs->decimal128Max)
|
||||
|
||||
#define COL_AGG_GET_MIN_PTR(pAggs, dataType) \
|
||||
(!IS_DECIMAL_TYPE(dataType) ? (void*)&pAggs->min : (void*)pAggs->decimal128Min)
|
||||
|
||||
typedef struct SBlockID {
|
||||
// The uid of table, from which current data block comes. And it is always 0, if current block is the
|
||||
// result of calculation.
|
||||
|
@ -430,6 +451,14 @@ static inline bool isTsmaResSTb(const char* stbName) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline STypeMod typeGetTypeModFromColInfo(const SColumnInfo* pCol) {
|
||||
return typeGetTypeMod(pCol->type, pCol->precision, pCol->scale, pCol->bytes);
|
||||
}
|
||||
|
||||
static inline STypeMod typeGetTypeModFromCol(const SColumn* pCol) {
|
||||
return typeGetTypeMod(pCol->type, pCol->precision, pCol->scale, pCol->bytes);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -80,6 +80,9 @@ typedef struct SBlockOrderInfo {
|
|||
#define IS_JSON_NULL(type, data) \
|
||||
((type) == TSDB_DATA_TYPE_JSON && (*(data) == TSDB_DATA_TYPE_NULL || tTagIsJsonNull(data)))
|
||||
|
||||
#define GET_COL_DATA_TYPE(col) \
|
||||
{ .type = (col).type, .precision = (col).precision, .bytes = (col).bytes, .scale = (col).scale }
|
||||
|
||||
static FORCE_INLINE bool colDataIsNull_s(const SColumnInfoData* pColumnInfoData, uint32_t row) {
|
||||
if (!pColumnInfoData->hasNull) {
|
||||
return false;
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct SColData SColData;
|
|||
|
||||
typedef struct SRowKey SRowKey;
|
||||
typedef struct SValueColumn SValueColumn;
|
||||
struct SColumnDataAgg;
|
||||
typedef struct SColumnDataAgg* SColumnDataAggPtr;
|
||||
|
||||
#define HAS_NONE ((uint8_t)0x1)
|
||||
#define HAS_NULL ((uint8_t)0x2)
|
||||
|
@ -187,7 +189,7 @@ uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal);
|
|||
int32_t tColDataCopy(SColData *pColDataFrom, SColData *pColData, xMallocFn xMalloc, void *arg);
|
||||
void tColDataArrGetRowKey(SColData *aColData, int32_t nColData, int32_t iRow, SRowKey *key);
|
||||
|
||||
extern void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, int16_t *numOfNull);
|
||||
extern void (*tColDataCalcSMA[])(SColData *pColData, SColumnDataAggPtr pAggs);
|
||||
|
||||
int32_t tColDataCompress(SColData *colData, SColDataCompressInfo *info, SBuffer *output, SBuffer *assist);
|
||||
int32_t tColDataDecompress(void *input, SColDataCompressInfo *info, SColData *colData, SBuffer *assist);
|
||||
|
@ -244,6 +246,8 @@ typedef struct {
|
|||
uint32_t offset;
|
||||
} SPrimaryKeyIndex;
|
||||
|
||||
#define DATUM_MAX_SIZE 16
|
||||
|
||||
struct SValue {
|
||||
int8_t type;
|
||||
union {
|
||||
|
@ -255,6 +259,16 @@ struct SValue {
|
|||
};
|
||||
};
|
||||
|
||||
#define VALUE_GET_DATUM(pVal, type) \
|
||||
(IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_DECIMAL) ? (pVal)->pData : (void*)&(pVal)->val
|
||||
|
||||
#define VALUE_GET_TRIVIAL_DATUM(pVal) ((pVal)->val)
|
||||
#define VALUE_SET_TRIVIAL_DATUM(pVal, v) (pVal)->val = v
|
||||
|
||||
void valueSetDatum(SValue *pVal, int8_t type, void *pDatum, uint32_t len);
|
||||
void valueCloneDatum(SValue *pDst, const SValue *pSrc, int8_t type);
|
||||
void valueClearDatum(SValue *pVal, int8_t type);
|
||||
|
||||
#define TD_MAX_PK_COLS 2
|
||||
struct SRowKey {
|
||||
TSKEY ts;
|
||||
|
|
|
@ -515,6 +515,7 @@ typedef struct SFieldWithOptions {
|
|||
int8_t flags;
|
||||
int32_t bytes;
|
||||
uint32_t compress;
|
||||
STypeMod typeMod;
|
||||
} SFieldWithOptions;
|
||||
|
||||
typedef struct SRetention {
|
||||
|
@ -596,6 +597,7 @@ struct SSchema {
|
|||
struct SSchemaExt {
|
||||
col_id_t colId;
|
||||
uint32_t compress;
|
||||
STypeMod typeMod;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -659,6 +661,7 @@ void tFreeSSubmitRsp(SSubmitRsp* pRsp);
|
|||
#define COL_SET_NULL ((int8_t)0x10)
|
||||
#define COL_SET_VAL ((int8_t)0x20)
|
||||
#define COL_IS_SYSINFO ((int8_t)0x40)
|
||||
#define COL_HAS_TYPE_MOD ((int8_t)0x80)
|
||||
|
||||
#define COL_IS_SET(FLG) (((FLG) & (COL_SET_VAL | COL_SET_NULL)) != 0)
|
||||
#define COL_CLR_SET(FLG) ((FLG) &= (~(COL_SET_VAL | COL_SET_NULL)))
|
||||
|
@ -677,6 +680,13 @@ void tFreeSSubmitRsp(SSubmitRsp* pRsp);
|
|||
(s)->flags &= (~COL_IDX_ON); \
|
||||
} while (0)
|
||||
|
||||
#define SSCHEMA_SET_TYPE_MOD(s) \
|
||||
do { \
|
||||
(s)->flags |= COL_HAS_TYPE_MOD; \
|
||||
} while (0)
|
||||
|
||||
#define HAS_TYPE_MOD(s) (((s)->flags & COL_HAS_TYPE_MOD))
|
||||
|
||||
#define SSCHMEA_TYPE(s) ((s)->type)
|
||||
#define SSCHMEA_FLAGS(s) ((s)->flags)
|
||||
#define SSCHMEA_COLID(s) ((s)->colId)
|
||||
|
@ -693,6 +703,12 @@ typedef struct {
|
|||
char tsSlowLogExceptDb[TSDB_DB_NAME_LEN];
|
||||
} SMonitorParas;
|
||||
|
||||
typedef struct {
|
||||
STypeMod typeMod;
|
||||
} SExtSchema;
|
||||
|
||||
bool hasExtSchema(const SExtSchema* pExtSchema);
|
||||
|
||||
typedef struct {
|
||||
int32_t nCols;
|
||||
int32_t version;
|
||||
|
@ -843,12 +859,14 @@ static FORCE_INLINE int32_t tDecodeSSchema(SDecoder* pDecoder, SSchema* pSchema)
|
|||
static FORCE_INLINE int32_t tEncodeSSchemaExt(SEncoder* pEncoder, const SSchemaExt* pSchemaExt) {
|
||||
TAOS_CHECK_RETURN(tEncodeI16v(pEncoder, pSchemaExt->colId));
|
||||
TAOS_CHECK_RETURN(tEncodeU32(pEncoder, pSchemaExt->compress));
|
||||
TAOS_CHECK_RETURN(tEncodeI32(pEncoder, pSchemaExt->typeMod));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tDecodeSSchemaExt(SDecoder* pDecoder, SSchemaExt* pSchemaExt) {
|
||||
TAOS_CHECK_RETURN(tDecodeI16v(pDecoder, &pSchemaExt->colId));
|
||||
TAOS_CHECK_RETURN(tDecodeU32(pDecoder, &pSchemaExt->compress));
|
||||
TAOS_CHECK_RETURN(tDecodeI32(pDecoder, &pSchemaExt->typeMod));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -881,6 +899,7 @@ static FORCE_INLINE void* taosDecodeSSchemaWrapper(const void* buf, SSchemaWrapp
|
|||
}
|
||||
|
||||
static FORCE_INLINE int32_t tEncodeSSchemaWrapper(SEncoder* pEncoder, const SSchemaWrapper* pSW) {
|
||||
if (pSW == NULL) {return TSDB_CODE_INVALID_PARA;}
|
||||
TAOS_CHECK_RETURN(tEncodeI32v(pEncoder, pSW->nCols));
|
||||
TAOS_CHECK_RETURN(tEncodeI32v(pEncoder, pSW->version));
|
||||
for (int32_t i = 0; i < pSW->nCols; i++) {
|
||||
|
@ -890,6 +909,7 @@ static FORCE_INLINE int32_t tEncodeSSchemaWrapper(SEncoder* pEncoder, const SSch
|
|||
}
|
||||
|
||||
static FORCE_INLINE int32_t tDecodeSSchemaWrapper(SDecoder* pDecoder, SSchemaWrapper* pSW) {
|
||||
if (pSW == NULL) {return TSDB_CODE_INVALID_PARA;}
|
||||
TAOS_CHECK_RETURN(tDecodeI32v(pDecoder, &pSW->nCols));
|
||||
TAOS_CHECK_RETURN(tDecodeI32v(pDecoder, &pSW->version));
|
||||
|
||||
|
@ -988,6 +1008,7 @@ typedef struct {
|
|||
int32_t sqlLen;
|
||||
char* sql;
|
||||
int64_t keep;
|
||||
SArray* pTypeMods;
|
||||
} SMAlterStbReq;
|
||||
|
||||
int32_t tSerializeSMAlterStbReq(void* buf, int32_t bufLen, SMAlterStbReq* pReq);
|
||||
|
@ -3243,6 +3264,7 @@ typedef struct SVCreateStbReq {
|
|||
int8_t colCmpred;
|
||||
SColCmprWrapper colCmpr;
|
||||
int64_t keep;
|
||||
SExtSchema* pExtSchemas;
|
||||
} SVCreateStbReq;
|
||||
|
||||
int tEncodeSVCreateStbReq(SEncoder* pCoder, const SVCreateStbReq* pReq);
|
||||
|
@ -3283,6 +3305,7 @@ typedef struct SVCreateTbReq {
|
|||
int32_t sqlLen;
|
||||
char* sql;
|
||||
SColCmprWrapper colCmpr;
|
||||
SExtSchema* pExtSchemas;
|
||||
} SVCreateTbReq;
|
||||
|
||||
int tEncodeSVCreateTbReq(SEncoder* pCoder, const SVCreateTbReq* pReq);
|
||||
|
@ -3306,6 +3329,7 @@ static FORCE_INLINE void tdDestroySVCreateTbReq(SVCreateTbReq* req) {
|
|||
taosMemoryFreeClear(req->ntb.schemaRow.pSchema);
|
||||
}
|
||||
taosMemoryFreeClear(req->colCmpr.pColCmpr);
|
||||
taosMemoryFreeClear(req->pExtSchemas);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -3422,6 +3446,8 @@ typedef struct {
|
|||
int8_t source; // TD_REQ_FROM_TAOX-taosX or TD_REQ_FROM_APP-taosClient
|
||||
uint32_t compress; // TSDB_ALTER_TABLE_UPDATE_COLUMN_COMPRESS
|
||||
SArray* pMultiTag; // TSDB_ALTER_TABLE_ADD_MULTI_TAGS
|
||||
// for Add column
|
||||
STypeMod typeMod;
|
||||
} SVAlterTbReq;
|
||||
|
||||
int32_t tEncodeSVAlterTbReq(SEncoder* pEncoder, const SVAlterTbReq* pReq);
|
||||
|
@ -4316,7 +4342,6 @@ typedef struct {
|
|||
};
|
||||
void* data; //for free in client, only effected if type is data or metadata. raw data not effected
|
||||
bool blockDataElementFree; // if true, free blockDataElement in blockData,(true in server, false in client)
|
||||
|
||||
} SMqDataRsp;
|
||||
|
||||
int32_t tEncodeMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pObj);
|
||||
|
|
|
@ -45,6 +45,9 @@ typedef struct {
|
|||
} SNCharNullT;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define STypeMod int32_t
|
||||
void extractTypeFromTypeMod(uint8_t type, STypeMod typeMod, uint8_t *prec, uint8_t* scale, int32_t *bytes);
|
||||
|
||||
#define varDataTLen(v) (sizeof(VarDataLenT) + varDataLen(v))
|
||||
#define varDataCopy(dst, v) (void)memcpy((dst), (void *)(v), varDataTLen(v))
|
||||
#define varDataLenByData(v) (*(VarDataLenT *)(((char *)(v)) - VARSTR_HEADER_SIZE))
|
||||
|
@ -53,45 +56,74 @@ typedef struct {
|
|||
#define varDataNetLen(v) (htons(((VarDataLenT *)(v))[0]))
|
||||
#define varDataNetTLen(v) (sizeof(VarDataLenT) + varDataNetLen(v))
|
||||
|
||||
#define GET_TYPED_DATA(_v, _finalType, _type, _data) \
|
||||
do { \
|
||||
switch (_type) { \
|
||||
case TSDB_DATA_TYPE_BOOL: \
|
||||
case TSDB_DATA_TYPE_TINYINT: \
|
||||
(_v) = (_finalType)GET_INT8_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UTINYINT: \
|
||||
(_v) = (_finalType)GET_UINT8_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_SMALLINT: \
|
||||
(_v) = (_finalType)GET_INT16_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_USMALLINT: \
|
||||
(_v) = (_finalType)GET_UINT16_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: \
|
||||
case TSDB_DATA_TYPE_BIGINT: \
|
||||
(_v) = (_finalType)(GET_INT64_VAL(_data)); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UBIGINT: \
|
||||
(_v) = (_finalType)(GET_UINT64_VAL(_data)); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_FLOAT: \
|
||||
(_v) = (_finalType)GET_FLOAT_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_DOUBLE: \
|
||||
(_v) = (_finalType)GET_DOUBLE_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UINT: \
|
||||
(_v) = (_finalType)GET_UINT32_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_INT: \
|
||||
(_v) = (_finalType)GET_INT32_VAL(_data); \
|
||||
break; \
|
||||
default: \
|
||||
(_v) = (_finalType)varDataLen(_data); \
|
||||
break; \
|
||||
} \
|
||||
#define DEFINE_TYPE_FROM_DECIMAL_FUNC(oType, decimalType) \
|
||||
oType oType##From##decimalType(const void* pDec, uint8_t prec, uint8_t scale)
|
||||
|
||||
#define DEFINE_TYPE_FROM_DECIMAL_FUNCS(prefix, decimalType) \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(bool, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(int8_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(uint8_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(int16_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(uint16_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(int32_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(uint32_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(int64_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(uint64_t, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(float, decimalType); \
|
||||
prefix DEFINE_TYPE_FROM_DECIMAL_FUNC(double, decimalType);
|
||||
|
||||
DEFINE_TYPE_FROM_DECIMAL_FUNCS(extern, Decimal64);
|
||||
DEFINE_TYPE_FROM_DECIMAL_FUNCS(extern, Decimal128);
|
||||
|
||||
#define GET_TYPED_DATA(_v, _finalType, _type, _data, inputTypeMod) \
|
||||
do { \
|
||||
switch (_type) { \
|
||||
case TSDB_DATA_TYPE_BOOL: \
|
||||
case TSDB_DATA_TYPE_TINYINT: \
|
||||
(_v) = (_finalType)GET_INT8_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UTINYINT: \
|
||||
(_v) = (_finalType)GET_UINT8_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_SMALLINT: \
|
||||
(_v) = (_finalType)GET_INT16_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_USMALLINT: \
|
||||
(_v) = (_finalType)GET_UINT16_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: \
|
||||
case TSDB_DATA_TYPE_BIGINT: \
|
||||
(_v) = (_finalType)(GET_INT64_VAL(_data)); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UBIGINT: \
|
||||
(_v) = (_finalType)(GET_UINT64_VAL(_data)); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_FLOAT: \
|
||||
(_v) = (_finalType)GET_FLOAT_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_DOUBLE: \
|
||||
(_v) = (_finalType)GET_DOUBLE_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_UINT: \
|
||||
(_v) = (_finalType)GET_UINT32_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_INT: \
|
||||
(_v) = (_finalType)GET_INT32_VAL(_data); \
|
||||
break; \
|
||||
case TSDB_DATA_TYPE_DECIMAL: { \
|
||||
uint8_t prec = 0, scale = 0; \
|
||||
extractTypeFromTypeMod(_type, inputTypeMod, &prec, &scale, NULL); \
|
||||
(_v) = _finalType##FromDecimal128(_data, prec, scale); \
|
||||
} break; \
|
||||
case TSDB_DATA_TYPE_DECIMAL64: { \
|
||||
uint8_t prec = 0, scale = 0; \
|
||||
extractTypeFromTypeMod(_type, inputTypeMod, &prec, &scale, NULL); \
|
||||
(_v) = _finalType##FromDecimal64(_data, prec, scale); \
|
||||
} break; \
|
||||
default: \
|
||||
(_v) = (_finalType)varDataLen(_data); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SET_TYPED_DATA(_v, _type, _data) \
|
||||
|
@ -265,8 +297,9 @@ typedef struct {
|
|||
#define IS_INTEGER_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)))
|
||||
#define IS_TIMESTAMP_TYPE(_t) ((_t) == TSDB_DATA_TYPE_TIMESTAMP)
|
||||
#define IS_BOOLEAN_TYPE(_t) ((_t) == TSDB_DATA_TYPE_BOOL)
|
||||
#define IS_DECIMAL_TYPE(_t) ((_t) == TSDB_DATA_TYPE_DECIMAL || (_t) == TSDB_DATA_TYPE_DECIMAL64)
|
||||
|
||||
#define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t)))
|
||||
#define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t)) || (IS_DECIMAL_TYPE(_t)))
|
||||
#define IS_MATHABLE_TYPE(_t) \
|
||||
(IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
||||
|
||||
|
@ -364,6 +397,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);
|
||||
|
@ -371,6 +411,21 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type);
|
|||
void *getDataMin(int32_t type, void *value);
|
||||
void *getDataMax(int32_t type, void *value);
|
||||
|
||||
STypeMod typeGetTypeMod(uint8_t type, uint8_t prec, uint8_t scale, int32_t bytes);
|
||||
STypeMod typeGetTypeModFromDataType(const SDataType* pDataType);
|
||||
uint8_t decimalTypeFromPrecision(uint8_t precision);
|
||||
STypeMod decimalCalcTypeMod(uint8_t prec, uint8_t scale);
|
||||
void decimalFromTypeMod(STypeMod typeMod, uint8_t *precision, uint8_t *scale);
|
||||
// pType->type should has been set
|
||||
void fillTypeFromTypeMod(SDataType *pType, STypeMod mod);
|
||||
uint8_t getScaleFromTypeMod(int32_t type, STypeMod mod);
|
||||
// TODO fix me!! for compatibility issue, save precision in scale in bytes, move it to somewhere else
|
||||
void fillBytesForDecimalType(int32_t *pBytes, int32_t type, uint8_t precision, uint8_t scale);
|
||||
void extractDecimalTypeInfoFromBytes(int32_t *pBytes, uint8_t *precision, uint8_t *scale);
|
||||
|
||||
int32_t calcTypeBytesFromSchemaBytes(int32_t type, int32_t schemaBytes, bool isStmt);
|
||||
int32_t calcSchemaBytesFromTypeBytes(int32_t type, int32_t varTypeBytes, bool isStmt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_DECIMAL_H_
|
||||
#define _TD_DECIMAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tdef.h"
|
||||
#include "ttypes.h"
|
||||
typedef struct SValue SValue;
|
||||
typedef void DecimalType;
|
||||
|
||||
typedef struct Decimal64 {
|
||||
DecimalWord words[1]; // do not touch it directly, use DECIMAL64_GET_VALUE MACRO
|
||||
} Decimal64;
|
||||
|
||||
#define DECIMAL64_GET_VALUE(pDec) (int64_t)((pDec)->words[0])
|
||||
#define DECIMAL64_SET_VALUE(pDec, val) (*(int64_t*)((pDec)->words)) = (int64_t)(val)
|
||||
#define DECIMAL64_CLONE(pDst, pFrom) ((Decimal64*)(pDst))->words[0] = ((Decimal64*)(pFrom))->words[0]
|
||||
|
||||
static const Decimal64 decimal64Zero = {0};
|
||||
static const Decimal64 decimal64Two = {2};
|
||||
static const Decimal64 decimal64Min = {(uint64_t)-999999999999999999LL};
|
||||
static const Decimal64 decimal64Max = {(uint64_t)999999999999999999LL};
|
||||
#define DECIMAL64_ZERO decimal64Zero
|
||||
#define DECIMAL64_MAX decimal64Max
|
||||
#define DECIMAL64_MIN decimal64Min
|
||||
|
||||
typedef struct Decimal128 {
|
||||
DecimalWord words[2]; // do not touch it directly, use DECIMAL128_HIGH_WORD/DECIMAL128_LOW_WORD
|
||||
} Decimal128;
|
||||
|
||||
#define Decimal Decimal128
|
||||
#define decimalFromStr decimal128FromStr
|
||||
#define makeDecimal makeDecimal128
|
||||
|
||||
#define DEFINE_DECIMAL128(lo, hi) {lo, hi}
|
||||
static const Decimal128 decimal128Zero = DEFINE_DECIMAL128(0, 0);
|
||||
static const Decimal128 decimal128Two = DEFINE_DECIMAL128(2, 0);
|
||||
static const Decimal128 decimal128Max = DEFINE_DECIMAL128(687399551400673280ULL - 1, 5421010862427522170LL);
|
||||
static const Decimal128 decimal128Min = DEFINE_DECIMAL128(17759344522308878337ULL, 13025733211282029445ULL);
|
||||
#define DECIMAL128_LOW_WORD(pDec) (uint64_t)((pDec)->words[0])
|
||||
#define DECIMAL128_SET_LOW_WORD(pDec, val) (pDec)->words[0] = val
|
||||
#define DECIMAL128_HIGH_WORD(pDec) (int64_t)((pDec)->words[1])
|
||||
#define DECIMAL128_SET_HIGH_WORD(pDec, val) *(int64_t*)((pDec)->words + 1) = val
|
||||
|
||||
#define DECIMAL128_ZERO decimal128Zero
|
||||
#define DECIMAL128_MAX decimal128Max
|
||||
#define DECIMAL128_MIN decimal128Min
|
||||
#define DECIMAL128_CLONE(pDst, pFrom) makeDecimal128(pDst, DECIMAL128_HIGH_WORD(pFrom), DECIMAL128_LOW_WORD(pFrom))
|
||||
|
||||
typedef struct SDecimalCompareCtx {
|
||||
const void* pData;
|
||||
int8_t type;
|
||||
STypeMod typeMod;
|
||||
} SDecimalCompareCtx;
|
||||
|
||||
void makeDecimal64(Decimal64* pDec64, int64_t w);
|
||||
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low);
|
||||
|
||||
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);
|
||||
int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale,
|
||||
Decimal128* result);
|
||||
|
||||
int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal);
|
||||
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal);
|
||||
|
||||
int32_t decimalToStr(const DecimalType* pDec, int8_t type, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen);
|
||||
|
||||
int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOperatorType opType, SDataType* pOutType);
|
||||
bool decimal64Compare(EOperatorType op, const SDecimalCompareCtx* pLeft, const SDecimalCompareCtx* pRight);
|
||||
bool decimalCompare(EOperatorType op, const SDecimalCompareCtx* pLeft, const SDecimalCompareCtx* pRight);
|
||||
int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pRightT, const SDataType* pOutT,
|
||||
const void* pLeftData, const void* pRightData, void* pOutputData);
|
||||
int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* pOut, const SDataType* pOutType);
|
||||
bool decimal128AddCheckOverflow(const Decimal128* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
void encodeDecimal(const DecimalType* pDec, int8_t type, void* pBuf);
|
||||
void decodeDecimal(const void* pBuf, int8_t type, DecimalType* pDec);
|
||||
|
||||
DEFINE_TYPE_FROM_DECIMAL_FUNCS(, Decimal64);
|
||||
DEFINE_TYPE_FROM_DECIMAL_FUNCS(, Decimal128);
|
||||
|
||||
// word num use DECIMAL_WORD_NUM(Decimal64) or DECIMAL_WORD_NUM(Decimal128)
|
||||
typedef struct SDecimalOps {
|
||||
void (*negate)(DecimalType* pWord);
|
||||
void (*abs)(DecimalType* pWord);
|
||||
void (*add)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
void (*subtract)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
void (*multiply)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
void (*divide)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, DecimalType* pRemainder);
|
||||
void (*mod)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
bool (*lt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
bool (*gt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
bool (*eq)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||
int32_t (*toStr)(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
|
||||
} SDecimalOps;
|
||||
|
||||
// all these ops only used for operations on decimal types with same scale
|
||||
const SDecimalOps* getDecimalOps(int8_t dataType);
|
||||
|
||||
#if 0
|
||||
__int128 decimal128ToInt128(const Decimal128* pDec);
|
||||
#endif
|
||||
int32_t TEST_decimal64From_int64_t(Decimal64* pDec, uint8_t prec, uint8_t scale, int64_t v);
|
||||
int32_t TEST_decimal64From_uint64_t(Decimal64* pDec, uint8_t prec, uint8_t scale, uint64_t v);
|
||||
int32_t TEST_decimal64From_double(Decimal64* pDec, uint8_t prec, uint8_t scale, double v);
|
||||
double TEST_decimal64ToDouble(Decimal64* pDec, uint8_t prec, uint8_t scale);
|
||||
int32_t TEST_decimal64FromDecimal64(const Decimal64* pInput, uint8_t inputPrec, uint8_t inputScale, Decimal64* pOutput,
|
||||
uint8_t outputPrec, uint8_t outputScale);
|
||||
int32_t TEST_decimal64FromDecimal128(const Decimal128* pInput, uint8_t prec, uint8_t scale, Decimal64* pOutput,
|
||||
uint8_t outputPrec, uint8_t outputScale);
|
||||
|
||||
int32_t TEST_decimal128From_int64_t(Decimal128* pDec, uint8_t prec, uint8_t scale, int64_t v);
|
||||
int32_t TEST_decimal128From_uint64_t(Decimal128* pDec, uint8_t prec, uint8_t scale, uint64_t v);
|
||||
int32_t TEST_decimal128From_double(Decimal128* pDec, uint8_t prec, uint8_t scale, double v);
|
||||
double TEST_decimal128ToDouble(Decimal128* pDec, uint8_t prec, uint8_t scale);
|
||||
int32_t TEST_decimal128FromDecimal64(const Decimal64* pInput, uint8_t inputPrec, uint8_t inputScale,
|
||||
Decimal128* pOutput, uint8_t outputPrec, uint8_t outputScale);
|
||||
int32_t TEST_decimal128FromDecimal128(const Decimal128* pDec, uint8_t prec, uint8_t scale, Decimal128* pOutput,
|
||||
uint8_t outputPrec, uint8_t outputScale);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_DECIMAL_H_*/
|
|
@ -84,6 +84,7 @@ typedef struct SMetaEntry {
|
|||
uint8_t* pBuf;
|
||||
|
||||
SColCmprWrapper colCmpr; // col compress alg
|
||||
SExtSchema* pExtSchemas;
|
||||
} SMetaEntry;
|
||||
|
||||
typedef struct SMetaReader {
|
||||
|
@ -136,6 +137,11 @@ typedef struct SMetaTableInfo {
|
|||
char tbName[TSDB_TABLE_NAME_LEN];
|
||||
} SMetaTableInfo;
|
||||
|
||||
static FORCE_INLINE void destroyMetaTableInfo(SMetaTableInfo* mtInfo){
|
||||
if (mtInfo == NULL) return;
|
||||
tDeleteSchemaWrapper(mtInfo->schema);
|
||||
}
|
||||
|
||||
typedef struct SSnapContext {
|
||||
struct SMeta* pMeta;
|
||||
int64_t snapVersion;
|
||||
|
|
|
@ -265,6 +265,7 @@ typedef struct SqlFunctionCtx {
|
|||
bool bInputFinished;
|
||||
bool hasWindowOrGroup; // denote that the function is used with time window or group
|
||||
bool needCleanup; // denote that the function need to be cleaned up
|
||||
int32_t inputType; // save the fuction input type funcs like finalize
|
||||
} SqlFunctionCtx;
|
||||
|
||||
typedef struct tExprNode {
|
||||
|
@ -291,12 +292,14 @@ struct SScalarParam {
|
|||
SColumnInfoData *columnData;
|
||||
SHashObj *pHashFilter;
|
||||
SHashObj *pHashFilterOthers;
|
||||
int32_t hashValueType;
|
||||
int32_t filterValueType;
|
||||
void *param; // other parameter, such as meta handle from vnode, to extract table name/tag value
|
||||
int32_t numOfRows;
|
||||
int32_t numOfQualified; // number of qualified elements in the final results
|
||||
timezone_t tz;
|
||||
void *charsetCxt;
|
||||
SArray *pFilterArr; // for types that can't filter with hash
|
||||
STypeMod filterValueTypeMod;
|
||||
};
|
||||
|
||||
static inline void setTzCharset(SScalarParam* param, timezone_t tz, void* charsetCxt){
|
||||
|
@ -315,7 +318,7 @@ typedef struct SPoint {
|
|||
} SPoint;
|
||||
|
||||
void taosGetLinearInterpolationVal(SPoint *point, int32_t outputType, SPoint *point1, SPoint *point2,
|
||||
int32_t inputType);
|
||||
int32_t inputType, STypeMod inputTypeMod);
|
||||
|
||||
#define LEASTSQUARES_DOUBLE_ITEM_LENGTH 25
|
||||
#define LEASTSQUARES_BUFF_LENGTH 128
|
||||
|
|
|
@ -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;
|
||||
|
@ -203,6 +197,8 @@ typedef struct SFunctionNode {
|
|||
bool dual; // whether select stmt without from stmt, true for without.
|
||||
timezone_t tz;
|
||||
void *charsetCxt;
|
||||
const struct SFunctionNode* pSrcFuncRef;
|
||||
SDataType srcFuncInputType;
|
||||
} SFunctionNode;
|
||||
|
||||
typedef struct STableNode {
|
||||
|
@ -655,6 +651,7 @@ typedef struct SQuery {
|
|||
SArray* pDbList;
|
||||
SArray* pPlaceholderValues;
|
||||
SNode* pPrepareRoot;
|
||||
SExtSchema* pResExtSchema;
|
||||
} SQuery;
|
||||
|
||||
void nodesWalkSelectStmtImpl(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
|
||||
|
|
|
@ -189,7 +189,7 @@ int32_t smlBuildOutputRaw(SQuery* handle, SHashObj* pVgHash);
|
|||
int rawBlockBindRawData(SHashObj* pVgroupHash, SArray* pVgroupList, STableMeta* pTableMeta, void* data);
|
||||
int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreateTbReq* pCreateTb, void* fields,
|
||||
int numFields, bool needChangeLength, char* errstr, int32_t errstrLen, bool raw);
|
||||
int32_t checkSchema(SSchema* pColSchema, int8_t* fields, char* errstr, int32_t errstrLen);
|
||||
int32_t checkSchema(SSchema* pColSchema, SSchemaExt* pColExtSchema, int8_t* fields, char* errstr, int32_t errstrLen);
|
||||
|
||||
int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray);
|
||||
int32_t serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap, SArray** pOut);
|
||||
|
|
|
@ -41,11 +41,12 @@ pDst need to freed in caller
|
|||
int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst);
|
||||
|
||||
int32_t scalarGetOperatorParamNum(EOperatorType type);
|
||||
int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type, int8_t processType);
|
||||
int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type, STypeMod typeMod, int8_t processType);
|
||||
|
||||
int32_t vectorGetConvertType(int32_t type1, int32_t type2);
|
||||
int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow, int32_t startIndex, int32_t numOfRows);
|
||||
int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, int32_t startIndex, int32_t numOfRows);
|
||||
int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, STypeMod typeMod, int32_t startIndex, int32_t numOfRows);
|
||||
STypeMod getConvertTypeMod(int32_t type, const SColumnInfo *pCol1, const SColumnInfo *pCol2);
|
||||
|
||||
/* Math functions */
|
||||
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
|
|
@ -166,6 +166,8 @@ int32_t taosGetErrSize();
|
|||
#define TSDB_CODE_UNSUPPORT_OS TAOS_DEF_ERROR_CODE(0, 0x013A)
|
||||
#define TSDB_CODE_TIME_ERROR TAOS_DEF_ERROR_CODE(0, 0x013B)
|
||||
#define TSDB_CODE_INVALID_DISK_ID TAOS_DEF_ERROR_CODE(0, 0x013C)
|
||||
#define TSDB_CODE_DECIMAL_OVERFLOW TAOS_DEF_ERROR_CODE(0, 0x013D)
|
||||
#define TSDB_CODE_DIVISION_BY_ZERO TAOS_DEF_ERROR_CODE(0, 0x013E)
|
||||
|
||||
//client
|
||||
#define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200)
|
||||
|
|
|
@ -60,11 +60,13 @@ int32_t setChkInBytes1(const void *pLeft, const void *pRight);
|
|||
int32_t setChkInBytes2(const void *pLeft, const void *pRight);
|
||||
int32_t setChkInBytes4(const void *pLeft, const void *pRight);
|
||||
int32_t setChkInBytes8(const void *pLeft, const void *pRight);
|
||||
int32_t setChkInDecimalHash(const void* pLeft, const void* pRight);
|
||||
|
||||
int32_t setChkNotInBytes1(const void *pLeft, const void *pRight);
|
||||
int32_t setChkNotInBytes2(const void *pLeft, const void *pRight);
|
||||
int32_t setChkNotInBytes4(const void *pLeft, const void *pRight);
|
||||
int32_t setChkNotInBytes8(const void *pLeft, const void *pRight);
|
||||
int32_t setChkNotInDecimalHash(const void* pLeft, const void* pRight);
|
||||
|
||||
int32_t compareChkInString(const void *pLeft, const void *pRight);
|
||||
int32_t compareChkNotInString(const void *pLeft, const void *pRight);
|
||||
|
@ -86,6 +88,12 @@ 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 compareDecimal64SameScale(const void* pleft, const void* pright);
|
||||
int32_t compareDecimal128SameScale(const void* pleft, const void* pright);
|
||||
|
||||
int32_t comparestrRegexMatch(const void *pLeft, const void *pRight);
|
||||
int32_t comparestrRegexNMatch(const void *pLeft, const void *pRight);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,7 +47,7 @@ extern "C" {
|
|||
#define TD_VER_MAX UINT64_MAX // TODO: use the real max version from query handle
|
||||
|
||||
// Bytes for each type.
|
||||
extern const int32_t TYPE_BYTES[21];
|
||||
extern const int32_t TYPE_BYTES[22];
|
||||
|
||||
#define CHAR_BYTES sizeof(char)
|
||||
#define SHORT_BYTES sizeof(int16_t)
|
||||
|
@ -60,6 +60,9 @@ extern const int32_t TYPE_BYTES[21];
|
|||
#define TSDB_KEYSIZE sizeof(TSKEY)
|
||||
#define TSDB_NCHAR_SIZE sizeof(TdUcs4)
|
||||
|
||||
#define DECIMAL64_BYTES 8
|
||||
#define DECIMAL128_BYTES 16
|
||||
|
||||
// NULL definition
|
||||
#define TSDB_DATA_BOOL_NULL 0x02
|
||||
#define TSDB_DATA_TINYINT_NULL 0x80
|
||||
|
@ -694,6 +697,24 @@ typedef enum {
|
|||
|
||||
#define MIN_RESERVE_MEM_SIZE 1024 // MB
|
||||
|
||||
// Decimal
|
||||
#define TSDB_DECIMAL64_MAX_PRECISION 18
|
||||
#define TSDB_DECIMAL64_MAX_SCALE TSDB_DECIMAL64_MAX_PRECISION
|
||||
|
||||
#define TSDB_DECIMAL128_MAX_PRECISION 38
|
||||
#define TSDB_DECIMAL128_MAX_SCALE TSDB_DECIMAL128_MAX_PRECISION
|
||||
|
||||
#define TSDB_DECIMAL_MIN_PRECISION 1
|
||||
#define TSDB_DECIMAL_MAX_PRECISION TSDB_DECIMAL128_MAX_PRECISION
|
||||
#define TSDB_DECIMAL_MIN_SCALE 0
|
||||
#define TSDB_DECIMAL_MAX_SCALE TSDB_DECIMAL_MAX_PRECISION
|
||||
#define GET_DEICMAL_MAX_PRECISION(type) (type) == TSDB_DATA_TYPE_DECIMAL64 ? TSDB_DECIMAL64_MAX_PRECISION : TSDB_DECIMAL_MAX_SCALE
|
||||
|
||||
typedef uint64_t DecimalWord;
|
||||
#define DECIMAL_WORD_NUM(TYPE) (sizeof(TYPE) / sizeof(DecimalWord))
|
||||
|
||||
#define COMPILE_TIME_ASSERT(pred) switch(0) {case 0: case pred:;}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@ char **strsplit(char *src, const char *delim, int32_t *num);
|
|||
char *strtolower(char *dst, const char *src);
|
||||
char *strntolower(char *dst, const char *src, int32_t n);
|
||||
char *strntolower_s(char *dst, const char *src, int32_t n);
|
||||
int64_t strnatoi(char *num, int32_t len);
|
||||
int64_t strnatoi(const char *num, int32_t len);
|
||||
|
||||
size_t tstrncspn(const char *str, size_t ssize, const char *reject, size_t rsize);
|
||||
size_t twcsncspn(const TdUcs4 *wcs, size_t size, const TdUcs4 *reject, size_t rsize);
|
||||
|
|
|
@ -28,7 +28,7 @@ endif()
|
|||
target_link_libraries(
|
||||
${TAOS_LIB}
|
||||
INTERFACE api
|
||||
PRIVATE os util common transport monitor nodes parser command planner catalog scheduler function qcom geometry ${TAOSD_MODULE}
|
||||
PRIVATE os util common transport monitor nodes parser command planner catalog scheduler function qcom geometry ${TAOSD_MODULE} decimal
|
||||
)
|
||||
|
||||
if(TD_WINDOWS)
|
||||
|
@ -67,7 +67,7 @@ target_include_directories(
|
|||
target_link_libraries(
|
||||
${TAOS_LIB_STATIC}
|
||||
INTERFACE api
|
||||
PRIVATE os util common transport monitor nodes parser command planner catalog scheduler function qcom geometry
|
||||
PRIVATE os util common transport monitor nodes parser command planner catalog scheduler function qcom geometry decimal
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
|
|
|
@ -205,7 +205,7 @@ typedef struct SReqResultInfo {
|
|||
SExecResult execRes;
|
||||
const char* pRspMsg;
|
||||
const char* pData;
|
||||
TAOS_FIELD* fields; // todo, column names are not needed.
|
||||
TAOS_FIELD_E* fields; // todo, column names are not needed.
|
||||
TAOS_FIELD* userFields; // the fields info that return to user
|
||||
uint32_t numOfCols;
|
||||
int32_t* length;
|
||||
|
@ -313,11 +313,11 @@ typedef struct SSyncQueryParam {
|
|||
void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
|
||||
void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4);
|
||||
|
||||
void doSetOneRowPtr(SReqResultInfo* pResultInfo);
|
||||
void doSetOneRowPtr(SReqResultInfo* pResultInfo, bool isStmt);
|
||||
void setResPrecision(SReqResultInfo* pResInfo, int32_t precision);
|
||||
int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableRsp* pRsp, bool convertUcs4);
|
||||
int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4);
|
||||
int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols);
|
||||
int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableRsp* pRsp, bool convertUcs4, bool isStmt);
|
||||
int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4, bool isStmt);
|
||||
int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols, const SExtSchema* pExtSchema, bool isStmt);
|
||||
void doFreeReqResultInfo(SReqResultInfo* pResInfo);
|
||||
int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName, SArray** pReq);
|
||||
void syncCatalogFn(SMetaData* pResult, void* param, int32_t code);
|
||||
|
|
|
@ -48,7 +48,7 @@ typedef struct SStmtTableCache {
|
|||
} SStmtTableCache;
|
||||
|
||||
typedef struct SStmtQueryResInfo {
|
||||
TAOS_FIELD *fields;
|
||||
TAOS_FIELD_E *fields;
|
||||
TAOS_FIELD *userFields;
|
||||
uint32_t numOfCols;
|
||||
int32_t precision;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "tref.h"
|
||||
#include "tsched.h"
|
||||
#include "tversion.h"
|
||||
#include "decimal.h"
|
||||
|
||||
static int32_t initEpSetFromCfg(const char* firstEp, const char* secondEp, SCorEpSet* pEpSet);
|
||||
static int32_t buildConnectMsg(SRequestObj* pRequest, SMsgSendInfo** pMsgSendInfo);
|
||||
|
||||
|
@ -313,7 +315,7 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC
|
|||
code = qParseSql(&cxt, pQuery);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if ((*pQuery)->haveResultSet) {
|
||||
code = setResSchemaInfo(&pRequest->body.resInfo, (*pQuery)->pResSchema, (*pQuery)->numOfResCols);
|
||||
code = setResSchemaInfo(&pRequest->body.resInfo, (*pQuery)->pResSchema, (*pQuery)->numOfResCols, (*pQuery)->pResExtSchema, pRequest->isStmtBind);
|
||||
setResPrecision(&pRequest->body.resInfo, (*pQuery)->precision);
|
||||
}
|
||||
}
|
||||
|
@ -335,7 +337,7 @@ int32_t execLocalCmd(SRequestObj* pRequest, SQuery* pQuery) {
|
|||
int8_t biMode = atomic_load_8(&pRequest->pTscObj->biMode);
|
||||
int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp, biMode, pRequest->pTscObj->optionInfo.charsetCxt);
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pRsp) {
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4);
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4, pRequest->isStmtBind);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -373,7 +375,7 @@ void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) {
|
|||
int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp,
|
||||
atomic_load_8(&pRequest->pTscObj->biMode), pRequest->pTscObj->optionInfo.charsetCxt);
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pRsp) {
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4);
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4, pRequest->isStmtBind);
|
||||
}
|
||||
|
||||
SReqResultInfo* pResultInfo = &pRequest->body.resInfo;
|
||||
|
@ -515,7 +517,7 @@ int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArra
|
|||
return qCreateQueryPlan(&cxt, pPlan, pNodeList);
|
||||
}
|
||||
|
||||
int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols) {
|
||||
int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols, const SExtSchema* pExtSchema, bool isStmt) {
|
||||
if (pResInfo == NULL || pSchema == NULL || numOfCols <= 0) {
|
||||
tscError("invalid paras, pResInfo == NULL || pSchema == NULL || numOfCols <= 0");
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
|
@ -528,7 +530,7 @@ int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32
|
|||
if (pResInfo->userFields != NULL) {
|
||||
taosMemoryFree(pResInfo->userFields);
|
||||
}
|
||||
pResInfo->fields = taosMemoryCalloc(numOfCols, sizeof(TAOS_FIELD));
|
||||
pResInfo->fields = taosMemoryCalloc(numOfCols, sizeof(TAOS_FIELD_E));
|
||||
if (NULL == pResInfo->fields) return terrno;
|
||||
pResInfo->userFields = taosMemoryCalloc(numOfCols, sizeof(TAOS_FIELD));
|
||||
if (NULL == pResInfo->userFields) {
|
||||
|
@ -541,17 +543,14 @@ int32_t setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32
|
|||
}
|
||||
|
||||
for (int32_t i = 0; i < pResInfo->numOfCols; ++i) {
|
||||
pResInfo->fields[i].bytes = pSchema[i].bytes;
|
||||
pResInfo->fields[i].type = pSchema[i].type;
|
||||
|
||||
pResInfo->userFields[i].bytes = pSchema[i].bytes;
|
||||
pResInfo->userFields[i].type = pSchema[i].type;
|
||||
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_VARCHAR || pSchema[i].type == TSDB_DATA_TYPE_VARBINARY ||
|
||||
pSchema[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
pResInfo->userFields[i].bytes -= VARSTR_HEADER_SIZE;
|
||||
} else if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR || pSchema[i].type == TSDB_DATA_TYPE_JSON) {
|
||||
pResInfo->userFields[i].bytes = (pResInfo->userFields[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
// userFields must convert to type bytes, no matter isStmt or not
|
||||
pResInfo->userFields[i].bytes = calcTypeBytesFromSchemaBytes(pSchema[i].type, pSchema[i].bytes, false);
|
||||
pResInfo->fields[i].bytes = calcTypeBytesFromSchemaBytes(pSchema[i].type, pSchema[i].bytes, isStmt);
|
||||
if (IS_DECIMAL_TYPE(pSchema[i].type) && pExtSchema) {
|
||||
decimalFromTypeMod(pExtSchema[i].typeMod, &pResInfo->fields[i].precision, &pResInfo->fields[i].scale);
|
||||
}
|
||||
|
||||
tstrncpy(pResInfo->fields[i].name, pSchema[i].name, tListLen(pResInfo->fields[i].name));
|
||||
|
@ -1942,15 +1941,15 @@ TAOS* taos_connect_auth(const char* ip, const char* user, const char* auth, cons
|
|||
// return taos_connect(ipStr, userStr, passStr, dbStr, port);
|
||||
// }
|
||||
|
||||
void doSetOneRowPtr(SReqResultInfo* pResultInfo) {
|
||||
void doSetOneRowPtr(SReqResultInfo* pResultInfo, bool isStmt) {
|
||||
for (int32_t i = 0; i < pResultInfo->numOfCols; ++i) {
|
||||
SResultColumn* pCol = &pResultInfo->pCol[i];
|
||||
|
||||
int32_t type = pResultInfo->fields[i].type;
|
||||
int32_t bytes = pResultInfo->fields[i].bytes;
|
||||
int32_t schemaBytes = calcSchemaBytesFromTypeBytes(type, pResultInfo->fields[i].bytes, isStmt);
|
||||
|
||||
if (IS_VAR_DATA_TYPE(type)) {
|
||||
if (!IS_VAR_NULL_TYPE(type, bytes) && pCol->offset[pResultInfo->current] != -1) {
|
||||
if (!IS_VAR_NULL_TYPE(type, schemaBytes) && pCol->offset[pResultInfo->current] != -1) {
|
||||
char* pStart = pResultInfo->pCol[i].offset[pResultInfo->current] + pResultInfo->pCol[i].pData;
|
||||
|
||||
pResultInfo->length[i] = varDataLen(pStart);
|
||||
|
@ -1961,8 +1960,8 @@ void doSetOneRowPtr(SReqResultInfo* pResultInfo) {
|
|||
}
|
||||
} else {
|
||||
if (!colDataIsNull_f(pCol->nullbitmap, pResultInfo->current)) {
|
||||
pResultInfo->row[i] = pResultInfo->pCol[i].pData + bytes * pResultInfo->current;
|
||||
pResultInfo->length[i] = bytes;
|
||||
pResultInfo->row[i] = pResultInfo->pCol[i].pData + schemaBytes * pResultInfo->current;
|
||||
pResultInfo->length[i] = schemaBytes;
|
||||
} else {
|
||||
pResultInfo->row[i] = NULL;
|
||||
pResultInfo->length[i] = 0;
|
||||
|
@ -1994,7 +1993,7 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4)
|
|||
}
|
||||
|
||||
pRequest->code =
|
||||
setQueryResultFromRsp(&pRequest->body.resInfo, (const SRetrieveTableRsp*)pResInfo->pData, convertUcs4);
|
||||
setQueryResultFromRsp(&pRequest->body.resInfo, (const SRetrieveTableRsp*)pResInfo->pData, convertUcs4, pRequest->isStmtBind);
|
||||
if (pRequest->code != TSDB_CODE_SUCCESS) {
|
||||
pResultInfo->numOfRows = 0;
|
||||
return NULL;
|
||||
|
@ -2013,7 +2012,7 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4)
|
|||
}
|
||||
|
||||
if (setupOneRowPtr) {
|
||||
doSetOneRowPtr(pResultInfo);
|
||||
doSetOneRowPtr(pResultInfo, pRequest->isStmtBind);
|
||||
pResultInfo->current += 1;
|
||||
}
|
||||
|
||||
|
@ -2060,7 +2059,7 @@ void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertU
|
|||
return NULL;
|
||||
} else {
|
||||
if (setupOneRowPtr) {
|
||||
doSetOneRowPtr(pResultInfo);
|
||||
doSetOneRowPtr(pResultInfo, pRequest->isStmtBind);
|
||||
pResultInfo->current += 1;
|
||||
}
|
||||
|
||||
|
@ -2087,14 +2086,14 @@ static int32_t doPrepareResPtr(SReqResultInfo* pResInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t* colLength) {
|
||||
static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t* colLength, bool isStmt) {
|
||||
int32_t idx = -1;
|
||||
iconv_t conv = taosAcquireConv(&idx, C2M, pResultInfo->charsetCxt);
|
||||
if (conv == (iconv_t)-1) return TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
|
||||
for (int32_t i = 0; i < pResultInfo->numOfCols; ++i) {
|
||||
int32_t type = pResultInfo->fields[i].type;
|
||||
int32_t bytes = pResultInfo->fields[i].bytes;
|
||||
int32_t schemaBytes = calcSchemaBytesFromTypeBytes(pResultInfo->fields[i].type, pResultInfo->fields[i].bytes, isStmt);
|
||||
|
||||
if (type == TSDB_DATA_TYPE_NCHAR && colLength[i] > 0) {
|
||||
char* p = taosMemoryRealloc(pResultInfo->convertBuf[i], colLength[i]);
|
||||
|
@ -2111,11 +2110,11 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t* colLength) {
|
|||
char* pStart = pCol->offset[j] + pCol->pData;
|
||||
|
||||
int32_t len = taosUcs4ToMbsEx((TdUcs4*)varDataVal(pStart), varDataLen(pStart), varDataVal(p), conv);
|
||||
if (len < 0 || len > bytes || (p + len) >= (pResultInfo->convertBuf[i] + colLength[i])) {
|
||||
if (len < 0 || len > schemaBytes || (p + len) >= (pResultInfo->convertBuf[i] + colLength[i])) {
|
||||
tscError(
|
||||
"doConvertUCS4 error, invalid data. len:%d, bytes:%d, (p + len):%p, (pResultInfo->convertBuf[i] + "
|
||||
"colLength[i]):%p",
|
||||
len, bytes, (p + len), (pResultInfo->convertBuf[i] + colLength[i]));
|
||||
len, schemaBytes, (p + len), (pResultInfo->convertBuf[i] + colLength[i]));
|
||||
taosReleaseConv(idx, conv, C2M, pResultInfo->charsetCxt);
|
||||
return TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -2134,6 +2133,36 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t* colLength) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t convertDecimalType(SReqResultInfo* pResultInfo) {
|
||||
for (int32_t i = 0; i < pResultInfo->numOfCols; ++i) {
|
||||
TAOS_FIELD_E* pField = pResultInfo->fields + i;
|
||||
int32_t type = pField->type;
|
||||
int32_t bufLen = 0;
|
||||
char* p = NULL;
|
||||
if (!IS_DECIMAL_TYPE(type) || !pResultInfo->pCol[i].pData) {
|
||||
continue;
|
||||
} else {
|
||||
bufLen = 64;
|
||||
p = taosMemoryRealloc(pResultInfo->convertBuf[i], bufLen * pResultInfo->numOfRows);
|
||||
pField->bytes = bufLen;
|
||||
}
|
||||
if (!p) return terrno;
|
||||
pResultInfo->convertBuf[i] = p;
|
||||
|
||||
for (int32_t j = 0; j < pResultInfo->numOfRows; ++j) {
|
||||
int32_t code = decimalToStr((DecimalWord*)(pResultInfo->pCol[i].pData + j * tDataTypes[type].bytes), type,
|
||||
pField->precision, pField->scale, p, bufLen);
|
||||
p += bufLen;
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
pResultInfo->pCol[i].pData = pResultInfo->convertBuf[i];
|
||||
pResultInfo->row[i] = pResultInfo->pCol[i].pData;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t getVersion1BlockMetaSize(const char* p, int32_t numOfCols) {
|
||||
return sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) * 3 + sizeof(uint64_t) +
|
||||
numOfCols * (sizeof(int8_t) + sizeof(int32_t));
|
||||
|
@ -2365,7 +2394,7 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4) {
|
||||
int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4, bool isStmt) {
|
||||
if (pResultInfo == NULL || pResultInfo->numOfCols <= 0 || pResultInfo->fields == NULL) {
|
||||
tscError("setResultDataPtr paras error");
|
||||
return TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
|
@ -2423,6 +2452,10 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4) {
|
|||
|
||||
int32_t bytes = *(int32_t*)p;
|
||||
p += sizeof(int32_t);
|
||||
|
||||
if (IS_DECIMAL_TYPE(type) && pResultInfo->fields[i].precision == 0) {
|
||||
extractDecimalTypeInfoFromBytes(&bytes, &pResultInfo->fields[i].precision, &pResultInfo->fields[i].scale);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t* colLength = (int32_t*)p;
|
||||
|
@ -2454,7 +2487,7 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4) {
|
|||
}
|
||||
|
||||
pResultInfo->pCol[i].pData = pStart;
|
||||
pResultInfo->length[i] = pResultInfo->fields[i].bytes;
|
||||
pResultInfo->length[i] = calcSchemaBytesFromTypeBytes(pResultInfo->fields[i].type, pResultInfo->fields[i].bytes, isStmt);
|
||||
pResultInfo->row[i] = pResultInfo->pCol[i].pData;
|
||||
|
||||
pStart += colLength[i];
|
||||
|
@ -2471,9 +2504,12 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, bool convertUcs4) {
|
|||
|
||||
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
|
||||
if (convertUcs4) {
|
||||
code = doConvertUCS4(pResultInfo, colLength);
|
||||
code = doConvertUCS4(pResultInfo, colLength, isStmt);
|
||||
}
|
||||
#endif
|
||||
if (TSDB_CODE_SUCCESS == code && convertUcs4) {
|
||||
code = convertDecimalType(pResultInfo);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -2514,7 +2550,7 @@ void resetConnectDB(STscObj* pTscObj) {
|
|||
(void)taosThreadMutexUnlock(&pTscObj->mutex);
|
||||
}
|
||||
|
||||
int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableRsp* pRsp, bool convertUcs4) {
|
||||
int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableRsp* pRsp, bool convertUcs4, bool isStmt) {
|
||||
if (pResultInfo == NULL || pRsp == NULL) {
|
||||
tscError("setQueryResultFromRsp paras is null");
|
||||
return TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
|
@ -2583,7 +2619,7 @@ int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableR
|
|||
// TODO handle the compressed case
|
||||
pResultInfo->totalRows += pResultInfo->numOfRows;
|
||||
|
||||
int32_t code = setResultDataPtr(pResultInfo, convertUcs4);
|
||||
int32_t code = setResultDataPtr(pResultInfo, convertUcs4, isStmt);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -3046,7 +3082,7 @@ static void fetchCallback(void* pResult, void* param, int32_t code) {
|
|||
}
|
||||
|
||||
pRequest->code =
|
||||
setQueryResultFromRsp(pResultInfo, (const SRetrieveTableRsp*)pResultInfo->pData, pResultInfo->convertUcs4);
|
||||
setQueryResultFromRsp(pResultInfo, (const SRetrieveTableRsp*)pResultInfo->pData, pResultInfo->convertUcs4, pRequest->isStmtBind);
|
||||
if (pRequest->code != TSDB_CODE_SUCCESS) {
|
||||
pResultInfo->numOfRows = 0;
|
||||
tscError("req:0x%" PRIx64 ", fetch results failed, code:%s, QID:0x%" PRIx64, pRequest->self, tstrerror(pRequest->code),
|
||||
|
|
|
@ -608,6 +608,14 @@ TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
|
|||
return taosQueryImplWithReqid(taos, sql, false, reqid);
|
||||
}
|
||||
|
||||
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
|
||||
if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
|
||||
return NULL;
|
||||
}
|
||||
SReqResultInfo* pResInfo = tscGetCurResInfo(res);
|
||||
return pResInfo->fields;
|
||||
}
|
||||
|
||||
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
|
@ -639,7 +647,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
|
|||
}
|
||||
|
||||
if (pResultInfo->current < pResultInfo->numOfRows) {
|
||||
doSetOneRowPtr(pResultInfo);
|
||||
doSetOneRowPtr(pResultInfo, false);
|
||||
pResultInfo->current += 1;
|
||||
return pResultInfo->row;
|
||||
} else {
|
||||
|
@ -647,7 +655,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
doSetOneRowPtr(pResultInfo);
|
||||
doSetOneRowPtr(pResultInfo, false);
|
||||
pResultInfo->current += 1;
|
||||
return pResultInfo->row;
|
||||
}
|
||||
|
@ -760,6 +768,14 @@ int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD
|
|||
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
uint32_t decimalLen = strlen(row[i]);
|
||||
uint32_t copyLen = TMIN(size - len - 1, decimalLen);
|
||||
(void)memcpy(str + len, row[i], copyLen);
|
||||
len += copyLen;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1269,7 +1285,7 @@ void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta
|
|||
}
|
||||
|
||||
if (pQuery->haveResultSet) {
|
||||
code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols);
|
||||
code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema, pRequest->isStmtBind);
|
||||
setResPrecision(&pRequest->body.resInfo, pQuery->precision);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -682,7 +682,7 @@ int32_t processShowVariablesRsp(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
code = buildShowVariablesRsp(rsp.variables, &pRes);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false);
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false, pRequest->isStmtBind);
|
||||
}
|
||||
|
||||
if (code != 0) {
|
||||
|
@ -837,7 +837,7 @@ int32_t processCompactDbRsp(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
code = buildRetriveTableRspForCompactDb(&rsp, &pRes);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false);
|
||||
code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false, pRequest->isStmtBind);
|
||||
}
|
||||
|
||||
if (code != 0) {
|
||||
|
|
|
@ -516,7 +516,7 @@ static void buildChildElement(cJSON* json, SVCreateTbReq* pCreateReq) {
|
|||
RAW_NULL_CHECK(tvalue);
|
||||
} else {
|
||||
double val = 0;
|
||||
GET_TYPED_DATA(val, double, pTagVal->type, &pTagVal->i64);
|
||||
GET_TYPED_DATA(val, double, pTagVal->type, &pTagVal->i64, 0); // currently tag type can't be decimal, so pass 0 as typeMod
|
||||
tvalue = cJSON_CreateNumber(val);
|
||||
RAW_NULL_CHECK(tvalue);
|
||||
}
|
||||
|
@ -1060,6 +1060,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, uint32_t metaLen) {
|
|||
SColCmpr* pCmp = &req.colCmpr.pColCmpr[i];
|
||||
field.compress = pCmp->alg;
|
||||
}
|
||||
if (req.pExtSchemas) field.typeMod = req.pExtSchemas[i].typeMod;
|
||||
RAW_NULL_CHECK(taosArrayPush(pReq.pColumns, &field));
|
||||
}
|
||||
pReq.pTags = taosArrayInit(req.schemaTag.nCols, sizeof(SField));
|
||||
|
@ -1974,10 +1975,11 @@ static bool needRefreshMeta(void* rawData, STableMeta* pTableMeta, SSchemaWrappe
|
|||
int j = 0;
|
||||
for (; j < pTableMeta->tableInfo.numOfColumns; j++) {
|
||||
SSchema* pColSchema = &pTableMeta->schema[j];
|
||||
SSchemaExt* pColExtSchema = &pTableMeta->schemaExt[j];
|
||||
char* fieldName = pSW->pSchema[i].name;
|
||||
|
||||
if (strcmp(pColSchema->name, fieldName) == 0) {
|
||||
if (checkSchema(pColSchema, fields, NULL, 0) != 0){
|
||||
if (checkSchema(pColSchema, pColExtSchema, fields, NULL, 0) != 0){
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -2714,4 +2716,4 @@ static int32_t tmqWriteBatchMetaDataImpl(TAOS* taos, void* meta, uint32_t metaLe
|
|||
end:
|
||||
tDeleteMqBatchMetaRsp(&rsp);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ int32_t stmtBackupQueryFields(STscStmt* pStmt) {
|
|||
|
||||
int32_t stmtRestoreQueryFields(STscStmt* pStmt) {
|
||||
SStmtQueryResInfo* pRes = &pStmt->sql.queryRes;
|
||||
int32_t size = pRes->numOfCols * sizeof(TAOS_FIELD);
|
||||
int32_t size = pRes->numOfCols * sizeof(TAOS_FIELD_E);
|
||||
|
||||
pStmt->exec.pRequest->body.resInfo.numOfCols = pRes->numOfCols;
|
||||
pStmt->exec.pRequest->body.resInfo.precision = pRes->precision;
|
||||
|
@ -1270,8 +1270,9 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
|
|||
|
||||
if (pStmt->sql.pQuery->haveResultSet) {
|
||||
STMT_ERR_RET(setResSchemaInfo(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->pResSchema,
|
||||
pStmt->sql.pQuery->numOfResCols));
|
||||
pStmt->sql.pQuery->numOfResCols, pStmt->sql.pQuery->pResExtSchema, true));
|
||||
taosMemoryFreeClear(pStmt->sql.pQuery->pResSchema);
|
||||
taosMemoryFreeClear(pStmt->sql.pQuery->pResExtSchema);
|
||||
setResPrecision(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->precision);
|
||||
}
|
||||
|
||||
|
@ -1861,7 +1862,7 @@ int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
|
|||
}
|
||||
|
||||
*type = pField[idx].type;
|
||||
*bytes = pField[idx].bytes;
|
||||
*bytes = calcSchemaBytesFromTypeBytes(pField[idx].type, pField[idx].bytes, true);
|
||||
|
||||
_return:
|
||||
|
||||
|
|
|
@ -1498,8 +1498,9 @@ int stmtBindBatch2(TAOS_STMT2* stmt, TAOS_STMT2_BIND* bind, int32_t colIdx, SVCr
|
|||
|
||||
if (pStmt->sql.pQuery->haveResultSet) {
|
||||
STMT_ERR_RET(setResSchemaInfo(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->pResSchema,
|
||||
pStmt->sql.pQuery->numOfResCols));
|
||||
pStmt->sql.pQuery->numOfResCols, pStmt->sql.pQuery->pResExtSchema, true));
|
||||
taosMemoryFreeClear(pStmt->sql.pQuery->pResSchema);
|
||||
taosMemoryFreeClear(pStmt->sql.pQuery->pResExtSchema);
|
||||
setResPrecision(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->precision);
|
||||
}
|
||||
|
||||
|
|
|
@ -3012,7 +3012,7 @@ int32_t tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4, SReqResultInfo** pRes
|
|||
doFreeReqResultInfo(&pRspObj->resInfo);
|
||||
SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(data->blockSchema, pRspObj->resIter);
|
||||
if (pSW) {
|
||||
TAOS_CHECK_RETURN(setResSchemaInfo(&pRspObj->resInfo, pSW->pSchema, pSW->nCols));
|
||||
TAOS_CHECK_RETURN(setResSchemaInfo(&pRspObj->resInfo, pSW->pSchema, pSW->nCols, NULL, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3028,7 +3028,7 @@ int32_t tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4, SReqResultInfo** pRes
|
|||
pRspObj->resInfo.precision = precision;
|
||||
|
||||
pRspObj->resInfo.totalRows += pRspObj->resInfo.numOfRows;
|
||||
int32_t code = setResultDataPtr(&pRspObj->resInfo, convertUcs4);
|
||||
int32_t code = setResultDataPtr(&pRspObj->resInfo, convertUcs4, false);
|
||||
if (code != 0) {
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -673,6 +673,7 @@ int32_t tSerializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pReq
|
|||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pField->bytes));
|
||||
TAOS_CHECK_EXIT(tEncodeCStr(&encoder, pField->name));
|
||||
TAOS_CHECK_EXIT(tEncodeU32(&encoder, pField->compress));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pField->typeMod));
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pReq->numOfTags; ++i) {
|
||||
|
@ -760,6 +761,7 @@ int32_t tDeserializeSMCreateStbReq(void *buf, int32_t bufLen, SMCreateStbReq *pR
|
|||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &field.bytes));
|
||||
TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, field.name));
|
||||
TAOS_CHECK_EXIT(tDecodeU32(&decoder, &field.compress));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &field.typeMod));
|
||||
if (taosArrayPush(pReq->pColumns, &field) == NULL) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
@ -922,6 +924,19 @@ int32_t tSerializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq)
|
|||
}
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pReq->keep));
|
||||
ENCODESQL();
|
||||
if (pReq->alterType == TSDB_ALTER_TABLE_ADD_COLUMN ||
|
||||
pReq->alterType == TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION) {
|
||||
if (taosArrayGetSize(pReq->pTypeMods) > 0) {
|
||||
int8_t hasTypeMod = 1;
|
||||
TAOS_CHECK_EXIT(tEncodeI8(&encoder, hasTypeMod));
|
||||
for (int32_t i = 0; i < pReq->pTypeMods->size; ++i) {
|
||||
const STypeMod *pTypeMod = taosArrayGet(pReq->pTypeMods, i);
|
||||
TAOS_CHECK_ERRNO(tEncodeI32(&encoder, *pTypeMod));
|
||||
}
|
||||
} else {
|
||||
TAOS_CHECK_EXIT(tEncodeI8(&encoder, 0));
|
||||
}
|
||||
}
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
|
@ -987,7 +1002,24 @@ int32_t tDeserializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq
|
|||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pReq->keep));
|
||||
}
|
||||
DECODESQL();
|
||||
|
||||
if (!tDecodeIsEnd(&decoder) && (pReq->alterType == TSDB_ALTER_TABLE_ADD_COLUMN ||
|
||||
pReq->alterType == TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION)) {
|
||||
int8_t hasTypeMod = 0;
|
||||
TAOS_CHECK_EXIT(tDecodeI8(&decoder, &hasTypeMod));
|
||||
if (hasTypeMod == 1) {
|
||||
pReq->pTypeMods = taosArrayInit(pReq->numOfFields, sizeof(STypeMod));
|
||||
if (!pReq->pTypeMods) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
for (int32_t i = 0; i < pReq->numOfFields; ++i) {
|
||||
STypeMod typeMod = 0;
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &typeMod));
|
||||
if (taosArrayPush(pReq->pTypeMods, &typeMod) == NULL) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tEndDecode(&decoder);
|
||||
|
||||
_exit:
|
||||
|
@ -1000,6 +1032,7 @@ void tFreeSMAltertbReq(SMAlterStbReq *pReq) {
|
|||
pReq->pFields = NULL;
|
||||
taosMemoryFreeClear(pReq->comment);
|
||||
FREESQL();
|
||||
taosArrayDestroy(pReq->pTypeMods);
|
||||
}
|
||||
|
||||
int32_t tSerializeSEpSet(void *buf, int32_t bufLen, const SEpSet *pEpset) {
|
||||
|
@ -3914,7 +3947,7 @@ int32_t tSerializeSTableCfgRsp(void *buf, int32_t bufLen, STableCfgRsp *pRsp) {
|
|||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pRsp->tagsLen));
|
||||
TAOS_CHECK_EXIT(tEncodeBinary(&encoder, pRsp->pTags, pRsp->tagsLen));
|
||||
|
||||
if (useCompress(pRsp->tableType)) {
|
||||
if (withExtSchema(pRsp->tableType)) {
|
||||
for (int32_t i = 0; i < pRsp->numOfColumns; ++i) {
|
||||
SSchemaExt *pSchemaExt = &pRsp->pSchemaExt[i];
|
||||
TAOS_CHECK_EXIT(tEncodeSSchemaExt(&encoder, pSchemaExt));
|
||||
|
@ -3990,7 +4023,7 @@ int32_t tDeserializeSTableCfgRsp(void *buf, int32_t bufLen, STableCfgRsp *pRsp)
|
|||
TAOS_CHECK_EXIT(tDecodeBinaryAlloc(&decoder, (void **)&pRsp->pTags, NULL));
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
if (useCompress(pRsp->tableType) && pRsp->numOfColumns > 0) {
|
||||
if (withExtSchema(pRsp->tableType) && pRsp->numOfColumns > 0) {
|
||||
pRsp->pSchemaExt = taosMemoryMalloc(sizeof(SSchemaExt) * pRsp->numOfColumns);
|
||||
if (pRsp->pSchemaExt == NULL) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
|
@ -6085,7 +6118,7 @@ static int32_t tEncodeSTableMetaRsp(SEncoder *pEncoder, STableMetaRsp *pRsp) {
|
|||
TAOS_CHECK_RETURN(tEncodeSSchema(pEncoder, pSchema));
|
||||
}
|
||||
|
||||
if (useCompress(pRsp->tableType)) {
|
||||
if (withExtSchema(pRsp->tableType)) {
|
||||
for (int32_t i = 0; i < pRsp->numOfColumns; ++i) {
|
||||
SSchemaExt *pSchemaExt = &pRsp->pSchemaExt[i];
|
||||
TAOS_CHECK_RETURN(tEncodeSSchemaExt(pEncoder, pSchemaExt));
|
||||
|
@ -6126,7 +6159,7 @@ static int32_t tDecodeSTableMetaRsp(SDecoder *pDecoder, STableMetaRsp *pRsp) {
|
|||
}
|
||||
|
||||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
if (useCompress(pRsp->tableType) && pRsp->numOfColumns > 0) {
|
||||
if (withExtSchema(pRsp->tableType) && pRsp->numOfColumns > 0) {
|
||||
pRsp->pSchemaExt = taosMemoryMalloc(sizeof(SSchemaExt) * pRsp->numOfColumns);
|
||||
if (pRsp->pSchemaExt == NULL) {
|
||||
TAOS_CHECK_RETURN(terrno);
|
||||
|
@ -10124,7 +10157,13 @@ int32_t tSerializeSCMCreateStreamReq(void *buf, int32_t bufLen, const SCMCreateS
|
|||
SFieldWithOptions *pField = taosArrayGet(pReq->pCols, i);
|
||||
TAOS_CHECK_EXIT(tEncodeI8(&encoder, pField->type));
|
||||
TAOS_CHECK_EXIT(tEncodeI8(&encoder, pField->flags));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pField->bytes));
|
||||
int32_t bytes = pField->bytes;
|
||||
if (IS_DECIMAL_TYPE(pField->type)) {
|
||||
uint8_t prec = 0, scale = 0;
|
||||
extractTypeFromTypeMod(pField->type, pField->typeMod, &prec, &scale, NULL);
|
||||
fillBytesForDecimalType(&bytes, pField->type, prec, scale);
|
||||
}
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, bytes));
|
||||
TAOS_CHECK_EXIT(tEncodeCStr(&encoder, pField->name));
|
||||
}
|
||||
|
||||
|
@ -10437,6 +10476,44 @@ _exit:
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t tEncodeSExtSchema(SEncoder* pCoder, const SExtSchema* pExtSchema) {
|
||||
int32_t code = 0, lino;
|
||||
TAOS_CHECK_EXIT(tEncodeI32v(pCoder, pExtSchema->typeMod));
|
||||
|
||||
_exit:
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tDecodeSExtSchema(SDecoder* pCoder, SExtSchema* pExtSchema) {
|
||||
int32_t code = 0, lino;
|
||||
TAOS_CHECK_EXIT(tDecodeI32v(pCoder, &pExtSchema->typeMod));
|
||||
|
||||
_exit:
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tEncodeSExtSchemas(SEncoder* pCoder, const SExtSchema* pExtSchemas, int32_t nCol) {
|
||||
int32_t code = 0, lino;
|
||||
for (int32_t i = 0; i < nCol; ++i) {
|
||||
TAOS_CHECK_EXIT(tEncodeSExtSchema(pCoder, pExtSchemas + i));
|
||||
}
|
||||
|
||||
_exit:
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tDecodeSExtSchemas(SDecoder* pCoder, SExtSchema** ppExtSchema, int32_t nCol) {
|
||||
int32_t code = 0, lino;
|
||||
*ppExtSchema = tDecoderMalloc(pCoder, sizeof(SExtSchema) * nCol);
|
||||
if (!*ppExtSchema) TAOS_CHECK_EXIT(terrno);
|
||||
for (int32_t i = 0; i < nCol; ++i) {
|
||||
TAOS_CHECK_EXIT(tDecodeSExtSchema(pCoder, (*ppExtSchema) + i));
|
||||
}
|
||||
|
||||
_exit:
|
||||
return code;
|
||||
}
|
||||
|
||||
int tEncodeSVCreateStbReq(SEncoder *pCoder, const SVCreateStbReq *pReq) {
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
|
@ -10461,6 +10538,12 @@ int tEncodeSVCreateStbReq(SEncoder *pCoder, const SVCreateStbReq *pReq) {
|
|||
TAOS_CHECK_EXIT(tEncodeI8(pCoder, pReq->colCmpred));
|
||||
TAOS_CHECK_EXIT(tEncodeSColCmprWrapper(pCoder, &pReq->colCmpr));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(pCoder, pReq->keep));
|
||||
if (pReq->pExtSchemas) {
|
||||
TAOS_CHECK_EXIT(tEncodeI8(pCoder, 1));
|
||||
TAOS_CHECK_EXIT(tEncodeSExtSchemas(pCoder, pReq->pExtSchemas, pReq->schemaRow.nCols));
|
||||
} else {
|
||||
TAOS_CHECK_EXIT(tEncodeI8(pCoder, 0));
|
||||
}
|
||||
tEndEncode(pCoder);
|
||||
|
||||
_exit:
|
||||
|
@ -10498,6 +10581,13 @@ int tDecodeSVCreateStbReq(SDecoder *pCoder, SVCreateStbReq *pReq) {
|
|||
if (!tDecodeIsEnd(pCoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeI64(pCoder, &pReq->keep));
|
||||
}
|
||||
if (!tDecodeIsEnd(pCoder)) {
|
||||
int8_t hasExtSchema = 0;
|
||||
TAOS_CHECK_EXIT(tDecodeI8(pCoder, &hasExtSchema));
|
||||
if (hasExtSchema) {
|
||||
TAOS_CHECK_EXIT(tDecodeSExtSchemas(pCoder, &pReq->pExtSchemas, pReq->schemaRow.nCols));
|
||||
}
|
||||
}
|
||||
}
|
||||
tEndDecode(pCoder);
|
||||
|
||||
|
@ -10547,6 +10637,12 @@ int tEncodeSVCreateTbReq(SEncoder *pCoder, const SVCreateTbReq *pReq) {
|
|||
// Encode Column Options: encode compress level
|
||||
if (pReq->type == TSDB_SUPER_TABLE || pReq->type == TSDB_NORMAL_TABLE) {
|
||||
TAOS_CHECK_EXIT(tEncodeSColCmprWrapper(pCoder, &pReq->colCmpr));
|
||||
if (pReq->pExtSchemas) {
|
||||
TAOS_CHECK_EXIT(tEncodeI8(pCoder, 1));
|
||||
TAOS_CHECK_EXIT(tEncodeSExtSchemas(pCoder, pReq->pExtSchemas, pReq->ntb.schemaRow.nCols));
|
||||
} else {
|
||||
TAOS_CHECK_EXIT(tEncodeI8(pCoder, 0));
|
||||
}
|
||||
}
|
||||
|
||||
tEndEncode(pCoder);
|
||||
|
@ -10611,6 +10707,14 @@ int tDecodeSVCreateTbReq(SDecoder *pCoder, SVCreateTbReq *pReq) {
|
|||
if (!tDecodeIsEnd(pCoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeSColCmprWrapperEx(pCoder, &pReq->colCmpr));
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(pCoder)) {
|
||||
int8_t hasExtSchema = 0;
|
||||
TAOS_CHECK_EXIT(tDecodeI8(pCoder, &hasExtSchema));
|
||||
if (hasExtSchema) {
|
||||
TAOS_CHECK_EXIT(tDecodeSExtSchemas(pCoder, &pReq->pExtSchemas, pReq->ntb.schemaRow.nCols));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tEndDecode(pCoder);
|
||||
|
@ -10968,6 +11072,9 @@ int32_t tEncodeSVAlterTbReq(SEncoder *pEncoder, const SVAlterTbReq *pReq) {
|
|||
}
|
||||
TAOS_CHECK_EXIT(tEncodeI64(pEncoder, pReq->ctimeMs));
|
||||
TAOS_CHECK_EXIT(tEncodeI8(pEncoder, pReq->source));
|
||||
if (pReq->action == TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION || pReq->action == TSDB_ALTER_TABLE_ADD_COLUMN) {
|
||||
TAOS_CHECK_EXIT(tEncodeI32(pEncoder, pReq->typeMod));
|
||||
}
|
||||
|
||||
tEndEncode(pEncoder);
|
||||
_exit:
|
||||
|
@ -11071,6 +11178,11 @@ int32_t tDecodeSVAlterTbReq(SDecoder *pDecoder, SVAlterTbReq *pReq) {
|
|||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeI8(pDecoder, &pReq->source));
|
||||
}
|
||||
if (pReq->action == TSDB_ALTER_TABLE_ADD_COLUMN || pReq->action == TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION) {
|
||||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeI32(pDecoder, &pReq->typeMod));
|
||||
}
|
||||
}
|
||||
|
||||
tEndDecode(pDecoder);
|
||||
_exit:
|
||||
|
@ -11250,7 +11362,7 @@ int32_t tEncodeSTqOffsetVal(SEncoder *pEncoder, const STqOffsetVal *pOffsetVal)
|
|||
if (IS_VAR_DATA_TYPE(pOffsetVal->primaryKey.type)) {
|
||||
TAOS_CHECK_EXIT(tEncodeBinary(pEncoder, pOffsetVal->primaryKey.pData, pOffsetVal->primaryKey.nData));
|
||||
} else {
|
||||
TAOS_CHECK_EXIT(tEncodeI64(pEncoder, pOffsetVal->primaryKey.val));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(pEncoder, VALUE_GET_TRIVIAL_DATUM(&pOffsetVal->primaryKey)));
|
||||
}
|
||||
|
||||
} else if (pOffsetVal->type == TMQ_OFFSET__LOG) {
|
||||
|
@ -11281,7 +11393,7 @@ int32_t tDecodeSTqOffsetVal(SDecoder *pDecoder, STqOffsetVal *pOffsetVal) {
|
|||
TAOS_CHECK_EXIT(
|
||||
tDecodeBinaryAlloc32(pDecoder, (void **)&pOffsetVal->primaryKey.pData, &pOffsetVal->primaryKey.nData));
|
||||
} else {
|
||||
TAOS_CHECK_EXIT(tDecodeI64(pDecoder, &pOffsetVal->primaryKey.val));
|
||||
TAOS_CHECK_EXIT(tDecodeI64(pDecoder, &VALUE_GET_TRIVIAL_DATUM(&pOffsetVal->primaryKey)));
|
||||
}
|
||||
}
|
||||
} else if (pOffsetVal->type == TMQ_OFFSET__LOG) {
|
||||
|
@ -11312,7 +11424,7 @@ void tFormatOffset(char *buf, int32_t maxLen, const STqOffsetVal *pVal) {
|
|||
taosMemoryFree(tmp);
|
||||
} else {
|
||||
(void)snprintf(buf, maxLen, "tsdb:%" PRId64 "|%" PRId64 ",pk type:%d,val:%" PRId64, pVal->uid, pVal->ts,
|
||||
pVal->primaryKey.type, pVal->primaryKey.val);
|
||||
pVal->primaryKey.type, VALUE_GET_TRIVIAL_DATUM(&pVal->primaryKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11694,7 +11806,7 @@ void tDeleteMqDataRsp(SMqDataRsp *rsp) { tDeleteMqDataRspCommon(rsp); }
|
|||
|
||||
int32_t tEncodeSTaosxRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
int32_t lino = 0;
|
||||
|
||||
TAOS_CHECK_EXIT(tEncodeMqDataRspCommon(pEncoder, pRsp));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(pEncoder, pRsp->createTableNum));
|
||||
|
@ -11736,7 +11848,6 @@ int32_t tDecodeSTaosxRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
_exit:
|
||||
return code;
|
||||
}
|
||||
|
@ -13403,3 +13514,7 @@ void tDeleteMqBatchMetaRsp(SMqBatchMetaRsp *pRsp) {
|
|||
pRsp->batchMetaReq = NULL;
|
||||
pRsp->batchMetaLen = NULL;
|
||||
}
|
||||
|
||||
bool hasExtSchema(const SExtSchema *pExtSchema) {
|
||||
return pExtSchema->typeMod != 0;
|
||||
}
|
|
@ -62,8 +62,9 @@ uint8_t getDefaultEncode(uint8_t type) {
|
|||
return TSDB_COLVAL_ENCODE_DISABLED;
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
return TSDB_COLVAL_ENCODE_DISABLED;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
return TSDB_COLVAL_ENCODE_DELTAD;
|
||||
return TSDB_COLVAL_ENCODE_DISABLED;
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
return TSDB_COLVAL_ENCODE_SIMPLE8B;
|
||||
case TSDB_DATA_TYPE_MEDIUMBLOB:
|
||||
|
@ -110,8 +111,9 @@ uint16_t getDefaultCompress(uint8_t type) {
|
|||
return TSDB_COLVAL_COMPRESS_LZ4;
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
return TSDB_COLVAL_COMPRESS_ZSTD;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
return TSDB_COLVAL_COMPRESS_LZ4;
|
||||
return TSDB_COLVAL_COMPRESS_ZSTD;
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
return TSDB_COLVAL_COMPRESS_LZ4;
|
||||
case TSDB_DATA_TYPE_MEDIUMBLOB:
|
||||
|
@ -348,7 +350,7 @@ int32_t setColCompressByOption(uint8_t type, uint8_t encode, uint16_t compressTy
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
bool useCompress(uint8_t tableType) {
|
||||
bool withExtSchema(uint8_t tableType) {
|
||||
return TSDB_SUPER_TABLE == tableType || TSDB_NORMAL_TABLE == tableType || TSDB_CHILD_TABLE == tableType;
|
||||
}
|
||||
|
||||
|
@ -413,6 +415,8 @@ int8_t validColEncode(uint8_t type, uint8_t l1) {
|
|||
return TSDB_COLVAL_ENCODE_SIMPLE8B == l1 || TSDB_COLVAL_ENCODE_XOR == l1 ? 1 : 0;
|
||||
} else if (type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return 1;
|
||||
} else if (type == TSDB_DATA_TYPE_DECIMAL64 || type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
return l1 == TSDB_COLVAL_ENCODE_DISABLED ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -725,10 +725,13 @@ int32_t blockDataUpdatePkRange(SSDataBlock* pDataBlock, int32_t pkColumnIndex, b
|
|||
void* skey = colDataGetData(pColInfoData, 0);
|
||||
void* ekey = colDataGetData(pColInfoData, (pInfo->rows - 1));
|
||||
|
||||
int64_t val = 0;
|
||||
if (asc) {
|
||||
if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
|
||||
GET_TYPED_DATA(pInfo->pks[0].val, int64_t, pColInfoData->info.type, skey);
|
||||
GET_TYPED_DATA(pInfo->pks[1].val, int64_t, pColInfoData->info.type, ekey);
|
||||
GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
|
||||
GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
|
||||
} else { // todo refactor
|
||||
memcpy(pInfo->pks[0].pData, varDataVal(skey), varDataLen(skey));
|
||||
pInfo->pks[0].nData = varDataLen(skey);
|
||||
|
@ -738,8 +741,10 @@ int32_t blockDataUpdatePkRange(SSDataBlock* pDataBlock, int32_t pkColumnIndex, b
|
|||
}
|
||||
} else {
|
||||
if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
|
||||
GET_TYPED_DATA(pInfo->pks[0].val, int64_t, pColInfoData->info.type, ekey);
|
||||
GET_TYPED_DATA(pInfo->pks[1].val, int64_t, pColInfoData->info.type, skey);
|
||||
GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
|
||||
GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
|
||||
} else { // todo refactor
|
||||
memcpy(pInfo->pks[0].pData, varDataVal(ekey), varDataLen(ekey));
|
||||
pInfo->pks[0].nData = varDataLen(ekey);
|
||||
|
@ -2803,7 +2808,9 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDat
|
|||
terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||
return terrno;
|
||||
}
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, ((SValue){.type = pCol->type, .val = *(TSKEY*)var}));
|
||||
SValue val = {.type = pCol->type};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, *(TSKEY*)var);
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, val);
|
||||
void* px = taosArrayPush(pVals, &cv);
|
||||
if (px == NULL) {
|
||||
return terrno;
|
||||
|
@ -2816,7 +2823,9 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDat
|
|||
return terrno;
|
||||
}
|
||||
} else {
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, ((SValue){.type = pCol->type, .val = *(int64_t*)var}));
|
||||
SValue val = {.type = pCol->type};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, *(int64_t*)var);
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, val);
|
||||
void* px = taosArrayPush(pVals, &cv);
|
||||
if (px == NULL) {
|
||||
return terrno;
|
||||
|
@ -2869,31 +2878,31 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDat
|
|||
} else {
|
||||
SValue sv = {.type = pCol->type};
|
||||
if (pCol->type == pColInfoData->info.type) {
|
||||
memcpy(&sv.val, var, tDataTypes[pCol->type].bytes);
|
||||
valueSetDatum(&sv, sv.type, var, tDataTypes[pCol->type].bytes);
|
||||
} else {
|
||||
/**
|
||||
* 1. sum/avg would convert to int64_t/uint64_t/double during aggregation
|
||||
* 2. below conversion may lead to overflow or loss, the app should select the right data type.
|
||||
*/
|
||||
char tv[8] = {0};
|
||||
char tv[DATUM_MAX_SIZE] = {0};
|
||||
if (pColInfoData->info.type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float v = 0;
|
||||
GET_TYPED_DATA(v, float, pColInfoData->info.type, var);
|
||||
GET_TYPED_DATA(v, float, pColInfoData->info.type, var, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
SET_TYPED_DATA(&tv, pCol->type, v);
|
||||
} else if (pColInfoData->info.type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, pColInfoData->info.type, var);
|
||||
GET_TYPED_DATA(v, double, pColInfoData->info.type, var, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
SET_TYPED_DATA(&tv, pCol->type, v);
|
||||
} else if (IS_SIGNED_NUMERIC_TYPE(pColInfoData->info.type)) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var);
|
||||
GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
SET_TYPED_DATA(&tv, pCol->type, v);
|
||||
} else {
|
||||
uint64_t v = 0;
|
||||
GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var);
|
||||
GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var, typeGetTypeModFromColInfo(&pColInfoData->info));
|
||||
SET_TYPED_DATA(&tv, pCol->type, v);
|
||||
}
|
||||
memcpy(&sv.val, tv, tDataTypes[pCol->type].bytes);
|
||||
valueSetDatum(&sv, sv.type, tv, tDataTypes[pCol->type].bytes);
|
||||
}
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
|
||||
void* px = taosArrayPush(pVals, &cv);
|
||||
|
@ -3187,7 +3196,12 @@ 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)) {
|
||||
fillBytesForDecimalType((int32_t*)data, pColInfoData->info.type, pColInfoData->info.precision,
|
||||
pColInfoData->info.scale);
|
||||
}
|
||||
data += sizeof(int32_t);
|
||||
}
|
||||
|
||||
|
@ -3328,6 +3342,10 @@ int32_t blockDecode(SSDataBlock* pBlock, const char* pData, const char** pEndPos
|
|||
pStart += sizeof(int8_t);
|
||||
|
||||
pColInfoData->info.bytes = *(int32_t*)pStart;
|
||||
if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
|
||||
extractDecimalTypeInfoFromBytes(&pColInfoData->info.bytes, &pColInfoData->info.precision,
|
||||
&pColInfoData->info.scale);
|
||||
}
|
||||
pStart += sizeof(int32_t);
|
||||
|
||||
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
|
||||
|
@ -3574,6 +3592,22 @@ int32_t trimDataBlock(SSDataBlock* pBlock, int32_t totalRows, const bool* pBoolL
|
|||
j += 1;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
while (j < totalRows) {
|
||||
if (pBoolList[j] == 0) {
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
if (colDataIsNull_f(pBitmap, j)) {
|
||||
colDataSetNull_f(pDst->nullbitmap, numOfRows);
|
||||
} else {
|
||||
memcpy(pDst->pData + numOfRows * pDst->info.bytes, pDst->pData + j * pDst->info.bytes, pDst->info.bytes);
|
||||
}
|
||||
numOfRows += 1;
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3700,12 +3734,14 @@ int32_t blockDataCheck(const SSDataBlock* pDataBlock) {
|
|||
} else {
|
||||
if (TSDB_DATA_TYPE_FLOAT == pCol->info.type) {
|
||||
float v = 0;
|
||||
GET_TYPED_DATA(v, float, pCol->info.type, colDataGetNumData(pCol, r));
|
||||
GET_TYPED_DATA(v, float, pCol->info.type, colDataGetNumData(pCol, r), typeGetTypeModFromColInfo(&pCol->info));
|
||||
} else if (TSDB_DATA_TYPE_DOUBLE == pCol->info.type) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, pCol->info.type, colDataGetNumData(pCol, r));
|
||||
GET_TYPED_DATA(v, double, pCol->info.type, colDataGetNumData(pCol, r), typeGetTypeModFromColInfo(&pCol->info));
|
||||
} else if (IS_DECIMAL_TYPE(pCol->info.type)) {
|
||||
// SKIP for decimal types
|
||||
} else {
|
||||
GET_TYPED_DATA(typeValue, int64_t, pCol->info.type, colDataGetNumData(pCol, r));
|
||||
GET_TYPED_DATA(typeValue, int64_t, pCol->info.type, colDataGetNumData(pCol, r), typeGetTypeModFromColInfo(&pCol->info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "tRealloc.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tlog.h"
|
||||
#include "decimal.h"
|
||||
|
||||
static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData);
|
||||
static int32_t (*tColDataUpdateValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward);
|
||||
|
@ -277,7 +278,7 @@ static int32_t tRowBuildTupleRow(SArray *aColVal, const SRowBuildScanInfo *sinfo
|
|||
(*ppRow)->numOfPKs = sinfo->numOfPKs;
|
||||
(*ppRow)->sver = schema->version;
|
||||
(*ppRow)->len = sinfo->tupleRowSize;
|
||||
(*ppRow)->ts = colValArray[0].value.val;
|
||||
(*ppRow)->ts = VALUE_GET_TRIVIAL_DATUM(&colValArray[0].value);
|
||||
|
||||
if (sinfo->tupleFlag == HAS_NONE || sinfo->tupleFlag == HAS_NULL) {
|
||||
return 0;
|
||||
|
@ -315,7 +316,8 @@ static int32_t tRowBuildTupleRow(SArray *aColVal, const SRowBuildScanInfo *sinfo
|
|||
varlen += colValArray[colValIndex].value.nData;
|
||||
}
|
||||
} else {
|
||||
(void)memcpy(fixed + schema->columns[i].offset, &colValArray[colValIndex].value.val,
|
||||
(void)memcpy(fixed + schema->columns[i].offset,
|
||||
VALUE_GET_DATUM(&colValArray[colValIndex].value, schema->columns[i].type),
|
||||
tDataTypes[schema->columns[i].type].bytes);
|
||||
}
|
||||
} else if (COL_VAL_IS_NULL(&colValArray[colValIndex])) { // NULL
|
||||
|
@ -360,7 +362,7 @@ static int32_t tRowBuildKVRow(SArray *aColVal, const SRowBuildScanInfo *sinfo, c
|
|||
(*ppRow)->numOfPKs = sinfo->numOfPKs;
|
||||
(*ppRow)->sver = schema->version;
|
||||
(*ppRow)->len = sinfo->kvRowSize;
|
||||
(*ppRow)->ts = colValArray[0].value.val;
|
||||
(*ppRow)->ts = VALUE_GET_TRIVIAL_DATUM(&colValArray[0].value);
|
||||
|
||||
if (!(sinfo->flag != HAS_NONE && sinfo->flag != HAS_NULL)) {
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
|
@ -397,7 +399,7 @@ static int32_t tRowBuildKVRow(SArray *aColVal, const SRowBuildScanInfo *sinfo, c
|
|||
payloadSize += colValArray[colValIndex].value.nData;
|
||||
} else {
|
||||
payloadSize += tPutI16v(payload + payloadSize, colValArray[colValIndex].cid);
|
||||
(void)memcpy(payload + payloadSize, &colValArray[colValIndex].value.val,
|
||||
(void)memcpy(payload + payloadSize, VALUE_GET_DATUM(&colValArray[colValIndex].value, schema->columns[i].type),
|
||||
tDataTypes[schema->columns[i].type].bytes);
|
||||
payloadSize += tDataTypes[schema->columns[i].type].bytes;
|
||||
}
|
||||
|
@ -490,8 +492,9 @@ int32_t tRowBuildFromBind(SBindInfo *infos, int32_t numOfInfos, bool infoSorted,
|
|||
}
|
||||
value.pData = (uint8_t *)infos[iInfo].bind->buffer + infos[iInfo].bind->buffer_length * iRow;
|
||||
} else {
|
||||
(void)memcpy(&value.val, (uint8_t *)infos[iInfo].bind->buffer + infos[iInfo].bind->buffer_length * iRow,
|
||||
infos[iInfo].bind->buffer_length);
|
||||
valueSetDatum(&value, infos[iInfo].type,
|
||||
(uint8_t *)infos[iInfo].bind->buffer + infos[iInfo].bind->buffer_length * iRow,
|
||||
infos[iInfo].bind->buffer_length);
|
||||
}
|
||||
colVal = COL_VAL_VALUE(infos[iInfo].columnId, value);
|
||||
}
|
||||
|
@ -543,7 +546,7 @@ int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal)
|
|||
pColVal->cid = pTColumn->colId;
|
||||
pColVal->value.type = pTColumn->type;
|
||||
pColVal->flag = CV_FLAG_VALUE;
|
||||
(void)memcpy(&pColVal->value.val, &pRow->ts, sizeof(TSKEY));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pColVal->value, pRow->ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -607,7 +610,7 @@ int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal)
|
|||
pColVal->value.pData = NULL;
|
||||
}
|
||||
} else {
|
||||
(void)memcpy(&pColVal->value.val, pData, pTColumn->bytes);
|
||||
valueSetDatum(&pColVal->value, pTColumn->type, pData, pTColumn->bytes);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -658,7 +661,7 @@ int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal)
|
|||
pColVal->value.pData = varlen + *(int32_t *)(fixed + pTColumn->offset);
|
||||
pColVal->value.pData += tGetU32v(pColVal->value.pData, &pColVal->value.nData);
|
||||
} else {
|
||||
(void)memcpy(&pColVal->value.val, fixed + pTColumn->offset, TYPE_BYTES[pTColumn->type]);
|
||||
valueSetDatum(&pColVal->value, pTColumn->type, fixed + pTColumn->offset, TYPE_BYTES[pTColumn->type]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -902,7 +905,7 @@ SColVal *tRowIterNext(SRowIter *pIter) {
|
|||
pIter->cv.cid = pTColumn->colId;
|
||||
pIter->cv.value.type = pTColumn->type;
|
||||
pIter->cv.flag = CV_FLAG_VALUE;
|
||||
(void)memcpy(&pIter->cv.value.val, &pIter->pRow->ts, sizeof(TSKEY));
|
||||
VALUE_SET_TRIVIAL_DATUM(&pIter->cv.value, pIter->pRow->ts);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
|
@ -947,7 +950,7 @@ SColVal *tRowIterNext(SRowIter *pIter) {
|
|||
pIter->cv.value.pData = NULL;
|
||||
}
|
||||
} else {
|
||||
(void)memcpy(&pIter->cv.value.val, pData, pTColumn->bytes);
|
||||
valueSetDatum(&pIter->cv.value, pTColumn->type, pData, pTColumn->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1006,7 +1009,7 @@ SColVal *tRowIterNext(SRowIter *pIter) {
|
|||
pIter->cv.value.pData = NULL;
|
||||
}
|
||||
} else {
|
||||
(void)memcpy(&pIter->cv.value.val, pIter->pf + pTColumn->offset, TYPE_BYTES[pTColumn->type]);
|
||||
valueSetDatum(&pIter->cv.value, pTColumn->type, pIter->pf + pTColumn->offset, TYPE_BYTES[pTColumn->type]);
|
||||
}
|
||||
goto _exit;
|
||||
}
|
||||
|
@ -1326,7 +1329,7 @@ void tRowGetPrimaryKey(SRow *row, SRowKey *key) {
|
|||
key->pks[i].pData = tdata;
|
||||
key->pks[i].pData += tGetU32v(key->pks[i].pData, &key->pks[i].nData);
|
||||
} else {
|
||||
(void)memcpy(&key->pks[i].val, tdata, tDataTypes[indices[i].type].bytes);
|
||||
valueSetDatum(key->pks + i, indices[i].type, tdata, tDataTypes[indices[i].type].bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1346,26 +1349,26 @@ int32_t tValueCompare(const SValue *tv1, const SValue *tv2) {
|
|||
switch (tv1->type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
T_COMPARE_SCALAR_VALUE(int8_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(int8_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
T_COMPARE_SCALAR_VALUE(int16_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(int16_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
T_COMPARE_SCALAR_VALUE(int32_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(int32_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
T_COMPARE_SCALAR_VALUE(int64_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(int64_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
T_COMPARE_SCALAR_VALUE(float, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(float, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
T_COMPARE_SCALAR_VALUE(double, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(double, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
T_COMPARE_SCALAR_VALUE(uint8_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(uint8_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
T_COMPARE_SCALAR_VALUE(uint16_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(uint16_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
T_COMPARE_SCALAR_VALUE(uint32_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(uint32_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
T_COMPARE_SCALAR_VALUE(uint64_t, &tv1->val, &tv2->val);
|
||||
T_COMPARE_SCALAR_VALUE(uint64_t, &VALUE_GET_TRIVIAL_DATUM(tv1), &VALUE_GET_TRIVIAL_DATUM(tv2));
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
int32_t ret = strncmp((const char *)tv1->pData, (const char *)tv2->pData, TMIN(tv1->nData, tv2->nData));
|
||||
|
@ -1420,12 +1423,7 @@ void tRowKeyAssign(SRowKey *pDst, SRowKey *pSrc) {
|
|||
SValue *pVal = &pDst->pks[i];
|
||||
pVal->type = pSrc->pks[i].type;
|
||||
|
||||
if (IS_NUMERIC_TYPE(pVal->type)) {
|
||||
pVal->val = pSrc->pks[i].val;
|
||||
} else {
|
||||
pVal->nData = pSrc->pks[i].nData;
|
||||
(void)memcpy(pVal->pData, pSrc->pks[i].pData, pVal->nData);
|
||||
}
|
||||
valueCloneDatum(pVal, pSrc->pks + i, pVal->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2267,8 +2265,7 @@ int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) {
|
|||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
return tColDataAppendValueImpl[pColData->flag][pColVal->flag](
|
||||
pColData, IS_VAR_DATA_TYPE(pColData->type) ? pColVal->value.pData : (uint8_t *)&pColVal->value.val,
|
||||
pColVal->value.nData);
|
||||
pColData, VALUE_GET_DATUM(&pColVal->value, pColData->type), pColVal->value.nData);
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tColDataUpdateValue10(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) {
|
||||
|
@ -2581,8 +2578,7 @@ int32_t tColDataUpdateValue(SColData *pColData, SColVal *pColVal, bool forward)
|
|||
if (tColDataUpdateValueImpl[pColData->flag][pColVal->flag] == NULL) return 0;
|
||||
|
||||
return tColDataUpdateValueImpl[pColData->flag][pColVal->flag](
|
||||
pColData, IS_VAR_DATA_TYPE(pColData->type) ? pColVal->value.pData : (uint8_t *)&pColVal->value.val,
|
||||
pColVal->value.nData, forward);
|
||||
pColData, VALUE_GET_DATUM(&pColVal->value, pColData->type), pColVal->value.nData, forward);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataGetValue1(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NONE
|
||||
|
@ -2614,8 +2610,8 @@ static FORCE_INLINE void tColDataGetValue4(SColData *pColData, int32_t iVal, SCo
|
|||
}
|
||||
value.pData = pColData->pData + pColData->aOffset[iVal];
|
||||
} else {
|
||||
(void)memcpy(&value.val, pColData->pData + tDataTypes[pColData->type].bytes * iVal,
|
||||
tDataTypes[pColData->type].bytes);
|
||||
valueSetDatum(&value, pColData->type, pColData->pData + tDataTypes[pColData->type].bytes * iVal,
|
||||
tDataTypes[pColData->type].bytes);
|
||||
}
|
||||
*pColVal = COL_VAL_VALUE(pColData->cid, value);
|
||||
}
|
||||
|
@ -3323,9 +3319,7 @@ int32_t tRowBuildFromBind2(SBindInfo2 *infos, int32_t numOfInfos, bool infoSorte
|
|||
if (TSDB_DATA_TYPE_BOOL == value.type && *val > 1) {
|
||||
*val = 1;
|
||||
}
|
||||
(void)memcpy(&value.val, val,
|
||||
/*(uint8_t *)infos[iInfo].bind->buffer + infos[iInfo].bind->buffer_length * iRow,*/
|
||||
infos[iInfo].bytes /*bind->buffer_length*/);
|
||||
valueSetDatum(&value, infos[iInfo].type, val, infos[iInfo].bytes);
|
||||
}
|
||||
colVal = COL_VAL_VALUE(infos[iInfo].columnId, value);
|
||||
}
|
||||
|
@ -3839,8 +3833,9 @@ int32_t tDecodeRow(SDecoder *pDecoder, SRow **ppRow) {
|
|||
if ((MIN) > (VAL)) (MIN) = (VAL); \
|
||||
} while (0)
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t*numOfNull = &pAggs->numOfNull;
|
||||
*sum = 0;
|
||||
*max = 0;
|
||||
*min = 1;
|
||||
|
@ -3870,8 +3865,9 @@ static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, int64_t *sum, i
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*sum = 0;
|
||||
*max = INT8_MIN;
|
||||
*min = INT8_MAX;
|
||||
|
@ -3901,8 +3897,9 @@ static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, int64_t *sum
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*sum = 0;
|
||||
*max = INT16_MIN;
|
||||
*min = INT16_MAX;
|
||||
|
@ -3932,8 +3929,9 @@ static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, int64_t
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*sum = 0;
|
||||
*max = INT32_MIN;
|
||||
*min = INT32_MAX;
|
||||
|
@ -3963,8 +3961,9 @@ static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, int64_t *sum, in
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*sum = 0;
|
||||
*max = INT64_MIN;
|
||||
*min = INT64_MAX;
|
||||
|
@ -3994,8 +3993,9 @@ static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, int64_t *sum,
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(double *)sum = 0;
|
||||
*(double *)max = -FLT_MAX;
|
||||
*(double *)min = FLT_MAX;
|
||||
|
@ -4025,8 +4025,9 @@ static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, int64_t *sum,
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(double *)sum = 0;
|
||||
*(double *)max = -DBL_MAX;
|
||||
*(double *)min = DBL_MAX;
|
||||
|
@ -4056,8 +4057,9 @@ static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, int64_t *sum,
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(uint64_t *)sum = 0;
|
||||
*(uint64_t *)max = 0;
|
||||
*(uint64_t *)min = UINT8_MAX;
|
||||
|
@ -4087,8 +4089,9 @@ static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, int64_t *su
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(uint64_t *)sum = 0;
|
||||
*(uint64_t *)max = 0;
|
||||
*(uint64_t *)min = UINT16_MAX;
|
||||
|
@ -4118,8 +4121,9 @@ static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, int64_
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(uint64_t *)sum = 0;
|
||||
*(uint64_t *)max = 0;
|
||||
*(uint64_t *)min = UINT32_MAX;
|
||||
|
@ -4149,8 +4153,9 @@ static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, int64_t *sum, i
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(uint64_t *)sum = 0;
|
||||
*(uint64_t *)max = 0;
|
||||
*(uint64_t *)min = UINT64_MAX;
|
||||
|
@ -4180,8 +4185,9 @@ static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, int64_t *sum
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min,
|
||||
int16_t *numOfNull) {
|
||||
static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, SColumnDataAgg* pAggs) {
|
||||
int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min;
|
||||
int16_t *numOfNull = &pAggs->numOfNull;
|
||||
*(uint64_t *)sum = 0;
|
||||
*(uint64_t *)max = 0;
|
||||
*(uint64_t *)min = 0;
|
||||
|
@ -4216,7 +4222,90 @@ static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, int64_t *sum
|
|||
}
|
||||
}
|
||||
|
||||
void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, int16_t *numOfNull) = {
|
||||
#define CALC_DECIMAL_SUM_MAX_MIN(TYPE, pSumOp, pCompOp, pColData, pSum, pMax, pMin) \
|
||||
do { \
|
||||
if (decimal128AddCheckOverflow((Decimal *)pSum, pVal, DECIMAL_WORD_NUM(TYPE))) *pOverflow = true; \
|
||||
pSumOp->add(pSum, pVal, DECIMAL_WORD_NUM(TYPE)); \
|
||||
if (pCompOp->gt(pVal, pMax, DECIMAL_WORD_NUM(TYPE))) { \
|
||||
*(pMax) = *pVal; \
|
||||
} \
|
||||
if (pCompOp->lt(pVal, pMin, DECIMAL_WORD_NUM(TYPE))) { \
|
||||
*(pMin) = *pVal; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMADecimal64Type(SColData* pColData, SColumnDataAgg* pAggs) {
|
||||
Decimal128 *pSum = (Decimal128 *)pAggs->decimal128Sum;
|
||||
Decimal64 *pMax = (Decimal64 *)pAggs->decimal128Max, *pMin = (Decimal64 *)pAggs->decimal128Min;
|
||||
uint8_t *pOverflow = &pAggs->overflow;
|
||||
*pSum = DECIMAL128_ZERO;
|
||||
*pMax = DECIMAL64_MIN;
|
||||
*pMin = DECIMAL64_MAX;
|
||||
pAggs->numOfNull = 0;
|
||||
pAggs->colId |= DECIMAL_AGG_FLAG;
|
||||
|
||||
Decimal64 *pVal = NULL;
|
||||
const SDecimalOps *pSumOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
const SDecimalOps *pCompOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
|
||||
if (HAS_VALUE == pColData->flag) {
|
||||
for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) {
|
||||
pVal = ((Decimal64*)pColData->pData) + iVal;
|
||||
CALC_DECIMAL_SUM_MAX_MIN(Decimal64, pSumOps, pCompOps, pColData, pSum, pMax, pMin);
|
||||
}
|
||||
} else {
|
||||
for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) {
|
||||
switch (tColDataGetBitValue(pColData, iVal)) {
|
||||
case 0:
|
||||
case 1:
|
||||
pAggs->numOfNull++;
|
||||
break;
|
||||
case 2:
|
||||
pVal = ((Decimal64 *)pColData->pData) + iVal;
|
||||
CALC_DECIMAL_SUM_MAX_MIN(Decimal64, pSumOps, pCompOps, pColData, pSum, pMax, pMin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tColDataCalcSMADecimal128Type(SColData* pColData, SColumnDataAgg* pAggs) {
|
||||
Decimal128 *pSum = (Decimal128 *)pAggs->decimal128Sum, *pMax = (Decimal128 *)pAggs->decimal128Max,
|
||||
*pMin = (Decimal128 *)pAggs->decimal128Min;
|
||||
uint8_t *pOverflow = &pAggs->overflow;
|
||||
*pSum = DECIMAL128_ZERO;
|
||||
*pMax = DECIMAL128_MIN;
|
||||
*pMin = DECIMAL128_MAX;
|
||||
pAggs->numOfNull = 0;
|
||||
pAggs->colId |= DECIMAL_AGG_FLAG;
|
||||
|
||||
Decimal128 *pVal = NULL;
|
||||
const SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
if (HAS_VALUE == pColData->flag) {
|
||||
for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) {
|
||||
pVal = ((Decimal128*)pColData->pData) + iVal;
|
||||
CALC_DECIMAL_SUM_MAX_MIN(Decimal128, pOps, pOps, pColData, pSum, pMax, pMin);
|
||||
}
|
||||
} else {
|
||||
for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) {
|
||||
switch (tColDataGetBitValue(pColData, iVal)) {
|
||||
case 0:
|
||||
case 1:
|
||||
pAggs->numOfNull++;
|
||||
break;
|
||||
case 2:
|
||||
pVal = ((Decimal128*)pColData->pData) + iVal;
|
||||
CALC_DECIMAL_SUM_MAX_MIN(Decimal128, pOps, pOps, pColData, pSum, pMax, pMin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void (*tColDataCalcSMA[])(SColData *pColData, SColumnDataAgg* pAggs) = {
|
||||
NULL,
|
||||
tColDataCalcSMABool, // TSDB_DATA_TYPE_BOOL
|
||||
tColDataCalcSMATinyInt, // TSDB_DATA_TYPE_TINYINT
|
||||
|
@ -4234,10 +4323,11 @@ void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_
|
|||
tColDataCalcSMAUBigInt, // TSDB_DATA_TYPE_UBIGINT
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_JSON
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_VARBINARY
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_DECIMAL
|
||||
tColDataCalcSMADecimal128Type, // TSDB_DATA_TYPE_DECIMAL
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_BLOB
|
||||
NULL, // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
tColDataCalcSMAVarType // TSDB_DATA_TYPE_GEOMETRY
|
||||
tColDataCalcSMAVarType, // TSDB_DATA_TYPE_GEOMETRY
|
||||
tColDataCalcSMADecimal64Type, // TSDB_DATA_TYPE_DECIMAL64
|
||||
};
|
||||
|
||||
// SValueColumn ================================
|
||||
|
@ -4284,7 +4374,7 @@ int32_t tValueColumnAppend(SValueColumn *valCol, const SValue *value) {
|
|||
return code;
|
||||
}
|
||||
} else {
|
||||
code = tBufferPut(&valCol->data, &value->val, tDataTypes[value->type].bytes);
|
||||
code = tBufferPut(&valCol->data, VALUE_GET_DATUM(value, value->type), tDataTypes[value->type].bytes);
|
||||
if (code) return code;
|
||||
}
|
||||
valCol->numOfValues++;
|
||||
|
@ -4317,7 +4407,7 @@ int32_t tValueColumnUpdate(SValueColumn *valCol, int32_t idx, const SValue *valu
|
|||
}
|
||||
return tBufferPutAt(&valCol->data, offsets[idx], value->pData, value->nData);
|
||||
} else {
|
||||
return tBufferPutAt(&valCol->data, idx * tDataTypes[valCol->type].bytes, &value->val,
|
||||
return tBufferPutAt(&valCol->data, idx * tDataTypes[valCol->type].bytes, VALUE_GET_DATUM(value, valCol->type),
|
||||
tDataTypes[valCol->type].bytes);
|
||||
}
|
||||
return 0;
|
||||
|
@ -4343,7 +4433,7 @@ int32_t tValueColumnGet(SValueColumn *valCol, int32_t idx, SValue *value) {
|
|||
value->pData = (uint8_t *)tBufferGetDataAt(&valCol->data, offset);
|
||||
} else {
|
||||
SBufferReader reader = BUFFER_READER_INITIALIZER(idx * tDataTypes[value->type].bytes, &valCol->data);
|
||||
TAOS_CHECK_RETURN(tBufferGet(&reader, tDataTypes[value->type].bytes, &value->val));
|
||||
TAOS_CHECK_RETURN(tBufferGet(&reader, tDataTypes[value->type].bytes, VALUE_GET_DATUM(value, value->type)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -4677,3 +4767,45 @@ int32_t tDecompressDataToBuffer(void *input, SCompressInfo *info, SBuffer *outpu
|
|||
output->size += info->originalSize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle all types, including var data
|
||||
void valueSetDatum(SValue *pVal, int8_t type, void *pDatum, uint32_t len) {
|
||||
if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
pVal->pData = pDatum;
|
||||
pVal->nData = len;
|
||||
} else {
|
||||
switch (len) {
|
||||
case sizeof(uint8_t):
|
||||
pVal->val = *(uint8_t *)pDatum;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
pVal->val = *(uint16_t *)pDatum;
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
pVal->val = *(uint32_t *)pDatum;
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
pVal->val = *(uint64_t *)pDatum;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void valueCloneDatum(SValue *pDst, const SValue *pSrc, int8_t type) {
|
||||
if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
memcpy(pDst->pData, pSrc->pData, pSrc->nData);
|
||||
pDst->nData = pSrc->nData;
|
||||
} else {
|
||||
pDst->val = pSrc->val;
|
||||
}
|
||||
}
|
||||
void valueClearDatum(SValue *pVal, int8_t type) {
|
||||
if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
taosMemoryFreeClear(pVal->pData);
|
||||
pVal->nData = 0;
|
||||
} else {
|
||||
pVal->val = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -517,7 +517,7 @@ int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow, int8_t r
|
|||
val = varBuf;
|
||||
++iBound;
|
||||
} else {
|
||||
val = (const void *)&pColVal->value.val;
|
||||
val = VALUE_GET_DATUM(&pColVal->value, pTColumn->type);
|
||||
++iBound;
|
||||
}
|
||||
} else {
|
||||
|
@ -972,7 +972,7 @@ int32_t tTSRowGetVal(STSRow *pRow, STSchema *pTSchema, int16_t iCol, SColVal *pC
|
|||
pColVal->value.nData = varDataLen(cv.val);
|
||||
pColVal->value.pData = varDataVal(cv.val);
|
||||
} else {
|
||||
(void)memcpy(&pColVal->value.val, cv.val, tDataTypes[pTColumn->type].bytes);
|
||||
valueSetDatum(&pColVal->value, pTColumn->type, cv.val, tDataTypes[pTColumn->type].bytes);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "ttypes.h"
|
||||
#include "tcompression.h"
|
||||
|
||||
const int32_t TYPE_BYTES[21] = {
|
||||
const int32_t TYPE_BYTES[TSDB_DATA_TYPE_MAX] = {
|
||||
2, // TSDB_DATA_TYPE_NULL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_BOOL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_TINYINT
|
||||
|
@ -35,10 +35,11 @@ const int32_t TYPE_BYTES[21] = {
|
|||
sizeof(uint64_t), // TSDB_DATA_TYPE_UBIGINT
|
||||
TSDB_MAX_JSON_TAG_LEN, // TSDB_DATA_TYPE_JSON
|
||||
sizeof(VarDataOffsetT), // TSDB_DATA_TYPE_VARBINARY
|
||||
TSDB_MAX_TAGS_LEN, // TSDB_DATA_TYPE_DECIMAL: placeholder, not implemented
|
||||
DECIMAL128_BYTES, // TSDB_DATA_TYPE_DECIMAL: placeholder, not implemented
|
||||
TSDB_MAX_TAGS_LEN, // TSDB_DATA_TYPE_BLOB: placeholder, not implemented
|
||||
TSDB_MAX_TAGS_LEN, // TSDB_DATA_TYPE_MEDIUMBLOB: placeholder, not implemented
|
||||
sizeof(VarDataOffsetT), // TSDB_DATA_TYPE_GEOMETRY
|
||||
DECIMAL64_BYTES, // TSDB_DATA_TYPE_DECIMAL64
|
||||
};
|
||||
|
||||
tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
||||
|
@ -62,11 +63,12 @@ tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
|||
{TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", 0, UINT64_MAX, tsCompressBigint, tsDecompressBigint},
|
||||
{TSDB_DATA_TYPE_JSON, 4, TSDB_MAX_JSON_TAG_LEN, "JSON", 0, 0, tsCompressString, tsDecompressString},
|
||||
{TSDB_DATA_TYPE_VARBINARY, 9, 1, "VARBINARY", 0, 0, tsCompressString,
|
||||
tsDecompressString}, // placeholder, not implemented
|
||||
{TSDB_DATA_TYPE_DECIMAL, 7, 1, "DECIMAL", 0, 0, NULL, NULL}, // 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
|
||||
tsDecompressString}, // placeholder, not implemented
|
||||
{TSDB_DATA_TYPE_DECIMAL, 7, DECIMAL128_BYTES, "DECIMAL", 0, 0, NULL, NULL}, // 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, tsCompressString, tsDecompressString},
|
||||
{TSDB_DATA_TYPE_DECIMAL64, 7, DECIMAL64_BYTES, "DECIMAL", 0, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
tDataTypeCompress tDataCompress[TSDB_DATA_TYPE_MAX] = {
|
||||
|
@ -92,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},
|
||||
{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},
|
||||
|
||||
};
|
||||
|
||||
|
@ -229,3 +232,83 @@ int32_t operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (precision) *precision = (uint8_t)((typeMod >> 8) & 0xFF);
|
||||
if (scale) *scale = (uint8_t)(typeMod & 0xFF);
|
||||
}
|
||||
|
||||
STypeMod typeGetTypeModFromDataType(const SDataType* pDataType) {
|
||||
if (IS_DECIMAL_TYPE(pDataType->type)) return decimalCalcTypeMod(pDataType->precision, pDataType->scale);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STypeMod typeGetTypeMod(uint8_t type, uint8_t prec, uint8_t scale, int32_t bytes) {
|
||||
if (IS_DECIMAL_TYPE(type)) {
|
||||
return decimalCalcTypeMod(prec, scale);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fillTypeFromTypeMod(SDataType* pType, STypeMod mod) {
|
||||
if (IS_DECIMAL_TYPE(pType->type)) {
|
||||
decimalFromTypeMod(mod, &pType->precision, &pType->scale);
|
||||
}
|
||||
}
|
||||
|
||||
void extractTypeFromTypeMod(uint8_t type, STypeMod typeMod, uint8_t *prec, uint8_t *scale, int32_t *bytes) {
|
||||
if (IS_DECIMAL_TYPE(type)) {
|
||||
decimalFromTypeMod(typeMod, prec, scale);
|
||||
} else {
|
||||
if (prec) *prec = 0;
|
||||
if (scale) *scale = 0;
|
||||
}
|
||||
if (bytes) *bytes = tDataTypes[type].bytes;
|
||||
}
|
||||
|
||||
uint8_t getScaleFromTypeMod(int32_t type, STypeMod mod) {
|
||||
if (IS_DECIMAL_TYPE(type)) return (uint8_t)(mod & 0xFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// bytes, 0, prec, scale
|
||||
void fillBytesForDecimalType(int32_t *pBytes, int32_t type, uint8_t precision, uint8_t scale) {
|
||||
*pBytes = 0;
|
||||
*pBytes = tDataTypes[type].bytes << 24;
|
||||
*pBytes |= (uint32_t)precision << 8;
|
||||
*pBytes |= scale;
|
||||
}
|
||||
|
||||
void extractDecimalTypeInfoFromBytes(int32_t *pBytes, uint8_t *precision, uint8_t *scale) {
|
||||
*precision = (uint8_t)((*pBytes >> 8) & 0xFF);
|
||||
*scale = (uint8_t)(*pBytes & 0xFF);
|
||||
*pBytes >>= 24;
|
||||
}
|
||||
|
||||
int32_t calcTypeBytesFromSchemaBytes(int32_t type, int32_t schemaBytes, bool isStmt) {
|
||||
if (isStmt) return schemaBytes;
|
||||
if (type == TSDB_DATA_TYPE_VARCHAR || type == TSDB_DATA_TYPE_VARBINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return schemaBytes - VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_JSON) {
|
||||
return (schemaBytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
return schemaBytes;
|
||||
}
|
||||
|
||||
int32_t calcSchemaBytesFromTypeBytes(int32_t type, int32_t varTypeBytes, bool isStmt) {
|
||||
if (isStmt) return varTypeBytes;
|
||||
if (type == TSDB_DATA_TYPE_VARCHAR || type == TSDB_DATA_TYPE_VARBINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return varTypeBytes + VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_JSON) {
|
||||
return varTypeBytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
}
|
||||
return varTypeBytes;
|
||||
}
|
|
@ -561,6 +561,7 @@ typedef struct {
|
|||
col_id_t colId;
|
||||
int32_t cmprAlg;
|
||||
} SCmprObj;
|
||||
|
||||
typedef struct {
|
||||
char name[TSDB_TABLE_FNAME_LEN];
|
||||
char db[TSDB_DB_FNAME_LEN];
|
||||
|
@ -591,6 +592,7 @@ typedef struct {
|
|||
int8_t source;
|
||||
SColCmpr* pCmpr;
|
||||
int64_t keep;
|
||||
SExtSchema* pExtSchemas;
|
||||
} SStbObj;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -664,6 +664,7 @@ static int32_t mndSetUpdateIdxStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStb
|
|||
pNew->pColumns = NULL;
|
||||
pNew->pCmpr = NULL;
|
||||
pNew->pTags = NULL;
|
||||
pNew->pExtSchemas = NULL;
|
||||
pNew->updateTime = taosGetTimestampMs();
|
||||
pNew->lock = 0;
|
||||
|
||||
|
@ -733,6 +734,7 @@ _OVER:
|
|||
taosMemoryFree(newStb.pTags);
|
||||
taosMemoryFree(newStb.pColumns);
|
||||
taosMemoryFree(newStb.pCmpr);
|
||||
taosMemoryFreeClear(newStb.pExtSchemas);
|
||||
}
|
||||
mndTransDrop(pTrans);
|
||||
TAOS_RETURN(code);
|
||||
|
@ -847,6 +849,7 @@ _OVER:
|
|||
taosMemoryFree(newObj.pTags);
|
||||
taosMemoryFree(newObj.pColumns);
|
||||
taosMemoryFree(newObj.pCmpr);
|
||||
taosMemoryFreeClear(newObj.pExtSchemas);
|
||||
|
||||
mndTransDrop(pTrans);
|
||||
mndReleaseStb(pMnode, pStb);
|
||||
|
|
|
@ -1595,8 +1595,8 @@ static int32_t mndCreateTSMABuildCreateStreamReq(SCreateTSMACxt *pCxt) {
|
|||
if (!pCxt->pCreateStreamReq->pTags) {
|
||||
return terrno;
|
||||
}
|
||||
SField f = {0};
|
||||
int32_t code = 0;
|
||||
SFieldWithOptions f = {0};
|
||||
int32_t code = 0;
|
||||
if (pCxt->pSrcStb) {
|
||||
for (int32_t idx = 0; idx < pCxt->pCreateStreamReq->numOfTags - 1; ++idx) {
|
||||
SSchema *pSchema = &pCxt->pSrcStb->pTags[idx];
|
||||
|
@ -1630,6 +1630,10 @@ static int32_t mndCreateTSMABuildCreateStreamReq(SCreateTSMACxt *pCxt) {
|
|||
f.type = pExprNode->resType.type;
|
||||
f.flags = COL_SMA_ON;
|
||||
tstrncpy(f.name, pExprNode->userAlias, TSDB_COL_NAME_LEN);
|
||||
if (IS_DECIMAL_TYPE(f.type)) {
|
||||
f.typeMod = decimalCalcTypeMod(pExprNode->resType.precision, pExprNode->resType.scale);
|
||||
f.flags |= COL_HAS_TYPE_MOD;
|
||||
}
|
||||
if (NULL == taosArrayPush(pCxt->pCreateStreamReq->pCols, &f)) {
|
||||
code = terrno;
|
||||
break;
|
||||
|
@ -1797,7 +1801,7 @@ static int32_t mndCreateTSMA(SCreateTSMACxt *pCxt) {
|
|||
}
|
||||
}
|
||||
if (LIST_LENGTH(pProjects) > 0) {
|
||||
createStreamReq.pCols = taosArrayInit(LIST_LENGTH(pProjects), sizeof(SField));
|
||||
createStreamReq.pCols = taosArrayInit(LIST_LENGTH(pProjects), sizeof(SFieldWithOptions));
|
||||
if (!createStreamReq.pCols) {
|
||||
code = terrno;
|
||||
goto _OVER;
|
||||
|
|
|
@ -117,11 +117,12 @@ void mndCleanupStb(SMnode *pMnode) {}
|
|||
SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
bool hasTypeMod = false;
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
int32_t size = sizeof(SStbObj) + (pStb->numOfColumns + pStb->numOfTags) * sizeof(SSchema) + pStb->commentLen +
|
||||
pStb->ast1Len + pStb->ast2Len + pStb->numOfColumns * sizeof(SColCmpr) + STB_RESERVE_SIZE +
|
||||
taosArrayGetSize(pStb->pFuncs) * TSDB_FUNC_NAME_LEN;
|
||||
taosArrayGetSize(pStb->pFuncs) * TSDB_FUNC_NAME_LEN + sizeof(int32_t) * pStb->numOfColumns;
|
||||
SSdbRaw *pRaw = sdbAllocRaw(SDB_STB, STB_VER_NUMBER, size);
|
||||
if (pRaw == NULL) goto _OVER;
|
||||
|
||||
|
@ -155,6 +156,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
|
|||
SDB_SET_INT16(pRaw, dataPos, pSchema->colId, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, pSchema->bytes, _OVER)
|
||||
SDB_SET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER)
|
||||
hasTypeMod = hasTypeMod || HAS_TYPE_MOD(pSchema);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pStb->numOfTags; ++i) {
|
||||
|
@ -192,6 +194,13 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) {
|
|||
}
|
||||
SDB_SET_INT64(pRaw, dataPos, pStb->keep, _OVER)
|
||||
|
||||
|
||||
if (hasTypeMod) {
|
||||
for (int32_t i = 0; i < pStb->numOfColumns; ++i) {
|
||||
SDB_SET_INT32(pRaw, dataPos, pStb->pExtSchemas[i].typeMod, _OVER);
|
||||
}
|
||||
}
|
||||
|
||||
SDB_SET_RESERVE(pRaw, dataPos, STB_RESERVE_SIZE, _OVER)
|
||||
SDB_SET_DATALEN(pRaw, dataPos, _OVER)
|
||||
|
||||
|
@ -214,6 +223,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
|
|||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
SSdbRow *pRow = NULL;
|
||||
SStbObj *pStb = NULL;
|
||||
bool hasExtSchemas = false;
|
||||
|
||||
int8_t sver = 0;
|
||||
if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
|
||||
|
@ -266,6 +276,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
|
|||
SDB_GET_INT16(pRaw, dataPos, &pSchema->colId, _OVER)
|
||||
SDB_GET_INT32(pRaw, dataPos, &pSchema->bytes, _OVER)
|
||||
SDB_GET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER)
|
||||
hasExtSchemas = hasExtSchemas || HAS_TYPE_MOD(pSchema);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pStb->numOfTags; ++i) {
|
||||
|
@ -320,6 +331,16 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) {
|
|||
}
|
||||
SDB_GET_INT64(pRaw, dataPos, &pStb->keep, _OVER)
|
||||
|
||||
// type mod
|
||||
if (hasExtSchemas) {
|
||||
pStb->pExtSchemas = taosMemoryCalloc(pStb->numOfColumns, sizeof(SExtSchema));
|
||||
if (!pStb->pExtSchemas) goto _OVER;
|
||||
for (int32_t i = 0; i < pStb->numOfColumns; ++i) {
|
||||
SSchema *pSchema = &pStb->pColumns[i];
|
||||
SDB_GET_INT32(pRaw, dataPos, &pStb->pExtSchemas[i].typeMod, _OVER)
|
||||
}
|
||||
}
|
||||
|
||||
SDB_GET_RESERVE(pRaw, dataPos, STB_RESERVE_SIZE, _OVER)
|
||||
|
||||
terrno = 0;
|
||||
|
@ -332,6 +353,7 @@ _OVER:
|
|||
taosMemoryFreeClear(pStb->pTags);
|
||||
taosMemoryFreeClear(pStb->comment);
|
||||
taosMemoryFree(pStb->pCmpr);
|
||||
taosMemoryFreeClear(pStb->pExtSchemas);
|
||||
}
|
||||
taosMemoryFreeClear(pRow);
|
||||
return NULL;
|
||||
|
@ -349,6 +371,7 @@ void mndFreeStb(SStbObj *pStb) {
|
|||
taosMemoryFreeClear(pStb->pAst1);
|
||||
taosMemoryFreeClear(pStb->pAst2);
|
||||
taosMemoryFreeClear(pStb->pCmpr);
|
||||
taosMemoryFreeClear(pStb->pExtSchemas);
|
||||
}
|
||||
|
||||
static int32_t mndStbActionInsert(SSdb *pSdb, SStbObj *pStb) {
|
||||
|
@ -363,69 +386,55 @@ static int32_t mndStbActionDelete(SSdb *pSdb, SStbObj *pStb) {
|
|||
}
|
||||
|
||||
static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew) {
|
||||
terrno = 0;
|
||||
mTrace("stb:%s, perform update action, old row:%p new row:%p", pOld->name, pOld, pNew);
|
||||
|
||||
taosWLockLatch(&pOld->lock);
|
||||
int32_t numOfColumns = pOld->numOfColumns;
|
||||
if (pOld->numOfColumns < pNew->numOfColumns) {
|
||||
void *pColumns = taosMemoryMalloc(pNew->numOfColumns * sizeof(SSchema));
|
||||
if (pColumns != NULL) {
|
||||
taosMemoryFree(pOld->pColumns);
|
||||
pOld->pColumns = pColumns;
|
||||
} else {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
mTrace("stb:%s, failed to perform update action since %s", pOld->name, terrstr());
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
if (pColumns == NULL) {
|
||||
goto END;
|
||||
}
|
||||
taosMemoryFree(pOld->pColumns);
|
||||
pOld->pColumns = pColumns;
|
||||
}
|
||||
|
||||
if (pOld->numOfTags < pNew->numOfTags) {
|
||||
void *pTags = taosMemoryMalloc(pNew->numOfTags * sizeof(SSchema));
|
||||
if (pTags != NULL) {
|
||||
taosMemoryFree(pOld->pTags);
|
||||
pOld->pTags = pTags;
|
||||
} else {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
mTrace("stb:%s, failed to perform update action since %s", pOld->name, terrstr());
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
if (pTags == NULL) {
|
||||
goto END;
|
||||
}
|
||||
taosMemoryFree(pOld->pTags);
|
||||
pOld->pTags = pTags;
|
||||
}
|
||||
|
||||
if (pOld->commentLen < pNew->commentLen && pNew->commentLen > 0) {
|
||||
void *comment = taosMemoryMalloc(pNew->commentLen + 1);
|
||||
if (comment != NULL) {
|
||||
taosMemoryFree(pOld->comment);
|
||||
pOld->comment = comment;
|
||||
} else {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
mTrace("stb:%s, failed to perform update action since %s", pOld->name, terrstr());
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
if (comment == NULL) {
|
||||
goto END;
|
||||
}
|
||||
taosMemoryFree(pOld->comment);
|
||||
pOld->comment = comment;
|
||||
}
|
||||
pOld->commentLen = pNew->commentLen;
|
||||
|
||||
if (pOld->ast1Len < pNew->ast1Len) {
|
||||
void *pAst1 = taosMemoryMalloc(pNew->ast1Len + 1);
|
||||
if (pAst1 != NULL) {
|
||||
taosMemoryFree(pOld->pAst1);
|
||||
pOld->pAst1 = pAst1;
|
||||
} else {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
mTrace("stb:%s, failed to perform update action since %s", pOld->name, terrstr());
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
if (pAst1 == NULL) {
|
||||
goto END;
|
||||
}
|
||||
taosMemoryFree(pOld->pAst1);
|
||||
pOld->pAst1 = pAst1;
|
||||
}
|
||||
|
||||
if (pOld->ast2Len < pNew->ast2Len) {
|
||||
void *pAst2 = taosMemoryMalloc(pNew->ast2Len + 1);
|
||||
if (pAst2 != NULL) {
|
||||
taosMemoryFree(pOld->pAst2);
|
||||
pOld->pAst2 = pAst2;
|
||||
} else {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
mTrace("stb:%s, failed to perform update action since %s", pOld->name, terrstr());
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
if (pAst2 == NULL) {
|
||||
goto END;
|
||||
}
|
||||
taosMemoryFree(pOld->pAst2);
|
||||
pOld->pAst2 = pAst2;
|
||||
}
|
||||
|
||||
pOld->updateTime = pNew->updateTime;
|
||||
|
@ -459,13 +468,26 @@ static int32_t mndStbActionUpdate(SSdb *pSdb, SStbObj *pOld, SStbObj *pNew) {
|
|||
if (numOfColumns < pNew->numOfColumns) {
|
||||
taosMemoryFree(pOld->pCmpr);
|
||||
pOld->pCmpr = taosMemoryCalloc(pNew->numOfColumns, sizeof(SColCmpr));
|
||||
if (pOld->pCmpr == NULL){
|
||||
goto END;
|
||||
}
|
||||
memcpy(pOld->pCmpr, pNew->pCmpr, pNew->numOfColumns * sizeof(SColCmpr));
|
||||
} else {
|
||||
memcpy(pOld->pCmpr, pNew->pCmpr, pNew->numOfColumns * sizeof(SColCmpr));
|
||||
}
|
||||
|
||||
if (pNew->pExtSchemas) {
|
||||
taosMemoryFreeClear(pOld->pExtSchemas);
|
||||
pOld->pExtSchemas = taosMemoryCalloc(pNew->numOfColumns, sizeof(SExtSchema));
|
||||
if (pOld->pExtSchemas == NULL){
|
||||
goto END;
|
||||
}
|
||||
memcpy(pOld->pExtSchemas, pNew->pExtSchemas, pNew->numOfColumns * sizeof(SExtSchema));
|
||||
}
|
||||
|
||||
END:
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
return 0;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
SStbObj *mndAcquireStb(SMnode *pMnode, char *stbName) {
|
||||
|
@ -563,6 +585,7 @@ void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int3
|
|||
}
|
||||
}
|
||||
}
|
||||
req.pExtSchemas = pStb->pExtSchemas; // only reference to it.
|
||||
// get length
|
||||
int32_t ret = 0;
|
||||
tEncodeSize(tEncodeSVCreateStbReq, &req, contLen, ret);
|
||||
|
@ -861,6 +884,7 @@ static SSchema *mndFindStbColumns(const SStbObj *pStb, const char *colName) {
|
|||
|
||||
int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreate, SDbObj *pDb) {
|
||||
int32_t code = 0;
|
||||
bool hasTypeMods = false;
|
||||
memcpy(pDst->name, pCreate->name, TSDB_TABLE_FNAME_LEN);
|
||||
memcpy(pDst->db, pDb->name, TSDB_DB_FNAME_LEN);
|
||||
pDst->createdTime = taosGetTimestampMs();
|
||||
|
@ -937,6 +961,7 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat
|
|||
memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN);
|
||||
pSchema->colId = pDst->nextColId;
|
||||
pDst->nextColId++;
|
||||
hasTypeMods = hasTypeMods || HAS_TYPE_MOD(pSchema);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pDst->numOfTags; ++i) {
|
||||
|
@ -961,6 +986,18 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat
|
|||
pColCmpr->id = pSchema->colId;
|
||||
pColCmpr->alg = pField->compress;
|
||||
}
|
||||
|
||||
if (hasTypeMods) {
|
||||
pDst->pExtSchemas = taosMemoryCalloc(pDst->numOfColumns, sizeof(SExtSchema));
|
||||
if (!pDst->pExtSchemas) {
|
||||
code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
for (int32_t i = 0; i < pDst->numOfColumns; ++i) {
|
||||
SFieldWithOptions * pField = taosArrayGet(pCreate->pColumns, i);
|
||||
pDst->pExtSchemas[i].typeMod = pField->typeMod;
|
||||
}
|
||||
}
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
static int32_t mndGenIdxNameForFirstTag(char *fullname, char *dbname, char *stbname, char *tagname) {
|
||||
|
@ -1204,8 +1241,9 @@ static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq
|
|||
pDst->pColumns = taosMemoryCalloc(1, pDst->numOfColumns * sizeof(SSchema));
|
||||
pDst->pTags = taosMemoryCalloc(1, pDst->numOfTags * sizeof(SSchema));
|
||||
pDst->pCmpr = taosMemoryCalloc(1, pDst->numOfColumns * sizeof(SColCmpr));
|
||||
pDst->pExtSchemas = taosMemoryCalloc(pDst->numOfColumns, sizeof(SExtSchema));
|
||||
|
||||
if (pDst->pColumns == NULL || pDst->pTags == NULL || pDst->pCmpr == NULL) {
|
||||
if (pDst->pColumns == NULL || pDst->pTags == NULL || pDst->pCmpr == NULL || pDst->pExtSchemas == NULL) {
|
||||
code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
@ -1253,6 +1291,9 @@ static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq
|
|||
} else {
|
||||
p->alg = pField->compress;
|
||||
}
|
||||
if (pField->flags & COL_HAS_TYPE_MOD) {
|
||||
pDst->pExtSchemas[i].typeMod = pField->typeMod;
|
||||
}
|
||||
}
|
||||
pDst->tagVer = createReq->tagVer;
|
||||
pDst->colVer = createReq->colVer;
|
||||
|
@ -1385,6 +1426,7 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
|
|||
taosMemoryFreeClear(pDst.pTags);
|
||||
taosMemoryFreeClear(pDst.pColumns);
|
||||
taosMemoryFreeClear(pDst.pCmpr);
|
||||
taosMemoryFreeClear(pDst.pExtSchemas);
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
|
@ -1392,6 +1434,7 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
|
|||
taosMemoryFreeClear(pDst.pTags);
|
||||
taosMemoryFreeClear(pDst.pColumns);
|
||||
taosMemoryFreeClear(pDst.pCmpr);
|
||||
taosMemoryFreeClear(pDst.pExtSchemas);
|
||||
} else {
|
||||
code = mndCreateStb(pMnode, pReq, &createReq, pDb);
|
||||
}
|
||||
|
@ -1458,6 +1501,13 @@ int32_t mndAllocStbSchemas(const SStbObj *pOld, SStbObj *pNew) {
|
|||
memcpy(pNew->pColumns, pOld->pColumns, sizeof(SSchema) * pOld->numOfColumns);
|
||||
memcpy(pNew->pTags, pOld->pTags, sizeof(SSchema) * pOld->numOfTags);
|
||||
memcpy(pNew->pCmpr, pOld->pCmpr, sizeof(SColCmpr) * pOld->numOfColumns);
|
||||
if (pOld->pExtSchemas) {
|
||||
pNew->pExtSchemas = taosMemoryCalloc(pNew->numOfColumns, sizeof(SExtSchema));
|
||||
if (pNew->pExtSchemas == NULL) {
|
||||
TAOS_RETURN(terrno);
|
||||
}
|
||||
memcpy(pNew->pExtSchemas, pOld->pExtSchemas, sizeof(SExtSchema) * pOld->numOfColumns);
|
||||
}
|
||||
|
||||
TAOS_RETURN(0);
|
||||
}
|
||||
|
@ -1880,7 +1930,7 @@ static int32_t mndUpdateSuperTableColumnCompress(SMnode *pMnode, const SStbObj *
|
|||
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray *pFields, int32_t ncols,
|
||||
static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, const SMAlterStbReq* pReq, int32_t ncols,
|
||||
int8_t withCompress) {
|
||||
int32_t code = 0;
|
||||
if (pOld->numOfColumns + ncols + pOld->numOfTags > TSDB_MAX_COLUMNS) {
|
||||
|
@ -1892,7 +1942,7 @@ static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray
|
|||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
if (!mndValidateSchema(pOld->pColumns, pOld->numOfColumns, pFields, TSDB_MAX_BYTES_PER_ROW)) {
|
||||
if (!mndValidateSchema(pOld->pColumns, pOld->numOfColumns, pReq->pFields, TSDB_MAX_BYTES_PER_ROW)) {
|
||||
code = TSDB_CODE_PAR_INVALID_ROW_LENGTH;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
@ -1908,7 +1958,7 @@ static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray
|
|||
|
||||
for (int32_t i = 0; i < ncols; i++) {
|
||||
if (withCompress) {
|
||||
SFieldWithOptions *pField = taosArrayGet(pFields, i);
|
||||
SFieldWithOptions *pField = taosArrayGet(pReq->pFields, i);
|
||||
if (mndFindSuperTableColumnIndex(pOld, pField->name) >= 0) {
|
||||
code = TSDB_CODE_MND_COLUMN_ALREADY_EXIST;
|
||||
TAOS_RETURN(code);
|
||||
|
@ -1931,7 +1981,7 @@ static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray
|
|||
pCmpr->alg = pField->compress;
|
||||
mInfo("stb:%s, start to add column %s", pNew->name, pSchema->name);
|
||||
} else {
|
||||
SField *pField = taosArrayGet(pFields, i);
|
||||
SField *pField = taosArrayGet(pReq->pFields, i);
|
||||
if (mndFindSuperTableColumnIndex(pOld, pField->name) >= 0) {
|
||||
code = TSDB_CODE_MND_COLUMN_ALREADY_EXIST;
|
||||
TAOS_RETURN(code);
|
||||
|
@ -1955,6 +2005,25 @@ static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray
|
|||
mInfo("stb:%s, start to add column %s", pNew->name, pSchema->name);
|
||||
}
|
||||
}
|
||||
// 1. old schema already has extschemas
|
||||
// 2. new schema has extschemas
|
||||
if (pReq->pTypeMods || pOld->pExtSchemas) {
|
||||
if (!pNew->pExtSchemas) {
|
||||
// all ext schemas reset to zero
|
||||
pNew->pExtSchemas = taosMemoryCalloc(pNew->numOfColumns, sizeof(SExtSchema));
|
||||
if (!pNew->pExtSchemas) TAOS_RETURN(terrno);
|
||||
}
|
||||
if (pOld->pExtSchemas) {
|
||||
memcpy(pNew->pExtSchemas, pOld->pExtSchemas, pOld->numOfColumns * sizeof(SExtSchema));
|
||||
}
|
||||
if (taosArrayGetSize(pReq->pTypeMods) > 0) {
|
||||
// copy added column ext schema
|
||||
for (int32_t i = 0; i < ncols; ++i) {
|
||||
pNew->pColumns[pOld->numOfColumns + i].flags |= COL_HAS_TYPE_MOD;
|
||||
pNew->pExtSchemas[pOld->numOfColumns + i].typeMod = *(STypeMod *)taosArrayGet(pReq->pTypeMods, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pNew->colVer++;
|
||||
TAOS_RETURN(code);
|
||||
|
@ -1986,6 +2055,9 @@ static int32_t mndDropSuperTableColumn(SMnode *pMnode, const SStbObj *pOld, SStb
|
|||
int32_t sz = pNew->numOfColumns - col - 1;
|
||||
memmove(pNew->pColumns + col, pNew->pColumns + col + 1, sizeof(SSchema) * sz);
|
||||
memmove(pNew->pCmpr + col, pNew->pCmpr + col + 1, sizeof(SColCmpr) * sz);
|
||||
if (pOld->pExtSchemas) {
|
||||
memmove(pNew->pExtSchemas + col, pNew->pExtSchemas + col + 1, sizeof(SExtSchema) * sz);
|
||||
}
|
||||
pNew->numOfColumns--;
|
||||
|
||||
pNew->colVer++;
|
||||
|
@ -2206,6 +2278,9 @@ static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbNa
|
|||
SSchemaExt *pSchEx = &pRsp->pSchemaExt[i];
|
||||
pSchEx->colId = pCmpr->id;
|
||||
pSchEx->compress = pCmpr->alg;
|
||||
if (pStb->pExtSchemas) {
|
||||
pSchEx->typeMod = pStb->pExtSchemas[i].typeMod;
|
||||
}
|
||||
}
|
||||
|
||||
taosRUnLockLatch(&pStb->lock);
|
||||
|
@ -2271,6 +2346,9 @@ static int32_t mndBuildStbCfgImp(SDbObj *pDb, SStbObj *pStb, const char *tbName,
|
|||
SSchemaExt *pSchExt = &pRsp->pSchemaExt[i];
|
||||
pSchExt->colId = pCmpr->id;
|
||||
pSchExt->compress = pCmpr->alg;
|
||||
if (pStb->pExtSchemas) {
|
||||
pSchExt->typeMod = pStb->pExtSchemas[i].typeMod;
|
||||
}
|
||||
}
|
||||
|
||||
taosRUnLockLatch(&pStb->lock);
|
||||
|
@ -2604,6 +2682,7 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
|
|||
stbObj.pTags = NULL;
|
||||
stbObj.pFuncs = NULL;
|
||||
stbObj.pCmpr = NULL;
|
||||
stbObj.pExtSchemas = NULL;
|
||||
stbObj.updateTime = taosGetTimestampMs();
|
||||
stbObj.lock = 0;
|
||||
bool updateTagIndex = false;
|
||||
|
@ -2625,7 +2704,7 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
|
|||
code = mndAlterStbTagBytes(pMnode, pOld, &stbObj, pField0);
|
||||
break;
|
||||
case TSDB_ALTER_TABLE_ADD_COLUMN:
|
||||
code = mndAddSuperTableColumn(pOld, &stbObj, pAlter->pFields, pAlter->numOfFields, 0);
|
||||
code = mndAddSuperTableColumn(pOld, &stbObj, pAlter, pAlter->numOfFields, 0);
|
||||
break;
|
||||
case TSDB_ALTER_TABLE_DROP_COLUMN:
|
||||
pField0 = taosArrayGet(pAlter->pFields, 0);
|
||||
|
@ -2643,7 +2722,7 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
|
|||
code = mndUpdateSuperTableColumnCompress(pMnode, pOld, &stbObj, pAlter->pFields, pAlter->numOfFields);
|
||||
break;
|
||||
case TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION:
|
||||
code = mndAddSuperTableColumn(pOld, &stbObj, pAlter->pFields, pAlter->numOfFields, 1);
|
||||
code = mndAddSuperTableColumn(pOld, &stbObj, pAlter, pAlter->numOfFields, 1);
|
||||
break;
|
||||
default:
|
||||
needRsp = false;
|
||||
|
@ -2665,6 +2744,7 @@ _OVER:
|
|||
if (pAlter->commentLen > 0) {
|
||||
taosMemoryFreeClear(stbObj.comment);
|
||||
}
|
||||
taosMemoryFreeClear(stbObj.pExtSchemas);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
|
@ -3646,6 +3726,11 @@ static int32_t mndRetrieveStbCol(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB
|
|||
colTypeLen +=
|
||||
tsnprintf(varDataVal(colTypeStr) + colTypeLen, sizeof(colTypeStr) - colTypeLen - VARSTR_HEADER_SIZE,
|
||||
"(%d)", (int32_t)((pStb->pColumns[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
|
||||
} else if (IS_DECIMAL_TYPE(colType)) {
|
||||
STypeMod typeMod = pStb->pExtSchemas[i].typeMod;
|
||||
uint8_t prec = 0, scale = 0;
|
||||
decimalFromTypeMod(typeMod, &prec, &scale);
|
||||
colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d,%d)", prec, scale);
|
||||
}
|
||||
varDataSetLen(colTypeStr, colTypeLen);
|
||||
RETRIEVE_CHECK_GOTO(colDataSetVal(pColInfo, numOfRows, (char *)colTypeStr, false), pStb, &lino, _OVER);
|
||||
|
|
|
@ -642,6 +642,11 @@ static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStre
|
|||
pField->type = pStream->outputSchema.pSchema[i].type;
|
||||
pField->bytes = pStream->outputSchema.pSchema[i].bytes;
|
||||
pField->compress = createDefaultColCmprByType(pField->type);
|
||||
if (IS_DECIMAL_TYPE(pField->type)) {
|
||||
uint8_t prec = 0, scale = 0;
|
||||
extractDecimalTypeInfoFromBytes(&pField->bytes, &prec, &scale);
|
||||
pField->typeMod = decimalCalcTypeMod(prec, scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (pStream->tagSchema.nCols == 0) {
|
||||
|
|
|
@ -221,6 +221,7 @@ typedef struct STqReader {
|
|||
SSDataBlock *pResBlock;
|
||||
int64_t lastTs;
|
||||
bool hasPrimaryKey;
|
||||
SExtSchema *extSchema;
|
||||
} STqReader;
|
||||
|
||||
STqReader *tqReaderOpen(SVnode *pVnode);
|
||||
|
|
|
@ -169,8 +169,9 @@ int32_t metaDropMultipleTables(SMeta* pMeta, int64_t version, SArray* tb
|
|||
int metaTtlFindExpired(SMeta* pMeta, int64_t timePointMs, SArray* tbUids, int32_t ttlDropMaxCount);
|
||||
int metaAlterTable(SMeta* pMeta, int64_t version, SVAlterTbReq* pReq, STableMetaRsp* pMetaRsp);
|
||||
int metaUpdateChangeTimeWithLock(SMeta* pMeta, tb_uid_t uid, int64_t changeTimeMs);
|
||||
SSchemaWrapper* metaGetTableSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver, int lock);
|
||||
int64_t metaGetTableCreateTime(SMeta* pMeta, tb_uid_t uid, int lock);
|
||||
SSchemaWrapper* metaGetTableSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver, int lock, SExtSchema** extSchema);
|
||||
int64_t metaGetTableCreateTime(SMeta *pMeta, tb_uid_t uid, int lock);
|
||||
SExtSchema* metaGetSExtSchema(const SMetaEntry *pME);
|
||||
int32_t metaGetTbTSchemaNotNull(SMeta* pMeta, tb_uid_t uid, int32_t sver, int lock, STSchema** ppTSchema);
|
||||
int32_t metaGetTbTSchemaMaybeNull(SMeta* pMeta, tb_uid_t uid, int32_t sver, int lock, STSchema** ppTSchema);
|
||||
STSchema* metaGetTbTSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver, int lock);
|
||||
|
|
|
@ -15,6 +15,83 @@
|
|||
|
||||
#include "meta.h"
|
||||
|
||||
static bool schemasHasTypeMod(const SSchema *pSchema, int32_t nCols) {
|
||||
for (int32_t i = 0; i < nCols; i++) {
|
||||
if (HAS_TYPE_MOD(pSchema + i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t metaEncodeExtSchema(SEncoder* pCoder, const SMetaEntry* pME) {
|
||||
if (pME->pExtSchemas) {
|
||||
const SSchemaWrapper *pSchWrapper = NULL;
|
||||
bool hasTypeMods = false;
|
||||
if (pME->type == TSDB_SUPER_TABLE) {
|
||||
pSchWrapper = &pME->stbEntry.schemaRow;
|
||||
} else if (pME->type == TSDB_NORMAL_TABLE) {
|
||||
pSchWrapper = &pME->ntbEntry.schemaRow;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
hasTypeMods = schemasHasTypeMod(pSchWrapper->pSchema, pSchWrapper->nCols);
|
||||
|
||||
for (int32_t i = 0; i < pSchWrapper->nCols && hasTypeMods; ++i) {
|
||||
TAOS_CHECK_RETURN(tEncodeI32v(pCoder, pME->pExtSchemas[i].typeMod));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t metaDecodeExtSchemas(SDecoder* pDecoder, SMetaEntry* pME) {
|
||||
bool hasExtSchema = false;
|
||||
SSchemaWrapper* pSchWrapper = NULL;
|
||||
if (pME->type == TSDB_SUPER_TABLE) {
|
||||
pSchWrapper = &pME->stbEntry.schemaRow;
|
||||
} else if (pME->type == TSDB_NORMAL_TABLE) {
|
||||
pSchWrapper = &pME->ntbEntry.schemaRow;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hasExtSchema = schemasHasTypeMod(pSchWrapper->pSchema, pSchWrapper->nCols);
|
||||
if (hasExtSchema && pSchWrapper->nCols > 0) {
|
||||
pME->pExtSchemas = (SExtSchema*)tDecoderMalloc(pDecoder, sizeof(SExtSchema) * pSchWrapper->nCols);
|
||||
if (pME->pExtSchemas == NULL) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pSchWrapper->nCols && hasExtSchema; i++) {
|
||||
TAOS_CHECK_RETURN(tDecodeI32v(pDecoder, &pME->pExtSchemas[i].typeMod));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SExtSchema* metaGetSExtSchema(const SMetaEntry *pME) {
|
||||
const SSchemaWrapper *pSchWrapper = NULL;
|
||||
bool hasTypeMods = false;
|
||||
if (pME->type == TSDB_SUPER_TABLE) {
|
||||
pSchWrapper = &pME->stbEntry.schemaRow;
|
||||
} else if (pME->type == TSDB_NORMAL_TABLE) {
|
||||
pSchWrapper = &pME->ntbEntry.schemaRow;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
hasTypeMods = schemasHasTypeMod(pSchWrapper->pSchema, pSchWrapper->nCols);
|
||||
|
||||
if (hasTypeMods) {
|
||||
SExtSchema* ret = taosMemoryMalloc(sizeof(SExtSchema) * pSchWrapper->nCols);
|
||||
if (ret != NULL){
|
||||
memcpy(ret, pME->pExtSchemas, pSchWrapper->nCols * sizeof(SExtSchema));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int meteEncodeColCmprEntry(SEncoder *pCoder, const SMetaEntry *pME) {
|
||||
const SColCmprWrapper *pw = &pME->colCmpr;
|
||||
TAOS_CHECK_RETURN(tEncodeI32v(pCoder, pw->nCols));
|
||||
|
@ -129,6 +206,7 @@ int metaEncodeEntry(SEncoder *pCoder, const SMetaEntry *pME) {
|
|||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
TAOS_CHECK_RETURN(meteEncodeColCmprEntry(pCoder, pME));
|
||||
TAOS_CHECK_RETURN(metaEncodeExtSchema(pCoder, pME));
|
||||
}
|
||||
if (pME->type == TSDB_SUPER_TABLE) {
|
||||
TAOS_CHECK_RETURN(tEncodeI64(pCoder, pME->stbEntry.keep));
|
||||
|
@ -211,6 +289,9 @@ int metaDecodeEntryImpl(SDecoder *pCoder, SMetaEntry *pME, bool headerOnly) {
|
|||
}
|
||||
TABLE_SET_COL_COMPRESSED(pME->flags);
|
||||
}
|
||||
if (!tDecodeIsEnd(pCoder)) {
|
||||
TAOS_CHECK_RETURN(metaDecodeExtSchemas(pCoder, pME));
|
||||
}
|
||||
}
|
||||
if (pME->type == TSDB_SUPER_TABLE) {
|
||||
if (!tDecodeIsEnd(pCoder)) {
|
||||
|
@ -218,6 +299,7 @@ int metaDecodeEntryImpl(SDecoder *pCoder, SMetaEntry *pME, bool headerOnly) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
tEndDecode(pCoder);
|
||||
return 0;
|
||||
}
|
||||
|
@ -270,6 +352,7 @@ void metaCloneEntryFree(SMetaEntry **ppEntry) {
|
|||
return;
|
||||
}
|
||||
metaCloneColCmprFree(&(*ppEntry)->colCmpr);
|
||||
taosMemoryFreeClear((*ppEntry)->pExtSchemas);
|
||||
|
||||
taosMemoryFreeClear(*ppEntry);
|
||||
return;
|
||||
|
@ -377,6 +460,15 @@ int32_t metaCloneEntry(const SMetaEntry *pEntry, SMetaEntry **ppEntry) {
|
|||
metaCloneEntryFree(ppEntry);
|
||||
return code;
|
||||
}
|
||||
if (pEntry->pExtSchemas && pEntry->colCmpr.nCols > 0) {
|
||||
(*ppEntry)->pExtSchemas = taosMemoryCalloc(pEntry->colCmpr.nCols, sizeof(SExtSchema));
|
||||
if (!(*ppEntry)->pExtSchemas) {
|
||||
code = terrno;
|
||||
metaCloneEntryFree(ppEntry);
|
||||
return code;
|
||||
}
|
||||
memcpy((*ppEntry)->pExtSchemas, pEntry->pExtSchemas, sizeof(SExtSchema) * pEntry->colCmpr.nCols);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -1080,7 +1080,6 @@ static int32_t metaHandleSuperTableCreateImpl(SMeta *pMeta, const SMetaEntry *pE
|
|||
const SMetaHandleParam param = {
|
||||
.pEntry = pEntry,
|
||||
};
|
||||
|
||||
code = metaTableOpFn[op->table][op->op](pMeta, ¶m);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
metaErr(TD_VID(pMeta->pVnode), code);
|
||||
|
|
|
@ -378,7 +378,7 @@ int32_t metaTbCursorPrev(SMTbCursor *pTbCur, ETableType jumpTableType) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock) {
|
||||
SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock, SExtSchema** extSchema) {
|
||||
void *pData = NULL;
|
||||
int nData = 0;
|
||||
int64_t version;
|
||||
|
@ -409,6 +409,7 @@ _query:
|
|||
if (me.type == TSDB_SUPER_TABLE) {
|
||||
if (sver == -1 || sver == me.stbEntry.schemaRow.version) {
|
||||
pSchema = tCloneSSchemaWrapper(&me.stbEntry.schemaRow);
|
||||
if (extSchema != NULL) *extSchema = metaGetSExtSchema(&me);
|
||||
tDecoderClear(&dc);
|
||||
goto _exit;
|
||||
}
|
||||
|
@ -419,10 +420,12 @@ _query:
|
|||
} else {
|
||||
if (sver == -1 || sver == me.ntbEntry.schemaRow.version) {
|
||||
pSchema = tCloneSSchemaWrapper(&me.ntbEntry.schemaRow);
|
||||
if (extSchema != NULL) *extSchema = metaGetSExtSchema(&me);
|
||||
tDecoderClear(&dc);
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
if (extSchema != NULL) *extSchema = metaGetSExtSchema(&me);
|
||||
tDecoderClear(&dc);
|
||||
|
||||
// query from skm db
|
||||
|
@ -664,7 +667,7 @@ STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock) {
|
|||
STSchema *pTSchema = NULL;
|
||||
SSchemaWrapper *pSW = NULL;
|
||||
|
||||
pSW = metaGetTableSchema(pMeta, uid, sver, lock);
|
||||
pSW = metaGetTableSchema(pMeta, uid, sver, lock, NULL);
|
||||
if (!pSW) return NULL;
|
||||
|
||||
pTSchema = tBuildTSchema(pSW->pSchema, pSW->nCols, pSW->version);
|
||||
|
@ -1465,6 +1468,7 @@ END:
|
|||
if (pCursor->pMeta) metaULock(pCursor->pMeta);
|
||||
if (pCursor->pCur) tdbTbcClose(pCursor->pCur);
|
||||
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
|
||||
taosMemoryFreeClear(oStbEntry.pExtSchemas);
|
||||
tDecoderClear(&dc);
|
||||
tdbFree(pData);
|
||||
|
||||
|
|
|
@ -593,7 +593,7 @@ int32_t setForSnapShot(SSnapContext* ctx, int64_t uid) {
|
|||
|
||||
void taosXSetTablePrimaryKey(SSnapContext* ctx, int64_t uid) {
|
||||
bool ret = false;
|
||||
SSchemaWrapper* schema = metaGetTableSchema(ctx->pMeta, uid, -1, 1);
|
||||
SSchemaWrapper* schema = metaGetTableSchema(ctx->pMeta, uid, -1, 1, NULL);
|
||||
if (schema && schema->nCols >= 2 && schema->pSchema[1].flags & COL_IS_KEY) {
|
||||
ret = true;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,40 @@ int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t addTableExtSchema(SMetaEntry *pEntry, const SSchema *pColumn, int32_t newColNum, SExtSchema *pExtSchema) {
|
||||
// no need to add ext schema when no column needs ext schemas
|
||||
if (!HAS_TYPE_MOD(pColumn) && !pEntry->pExtSchemas) return 0;
|
||||
if (!pEntry->pExtSchemas) {
|
||||
// add a column which needs ext schema
|
||||
// set all extschemas to zero for all columns alrady existed
|
||||
pEntry->pExtSchemas = (SExtSchema *)taosMemoryCalloc(newColNum, sizeof(SExtSchema));
|
||||
} else {
|
||||
// already has columns with ext schema
|
||||
pEntry->pExtSchemas = (SExtSchema *)taosMemoryRealloc(pEntry->pExtSchemas, sizeof(SExtSchema) * newColNum);
|
||||
}
|
||||
if (!pEntry->pExtSchemas) return terrno;
|
||||
pEntry->pExtSchemas[newColNum - 1] = *pExtSchema;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t dropTableExtSchema(SMetaEntry *pEntry, int32_t dropColId, int32_t newColNum) {
|
||||
// no ext schema, no need to drop
|
||||
if (!pEntry->pExtSchemas) return 0;
|
||||
if (dropColId == newColNum) {
|
||||
// drop the last column
|
||||
pEntry->pExtSchemas[dropColId - 1] = (SExtSchema){0};
|
||||
} else {
|
||||
// drop a column in the middle
|
||||
memmove(pEntry->pExtSchemas + dropColId, pEntry->pExtSchemas + dropColId + 1,
|
||||
(newColNum - dropColId) * sizeof(SExtSchema));
|
||||
}
|
||||
for (int32_t i = 0; i < newColNum; i++) {
|
||||
if (hasExtSchema(pEntry->pExtSchemas + i)) return 0;
|
||||
}
|
||||
taosMemoryFreeClear(pEntry->pExtSchemas);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metaUpdateMetaRsp(tb_uid_t uid, char *tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) {
|
||||
pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema));
|
||||
if (NULL == pMetaRsp->pSchemas) {
|
||||
|
@ -812,7 +846,7 @@ int32_t metaGetColCmpr(SMeta *pMeta, tb_uid_t uid, SHashObj **ppColCmprObj) {
|
|||
taosHashClear(pColCmprObj);
|
||||
return rc;
|
||||
}
|
||||
if (useCompress(e.type)) {
|
||||
if (withExtSchema(e.type)) {
|
||||
SColCmprWrapper *p = &e.colCmpr;
|
||||
for (int32_t i = 0; i < p->nCols; i++) {
|
||||
SColCmpr *pCmpr = &p->pColCmpr[i];
|
||||
|
|
|
@ -21,6 +21,8 @@ extern int32_t metaFetchEntryByUid(SMeta *pMeta, int64_t uid, SMetaEntry **ppEnt
|
|||
extern int32_t metaFetchEntryByName(SMeta *pMeta, const char *name, SMetaEntry **ppEntry);
|
||||
extern void metaFetchEntryFree(SMetaEntry **ppEntry);
|
||||
extern int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, uint32_t compress);
|
||||
extern int32_t addTableExtSchema(SMetaEntry* pEntry, const SSchema* pColumn, int32_t newColNum, SExtSchema* pExtSchema);
|
||||
extern int32_t dropTableExtSchema(SMetaEntry* pEntry, int32_t dropColId, int32_t newColNum);
|
||||
|
||||
static int32_t metaCheckCreateSuperTableReq(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
|
||||
int32_t vgId = TD_VID(pMeta->pVnode);
|
||||
|
@ -190,6 +192,7 @@ int32_t metaCreateSuperTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq
|
|||
TABLE_SET_COL_COMPRESSED(entry.flags);
|
||||
entry.colCmpr = pReq->colCmpr;
|
||||
}
|
||||
entry.pExtSchemas = pReq->pExtSchemas;
|
||||
|
||||
code = metaHandleEntry2(pMeta, &entry);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -436,6 +439,9 @@ static int32_t metaBuildCreateNormalTableRsp(SMeta *pMeta, SMetaEntry *pEntry, S
|
|||
SColCmpr *p = &pEntry->colCmpr.pColCmpr[i];
|
||||
(*ppRsp)->pSchemaExt[i].colId = p->id;
|
||||
(*ppRsp)->pSchemaExt[i].compress = p->alg;
|
||||
if (pEntry->pExtSchemas) {
|
||||
(*ppRsp)->pSchemaExt[i].typeMod = pEntry->pExtSchemas[i].typeMod;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -455,17 +461,18 @@ static int32_t metaCreateNormalTable(SMeta *pMeta, int64_t version, SVCreateTbRe
|
|||
}
|
||||
|
||||
SMetaEntry entry = {
|
||||
.version = version,
|
||||
.type = TSDB_NORMAL_TABLE,
|
||||
.uid = pReq->uid,
|
||||
.name = pReq->name,
|
||||
.ntbEntry.btime = pReq->btime,
|
||||
.ntbEntry.ttlDays = pReq->ttl,
|
||||
.ntbEntry.commentLen = pReq->commentLen,
|
||||
.ntbEntry.comment = pReq->comment,
|
||||
.ntbEntry.schemaRow = pReq->ntb.schemaRow,
|
||||
.ntbEntry.ncid = pReq->ntb.schemaRow.pSchema[pReq->ntb.schemaRow.nCols - 1].colId + 1,
|
||||
.colCmpr = pReq->colCmpr,
|
||||
.version = version,
|
||||
.type = TSDB_NORMAL_TABLE,
|
||||
.uid = pReq->uid,
|
||||
.name = pReq->name,
|
||||
.ntbEntry.btime = pReq->btime,
|
||||
.ntbEntry.ttlDays = pReq->ttl,
|
||||
.ntbEntry.commentLen = pReq->commentLen,
|
||||
.ntbEntry.comment = pReq->comment,
|
||||
.ntbEntry.schemaRow = pReq->ntb.schemaRow,
|
||||
.ntbEntry.ncid = pReq->ntb.schemaRow.pSchema[pReq->ntb.schemaRow.nCols - 1].colId + 1,
|
||||
.colCmpr = pReq->colCmpr,
|
||||
.pExtSchemas = pReq->pExtSchemas,
|
||||
};
|
||||
TABLE_SET_COL_COMPRESSED(entry.flags);
|
||||
|
||||
|
@ -621,6 +628,7 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
|
|||
int32_t rowSize = 0;
|
||||
SSchemaWrapper *pSchema = &pEntry->ntbEntry.schemaRow;
|
||||
SSchema *pColumn;
|
||||
SExtSchema extSchema = {0};
|
||||
pEntry->version = version;
|
||||
for (int32_t i = 0; i < pSchema->nCols; i++) {
|
||||
pColumn = &pSchema->pSchema[i];
|
||||
|
@ -655,6 +663,7 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
|
|||
pColumn->type = pReq->type;
|
||||
pColumn->flags = pReq->flags;
|
||||
pColumn->colId = pEntry->ntbEntry.ncid++;
|
||||
extSchema.typeMod = pReq->typeMod;
|
||||
tstrncpy(pColumn->name, pReq->colName, TSDB_COL_NAME_LEN);
|
||||
uint32_t compress;
|
||||
if (TSDB_ALTER_TABLE_ADD_COLUMN == pReq->action) {
|
||||
|
@ -669,6 +678,13 @@ int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, ST
|
|||
metaFetchEntryFree(&pEntry);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
code = addTableExtSchema(pEntry, pColumn, pSchema->nCols, &extSchema);
|
||||
if (code) {
|
||||
metaError("vgId:%d, %s failed to add ext schema at %s:%d since %s, version:%" PRId64, TD_VID(pMeta->pVnode),
|
||||
__func__, __FILE__, __LINE__, tstrerror(code), version);
|
||||
metaFetchEntryFree(&pEntry);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
// do handle entry
|
||||
code = metaHandleEntry2(pMeta, pEntry);
|
||||
|
@ -777,6 +793,15 @@ int32_t metaDropTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, S
|
|||
TAOS_RETURN(TSDB_CODE_VND_INVALID_TABLE_ACTION);
|
||||
}
|
||||
|
||||
// update column extschema
|
||||
code = dropTableExtSchema(pEntry, iColumn, pSchema->nCols);
|
||||
if (code) {
|
||||
metaError("vgId:%d, %s failed to remove extschema at %s:%d since %s, version:%" PRId64, TD_VID(pMeta->pVnode),
|
||||
__func__, __FILE__, __LINE__, tstrerror(code), version);
|
||||
metaFetchEntryFree(&pEntry);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
// do handle entry
|
||||
code = metaHandleEntry2(pMeta, pEntry);
|
||||
if (code) {
|
||||
|
@ -1763,6 +1788,7 @@ int32_t metaAlterSuperTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq)
|
|||
.stbEntry.schemaTag = pReq->schemaTag,
|
||||
.stbEntry.keep = pReq->keep,
|
||||
.colCmpr = pReq->colCmpr,
|
||||
.pExtSchemas = pReq->pExtSchemas,
|
||||
};
|
||||
TABLE_SET_COL_COMPRESSED(entry.flags);
|
||||
|
||||
|
@ -1819,4 +1845,4 @@ int32_t metaDropMultipleTables(SMeta *pMeta, int64_t version, SArray *uidArray)
|
|||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ void tqSetTablePrimaryKey(STqReader* pReader, int64_t uid) {
|
|||
return;
|
||||
}
|
||||
bool ret = false;
|
||||
SSchemaWrapper* schema = metaGetTableSchema(pReader->pVnodeMeta, uid, -1, 1);
|
||||
SSchemaWrapper* schema = metaGetTableSchema(pReader->pVnodeMeta, uid, -1, 1, NULL);
|
||||
if (schema && schema->nCols >= 2 && schema->pSchema[1].flags & COL_IS_KEY) {
|
||||
ret = true;
|
||||
}
|
||||
|
@ -336,6 +336,7 @@ void tqReaderClose(STqReader* pReader) {
|
|||
tDeleteSchemaWrapper(pReader->pSchemaWrapper);
|
||||
}
|
||||
|
||||
taosMemoryFree(pReader->extSchema);
|
||||
if (pReader->pColIdList) {
|
||||
taosArrayDestroy(pReader->pColIdList);
|
||||
}
|
||||
|
@ -597,7 +598,7 @@ END:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t tqMaskBlock(SSchemaWrapper* pDst, SSDataBlock* pBlock, const SSchemaWrapper* pSrc, char* mask) {
|
||||
int32_t tqMaskBlock(SSchemaWrapper* pDst, SSDataBlock* pBlock, const SSchemaWrapper* pSrc, char* mask, SExtSchema* extSrc) {
|
||||
if (pDst == NULL || pBlock == NULL || pSrc == NULL || mask == NULL) {
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
@ -620,6 +621,9 @@ int32_t tqMaskBlock(SSchemaWrapper* pDst, SSDataBlock* pBlock, const SSchemaWrap
|
|||
pDst->pSchema[j++] = pSrc->pSchema[i];
|
||||
SColumnInfoData colInfo =
|
||||
createColumnInfoData(pSrc->pSchema[i].type, pSrc->pSchema[i].bytes, pSrc->pSchema[i].colId);
|
||||
if (extSrc != NULL) {
|
||||
decimalFromTypeMod(extSrc[i].typeMod, &colInfo.info.precision, &colInfo.info.scale);
|
||||
}
|
||||
code = blockDataAppendColInfo(pBlock, &colInfo);
|
||||
if (code != 0) {
|
||||
return code;
|
||||
|
@ -653,6 +657,9 @@ static int32_t buildResSDataBlock(STqReader* pReader, SSchemaWrapper* pSchema, c
|
|||
SSchema* pColSchema = &pSchema->pSchema[i];
|
||||
SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId);
|
||||
|
||||
if (IS_DECIMAL_TYPE(pColSchema->type) && pReader->extSchema != NULL) {
|
||||
decimalFromTypeMod(pReader->extSchema[i].typeMod, &colInfo.info.precision, &colInfo.info.scale);
|
||||
}
|
||||
int32_t code = blockDataAppendColInfo(pBlock, &colInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
blockDataFreeRes(pBlock);
|
||||
|
@ -680,6 +687,9 @@ static int32_t buildResSDataBlock(STqReader* pReader, SSchemaWrapper* pSchema, c
|
|||
j++;
|
||||
} else {
|
||||
SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId);
|
||||
if (IS_DECIMAL_TYPE(pColSchema->type) && pReader->extSchema != NULL) {
|
||||
decimalFromTypeMod(pReader->extSchema[i].typeMod, &colInfo.info.precision, &colInfo.info.scale);
|
||||
}
|
||||
int32_t code = blockDataAppendColInfo(pBlock, &colInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return -1;
|
||||
|
@ -708,7 +718,7 @@ static int32_t doSetVal(SColumnInfoData* pColumnInfoData, int32_t rowIndex, SCol
|
|||
colDataSetNULL(pColumnInfoData, rowIndex);
|
||||
}
|
||||
} else {
|
||||
code = colDataSetVal(pColumnInfoData, rowIndex, (void*)&pColVal->value.val, !COL_VAL_IS_VALUE(pColVal));
|
||||
code = colDataSetVal(pColumnInfoData, rowIndex, VALUE_GET_DATUM(&pColVal->value, pColVal->value.type), !COL_VAL_IS_VALUE(pColVal));
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -741,8 +751,8 @@ int32_t tqRetrieveDataBlock(STqReader* pReader, SSDataBlock** pRes, const char*
|
|||
if ((suid != 0 && pReader->cachedSchemaSuid != suid) || (suid == 0 && pReader->cachedSchemaUid != uid) ||
|
||||
(pReader->cachedSchemaVer != sversion)) {
|
||||
tDeleteSchemaWrapper(pReader->pSchemaWrapper);
|
||||
|
||||
pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1);
|
||||
taosMemoryFree(pReader->extSchema);
|
||||
pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1, &pReader->extSchema);
|
||||
if (pReader->pSchemaWrapper == NULL) {
|
||||
tqWarn("vgId:%d, cannot found schema wrapper for table: suid:%" PRId64 ", uid:%" PRId64
|
||||
"version %d, possibly dropped table",
|
||||
|
@ -883,7 +893,7 @@ END:
|
|||
}
|
||||
|
||||
static int32_t processBuildNew(STqReader* pReader, SSubmitTbData* pSubmitTbData, SArray* blocks, SArray* schemas,
|
||||
SSchemaWrapper* pSchemaWrapper, char* assigned, int32_t numOfRows, int32_t curRow,
|
||||
char* assigned, int32_t numOfRows, int32_t curRow,
|
||||
int32_t* lastRow) {
|
||||
int32_t code = 0;
|
||||
SSchemaWrapper* pSW = NULL;
|
||||
|
@ -901,7 +911,7 @@ static int32_t processBuildNew(STqReader* pReader, SSubmitTbData* pSubmitTbData,
|
|||
pSW = taosMemoryCalloc(1, sizeof(SSchemaWrapper));
|
||||
TQ_NULL_GO_TO_END(pSW);
|
||||
|
||||
TQ_ERR_GO_TO_END(tqMaskBlock(pSW, block, pSchemaWrapper, assigned));
|
||||
TQ_ERR_GO_TO_END(tqMaskBlock(pSW, block, pReader->pSchemaWrapper, assigned, pReader->extSchema));
|
||||
tqTrace("vgId:%d, build new block, col %d", pReader->pWalReader->pWal->cfg.vgId,
|
||||
(int32_t)taosArrayGetSize(block->pDataBlock));
|
||||
|
||||
|
@ -911,6 +921,7 @@ static int32_t processBuildNew(STqReader* pReader, SSubmitTbData* pSubmitTbData,
|
|||
TQ_NULL_GO_TO_END(taosArrayPush(blocks, block));
|
||||
TQ_NULL_GO_TO_END(taosArrayPush(schemas, &pSW));
|
||||
pSW = NULL;
|
||||
|
||||
taosMemoryFreeClear(block);
|
||||
|
||||
END:
|
||||
|
@ -949,7 +960,7 @@ static int32_t tqProcessColData(STqReader* pReader, SSubmitTbData* pSubmitTbData
|
|||
}
|
||||
|
||||
if (buildNew) {
|
||||
TQ_ERR_GO_TO_END(processBuildNew(pReader, pSubmitTbData, blocks, schemas, pSchemaWrapper, assigned, numOfRows,
|
||||
TQ_ERR_GO_TO_END(processBuildNew(pReader, pSubmitTbData, blocks, schemas, assigned, numOfRows,
|
||||
curRow, &lastRow));
|
||||
}
|
||||
|
||||
|
@ -1013,7 +1024,7 @@ int32_t tqProcessRowData(STqReader* pReader, SSubmitTbData* pSubmitTbData, SArra
|
|||
}
|
||||
|
||||
if (buildNew) {
|
||||
TQ_ERR_GO_TO_END(processBuildNew(pReader, pSubmitTbData, blocks, schemas, pSchemaWrapper, assigned, numOfRows,
|
||||
TQ_ERR_GO_TO_END(processBuildNew(pReader, pSubmitTbData, blocks, schemas, assigned, numOfRows,
|
||||
curRow, &lastRow));
|
||||
}
|
||||
|
||||
|
@ -1119,7 +1130,8 @@ int32_t tqRetrieveTaosxBlock(STqReader* pReader, SMqDataRsp* pRsp, SArray* block
|
|||
pReader->lastBlkUid = uid;
|
||||
|
||||
tDeleteSchemaWrapper(pReader->pSchemaWrapper);
|
||||
pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1);
|
||||
taosMemoryFree(pReader->extSchema);
|
||||
pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1, &pReader->extSchema);
|
||||
if (pReader->pSchemaWrapper == NULL) {
|
||||
tqWarn("vgId:%d, cannot found schema wrapper for table: suid:%" PRId64 ", version %d, possibly dropped table",
|
||||
pReader->pWalReader->pWal->cfg.vgId, uid, pReader->cachedSchemaVer);
|
||||
|
|
|
@ -313,7 +313,7 @@ END:
|
|||
if (code != 0){
|
||||
tqError("%s failed at %d, vgId:%d, task exec error since %s", __FUNCTION__ , lino, pTq->pVnode->config.vgId, tstrerror(code));
|
||||
}
|
||||
taosMemoryFree(pSW);
|
||||
tDeleteSchemaWrapper(pSW);
|
||||
taosMemoryFree(tbName);
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -823,7 +823,7 @@ int32_t doConvertRows(SSubmitTbData* pTableData, const STSchema* pTSchema, SSDat
|
|||
}
|
||||
} else {
|
||||
SValue sv = {.type = pCol->type};
|
||||
memcpy(&sv.val, colData, tDataTypes[pCol->type].bytes);
|
||||
valueSetDatum(&sv, pCol->type, colData, tDataTypes[pCol->type].bytes);
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
|
||||
void* p = taosArrayPush(pVals, &cv);
|
||||
if (p == NULL) {
|
||||
|
|
|
@ -75,7 +75,6 @@ static int32_t tqInitTaosxRsp(SMqDataRsp* pRsp, STqOffsetVal pOffset) {
|
|||
pRsp->blockSchema = taosArrayInit(0, sizeof(void*));
|
||||
TSDB_CHECK_NULL(pRsp->blockSchema, code, lino, END, terrno);
|
||||
|
||||
|
||||
END:
|
||||
if (code != 0){
|
||||
tqError("%s failed at:%d, code:%s", __FUNCTION__ , lino, tstrerror(code));
|
||||
|
|
|
@ -334,6 +334,10 @@ static int32_t tsdbCacheDeserializeV0(char const *value, SLastCol *pLastCol) {
|
|||
pLastCol->colVal.value.pData = (uint8_t *)(&pLastColV0[1]);
|
||||
}
|
||||
return sizeof(SLastColV0) + pLastColV0->colVal.value.nData;
|
||||
} else if (pLastCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
pLastCol->colVal.value.nData = pLastColV0->colVal.value.nData;
|
||||
pLastCol->colVal.value.pData = (uint8_t*)(&pLastColV0[1]);
|
||||
return sizeof(SLastColV0) + pLastColV0->colVal.value.nData;
|
||||
} else {
|
||||
pLastCol->colVal.value.val = pLastColV0->colVal.value.val;
|
||||
return sizeof(SLastColV0);
|
||||
|
@ -426,6 +430,12 @@ static int32_t tsdbCacheSerializeV0(char const *value, SLastCol *pLastCol) {
|
|||
memcpy(&pLastColV0[1], pLastCol->colVal.value.pData, pLastCol->colVal.value.nData);
|
||||
}
|
||||
return sizeof(SLastColV0) + pLastCol->colVal.value.nData;
|
||||
} else if (pLastCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
pLastColV0->colVal.value.nData = pLastCol->colVal.value.nData;
|
||||
if (pLastCol->colVal.value.nData > 0) {
|
||||
memcpy(&pLastColV0[1], pLastCol->colVal.value.pData, pLastCol->colVal.value.nData);
|
||||
}
|
||||
return sizeof(SLastColV0) + pLastCol->colVal.value.nData;
|
||||
} else {
|
||||
pLastColV0->colVal.value.val = pLastCol->colVal.value.val;
|
||||
return sizeof(SLastColV0);
|
||||
|
@ -439,6 +449,9 @@ static int32_t tsdbCacheSerialize(SLastCol *pLastCol, char **value, size_t *size
|
|||
if (IS_VAR_DATA_TYPE(pLastCol->colVal.value.type)) {
|
||||
*size += pLastCol->colVal.value.nData;
|
||||
}
|
||||
if (pLastCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
*size += DECIMAL128_BYTES;
|
||||
}
|
||||
*size += sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t); // version + numOfPKs + cacheStatus
|
||||
|
||||
for (int8_t i = 0; i < pLastCol->rowKey.numOfPKs; i++) {
|
||||
|
@ -840,6 +853,16 @@ static int32_t tsdbCacheReallocSLastCol(SLastCol *pCol, size_t *pCharge) {
|
|||
charge += pCol->colVal.value.nData;
|
||||
}
|
||||
|
||||
if (pCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
if (pCol->colVal.value.nData > 0) {
|
||||
void *p = taosMemoryMalloc(pCol->colVal.value.nData);
|
||||
if (!p) TAOS_CHECK_EXIT(terrno);
|
||||
(void)memcpy(p, pCol->colVal.value.pData, pCol->colVal.value.nData);
|
||||
pCol->colVal.value.pData = p;
|
||||
}
|
||||
charge += pCol->colVal.value.nData;
|
||||
}
|
||||
|
||||
if (pCharge) {
|
||||
*pCharge = charge;
|
||||
}
|
||||
|
@ -866,7 +889,8 @@ void tsdbCacheFreeSLastColItem(void *pItem) {
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_VAR_DATA_TYPE(pCol->colVal.value.type) && pCol->colVal.value.pData) {
|
||||
if ((IS_VAR_DATA_TYPE(pCol->colVal.value.type) || pCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL) &&
|
||||
pCol->colVal.value.pData) {
|
||||
taosMemoryFree(pCol->colVal.value.pData);
|
||||
}
|
||||
}
|
||||
|
@ -888,7 +912,8 @@ static void tsdbCacheDeleter(const void *key, size_t klen, void *value, void *ud
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_VAR_DATA_TYPE(pLastCol->colVal.value.type) /* && pLastCol->colVal.value.nData > 0*/) {
|
||||
if (IS_VAR_DATA_TYPE(pLastCol->colVal.value.type) ||
|
||||
pLastCol->colVal.value.type == TSDB_DATA_TYPE_DECIMAL /* && pLastCol->colVal.value.nData > 0*/) {
|
||||
taosMemoryFree(pLastCol->colVal.value.pData);
|
||||
}
|
||||
|
||||
|
@ -1341,7 +1366,7 @@ static void tsdbCacheUpdateLastColToNone(SLastCol *pLastCol, ELastCacheStatus ca
|
|||
taosMemoryFreeClear(pPKValue->pData);
|
||||
pPKValue->nData = 0;
|
||||
} else {
|
||||
pPKValue->val = 0;
|
||||
valueClearDatum(pPKValue, pPKValue->type);
|
||||
}
|
||||
}
|
||||
pLastCol->rowKey.numOfPKs = 0;
|
||||
|
@ -1351,7 +1376,7 @@ static void tsdbCacheUpdateLastColToNone(SLastCol *pLastCol, ELastCacheStatus ca
|
|||
taosMemoryFreeClear(pLastCol->colVal.value.pData);
|
||||
pLastCol->colVal.value.nData = 0;
|
||||
} else {
|
||||
pLastCol->colVal.value.val = 0;
|
||||
valueClearDatum(&pLastCol->colVal.value, pLastCol->colVal.value.type);
|
||||
}
|
||||
|
||||
pLastCol->colVal = COL_VAL_NONE(pLastCol->colVal.cid, pLastCol->colVal.value.type);
|
||||
|
@ -1708,11 +1733,12 @@ int32_t tsdbCacheColFormatUpdate(STsdb *pTsdb, tb_uid_t suid, tb_uid_t uid, SBlo
|
|||
tsdbRowGetKey(&lRow, &tsdbRowKey);
|
||||
|
||||
{
|
||||
SValue tsVal = {.type = TSDB_DATA_TYPE_TIMESTAMP};
|
||||
VALUE_SET_TRIVIAL_DATUM(&tsVal, lRow.pBlockData->aTSKEY[lRow.iRow]);
|
||||
SLastUpdateCtx updateCtx = {
|
||||
.lflag = LFLAG_LAST,
|
||||
.tsdbRowKey = tsdbRowKey,
|
||||
.colVal = COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID, ((SValue){.type = TSDB_DATA_TYPE_TIMESTAMP,
|
||||
.val = lRow.pBlockData->aTSKEY[lRow.iRow]}))};
|
||||
.colVal = COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID, tsVal)};
|
||||
if (!taosArrayPush(ctxArray, &updateCtx)) {
|
||||
TAOS_CHECK_GOTO(terrno, &lino, _exit);
|
||||
}
|
||||
|
@ -3857,7 +3883,9 @@ static int32_t mergeLastCid(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SC
|
|||
}
|
||||
if (slotIds[iCol] == 0) {
|
||||
STColumn *pTColumn = &pTSchema->columns[0];
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, ((SValue){.type = pTColumn->type, .val = rowKey.key.ts}));
|
||||
SValue val = {.type = pTColumn->type};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, rowKey.key.ts);
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, val);
|
||||
|
||||
SLastCol colTmp = {.rowKey = rowKey.key, .colVal = *pColVal, .cacheStatus = TSDB_LAST_CACHE_VALID};
|
||||
TAOS_CHECK_GOTO(tsdbCacheReallocSLastCol(&colTmp, NULL), &lino, _err);
|
||||
|
@ -4025,7 +4053,9 @@ static int32_t mergeLastRowCid(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray,
|
|||
}
|
||||
if (slotIds[iCol] == 0) {
|
||||
STColumn *pTColumn = &pTSchema->columns[0];
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, ((SValue){.type = pTColumn->type, .val = rowKey.key.ts}));
|
||||
SValue val = {.type = pTColumn->type};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, rowKey.key.ts);
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, val);
|
||||
|
||||
SLastCol colTmp = {.rowKey = rowKey.key, .colVal = *pColVal, .cacheStatus = TSDB_LAST_CACHE_VALID};
|
||||
TAOS_CHECK_GOTO(tsdbCacheReallocSLastCol(&colTmp, NULL), &lino, _err);
|
||||
|
|
|
@ -77,7 +77,8 @@ static int32_t saveOneRowForLastRaw(SLastCol* pColVal, SCacheRowsReader* pReader
|
|||
TSDB_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
} else {
|
||||
code = colDataSetVal(pColInfoData, numOfRows, (const char*)&pVal->value.val, !COL_VAL_IS_VALUE(pVal));
|
||||
code = colDataSetVal(pColInfoData, numOfRows, VALUE_GET_DATUM(&pVal->value, pColVal->colVal.value.type),
|
||||
!COL_VAL_IS_VALUE(pVal));
|
||||
TSDB_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
|
||||
|
@ -166,7 +167,8 @@ static int32_t saveOneRow(SArray* pRow, SSDataBlock* pBlock, SCacheRowsReader* p
|
|||
memcpy(varDataVal(p->buf), pColVal->colVal.value.pData, pColVal->colVal.value.nData);
|
||||
p->bytes = pColVal->colVal.value.nData + VARSTR_HEADER_SIZE; // binary needs to plus the header size
|
||||
} else {
|
||||
memcpy(p->buf, &pColVal->colVal.value.val, pReader->pSchema->columns[slotId].bytes);
|
||||
memcpy(p->buf, VALUE_GET_DATUM(&pColVal->colVal.value, pColVal->colVal.value.type),
|
||||
pReader->pSchema->columns[slotId].bytes);
|
||||
p->bytes = pReader->pSchema->columns[slotId].bytes;
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +545,7 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
||||
if (IS_VAR_DATA_TYPE(pCol->type) || pCol->type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
p.colVal.value.pData = taosMemoryCalloc(pCol->bytes, sizeof(char));
|
||||
TSDB_CHECK_NULL(p.colVal.value.pData, code, lino, _end, terrno);
|
||||
}
|
||||
|
@ -601,7 +603,7 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32
|
|||
memcpy(p->rowKey.pks[j].pData, pColVal->rowKey.pks[j].pData, pColVal->rowKey.pks[j].nData);
|
||||
p->rowKey.pks[j].nData = pColVal->rowKey.pks[j].nData;
|
||||
} else {
|
||||
p->rowKey.pks[j].val = pColVal->rowKey.pks[j].val;
|
||||
valueCloneDatum(p->rowKey.pks + j, pColVal->rowKey.pks + j, p->rowKey.pks[j].type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,7 +630,7 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32
|
|||
goto _end;
|
||||
}
|
||||
|
||||
if (!IS_VAR_DATA_TYPE(pColVal->colVal.value.type)) {
|
||||
if (!IS_VAR_DATA_TYPE(pColVal->colVal.value.type) && pColVal->colVal.value.type != TSDB_DATA_TYPE_DECIMAL) {
|
||||
p->colVal = pColVal->colVal;
|
||||
} else {
|
||||
if (COL_VAL_IS_VALUE(&pColVal->colVal)) {
|
||||
|
|
|
@ -1069,7 +1069,7 @@ static int32_t tsdbDataFileDoWriteBlockData(SDataFileWriter *writer, SBlockData
|
|||
if ((colData->cflag & COL_SMA_ON) == 0 || ((colData->flag & HAS_VALUE) == 0)) continue;
|
||||
|
||||
SColumnDataAgg sma[1] = {{.colId = colData->cid}};
|
||||
tColDataCalcSMA[colData->type](colData, &sma->sum, &sma->max, &sma->min, &sma->numOfNull);
|
||||
tColDataCalcSMA[colData->type](colData, sma);
|
||||
|
||||
TAOS_CHECK_GOTO(tPutColumnDataAgg(&buffers[0], sma), &lino, _exit);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ int32_t tCreateSttBlockLoadInfo(STSchema *pSchema, int16_t *colList, int32_t num
|
|||
|
||||
static void freeItem(void *pValue) {
|
||||
SValue *p = (SValue *)pValue;
|
||||
if (IS_VAR_DATA_TYPE(p->type)) {
|
||||
if (IS_VAR_DATA_TYPE(p->type) || p->type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
taosMemoryFree(p->pData);
|
||||
}
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ static int32_t extractSttBlockInfo(SLDataIter *pIter, const TSttBlkArray *pArray
|
|||
}
|
||||
|
||||
static int32_t tValueDupPayload(SValue *pVal) {
|
||||
if (IS_VAR_DATA_TYPE(pVal->type)) {
|
||||
if (IS_VAR_DATA_TYPE(pVal->type) || pVal->type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
char *p = (char *)pVal->pData;
|
||||
char *pBuf = taosMemoryMalloc(pVal->nData);
|
||||
if (pBuf == NULL) {
|
||||
|
|
|
@ -130,7 +130,7 @@ static int32_t tColRowGetPriamyKeyDeepCopy(SBlockData* pBlock, int32_t irow, int
|
|||
pKey->pks[0].type = cv.value.type;
|
||||
|
||||
if (IS_NUMERIC_TYPE(cv.value.type)) {
|
||||
pKey->pks[0].val = cv.value.val;
|
||||
valueCloneDatum(pKey->pks, &cv.value, cv.value.type);
|
||||
} else {
|
||||
pKey->pks[0].nData = cv.value.nData;
|
||||
TAOS_MEMCPY(pKey->pks[0].pData, cv.value.pData, cv.value.nData);
|
||||
|
@ -182,7 +182,7 @@ static int32_t tRowGetPrimaryKeyDeepCopy(SRow* pRow, SRowKey* pKey) {
|
|||
tdata += tGetU32v(tdata, &pKey->pks[i].nData);
|
||||
TAOS_MEMCPY(pKey->pks[i].pData, tdata, pKey->pks[i].nData);
|
||||
} else {
|
||||
TAOS_MEMCPY(&pKey->pks[i].val, data + indices[i].offset, tDataTypes[pKey->pks[i].type].bytes);
|
||||
valueSetDatum(pKey->pks + i, indices[i].type, data + indices[i].offset, tDataTypes[pKey->pks[i].type].bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1084,7 @@ static int32_t updateLastKeyInfo(SRowKey* pKey, SFileDataBlockInfo* pBlockInfo,
|
|||
|
||||
TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
|
||||
if (IS_NUMERIC_TYPE(pKey->pks[0].type)) {
|
||||
pKey->pks[0].val = asc ? pBlockInfo->lastPk.val : pBlockInfo->firstPk.val;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, asc ? pBlockInfo->lastPk.val : pBlockInfo->firstPk.val);
|
||||
} else {
|
||||
uint8_t* p = asc ? pBlockInfo->lastPk.pData : pBlockInfo->firstPk.pData;
|
||||
pKey->pks[0].nData = asc ? varDataLen(pBlockInfo->lastPk.pData) : varDataLen(pBlockInfo->firstPk.pData);
|
||||
|
@ -1127,7 +1127,8 @@ static int32_t doCopyColVal(SColumnInfoData* pColInfoData, int32_t rowIndex, int
|
|||
TSDB_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
} else {
|
||||
code = colDataSetVal(pColInfoData, rowIndex, (const char*)&pColVal->value.val, !COL_VAL_IS_VALUE(pColVal));
|
||||
code = colDataSetVal(pColInfoData, rowIndex, VALUE_GET_DATUM(&pColVal->value, pColVal->value.type),
|
||||
!COL_VAL_IS_VALUE(pColVal));
|
||||
TSDB_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
|
||||
|
@ -1353,6 +1354,7 @@ static int32_t copyNumericCols(const SColData* pData, SFileBlockDumpInfo* pDumpI
|
|||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_UBIGINT: {
|
||||
int32_t mid = dumpedRows >> 1u;
|
||||
int64_t* pts = (int64_t*)pColData->pData;
|
||||
|
@ -1401,6 +1403,20 @@ static int32_t copyNumericCols(const SColData* pData, SFileBlockDumpInfo* pDumpI
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
int32_t mid = dumpedRows >> 1u;
|
||||
DecimalWord* pDec = (DecimalWord*)pColData->pData;
|
||||
DecimalWord tmp[2] = {0};
|
||||
for (int32_t j = 0; j < mid; ++j) {
|
||||
tmp[0] = pDec[2 * j];
|
||||
tmp[1] = pDec[2 * j + 1];
|
||||
pDec[2 * j] = pDec[2 * (dumpedRows - j - 1)];
|
||||
pDec[2 * j + 1] = pDec[2 * (dumpedRows - j - 1) + 1];
|
||||
pDec[2 * (dumpedRows - j - 1)] = tmp[0];
|
||||
pDec[2 * (dumpedRows - j - 1) + 1] = tmp[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1443,8 +1459,8 @@ static void blockInfoToRecord(SBrinRecord* record, SFileDataBlockInfo* pBlockInf
|
|||
pLast->pData = (uint8_t*)varDataVal(pBlockInfo->lastPk.pData);
|
||||
pLast->nData = varDataLen(pBlockInfo->lastPk.pData);
|
||||
} else {
|
||||
pFirst->val = pBlockInfo->firstPk.val;
|
||||
pLast->val = pBlockInfo->lastPk.val;
|
||||
VALUE_SET_TRIVIAL_DATUM(pFirst, pBlockInfo->firstPk.val);
|
||||
VALUE_SET_TRIVIAL_DATUM(pLast, pBlockInfo->lastPk.val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1899,7 +1915,7 @@ static bool overlapWithNeighborBlock2(SFileDataBlockInfo* pBlock, SBrinRecord* p
|
|||
if (IS_VAR_DATA_TYPE(pkType)) {
|
||||
v1.pData = (uint8_t*)varDataVal(pBlock->lastPk.pData), v1.nData = varDataLen(pBlock->lastPk.pData);
|
||||
} else {
|
||||
v1.val = pBlock->lastPk.val;
|
||||
VALUE_SET_TRIVIAL_DATUM(&v1, pBlock->lastPk.val);
|
||||
}
|
||||
return (tValueCompare(&v1, &pRec->firstKey.key.pks[0]) == 0);
|
||||
} else { // no pk
|
||||
|
@ -1915,7 +1931,7 @@ static bool overlapWithNeighborBlock2(SFileDataBlockInfo* pBlock, SBrinRecord* p
|
|||
if (IS_VAR_DATA_TYPE(pkType)) {
|
||||
v1.pData = (uint8_t*)varDataVal(pBlock->firstPk.pData), v1.nData = varDataLen(pBlock->firstPk.pData);
|
||||
} else {
|
||||
v1.val = pBlock->firstPk.val;
|
||||
VALUE_SET_TRIVIAL_DATUM(&v1, pBlock->firstPk.val);
|
||||
}
|
||||
return (tValueCompare(&v1, &pRec->lastKey.key.pks[0]) == 0);
|
||||
} else { // no pk
|
||||
|
@ -2192,7 +2208,7 @@ static int32_t nextRowFromSttBlocks(SSttBlockReader* pSttBlockReader, STableBloc
|
|||
pNextProc->ts += step;
|
||||
if (pSttBlockReader->numOfPks > 0) {
|
||||
if (IS_NUMERIC_TYPE(pNextProc->pks[0].type)) {
|
||||
pNextProc->pks[0].val = INT64_MIN;
|
||||
VALUE_SET_TRIVIAL_DATUM(pNextProc->pks, INT64_MAX);
|
||||
} else {
|
||||
memset(pNextProc->pks[0].pData, 0, pNextProc->pks[0].nData);
|
||||
}
|
||||
|
@ -3759,8 +3775,8 @@ static int32_t buildCleanBlockFromDataFiles(STsdbReader* pReader, STableBlockSca
|
|||
|
||||
if (pReader->suppInfo.numOfPks > 0) {
|
||||
if (IS_NUMERIC_TYPE(pReader->suppInfo.pk.type)) {
|
||||
pInfo->pks[0].val = pBlockInfo->firstPk.val;
|
||||
pInfo->pks[1].val = pBlockInfo->lastPk.val;
|
||||
VALUE_SET_TRIVIAL_DATUM(pInfo->pks, pBlockInfo->firstPk.val);
|
||||
VALUE_SET_TRIVIAL_DATUM(pInfo->pks + 1, pBlockInfo->lastPk.val);
|
||||
} else {
|
||||
(void)memcpy(pInfo->pks[0].pData, varDataVal(pBlockInfo->firstPk.pData), varDataLen(pBlockInfo->firstPk.pData));
|
||||
(void)memcpy(pInfo->pks[1].pData, varDataVal(pBlockInfo->lastPk.pData), varDataLen(pBlockInfo->lastPk.pData));
|
||||
|
|
|
@ -221,29 +221,29 @@ int32_t initRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, in
|
|||
if (asc) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
pKey->pks[0].val = INT64_MIN;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, INT64_MIN);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
int32_t min = INT32_MIN;
|
||||
(void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
|
||||
valueSetDatum(pKey->pks, type, &min, tDataTypes[type].bytes);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
int16_t min = INT16_MIN;
|
||||
(void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
|
||||
valueSetDatum(pKey->pks, type, &min, tDataTypes[type].bytes);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
int8_t min = INT8_MIN;
|
||||
(void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
|
||||
valueSetDatum(pKey->pks, type, &min, tDataTypes[type].bytes);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT: {
|
||||
pKey->pks[0].val = 0;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -253,28 +253,28 @@ int32_t initRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, in
|
|||
} else {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
pKey->pks[0].val = INT64_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, INT64_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
pKey->pks[0].val = INT32_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, INT32_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
pKey->pks[0].val = INT16_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, INT16_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
pKey->pks[0].val = INT8_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, INT8_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
pKey->pks[0].val = UINT64_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, UINT64_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
pKey->pks[0].val = UINT32_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, UINT32_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
pKey->pks[0].val = UINT16_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, UINT16_MAX);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
pKey->pks[0].val = UINT8_MAX;
|
||||
VALUE_SET_TRIVIAL_DATUM(pKey->pks, UINT8_MAX);
|
||||
break;
|
||||
default:
|
||||
code = TSDB_CODE_INVALID_PARA;
|
||||
|
@ -722,8 +722,8 @@ int32_t recordToBlockInfo(SFileDataBlockInfo* pBlockInfo, SBrinRecord* record) {
|
|||
TSDB_CHECK_CONDITION((pFirstKey->numOfPKs == pLastKey->numOfPKs), code, lino, _end, TSDB_CODE_INVALID_PARA);
|
||||
if (pFirstKey->numOfPKs > 0) {
|
||||
if (IS_NUMERIC_TYPE(pFirstKey->pks[0].type)) {
|
||||
pBlockInfo->firstPk.val = pFirstKey->pks[0].val;
|
||||
pBlockInfo->lastPk.val = pLastKey->pks[0].val;
|
||||
pBlockInfo->firstPk.val = VALUE_GET_TRIVIAL_DATUM(pFirstKey->pks);
|
||||
pBlockInfo->lastPk.val = VALUE_GET_TRIVIAL_DATUM(pLastKey->pks);
|
||||
} else {
|
||||
int32_t keyLen = pFirstKey->pks[0].nData;
|
||||
char* p = taosMemoryMalloc(keyLen + VARSTR_HEADER_SIZE);
|
||||
|
|
|
@ -615,9 +615,9 @@ void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *
|
|||
}
|
||||
} else if (pRow->type == TSDBROW_COL_FMT) {
|
||||
if (iCol == 0) {
|
||||
*pColVal =
|
||||
COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID,
|
||||
((SValue){.type = TSDB_DATA_TYPE_TIMESTAMP, .val = pRow->pBlockData->aTSKEY[pRow->iRow]}));
|
||||
SValue val = {.type = TSDB_DATA_TYPE_TIMESTAMP};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, pRow->pBlockData->aTSKEY[pRow->iRow]);
|
||||
*pColVal = COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID, val);
|
||||
} else {
|
||||
SColData *pColData = tBlockDataGetColData(pRow->pBlockData, pTColumn->colId);
|
||||
|
||||
|
@ -715,9 +715,9 @@ SColVal *tsdbRowIterNext(STSDBRowIter *pIter) {
|
|||
return tRowIterNext(pIter->pIter);
|
||||
} else if (pIter->pRow->type == TSDBROW_COL_FMT) {
|
||||
if (pIter->iColData == 0) {
|
||||
pIter->cv = COL_VAL_VALUE(
|
||||
PRIMARYKEY_TIMESTAMP_COL_ID,
|
||||
((SValue){.type = TSDB_DATA_TYPE_TIMESTAMP, .val = pIter->pRow->pBlockData->aTSKEY[pIter->pRow->iRow]}));
|
||||
SValue val = {.type = TSDB_DATA_TYPE_TIMESTAMP};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, pIter->pRow->pBlockData->aTSKEY[pIter->pRow->iRow]);
|
||||
pIter->cv = COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID, val);
|
||||
++pIter->iColData;
|
||||
return &pIter->cv;
|
||||
}
|
||||
|
@ -754,8 +754,9 @@ int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema)
|
|||
// ts
|
||||
jCol = 0;
|
||||
pTColumn = &pTSchema->columns[jCol++];
|
||||
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, ((SValue){.type = pTColumn->type, .val = key.ts}));
|
||||
SValue val = {.type = pTColumn->type};
|
||||
VALUE_SET_TRIVIAL_DATUM(&val, key.ts);
|
||||
*pColVal = COL_VAL_VALUE(pTColumn->colId, val);
|
||||
if (taosArrayPush(pMerger->pArray, pColVal) == NULL) {
|
||||
code = terrno;
|
||||
return code;
|
||||
|
@ -776,7 +777,8 @@ int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema)
|
|||
}
|
||||
|
||||
tsdbRowGetColVal(pRow, pTSchema, jCol++, pColVal);
|
||||
if ((!COL_VAL_IS_NONE(pColVal)) && (!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->value.type)) {
|
||||
bool usepData = IS_VAR_DATA_TYPE(pColVal->value.type) || pColVal->value.type == TSDB_DATA_TYPE_DECIMAL;
|
||||
if ((!COL_VAL_IS_NONE(pColVal)) && (!COL_VAL_IS_NULL(pColVal)) && usepData) {
|
||||
uint8_t *pVal = pColVal->value.pData;
|
||||
|
||||
pColVal->value.pData = NULL;
|
||||
|
@ -819,7 +821,7 @@ int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema)
|
|||
|
||||
if (key.version > pMerger->version) {
|
||||
if (!COL_VAL_IS_NONE(pColVal)) {
|
||||
if (IS_VAR_DATA_TYPE(pColVal->value.type)) {
|
||||
if (IS_VAR_DATA_TYPE(pColVal->value.type) || pColVal->value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol);
|
||||
if (!pTColVal) return terrno;
|
||||
if (!COL_VAL_IS_NULL(pColVal)) {
|
||||
|
@ -842,7 +844,8 @@ int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema)
|
|||
} else if (key.version < pMerger->version) {
|
||||
SColVal *tColVal = (SColVal *)taosArrayGet(pMerger->pArray, iCol);
|
||||
if (COL_VAL_IS_NONE(tColVal) && !COL_VAL_IS_NONE(pColVal)) {
|
||||
if ((!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->value.type)) {
|
||||
bool usepData = IS_VAR_DATA_TYPE(pColVal->value.type) || pColVal->value.type == TSDB_DATA_TYPE_DECIMAL;
|
||||
if ((!COL_VAL_IS_NULL(pColVal)) && usepData) {
|
||||
code = tRealloc(&tColVal->value.pData, pColVal->value.nData);
|
||||
if (code) return code;
|
||||
|
||||
|
@ -878,7 +881,7 @@ int32_t tsdbRowMergerInit(SRowMerger *pMerger, STSchema *pSchema) {
|
|||
void tsdbRowMergerClear(SRowMerger *pMerger) {
|
||||
for (int32_t iCol = 1; iCol < pMerger->pTSchema->numOfCols; iCol++) {
|
||||
SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol);
|
||||
if (IS_VAR_DATA_TYPE(pTColVal->value.type)) {
|
||||
if (IS_VAR_DATA_TYPE(pTColVal->value.type) || pTColVal->value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
tFree(pTColVal->value.pData);
|
||||
}
|
||||
}
|
||||
|
@ -890,7 +893,7 @@ void tsdbRowMergerCleanup(SRowMerger *pMerger) {
|
|||
int32_t numOfCols = taosArrayGetSize(pMerger->pArray);
|
||||
for (int32_t iCol = 1; iCol < numOfCols; iCol++) {
|
||||
SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol);
|
||||
if (IS_VAR_DATA_TYPE(pTColVal->value.type)) {
|
||||
if (IS_VAR_DATA_TYPE(pTColVal->value.type) || pTColVal->value.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
tFree(pTColVal->value.pData);
|
||||
}
|
||||
}
|
||||
|
@ -1573,11 +1576,23 @@ int32_t tGetDiskDataHdr(SBufferReader *br, SDiskDataHdr *pHdr) {
|
|||
int32_t tPutColumnDataAgg(SBuffer *buffer, SColumnDataAgg *pColAgg) {
|
||||
int32_t code;
|
||||
|
||||
if ((code = tBufferPutI16v(buffer, pColAgg->colId))) return code;
|
||||
if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->sum))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->max))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->min))) return code;
|
||||
if (pColAgg->colId & DECIMAL_AGG_FLAG) {
|
||||
if ((code = tBufferPutI32v(buffer, pColAgg->colId))) return code;
|
||||
if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Sum[0]))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Sum[1]))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Max[0]))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Max[1]))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Min[0]))) return code;
|
||||
if ((code = tBufferPutU64(buffer, pColAgg->decimal128Min[1]))) return code;
|
||||
if ((code = tBufferPutU8(buffer, pColAgg->overflow))) return code;
|
||||
} else {
|
||||
if ((code = tBufferPutI32v(buffer, pColAgg->colId))) return code;
|
||||
if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->sum))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->max))) return code;
|
||||
if ((code = tBufferPutI64(buffer, pColAgg->min))) return code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1585,11 +1600,22 @@ int32_t tPutColumnDataAgg(SBuffer *buffer, SColumnDataAgg *pColAgg) {
|
|||
int32_t tGetColumnDataAgg(SBufferReader *br, SColumnDataAgg *pColAgg) {
|
||||
int32_t code;
|
||||
|
||||
if ((code = tBufferGetI16v(br, &pColAgg->colId))) return code;
|
||||
if ((code = tBufferGetI32v(br, &pColAgg->colId))) return code;
|
||||
if ((code = tBufferGetI16v(br, &pColAgg->numOfNull))) return code;
|
||||
if ((code = tBufferGetI64(br, &pColAgg->sum))) return code;
|
||||
if ((code = tBufferGetI64(br, &pColAgg->max))) return code;
|
||||
if ((code = tBufferGetI64(br, &pColAgg->min))) return code;
|
||||
if (pColAgg->colId & DECIMAL_AGG_FLAG) {
|
||||
pColAgg->colId &= 0xFFFF;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Sum[0]))) return code;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Sum[1]))) return code;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Max[0]))) return code;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Max[1]))) return code;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Min[0]))) return code;
|
||||
if ((code = tBufferGetU64(br, &pColAgg->decimal128Min[1]))) return code;
|
||||
if ((code = tBufferGetU8(br, &pColAgg->overflow))) return code;
|
||||
} else {
|
||||
if ((code = tBufferGetI64(br, &pColAgg->sum))) return code;
|
||||
if ((code = tBufferGetI64(br, &pColAgg->max))) return code;
|
||||
if ((code = tBufferGetI64(br, &pColAgg->min))) return code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ void vnodeQueryClose(SVnode *pVnode) { qWorkerDestroy((void **)&pVnode->pQuery);
|
|||
|
||||
int32_t fillTableColCmpr(SMetaReader *reader, SSchemaExt *pExt, int32_t numOfCol) {
|
||||
int8_t tblType = reader->me.type;
|
||||
if (useCompress(tblType)) {
|
||||
if (withExtSchema(tblType)) {
|
||||
SColCmprWrapper *p = &(reader->me.colCmpr);
|
||||
if (numOfCol != p->nCols) {
|
||||
vError("fillTableColCmpr table type:%d, col num:%d, col cmpr num:%d mismatch", tblType, numOfCol, p->nCols);
|
||||
|
@ -180,6 +180,9 @@ int32_t vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
if (code < 0) {
|
||||
goto _exit;
|
||||
}
|
||||
for (int32_t i = 0; i < metaRsp.numOfColumns && pReader->me.pExtSchemas; i++) {
|
||||
metaRsp.pSchemaExt[i].typeMod = pReader->me.pExtSchemas[i].typeMod;
|
||||
}
|
||||
} else {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _exit;
|
||||
|
@ -348,6 +351,10 @@ int32_t vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg, bool direct) {
|
|||
SSchemaExt *pSchExt = cfgRsp.pSchemaExt + i;
|
||||
pSchExt->colId = pCmpr->id;
|
||||
pSchExt->compress = pCmpr->alg;
|
||||
if (pReader->me.pExtSchemas)
|
||||
pSchExt->typeMod = pReader->me.pExtSchemas[i].typeMod;
|
||||
else
|
||||
pSchExt->typeMod = 0;
|
||||
}
|
||||
//}
|
||||
|
||||
|
@ -753,7 +760,7 @@ int32_t vnodeGetCtbNum(SVnode *pVnode, int64_t suid, int64_t *num) {
|
|||
}
|
||||
|
||||
int32_t vnodeGetStbColumnNum(SVnode *pVnode, tb_uid_t suid, int *num) {
|
||||
SSchemaWrapper *pSW = metaGetTableSchema(pVnode->pMeta, suid, -1, 0);
|
||||
SSchemaWrapper *pSW = metaGetTableSchema(pVnode->pMeta, suid, -1, 0, NULL);
|
||||
if (pSW) {
|
||||
*num = pSW->nCols;
|
||||
tDeleteSchemaWrapper(pSW);
|
||||
|
|
|
@ -1800,11 +1800,11 @@ static int32_t vnodeCellValConvertToColVal(STColumn *pCol, SCellVal *pCellVal, S
|
|||
pColVal->value.pData = (uint8_t *)varDataVal(pCellVal->val);
|
||||
} else if (TSDB_DATA_TYPE_FLOAT == pCol->type) {
|
||||
float f = GET_FLOAT_VAL(pCellVal->val);
|
||||
memcpy(&pColVal->value.val, &f, sizeof(f));
|
||||
valueSetDatum(&pColVal->value, pCol->type, &f, sizeof(f));
|
||||
} else if (TSDB_DATA_TYPE_DOUBLE == pCol->type) {
|
||||
taosSetPInt64Aligned(&pColVal->value.val, (int64_t *)pCellVal->val);
|
||||
} else {
|
||||
GET_TYPED_DATA(pColVal->value.val, int64_t, pCol->type, pCellVal->val);
|
||||
valueSetDatum(&pColVal->value, pCol->type, pCellVal->val, tDataTypes[pCol->type].bytes);
|
||||
}
|
||||
|
||||
pColVal->flag = CV_FLAG_VALUE;
|
||||
|
|
|
@ -25,3 +25,4 @@ add_subdirectory(geometry)
|
|||
add_subdirectory(command)
|
||||
add_subdirectory(azure)
|
||||
add_subdirectory(tcs)
|
||||
add_subdirectory(decimal)
|
||||
|
|
|
@ -598,13 +598,22 @@ int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCt
|
|||
}
|
||||
|
||||
metaSize = CTG_META_SIZE(stbMeta);
|
||||
*pTableMeta = taosMemoryRealloc(*pTableMeta, metaSize);
|
||||
int32_t schemaExtSize = 0;
|
||||
if (stbMeta->schemaExt) {
|
||||
schemaExtSize = stbMeta->tableInfo.numOfColumns * sizeof(SSchemaExt);
|
||||
}
|
||||
*pTableMeta = taosMemoryRealloc(*pTableMeta, metaSize + schemaExtSize);
|
||||
if (NULL == *pTableMeta) {
|
||||
CTG_ERR_RET(terrno);
|
||||
}
|
||||
|
||||
TAOS_MEMCPY(&(*pTableMeta)->sversion, &stbMeta->sversion, metaSize - sizeof(SCTableMeta));
|
||||
(*pTableMeta)->schemaExt = NULL;
|
||||
if (stbMeta->schemaExt) {
|
||||
(*pTableMeta)->schemaExt = (SSchemaExt*)((char*)*pTableMeta + metaSize);
|
||||
TAOS_MEMCPY((*pTableMeta)->schemaExt, stbMeta->schemaExt, schemaExtSize);
|
||||
} else {
|
||||
(*pTableMeta)->schemaExt = NULL;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1684,7 +1684,7 @@ int32_t ctgCloneMetaOutput(STableMetaOutput* output, STableMetaOutput** pOutput)
|
|||
if (output->tbMeta) {
|
||||
int32_t metaSize = CTG_META_SIZE(output->tbMeta);
|
||||
int32_t schemaExtSize = 0;
|
||||
if (useCompress(output->tbMeta->tableType) && (*pOutput)->tbMeta->schemaExt) {
|
||||
if (withExtSchema(output->tbMeta->tableType) && (*pOutput)->tbMeta->schemaExt) {
|
||||
schemaExtSize = output->tbMeta->tableInfo.numOfColumns * sizeof(SSchemaExt);
|
||||
}
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ int32_t ctgCloneMetaOutput(STableMetaOutput* output, STableMetaOutput** pOutput)
|
|||
}
|
||||
|
||||
TAOS_MEMCPY((*pOutput)->tbMeta, output->tbMeta, metaSize);
|
||||
if (useCompress(output->tbMeta->tableType) && (*pOutput)->tbMeta->schemaExt) {
|
||||
if (withExtSchema(output->tbMeta->tableType) && (*pOutput)->tbMeta->schemaExt) {
|
||||
(*pOutput)->tbMeta->schemaExt = (SSchemaExt*)((char*)(*pOutput)->tbMeta + metaSize);
|
||||
TAOS_MEMCPY((*pOutput)->tbMeta->schemaExt, output->tbMeta->schemaExt, schemaExtSize);
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
|||
|
||||
target_link_libraries(
|
||||
command
|
||||
PRIVATE os util nodes catalog function transport qcom scheduler
|
||||
PRIVATE os util nodes catalog function transport qcom scheduler decimal
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "catalog.h"
|
||||
#include "command.h"
|
||||
#include "commandInt.h"
|
||||
#include "decimal.h"
|
||||
#include "scheduler.h"
|
||||
#include "systable.h"
|
||||
#include "taosdef.h"
|
||||
|
@ -150,7 +151,7 @@ static int32_t setDescResultIntoDataBlock(bool sysInfoUser, SSDataBlock* pBlock,
|
|||
SColumnInfoData* pCol6 = NULL;
|
||||
// level
|
||||
SColumnInfoData* pCol7 = NULL;
|
||||
if (useCompress(pMeta->tableType)) {
|
||||
if (withExtSchema(pMeta->tableType)) {
|
||||
pCol5 = taosArrayGet(pBlock->pDataBlock, 4);
|
||||
pCol6 = taosArrayGet(pBlock->pDataBlock, 5);
|
||||
pCol7 = taosArrayGet(pBlock->pDataBlock, 6);
|
||||
|
@ -165,7 +166,15 @@ static int32_t setDescResultIntoDataBlock(bool sysInfoUser, SSDataBlock* pBlock,
|
|||
STR_TO_VARSTR(buf, pMeta->schema[i].name);
|
||||
COL_DATA_SET_VAL_AND_CHECK(pCol1, pBlock->info.rows, buf, false);
|
||||
|
||||
STR_TO_VARSTR(buf, tDataTypes[pMeta->schema[i].type].name);
|
||||
if (IS_DECIMAL_TYPE(pMeta->schema[i].type) && withExtSchema(pMeta->tableType)) {
|
||||
uint8_t prec = 0, scale = 0;
|
||||
decimalFromTypeMod(pMeta->schemaExt[i].typeMod, &prec, &scale);
|
||||
size_t len = snprintf(buf + VARSTR_HEADER_SIZE, DESCRIBE_RESULT_FIELD_LEN - VARSTR_HEADER_SIZE, "%s(%hhu, %hhu)",
|
||||
tDataTypes[pMeta->schema[i].type].name, prec, scale);
|
||||
varDataSetLen(buf, len);
|
||||
} else {
|
||||
STR_TO_VARSTR(buf, tDataTypes[pMeta->schema[i].type].name);
|
||||
}
|
||||
COL_DATA_SET_VAL_AND_CHECK(pCol2, pBlock->info.rows, buf, false);
|
||||
int32_t bytes = getSchemaBytes(pMeta->schema + i);
|
||||
COL_DATA_SET_VAL_AND_CHECK(pCol3, pBlock->info.rows, (const char*)&bytes, false);
|
||||
|
@ -182,7 +191,7 @@ static int32_t setDescResultIntoDataBlock(bool sysInfoUser, SSDataBlock* pBlock,
|
|||
STR_TO_VARSTR(buf, "VIEW COL");
|
||||
}
|
||||
COL_DATA_SET_VAL_AND_CHECK(pCol4, pBlock->info.rows, buf, false);
|
||||
if (useCompress(pMeta->tableType) && pMeta->schemaExt) {
|
||||
if (withExtSchema(pMeta->tableType) && pMeta->schemaExt) {
|
||||
if (i < pMeta->tableInfo.numOfColumns) {
|
||||
STR_TO_VARSTR(buf, columnEncodeStr(COMPRESS_L1_TYPE_U32(pMeta->schemaExt[i].compress)));
|
||||
COL_DATA_SET_VAL_AND_CHECK(pCol5, pBlock->info.rows, buf, false);
|
||||
|
@ -235,7 +244,7 @@ static int32_t execDescribe(bool sysInfoUser, SNode* pStmt, SRetrieveTableRsp**
|
|||
code = setDescResultIntoDataBlock(sysInfoUser, pBlock, numOfRows, pDesc->pMeta, biMode);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (pDesc->pMeta && useCompress(pDesc->pMeta->tableType) && pDesc->pMeta->schemaExt) {
|
||||
if (pDesc->pMeta && withExtSchema(pDesc->pMeta->tableType) && pDesc->pMeta->schemaExt) {
|
||||
code = buildRetrieveTableRsp(pBlock, DESCRIBE_RESULT_COLS_COMPRESS, pRsp);
|
||||
} else {
|
||||
code = buildRetrieveTableRsp(pBlock, DESCRIBE_RESULT_COLS, pRsp);
|
||||
|
@ -537,9 +546,13 @@ static void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) {
|
|||
} else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) {
|
||||
typeLen += tsnprintf(type + typeLen, LTYPE_LEN - typeLen, "(%d)",
|
||||
(int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
|
||||
} else if (IS_DECIMAL_TYPE(pSchema->type)) {
|
||||
uint8_t precision, scale;
|
||||
decimalFromTypeMod(pCfg->pSchemaExt[i].typeMod, &precision, &scale);
|
||||
typeLen += tsnprintf(type + typeLen, LTYPE_LEN - typeLen, "(%d,%d)", precision, scale);
|
||||
}
|
||||
|
||||
if (useCompress(pCfg->tableType) && pCfg->pSchemaExt) {
|
||||
if (withExtSchema(pCfg->tableType) && pCfg->pSchemaExt) {
|
||||
typeLen += tsnprintf(type + typeLen, LTYPE_LEN - typeLen, " ENCODE \'%s\'",
|
||||
columnEncodeStr(COMPRESS_L1_TYPE_U32(pCfg->pSchemaExt[i].compress)));
|
||||
typeLen += tsnprintf(type + typeLen, LTYPE_LEN - typeLen, " COMPRESS \'%s\'",
|
||||
|
@ -1027,6 +1040,8 @@ static int32_t createSelectResultDataBlock(SNodeList* pProjects, SSDataBlock** p
|
|||
} else {
|
||||
infoData.info.type = pExpr->resType.type;
|
||||
infoData.info.bytes = pExpr->resType.bytes;
|
||||
infoData.info.precision = pExpr->resType.precision;
|
||||
infoData.info.scale = pExpr->resType.scale;
|
||||
}
|
||||
QRY_ERR_RET(blockDataAppendColInfo(pBlock, &infoData));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
aux_source_directory(src DECIMAL_SRC)
|
||||
|
||||
add_library(decimal STATIC ${DECIMAL_SRC})
|
||||
|
||||
target_include_directories(
|
||||
decimal
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/libs/decimal"
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
||||
)
|
||||
target_link_libraries(
|
||||
decimal
|
||||
PRIVATE os common wideInteger
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
ADD_SUBDIRECTORY(test)
|
||||
endif(${BUILD_TEST})
|
||||
ADD_SUBDIRECTORY(src/detail)
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_WIDE_INTEGER_H_
|
||||
#define _TD_WIDE_INTEGER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct uint128 {
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
};
|
||||
|
||||
struct int128 {
|
||||
uint64_t low;
|
||||
int64_t high;
|
||||
};
|
||||
|
||||
struct uint256 {
|
||||
struct uint128 low;
|
||||
struct uint128 high;
|
||||
};
|
||||
|
||||
struct int256 {
|
||||
struct uint128 low;
|
||||
struct int128 high;
|
||||
};
|
||||
|
||||
#define UInt128 struct uint128
|
||||
#define UInt256 struct uint256
|
||||
#define Int128 struct int128
|
||||
#define Int256 struct int256
|
||||
|
||||
#define SAFE_SIGNED_OP(a, b, SIGNED_TYPE, UNSIGNED_TYPE, OP) (SIGNED_TYPE)((UNSIGNED_TYPE)(a)OP(UNSIGNED_TYPE)(b))
|
||||
#define SAFE_INT64_ADD(a, b) SAFE_SIGNED_OP(a, b, int64_t, uint64_t, +)
|
||||
#define SAFE_INT64_SUBTRACT(a, b) SAFE_SIGNED_OP(a, b, int64_t, uint64_t, -)
|
||||
|
||||
void makeUInt128(UInt128* pInt, uint64_t hi, uint64_t lo);
|
||||
uint64_t uInt128Hi(const UInt128* pInt);
|
||||
uint64_t uInt128Lo(const UInt128* pInt);
|
||||
void uInt128Add(UInt128* pLeft, const UInt128* pRight);
|
||||
void uInt128Subtract(UInt128* pLeft, const UInt128* pRight);
|
||||
void uInt128Multiply(UInt128* pLeft, const UInt128* pRight);
|
||||
void uInt128Divide(UInt128* pLeft, const UInt128* pRight);
|
||||
void uInt128Mod(UInt128* pLeft, const UInt128* pRight);
|
||||
bool uInt128Lt(const UInt128* pLeft, const UInt128* pRight);
|
||||
bool uInt128Gt(const UInt128* pLeft, const UInt128* pRight);
|
||||
bool uInt128Eq(const UInt128* pLeft, const UInt128* pRight);
|
||||
|
||||
extern const UInt128 uInt128_1e18;
|
||||
extern const UInt128 uInt128Zero;
|
||||
extern const uint64_t k1e18;
|
||||
extern const UInt128 uInt128One;
|
||||
extern const UInt128 uInt128Two;
|
||||
|
||||
Int128 makeInt128(int64_t high, uint64_t low);
|
||||
int64_t int128Hi(const Int128* pUint128);
|
||||
uint64_t int128Lo(const Int128* pUint128);
|
||||
Int128 int128Abs(const Int128* pInt128);
|
||||
Int128 int128Negate(const Int128* pInt128);
|
||||
Int128 int128Add(const Int128* pLeft, const Int128* pRight);
|
||||
Int128 int128Subtract(const Int128* pLeft, const Int128* pRight);
|
||||
Int128 int128Multiply(const Int128* pLeft, const Int128* pRight);
|
||||
Int128 int128Divide(const Int128* pLeft, const Int128* pRight);
|
||||
Int128 int128Mod(const Int128* pLeft, const Int128* pRight);
|
||||
bool int128Lt(const Int128* pLeft, const Int128* pRight);
|
||||
bool int128Gt(const Int128* pLeft, const Int128* pRight);
|
||||
bool int128Eq(const Int128* pLeft, const Int128* pRight);
|
||||
Int128 int128RightShift(const Int128* pLeft, int32_t shift);
|
||||
|
||||
extern const Int128 int128Zero;
|
||||
extern const Int128 int128One;
|
||||
|
||||
UInt256 makeUint256(UInt128 high, UInt128 low);
|
||||
UInt128 uInt256Hi(const UInt256* pUint256);
|
||||
UInt128 uInt256Lo(const UInt256* pUint256);
|
||||
UInt256 uInt256Add(const UInt256* pLeft, const UInt256* pRight);
|
||||
UInt256 uInt256Subtract(const UInt256* pLeft, const UInt256* pRight);
|
||||
UInt256 uInt256Multiply(const UInt256* pLeft, const UInt256* pRight);
|
||||
UInt256 uInt256Divide(const UInt256* pLeft, const UInt256* pRight);
|
||||
UInt256 uInt256Mod(const UInt256* pLeft, const UInt256* pRight);
|
||||
bool uInt256Lt(const UInt256* pLeft, const UInt256* pRight);
|
||||
bool uInt256Gt(const UInt256* pLeft, const UInt256* pRight);
|
||||
bool uInt256Eq(const UInt256* pLeft, const UInt256* pRight);
|
||||
UInt256 uInt256RightShift(const UInt256* pLeft, int32_t shift);
|
||||
|
||||
extern const UInt256 uInt256Zero;
|
||||
extern const UInt256 uInt256One;
|
||||
|
||||
Int256 makeInt256(Int128 high, UInt128 low);
|
||||
Int128 int256Hi(const Int256* pUint256);
|
||||
UInt128 int256Lo(const Int256* pUint256);
|
||||
Int256 int256Abs(const Int256* pInt256);
|
||||
Int256 int256Negate(const Int256* pInt256);
|
||||
Int256 int256Add(const Int256* pLeft, const Int256* pRight);
|
||||
Int256 int256Subtract(const Int256* pLeft, const Int256* pRight);
|
||||
Int256 int256Multiply(const Int256* pLeft, const Int256* pRight);
|
||||
Int256 int256Divide(const Int256* pLeft, const Int256* pRight);
|
||||
Int256 int256Mod(const Int256* pLeft, const Int256* pRight);
|
||||
bool int256Lt(const Int256* pLeft, const Int256* pRight);
|
||||
bool int256Gt(const Int256* pLeft, const Int256* pRight);
|
||||
bool int256Eq(const Int256* pLeft, const Int256* pRight);
|
||||
Int256 int256RightShift(const Int256* pLeft, int32_t shift);
|
||||
|
||||
extern const Int256 int256Zero;
|
||||
extern const Int256 int256One;
|
||||
extern const Int256 int256Two;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int32_t countLeadingZeros(uint64_t v) {
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
if (v == 0) return 64;
|
||||
return __builtin_clzll(v);
|
||||
#else
|
||||
int32_t bitpos = 0;
|
||||
while (v != 0) {
|
||||
v >>= 1;
|
||||
++bitpos;
|
||||
}
|
||||
return 64 - bitpos;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif /* _TD_WIDE_INTEGER_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
|||
MESSAGE(STATUS "Building decimal/src/detail")
|
||||
aux_source_directory(. WIDE_INTEGER_SRC)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 14)
|
||||
add_library(wideInteger STATIC ${WIDE_INTEGER_SRC})
|
||||
|
||||
target_include_directories(
|
||||
wideInteger
|
||||
PUBLIC "${TD_SOURCE_DIR}/source/libs/decimal/inc/"
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/intx/"
|
||||
)
|
||||
target_link_libraries(
|
||||
wideInteger
|
||||
PUBLIC
|
||||
)
|
|
@ -0,0 +1,885 @@
|
|||
// intx: extended precision integer library.
|
||||
// Copyright 2019-2020 Pawel Bylica.
|
||||
// Licensed under the Apache License, Version 2.0.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define INTX_UNREACHABLE __assume(0)
|
||||
#else
|
||||
#define INTX_UNREACHABLE __builtin_unreachable()
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define INTX_UNLIKELY(EXPR) (bool{EXPR})
|
||||
#else
|
||||
#define INTX_UNLIKELY(EXPR) __builtin_expect(bool{EXPR}, false)
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define INTX_REQUIRE(X) (X) ? (void)0 : INTX_UNREACHABLE
|
||||
#else
|
||||
#include <cassert>
|
||||
#define INTX_REQUIRE assert
|
||||
#endif
|
||||
|
||||
namespace intx
|
||||
{
|
||||
template <unsigned N>
|
||||
struct uint;
|
||||
|
||||
/// The 128-bit unsigned integer.
|
||||
///
|
||||
/// This type is defined as a specialization of uint<> to easier integration with full intx package,
|
||||
/// however, uint128 may be used independently.
|
||||
template <>
|
||||
struct uint<128>
|
||||
{
|
||||
static constexpr unsigned num_bits = 128;
|
||||
|
||||
uint64_t lo = 0;
|
||||
uint64_t hi = 0;
|
||||
|
||||
constexpr uint() noexcept = default;
|
||||
|
||||
constexpr uint(uint64_t high, uint64_t low) noexcept : lo{low}, hi{high} {}
|
||||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if_t<std::is_convertible<T, uint64_t>::value>>
|
||||
constexpr uint(T x) noexcept : lo(static_cast<uint64_t>(x)) // NOLINT
|
||||
{}
|
||||
|
||||
#ifdef __SIZEOF_INT128__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
constexpr uint(unsigned __int128 x) noexcept // NOLINT
|
||||
: lo{uint64_t(x)}, hi{uint64_t(x >> 64)}
|
||||
{}
|
||||
|
||||
constexpr explicit operator unsigned __int128() const noexcept
|
||||
{
|
||||
return (static_cast<unsigned __int128>(hi) << 64) | lo;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
constexpr explicit operator bool() const noexcept { return hi | lo; }
|
||||
|
||||
/// Explicit converting operator for all builtin integral types.
|
||||
template <typename Int, typename = typename std::enable_if<std::is_integral<Int>::value>::type>
|
||||
constexpr explicit operator Int() const noexcept
|
||||
{
|
||||
return static_cast<Int>(lo);
|
||||
}
|
||||
};
|
||||
|
||||
using uint128 = uint<128>;
|
||||
|
||||
|
||||
/// Contains result of add/sub/etc with a carry flag.
|
||||
template <typename T>
|
||||
struct result_with_carry
|
||||
{
|
||||
T value;
|
||||
bool carry;
|
||||
|
||||
/// Conversion to tuple of references, to allow usage with std::tie().
|
||||
constexpr operator std::tuple<T&, bool&>() noexcept { return {value, carry}; }
|
||||
};
|
||||
|
||||
|
||||
/// Linear arithmetic operators.
|
||||
/// @{
|
||||
|
||||
constexpr inline result_with_carry<uint64_t> add_with_carry(
|
||||
uint64_t x, uint64_t y, bool carry = false) noexcept
|
||||
{
|
||||
const auto s = x + y;
|
||||
const auto carry1 = s < x;
|
||||
const auto t = s + carry;
|
||||
const auto carry2 = t < s;
|
||||
return {t, carry1 || carry2};
|
||||
}
|
||||
|
||||
template <unsigned N>
|
||||
constexpr result_with_carry<uint<N>> add_with_carry(
|
||||
const uint<N>& a, const uint<N>& b, bool carry = false) noexcept
|
||||
{
|
||||
const auto lo = add_with_carry(a.lo, b.lo, carry);
|
||||
const auto hi = add_with_carry(a.hi, b.hi, lo.carry);
|
||||
return {{hi.value, lo.value}, hi.carry};
|
||||
}
|
||||
|
||||
constexpr inline uint128 operator+(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return add_with_carry(x, y).value;
|
||||
}
|
||||
|
||||
constexpr inline uint128 operator+(uint128 x) noexcept
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
constexpr inline result_with_carry<uint64_t> sub_with_carry(
|
||||
uint64_t x, uint64_t y, bool carry = false) noexcept
|
||||
{
|
||||
const auto d = x - y;
|
||||
const auto carry1 = d > x;
|
||||
const auto e = d - carry;
|
||||
const auto carry2 = e > d;
|
||||
return {e, carry1 || carry2};
|
||||
}
|
||||
|
||||
/// Performs subtraction of two unsigned numbers and returns the difference
|
||||
/// and the carry bit (aka borrow, overflow).
|
||||
template <unsigned N>
|
||||
constexpr inline result_with_carry<uint<N>> sub_with_carry(
|
||||
const uint<N>& a, const uint<N>& b, bool carry = false) noexcept
|
||||
{
|
||||
const auto lo = sub_with_carry(a.lo, b.lo, carry);
|
||||
const auto hi = sub_with_carry(a.hi, b.hi, lo.carry);
|
||||
return {{hi.value, lo.value}, hi.carry};
|
||||
}
|
||||
|
||||
constexpr inline uint128 operator-(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return sub_with_carry(x, y).value;
|
||||
}
|
||||
|
||||
constexpr inline uint128 operator-(uint128 x) noexcept
|
||||
{
|
||||
// Implementing as subtraction is better than ~x + 1.
|
||||
// Clang9: Perfect.
|
||||
// GCC8: Does something weird.
|
||||
return 0 - x;
|
||||
}
|
||||
|
||||
inline uint128& operator++(uint128& x) noexcept
|
||||
{
|
||||
return x = x + 1;
|
||||
}
|
||||
|
||||
inline uint128& operator--(uint128& x) noexcept
|
||||
{
|
||||
return x = x - 1;
|
||||
}
|
||||
|
||||
inline uint128 operator++(uint128& x, int) noexcept
|
||||
{
|
||||
auto ret = x;
|
||||
++x;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline uint128 operator--(uint128& x, int) noexcept
|
||||
{
|
||||
auto ret = x;
|
||||
--x;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Optimized addition.
|
||||
///
|
||||
/// This keeps the multiprecision addition until CodeGen so the pattern is not
|
||||
/// broken during other optimizations.
|
||||
constexpr uint128 fast_add(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
#ifdef __SIZEOF_INT128__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
using uint128_native = unsigned __int128;
|
||||
return uint128_native{x} + uint128_native{y};
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
// Fallback to regular addition.
|
||||
return x + y;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// Comparison operators.
|
||||
///
|
||||
/// In all implementations bitwise operators are used instead of logical ones
|
||||
/// to avoid branching.
|
||||
///
|
||||
/// @{
|
||||
|
||||
constexpr bool operator==(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
// Clang7: generates perfect xor based code,
|
||||
// much better than __int128 where it uses vector instructions.
|
||||
// GCC8: generates a bit worse cmp based code
|
||||
// although it generates the xor based one for __int128.
|
||||
return (x.lo == y.lo) & (x.hi == y.hi);
|
||||
}
|
||||
|
||||
constexpr bool operator!=(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
// Analogous to ==, but == not used directly, because that confuses GCC 8-9.
|
||||
return (x.lo != y.lo) | (x.hi != y.hi);
|
||||
}
|
||||
|
||||
constexpr bool operator<(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
// OPT: This should be implemented by checking the borrow of x - y,
|
||||
// but compilers (GCC8, Clang7)
|
||||
// have problem with properly optimizing subtraction.
|
||||
return (x.hi < y.hi) | ((x.hi == y.hi) & (x.lo < y.lo));
|
||||
}
|
||||
|
||||
constexpr bool operator<=(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
constexpr bool operator>(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// Bitwise operators.
|
||||
/// @{
|
||||
|
||||
constexpr uint128 operator~(uint128 x) noexcept
|
||||
{
|
||||
return {~x.hi, ~x.lo};
|
||||
}
|
||||
|
||||
constexpr uint128 operator|(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
// Clang7: perfect.
|
||||
// GCC8: stupidly uses a vector instruction in all bitwise operators.
|
||||
return {x.hi | y.hi, x.lo | y.lo};
|
||||
}
|
||||
|
||||
constexpr uint128 operator&(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return {x.hi & y.hi, x.lo & y.lo};
|
||||
}
|
||||
|
||||
constexpr uint128 operator^(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return {x.hi ^ y.hi, x.lo ^ y.lo};
|
||||
}
|
||||
|
||||
constexpr uint128 operator<<(uint128 x, unsigned shift) noexcept
|
||||
{
|
||||
return (shift < 64) ?
|
||||
// Find the part moved from lo to hi.
|
||||
// For shift == 0 right shift by (64 - shift) is invalid so
|
||||
// split it into 2 shifts by 1 and (63 - shift).
|
||||
uint128{(x.hi << shift) | ((x.lo >> 1) >> (63 - shift)), x.lo << shift} :
|
||||
|
||||
// Guarantee "defined" behavior for shifts larger than 128.
|
||||
(shift < 128) ? uint128{x.lo << (shift - 64), 0} : 0;
|
||||
}
|
||||
|
||||
constexpr uint128 operator<<(uint128 x, uint128 shift) noexcept
|
||||
{
|
||||
if (shift < 128)
|
||||
return x << unsigned(shift);
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr uint128 operator>>(uint128 x, unsigned shift) noexcept
|
||||
{
|
||||
return (shift < 64) ?
|
||||
// Find the part moved from lo to hi.
|
||||
// For shift == 0 left shift by (64 - shift) is invalid so
|
||||
// split it into 2 shifts by 1 and (63 - shift).
|
||||
uint128{x.hi >> shift, (x.lo >> shift) | ((x.hi << 1) << (63 - shift))} :
|
||||
|
||||
// Guarantee "defined" behavior for shifts larger than 128.
|
||||
(shift < 128) ? uint128{0, x.hi >> (shift - 64)} : 0;
|
||||
}
|
||||
|
||||
constexpr uint128 operator>>(uint128 x, uint128 shift) noexcept
|
||||
{
|
||||
if (shift < 128)
|
||||
return x >> unsigned(shift);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// Multiplication
|
||||
/// @{
|
||||
|
||||
/// Portable full unsigned multiplication 64 x 64 -> 128.
|
||||
constexpr uint128 constexpr_umul(uint64_t x, uint64_t y) noexcept
|
||||
{
|
||||
uint64_t xl = x & 0xffffffff;
|
||||
uint64_t xh = x >> 32;
|
||||
uint64_t yl = y & 0xffffffff;
|
||||
uint64_t yh = y >> 32;
|
||||
|
||||
uint64_t t0 = xl * yl;
|
||||
uint64_t t1 = xh * yl;
|
||||
uint64_t t2 = xl * yh;
|
||||
uint64_t t3 = xh * yh;
|
||||
|
||||
uint64_t u1 = t1 + (t0 >> 32);
|
||||
uint64_t u2 = t2 + (u1 & 0xffffffff);
|
||||
|
||||
uint64_t lo = (u2 << 32) | (t0 & 0xffffffff);
|
||||
uint64_t hi = t3 + (u2 >> 32) + (u1 >> 32);
|
||||
return {hi, lo};
|
||||
}
|
||||
|
||||
/// Full unsigned multiplication 64 x 64 -> 128.
|
||||
inline uint128 umul(uint64_t x, uint64_t y) noexcept
|
||||
{
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
const auto p = static_cast<unsigned __int128>(x) * y;
|
||||
return {uint64_t(p >> 64), uint64_t(p)};
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned __int64 hi;
|
||||
const auto lo = _umul128(x, y, &hi);
|
||||
return {hi, lo};
|
||||
#else
|
||||
return constexpr_umul(x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint128 operator*(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
auto p = umul(x.lo, y.lo);
|
||||
p.hi += (x.lo * y.hi) + (x.hi * y.lo);
|
||||
return {p.hi, p.lo};
|
||||
}
|
||||
|
||||
constexpr uint128 constexpr_mul(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
auto p = constexpr_umul(x.lo, y.lo);
|
||||
p.hi += (x.lo * y.hi) + (x.hi * y.lo);
|
||||
return {p.hi, p.lo};
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// Assignment operators.
|
||||
/// @{
|
||||
|
||||
constexpr uint128& operator+=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x + y;
|
||||
}
|
||||
|
||||
constexpr uint128& operator-=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x - y;
|
||||
}
|
||||
|
||||
inline uint128& operator*=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x * y;
|
||||
}
|
||||
|
||||
constexpr uint128& operator|=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x | y;
|
||||
}
|
||||
|
||||
constexpr uint128& operator&=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x & y;
|
||||
}
|
||||
|
||||
constexpr uint128& operator^=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x ^ y;
|
||||
}
|
||||
|
||||
constexpr uint128& operator<<=(uint128& x, unsigned shift) noexcept
|
||||
{
|
||||
return x = x << shift;
|
||||
}
|
||||
|
||||
constexpr uint128& operator>>=(uint128& x, unsigned shift) noexcept
|
||||
{
|
||||
return x = x >> shift;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
constexpr unsigned clz_generic(uint32_t x) noexcept
|
||||
{
|
||||
unsigned n = 32;
|
||||
for (int i = 4; i >= 0; --i)
|
||||
{
|
||||
const auto s = unsigned{1} << i;
|
||||
const auto hi = x >> s;
|
||||
if (hi != 0)
|
||||
{
|
||||
n -= s;
|
||||
x = hi;
|
||||
}
|
||||
}
|
||||
return n - x;
|
||||
}
|
||||
|
||||
constexpr unsigned clz_generic(uint64_t x) noexcept
|
||||
{
|
||||
unsigned n = 64;
|
||||
for (int i = 5; i >= 0; --i)
|
||||
{
|
||||
const auto s = unsigned{1} << i;
|
||||
const auto hi = x >> s;
|
||||
if (hi != 0)
|
||||
{
|
||||
n -= s;
|
||||
x = hi;
|
||||
}
|
||||
}
|
||||
return n - static_cast<unsigned>(x);
|
||||
}
|
||||
|
||||
constexpr inline unsigned clz(uint32_t x) noexcept
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return clz_generic(x);
|
||||
#else
|
||||
return x != 0 ? unsigned(__builtin_clz(x)) : 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline unsigned clz(uint64_t x) noexcept
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return clz_generic(x);
|
||||
#else
|
||||
return x != 0 ? unsigned(__builtin_clzll(x)) : 64;
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline unsigned clz(uint128 x) noexcept
|
||||
{
|
||||
// In this order `h == 0` we get less instructions than in case of `h != 0`.
|
||||
return x.hi == 0 ? clz(x.lo) + 64 : clz(x.hi);
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t bswap(uint64_t x) noexcept
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_uint64(x);
|
||||
#else
|
||||
return __builtin_bswap64(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint128 bswap(uint128 x) noexcept
|
||||
{
|
||||
return {bswap(x.lo), bswap(x.hi)};
|
||||
}
|
||||
|
||||
|
||||
/// Division.
|
||||
/// @{
|
||||
|
||||
template <typename QuotT, typename RemT = QuotT>
|
||||
struct div_result
|
||||
{
|
||||
QuotT quot;
|
||||
RemT rem;
|
||||
|
||||
/// Conversion to tuple of references, to allow usage with std::tie().
|
||||
constexpr operator std::tuple<QuotT&, RemT&>() noexcept { return {quot, rem}; }
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
constexpr uint16_t reciprocal_table_item(uint8_t d9) noexcept
|
||||
{
|
||||
return uint16_t(0x7fd00 / (0x100 | d9));
|
||||
}
|
||||
|
||||
#define REPEAT4(x) \
|
||||
reciprocal_table_item((x) + 0), reciprocal_table_item((x) + 1), \
|
||||
reciprocal_table_item((x) + 2), reciprocal_table_item((x) + 3)
|
||||
|
||||
#define REPEAT32(x) \
|
||||
REPEAT4((x) + 4 * 0), REPEAT4((x) + 4 * 1), REPEAT4((x) + 4 * 2), REPEAT4((x) + 4 * 3), \
|
||||
REPEAT4((x) + 4 * 4), REPEAT4((x) + 4 * 5), REPEAT4((x) + 4 * 6), REPEAT4((x) + 4 * 7)
|
||||
|
||||
#define REPEAT256() \
|
||||
REPEAT32(32 * 0), REPEAT32(32 * 1), REPEAT32(32 * 2), REPEAT32(32 * 3), REPEAT32(32 * 4), \
|
||||
REPEAT32(32 * 5), REPEAT32(32 * 6), REPEAT32(32 * 7)
|
||||
|
||||
/// Reciprocal lookup table.
|
||||
constexpr uint16_t reciprocal_table[] = {REPEAT256()};
|
||||
|
||||
#undef REPEAT4
|
||||
#undef REPEAT32
|
||||
#undef REPEAT256
|
||||
} // namespace internal
|
||||
|
||||
/// Computes the reciprocal (2^128 - 1) / d - 2^64 for normalized d.
|
||||
///
|
||||
/// Based on Algorithm 2 from "Improved division by invariant integers".
|
||||
inline uint64_t reciprocal_2by1(uint64_t d) noexcept
|
||||
{
|
||||
INTX_REQUIRE(d & 0x8000000000000000); // Must be normalized.
|
||||
|
||||
const uint64_t d9 = d >> 55;
|
||||
const uint32_t v0 = internal::reciprocal_table[d9 - 256];
|
||||
|
||||
const uint64_t d40 = (d >> 24) + 1;
|
||||
const uint64_t v1 = (v0 << 11) - uint32_t(v0 * v0 * d40 >> 40) - 1;
|
||||
|
||||
const uint64_t v2 = (v1 << 13) + (v1 * (0x1000000000000000 - v1 * d40) >> 47);
|
||||
|
||||
const uint64_t d0 = d & 1;
|
||||
const uint64_t d63 = (d >> 1) + d0; // ceil(d/2)
|
||||
const uint64_t e = ((v2 >> 1) & (0 - d0)) - v2 * d63;
|
||||
const uint64_t v3 = (umul(v2, e).hi >> 1) + (v2 << 31);
|
||||
|
||||
const uint64_t v4 = v3 - (umul(v3, d) + d).hi - d;
|
||||
return v4;
|
||||
}
|
||||
|
||||
inline uint64_t reciprocal_3by2(uint128 d) noexcept
|
||||
{
|
||||
auto v = reciprocal_2by1(d.hi);
|
||||
auto p = d.hi * v;
|
||||
p += d.lo;
|
||||
if (p < d.lo)
|
||||
{
|
||||
--v;
|
||||
if (p >= d.hi)
|
||||
{
|
||||
--v;
|
||||
p -= d.hi;
|
||||
}
|
||||
p -= d.hi;
|
||||
}
|
||||
|
||||
const auto t = umul(v, d.lo);
|
||||
|
||||
p += t.hi;
|
||||
if (p < t.hi)
|
||||
{
|
||||
--v;
|
||||
if (p >= d.hi)
|
||||
{
|
||||
if (p > d.hi || t.lo >= d.lo)
|
||||
--v;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
inline div_result<uint64_t> udivrem_2by1(uint128 u, uint64_t d, uint64_t v) noexcept
|
||||
{
|
||||
auto q = umul(v, u.hi);
|
||||
q = fast_add(q, u);
|
||||
|
||||
++q.hi;
|
||||
|
||||
auto r = u.lo - q.hi * d;
|
||||
|
||||
if (r > q.lo)
|
||||
{
|
||||
--q.hi;
|
||||
r += d;
|
||||
}
|
||||
|
||||
if (r >= d)
|
||||
{
|
||||
++q.hi;
|
||||
r -= d;
|
||||
}
|
||||
|
||||
return {q.hi, r};
|
||||
}
|
||||
|
||||
inline div_result<uint64_t, uint128> udivrem_3by2(
|
||||
uint64_t u2, uint64_t u1, uint64_t u0, uint128 d, uint64_t v) noexcept
|
||||
{
|
||||
auto q = umul(v, u2);
|
||||
q = fast_add(q, {u2, u1});
|
||||
|
||||
auto r1 = u1 - q.hi * d.hi;
|
||||
|
||||
auto t = umul(d.lo, q.hi);
|
||||
|
||||
auto r = uint128{r1, u0} - t - d;
|
||||
r1 = r.hi;
|
||||
|
||||
++q.hi;
|
||||
|
||||
if (r1 >= q.lo)
|
||||
{
|
||||
--q.hi;
|
||||
r += d;
|
||||
}
|
||||
|
||||
if (r >= d)
|
||||
{
|
||||
++q.hi;
|
||||
r -= d;
|
||||
}
|
||||
|
||||
return {q.hi, r};
|
||||
}
|
||||
|
||||
inline div_result<uint128> udivrem(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
if (y.hi == 0)
|
||||
{
|
||||
INTX_REQUIRE(y.lo != 0); // Division by 0.
|
||||
|
||||
const auto lsh = clz(y.lo);
|
||||
const auto rsh = (64 - lsh) % 64;
|
||||
const auto rsh_mask = uint64_t{lsh == 0} - 1;
|
||||
|
||||
const auto yn = y.lo << lsh;
|
||||
const auto xn_lo = x.lo << lsh;
|
||||
const auto xn_hi = (x.hi << lsh) | ((x.lo >> rsh) & rsh_mask);
|
||||
const auto xn_ex = (x.hi >> rsh) & rsh_mask;
|
||||
|
||||
const auto v = reciprocal_2by1(yn);
|
||||
const auto res1 = udivrem_2by1({xn_ex, xn_hi}, yn, v);
|
||||
const auto res2 = udivrem_2by1({res1.rem, xn_lo}, yn, v);
|
||||
return {{res1.quot, res2.quot}, res2.rem >> lsh};
|
||||
}
|
||||
|
||||
if (y.hi > x.hi)
|
||||
return {0, x};
|
||||
|
||||
const auto lsh = clz(y.hi);
|
||||
if (lsh == 0)
|
||||
{
|
||||
const auto q = unsigned{y.hi < x.hi} | unsigned{y.lo <= x.lo};
|
||||
return {q, x - (q ? y : 0)};
|
||||
}
|
||||
|
||||
const auto rsh = 64 - lsh;
|
||||
|
||||
const auto yn_lo = y.lo << lsh;
|
||||
const auto yn_hi = (y.hi << lsh) | (y.lo >> rsh);
|
||||
const auto xn_lo = x.lo << lsh;
|
||||
const auto xn_hi = (x.hi << lsh) | (x.lo >> rsh);
|
||||
const auto xn_ex = x.hi >> rsh;
|
||||
|
||||
const auto v = reciprocal_3by2({yn_hi, yn_lo});
|
||||
const auto res = udivrem_3by2(xn_ex, xn_hi, xn_lo, {yn_hi, yn_lo}, v);
|
||||
|
||||
return {res.quot, res.rem >> lsh};
|
||||
}
|
||||
|
||||
inline div_result<uint128> sdivrem(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
constexpr auto sign_mask = uint128{1} << 127;
|
||||
const auto x_is_neg = (x & sign_mask) != 0;
|
||||
const auto y_is_neg = (y & sign_mask) != 0;
|
||||
|
||||
const auto x_abs = x_is_neg ? -x : x;
|
||||
const auto y_abs = y_is_neg ? -y : y;
|
||||
|
||||
const auto q_is_neg = x_is_neg ^ y_is_neg;
|
||||
|
||||
const auto res = udivrem(x_abs, y_abs);
|
||||
|
||||
return {q_is_neg ? -res.quot : res.quot, x_is_neg ? -res.rem : res.rem};
|
||||
}
|
||||
|
||||
inline uint128 operator/(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return udivrem(x, y).quot;
|
||||
}
|
||||
|
||||
inline uint128 operator%(uint128 x, uint128 y) noexcept
|
||||
{
|
||||
return udivrem(x, y).rem;
|
||||
}
|
||||
|
||||
inline uint128& operator/=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x / y;
|
||||
}
|
||||
|
||||
inline uint128& operator%=(uint128& x, uint128 y) noexcept
|
||||
{
|
||||
return x = x % y;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
} // namespace intx
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <unsigned N>
|
||||
struct numeric_limits<intx::uint<N>>
|
||||
{
|
||||
using type = intx::uint<N>;
|
||||
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_NaN = false;
|
||||
static constexpr bool has_signaling_NaN = false;
|
||||
static constexpr float_denorm_style has_denorm = denorm_absent;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr float_round_style round_style = round_toward_zero;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr int digits = CHAR_BIT * sizeof(type);
|
||||
static constexpr int digits10 = int(0.3010299956639812 * digits);
|
||||
static constexpr int max_digits10 = 0;
|
||||
static constexpr int radix = 2;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr bool traps = std::numeric_limits<unsigned>::traps;
|
||||
static constexpr bool tinyness_before = false;
|
||||
|
||||
static constexpr type min() noexcept { return 0; }
|
||||
static constexpr type lowest() noexcept { return min(); }
|
||||
static constexpr type max() noexcept { return ~type{0}; }
|
||||
static constexpr type epsilon() noexcept { return 0; }
|
||||
static constexpr type round_error() noexcept { return 0; }
|
||||
static constexpr type infinity() noexcept { return 0; }
|
||||
static constexpr type quiet_NaN() noexcept { return 0; }
|
||||
static constexpr type signaling_NaN() noexcept { return 0; }
|
||||
static constexpr type denorm_min() noexcept { return 0; }
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace intx
|
||||
{
|
||||
template <typename T>
|
||||
[[noreturn]] inline void throw_(const char* what)
|
||||
{
|
||||
#if __cpp_exceptions
|
||||
throw T{what};
|
||||
#else
|
||||
std::fputs(what, stderr);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline int from_dec_digit(char c)
|
||||
{
|
||||
if (c < '0' || c > '9')
|
||||
throw_<std::invalid_argument>("invalid digit");
|
||||
return c - '0';
|
||||
}
|
||||
|
||||
constexpr inline int from_hex_digit(char c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - ('a' - 10);
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - ('A' - 10);
|
||||
return from_dec_digit(c);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr Int from_string(const char* str)
|
||||
{
|
||||
auto s = str;
|
||||
auto x = Int{};
|
||||
int num_digits = 0;
|
||||
|
||||
if (s[0] == '0' && s[1] == 'x')
|
||||
{
|
||||
s += 2;
|
||||
while (const auto c = *s++)
|
||||
{
|
||||
if (++num_digits > int{sizeof(x) * 2})
|
||||
throw_<std::out_of_range>(str);
|
||||
x = (x << 4) | from_hex_digit(c);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
while (const auto c = *s++)
|
||||
{
|
||||
if (num_digits++ > std::numeric_limits<Int>::digits10)
|
||||
throw_<std::out_of_range>(str);
|
||||
|
||||
const auto d = from_dec_digit(c);
|
||||
x = constexpr_mul(x, Int{10}) + d;
|
||||
if (x < d)
|
||||
throw_<std::out_of_range>(str);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr Int from_string(const std::string& s)
|
||||
{
|
||||
return from_string<Int>(s.c_str());
|
||||
}
|
||||
|
||||
constexpr uint128 operator""_u128(const char* s)
|
||||
{
|
||||
return from_string<uint128>(s);
|
||||
}
|
||||
|
||||
template <unsigned N>
|
||||
inline std::string to_string(uint<N> x, int base = 10)
|
||||
{
|
||||
if (base < 2 || base > 36)
|
||||
base = 10;
|
||||
|
||||
if (x == 0)
|
||||
return "0";
|
||||
|
||||
auto s = std::string{};
|
||||
while (x != 0)
|
||||
{
|
||||
// TODO: Use constexpr udivrem_1?
|
||||
const auto res = udivrem(x, uint<N>{base});
|
||||
const auto d = int(res.rem);
|
||||
const auto c = d < 10 ? '0' + d : 'a' + d - 10;
|
||||
s.push_back(char(c));
|
||||
x = res.quot;
|
||||
}
|
||||
std::reverse(s.begin(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
template <unsigned N>
|
||||
inline std::string hex(uint<N> x)
|
||||
{
|
||||
return to_string(x, 16);
|
||||
}
|
||||
} // namespace intx
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,262 @@
|
|||
#include "wideInteger.h"
|
||||
#include "intx/int128.hpp"
|
||||
#include "intx/intx.hpp"
|
||||
|
||||
|
||||
const UInt128 uInt128Zero = {0, 0};
|
||||
const uint64_t k1e18 = 1000000000000000000LL;
|
||||
const UInt128 uInt128_1e18 = {k1e18, 0};
|
||||
const UInt128 uInt128One = {1, 0};
|
||||
const UInt128 uInt128Two = {2, 0};
|
||||
|
||||
void makeUInt128(uint128* pUint128, uint64_t high, uint64_t low) {
|
||||
intx::uint128* pIntxUint = (intx::uint128*)pUint128;
|
||||
pIntxUint->hi = high;
|
||||
pIntxUint->lo = low;
|
||||
}
|
||||
|
||||
uint64_t uInt128Hi(const UInt128* pInt) {
|
||||
intx::uint128 *pIntUint = (intx::uint128*)pInt;
|
||||
return pIntUint->hi;
|
||||
}
|
||||
|
||||
uint64_t uInt128Lo(const UInt128* pInt) {
|
||||
intx::uint128 *pIntUint = (intx::uint128*)pInt;
|
||||
return pIntUint->lo;
|
||||
}
|
||||
|
||||
void uInt128Add(UInt128* pLeft, const UInt128* pRight) {
|
||||
intx::uint128 *pX = (intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
*pX += *pY;
|
||||
}
|
||||
void uInt128Subtract(UInt128* pLeft, const UInt128* pRight) {
|
||||
intx::uint128 *pX = (intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
*pX -= *pY;
|
||||
}
|
||||
void uInt128Multiply(UInt128* pLeft, const UInt128* pRight) {
|
||||
intx::uint128 *pX = (intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
*pX *= *pY;
|
||||
/* __uint128_t *px = (__uint128_t*)pLeft;
|
||||
const __uint128_t *py = (__uint128_t*)pRight;
|
||||
*px = *px * *py; */
|
||||
}
|
||||
void uInt128Divide(UInt128* pLeft, const UInt128* pRight) {
|
||||
intx::uint128 *pX = (intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
*pX /= *pY;
|
||||
/* __uint128_t *px = (__uint128_t*)pLeft;
|
||||
const __uint128_t *py = (__uint128_t*)pRight;
|
||||
*px = *px / *py; */
|
||||
}
|
||||
void uInt128Mod(UInt128* pLeft, const UInt128* pRight) {
|
||||
intx::uint128 *pX = (intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
*pX %= *pY;
|
||||
/* __uint128_t *px = (__uint128_t*)pLeft;
|
||||
const __uint128_t *py = (__uint128_t*)pRight;
|
||||
*px = *px % *py; */
|
||||
}
|
||||
bool uInt128Lt(const UInt128* pLeft, const UInt128* pRight) {
|
||||
const intx::uint128 *pX = (const intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
return *pX < *pY;
|
||||
}
|
||||
bool uInt128Gt(const UInt128* pLeft, const UInt128* pRight) {
|
||||
const intx::uint128 *pX = (const intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
return *pX > *pY;
|
||||
}
|
||||
bool uInt128Eq(const UInt128* pLeft, const UInt128* pRight) {
|
||||
const intx::uint128 *pX = (const intx::uint128*)pLeft;
|
||||
const intx::uint128 *pY = (const intx::uint128*)pRight;
|
||||
return *pX == *pY;
|
||||
}
|
||||
|
||||
Int128 makeInt128(int64_t high, uint64_t low) {
|
||||
Int128 int128 = {low, high};
|
||||
return int128;
|
||||
}
|
||||
int64_t int128Hi(const Int128* pUint128) {
|
||||
return pUint128->high;
|
||||
}
|
||||
uint64_t int128Lo(const Int128* pUint128) {
|
||||
return pUint128->low;
|
||||
}
|
||||
Int128 int128Abs(const Int128* pInt128) {
|
||||
if (int128Lt(pInt128, &int128Zero)) {
|
||||
return int128Negate(pInt128);
|
||||
}
|
||||
return *pInt128;
|
||||
}
|
||||
Int128 int128Negate(const Int128* pInt128) {
|
||||
uint64_t low = ~pInt128->low + 1;
|
||||
int64_t high = ~pInt128->high;
|
||||
if (low == 0) high += 1;
|
||||
return makeInt128(high, low);
|
||||
}
|
||||
Int128 int128Add(const Int128* pLeft, const Int128* pRight) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft + *(intx::uint128*)pRight;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
Int128 int128Subtract(const Int128* pLeft, const Int128* pRight) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft - *(intx::uint128*)pRight;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
Int128 int128Multiply(const Int128* pLeft, const Int128* pRight) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft * *(intx::uint128*)pRight;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
Int128 int128Divide(const Int128* pLeft, const Int128* pRight) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft / *(intx::uint128*)pRight;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
Int128 int128Mod(const Int128* pLeft, const Int128* pRight) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft % *(intx::uint128*)pRight;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
bool int128Lt(const Int128* pLeft, const Int128* pRight) {
|
||||
return pLeft->high < pRight->high || (pLeft->high == pRight->high && pLeft->low < pRight->low);
|
||||
}
|
||||
bool int128Gt(const Int128* pLeft, const Int128* pRight) {
|
||||
return int128Lt(pRight, pLeft);
|
||||
}
|
||||
bool int128Eq(const Int128* pLeft, const Int128* pRight) {
|
||||
return pLeft->high == pRight->high && pLeft->low == pRight->low;
|
||||
}
|
||||
Int128 int128RightShift(const Int128* pLeft, int32_t shift) {
|
||||
intx::uint128 result = *(intx::uint128*)pLeft >> shift;
|
||||
return *(Int128*)&result;
|
||||
}
|
||||
|
||||
const Int128 int128Zero = {0, 0};
|
||||
const Int128 int128One = {1, 0};
|
||||
|
||||
UInt256 makeUint256(UInt128 high, UInt128 low) {
|
||||
UInt256 uint256 = {high, low};
|
||||
return uint256;
|
||||
}
|
||||
uint128 uInt256Hi(const UInt256* pUint256) {
|
||||
return pUint256->high;
|
||||
}
|
||||
uint128 uInt256Lo(const UInt256* pUint256) {
|
||||
return pUint256->low;
|
||||
}
|
||||
UInt256 uInt256Add(const UInt256* pLeft, const UInt256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft + *(intx::uint256*)pRight;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
UInt256 uInt256Subtract(const UInt256* pLeft, const UInt256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft - *(intx::uint256*)pRight;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
UInt256 uInt256Multiply(const UInt256* pLeft, const UInt256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft * *(intx::uint256*)pRight;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
UInt256 uInt256Divide(const UInt256* pLeft, const UInt256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft / *(intx::uint256*)pRight;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
UInt256 uInt256Mod(const UInt256* pLeft, const UInt256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft % *(intx::uint256*)pRight;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
bool uInt256Lt(const UInt256* pLeft, const UInt256* pRight) {
|
||||
return *(intx::uint256*)pLeft < *(intx::uint256*)pRight;
|
||||
}
|
||||
bool uInt256Gt(const UInt256* pLeft, const UInt256* pRight) {
|
||||
return *(intx::uint256*)pLeft > *(intx::uint256*)pRight;
|
||||
}
|
||||
bool uInt256Eq(const UInt256* pLeft, const UInt256* pRight) {
|
||||
return *(intx::uint256*)pLeft == *(intx::uint256*)pRight;
|
||||
}
|
||||
UInt256 uInt256RightShift(const UInt256* pLeft, int32_t shift) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft >> shift;
|
||||
return *(UInt256*)&result;
|
||||
}
|
||||
|
||||
Int256 makeInt256(Int128 high, UInt128 low) {
|
||||
Int256 int256 = {low, high};
|
||||
return int256;
|
||||
}
|
||||
Int128 int256Hi(const Int256* pUint256) {
|
||||
return pUint256->high;
|
||||
}
|
||||
UInt128 int256Lo(const Int256* pUint256) {
|
||||
return pUint256->low;
|
||||
}
|
||||
Int256 int256Abs(const Int256* pInt256) {
|
||||
if (int256Lt(pInt256, &int256Zero)) {
|
||||
return int256Negate(pInt256);
|
||||
}
|
||||
return *pInt256;
|
||||
}
|
||||
|
||||
Int256 int256Negate(const Int256* pInt256) {
|
||||
return int256Subtract(&int256Zero, pInt256);
|
||||
}
|
||||
Int256 int256Add(const Int256* pLeft, const Int256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft + *(intx::uint256*)pRight;
|
||||
return *(Int256*)&result;
|
||||
}
|
||||
Int256 int256Subtract(const Int256* pLeft, const Int256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft - *(intx::uint256*)pRight;
|
||||
return *(Int256*)&result;
|
||||
}
|
||||
Int256 int256Multiply(const Int256* pLeft, const Int256* pRight) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft * *(intx::uint256*)pRight;
|
||||
return *(Int256*)&result;
|
||||
}
|
||||
Int256 int256Divide(const Int256* pLeft, const Int256* pRight) {
|
||||
Int256 l = *pLeft, r = *pRight;
|
||||
bool leftNegative = int256Lt(pLeft, &int256Zero), rightNegative = int256Lt(pRight, &int256Zero);
|
||||
if (leftNegative) {
|
||||
l = int256Abs(pLeft);
|
||||
}
|
||||
if (rightNegative) {
|
||||
r = int256Abs(pRight);
|
||||
}
|
||||
intx::uint256 result = *(intx::uint256*)&l / *(intx::uint256*)&r;
|
||||
Int256 res = *(Int256*)&result;
|
||||
if (leftNegative != rightNegative)
|
||||
res = int256Negate(&res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Int256 int256Mod(const Int256* pLeft, const Int256* pRight) {
|
||||
Int256 left = *pLeft, right = *pRight;
|
||||
bool leftNegative = int256Lt(pLeft, &int256Zero);
|
||||
if (leftNegative) {
|
||||
left = int256Abs(&left);
|
||||
}
|
||||
bool rightNegate = int256Lt(pRight, &int256Zero);
|
||||
if (rightNegate) right = int256Abs(pRight);
|
||||
intx::uint256 result = *(intx::uint256*)&left % *(intx::uint256*)&right;
|
||||
Int256 res = *(Int256*)&result;
|
||||
if (leftNegative) res = int256Negate(&res);
|
||||
return res;
|
||||
}
|
||||
bool int256Lt(const Int256* pLeft, const Int256* pRight) {
|
||||
Int128 hiLeft = int256Hi(pLeft), hiRight = int256Hi(pRight);
|
||||
UInt128 lowLeft = int256Lo(pLeft), lowRight = int256Lo(pRight);
|
||||
return int128Lt(&hiLeft, &hiRight) || (int128Eq(&hiLeft, &hiRight) && uInt128Lt(&lowLeft, &lowRight));
|
||||
}
|
||||
bool int256Gt(const Int256* pLeft, const Int256* pRight) {
|
||||
return int256Lt(pRight, pLeft);
|
||||
}
|
||||
bool int256Eq(const Int256* pLeft, const Int256* pRight) {
|
||||
Int128 hiLeft = int256Hi(pLeft), hiRight = int256Hi(pRight);
|
||||
UInt128 lowLeft = int256Lo(pLeft), lowRight = int256Lo(pRight);
|
||||
return int128Eq(&hiLeft, &hiRight) && uInt128Eq(&lowLeft, &lowRight);
|
||||
}
|
||||
Int256 int256RightShift(const Int256* pLeft, int32_t shift) {
|
||||
intx::uint256 result = *(intx::uint256*)pLeft >> shift;
|
||||
return *(Int256*)&result;
|
||||
}
|
||||
|
||||
const Int256 int256One = {uInt128One, int128Zero};
|
||||
const Int256 int256Zero = {uInt128Zero, int128Zero};
|
||||
const Int256 int256Two = {uInt128Two, int128Zero};
|
|
@ -0,0 +1,23 @@
|
|||
MESSAGE(STATUS "build decimal unit test")
|
||||
|
||||
# GoogleTest requires at least C++11
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||
|
||||
ADD_EXECUTABLE(decimalTest ${SOURCE_LIST})
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
decimalTest
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/libs/decimal/"
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
decimalTest
|
||||
PUBLIC gtest taos os common
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME decimalTest
|
||||
COMMAND decimalTest
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -264,7 +264,6 @@ int32_t buildSubmitReqFromBlock(SDataInserterHandle* pInserter, SSubmitReq2** pp
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_MEDIUMBLOB:
|
||||
|
@ -295,7 +294,7 @@ int32_t buildSubmitReqFromBlock(SDataInserterHandle* pInserter, SSubmitReq2** pp
|
|||
}
|
||||
|
||||
SValue sv = {.type = pCol->type};
|
||||
TAOS_MEMCPY(&sv.val, var, tDataTypes[pCol->type].bytes);
|
||||
valueSetDatum(&sv, sv.type, var, tDataTypes[pCol->type].bytes);
|
||||
SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
|
||||
if (NULL == taosArrayPush(pVals, &cv)) {
|
||||
goto _end;
|
||||
|
|
|
@ -1536,6 +1536,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
SMetaTableInfo mtInfo = {0};
|
||||
code = pTaskInfo->storageAPI.snapshotFn.getMetaTableInfoFromSnapshot(sContext, &mtInfo);
|
||||
if (code != 0) {
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
return code;
|
||||
}
|
||||
pTaskInfo->storageAPI.tsdReader.tsdReaderClose(pInfo->dataReader);
|
||||
|
@ -1545,7 +1546,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
tableListClear(pTableListInfo);
|
||||
|
||||
if (mtInfo.uid == 0) {
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
goto end; // no data
|
||||
}
|
||||
|
||||
|
@ -1553,7 +1554,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
code = initQueryTableDataCondForTmq(&pTaskInfo->streamInfo.tableCond, sContext, &mtInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
return code;
|
||||
}
|
||||
if (pAPI->snapshotFn.taosXGetTablePrimaryKey(sContext)) {
|
||||
|
@ -1564,7 +1565,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
|
||||
code = tableListAddTableInfo(pTableListInfo, mtInfo.uid, 0);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
@ -1572,14 +1573,14 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
STableKeyInfo* pList = tableListGetInfo(pTableListInfo, 0);
|
||||
if (!pList) {
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
return code;
|
||||
}
|
||||
int32_t size = 0;
|
||||
code = tableListGetSize(pTableListInfo, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -1587,7 +1588,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
NULL, (void**)&pInfo->dataReader, NULL, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -2868,7 +2868,8 @@ static int32_t doBlockDataPrimaryKeyFilter(SSDataBlock* pBlock, STqOffsetVal* of
|
|||
SColumnInfoData* pColTs = taosArrayGet(pBlock->pDataBlock, 0);
|
||||
SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
|
||||
|
||||
qDebug("doBlockDataWindowFilter primary key, ts:%" PRId64 " %" PRId64, offset->ts, offset->primaryKey.val);
|
||||
qDebug("doBlockDataWindowFilter primary key, ts:%" PRId64 " %" PRId64, offset->ts,
|
||||
VALUE_GET_TRIVIAL_DATUM(&offset->primaryKey));
|
||||
QUERY_CHECK_CONDITION((pColPk->info.type == offset->primaryKey.type), code, lino, _end,
|
||||
TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
|
||||
|
||||
|
@ -2885,7 +2886,7 @@ static int32_t doBlockDataPrimaryKeyFilter(SSDataBlock* pBlock, STqOffsetVal* of
|
|||
p[i] = (*ts > offset->ts) || (func(data, tmq) > 0);
|
||||
taosMemoryFree(tmq);
|
||||
} else {
|
||||
p[i] = (*ts > offset->ts) || (func(data, &offset->primaryKey.val) > 0);
|
||||
p[i] = (*ts > offset->ts) || (func(data, VALUE_GET_DATUM(&offset->primaryKey, pColPk->info.type)) > 0);
|
||||
}
|
||||
|
||||
if (!p[i]) {
|
||||
|
@ -3124,7 +3125,7 @@ static int32_t processPrimaryKey(SSDataBlock* pBlock, bool hasPrimaryKey, STqOff
|
|||
val.nData = varDataLen(tmp);
|
||||
memcpy(val.pData, varDataVal(tmp), varDataLen(tmp));
|
||||
} else {
|
||||
memcpy(&val.val, tmp, pColPk->info.bytes);
|
||||
valueSetDatum(&val, pColPk->info.type, tmp, pColPk->info.bytes);
|
||||
}
|
||||
}
|
||||
tqOffsetResetToData(offset, pBlock->info.id.uid, pBlock->info.window.ekey, val);
|
||||
|
@ -4149,7 +4150,7 @@ static int32_t doRawScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
|
|||
code = pAPI->snapshotFn.getMetaTableInfoFromSnapshot(pInfo->sContext, &mtInfo);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
if (code != 0) {
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
STqOffsetVal offset = {0};
|
||||
|
@ -4161,7 +4162,7 @@ static int32_t doRawScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
|
|||
tqOffsetResetToData(&offset, mtInfo.uid, INT64_MIN, val);
|
||||
qDebug("tmqsnap change get data uid:%" PRId64 "", mtInfo.uid);
|
||||
}
|
||||
tDeleteSchemaWrapper(mtInfo.schema);
|
||||
destroyMetaTableInfo(&mtInfo);
|
||||
code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
(*ppRes) = NULL;
|
||||
|
@ -5303,7 +5304,6 @@ int32_t createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* p
|
|||
nodesRewriteExprPostOrder(&pTagCond, tagScanRewriteTagColumn, (void*)&pInfo->filterCtx);
|
||||
}
|
||||
}
|
||||
// TODO wjm check pInfo->filterCtx.code
|
||||
__optr_fn_t tagScanNextFn = (pTagScanNode->onlyMetaCtbIdx) ? doTagScanFromCtbIdxNext : doTagScanFromMetaEntryNext;
|
||||
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, tagScanNextFn, NULL, destroyTagScanOperatorInfo,
|
||||
optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
|
||||
|
|
|
@ -603,7 +603,7 @@ static void doStreamFillLinear(SStreamFillSupporter* pFillSup, SStreamFillInfo*
|
|||
cur.key = pFillInfo->current;
|
||||
cur.val = taosMemoryCalloc(1, pCell->bytes);
|
||||
QUERY_CHECK_NULL(cur.val, code, lino, _end, terrno);
|
||||
taosGetLinearInterpolationVal(&cur, pCell->type, &start, pEnd, pCell->type);
|
||||
taosGetLinearInterpolationVal(&cur, pCell->type, &start, pEnd, pCell->type, typeGetTypeModFromColInfo(&pColData->info));
|
||||
code = colDataSetVal(pColData, index, (const char*)cur.val, false);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
destroySPoint(&cur);
|
||||
|
@ -1712,15 +1712,15 @@ static void setValueForFillInfo(SStreamFillSupporter* pFillSup, SStreamFillInfo*
|
|||
SVariant* pVar = &(pFillCol->fillVal);
|
||||
if (pCell->type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float v = 0;
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else if (IS_FLOAT_TYPE(pCell->type)) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else if (IS_INTEGER_TYPE(pCell->type)) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else {
|
||||
pCell->isNull = true;
|
||||
|
|
|
@ -217,15 +217,15 @@ void doStreamSliceInterpolation(SSliceRowData* pPrevWinVal, TSKEY winKey, TSKEY
|
|||
|
||||
double prevVal = 0, curVal = 0, winVal = 0;
|
||||
SResultCellData* pCell = getSliceResultCell((SResultCellData*)pPrevWinVal->pRowVal, pParam->pCol->slotId, pOffsetInfo);
|
||||
GET_TYPED_DATA(prevVal, double, pCell->type, pCell->pData);
|
||||
GET_TYPED_DATA(curVal, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex));
|
||||
GET_TYPED_DATA(prevVal, double, pCell->type, pCell->pData, typeGetTypeModFromColInfo(&pColInfo->info));
|
||||
GET_TYPED_DATA(curVal, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex), typeGetTypeModFromColInfo(&pColInfo->info));
|
||||
|
||||
SPoint point1 = (SPoint){.key = pPrevWinVal->key, .val = &prevVal};
|
||||
SPoint point2 = (SPoint){.key = curTs, .val = &curVal};
|
||||
SPoint point = (SPoint){.key = winKey, .val = &winVal};
|
||||
|
||||
if (!fmIsElapsedFunc(pCtx[k].functionId)) {
|
||||
taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE);
|
||||
taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE, 0);
|
||||
}
|
||||
|
||||
if (type == INTERVAL_SLICE_START) {
|
||||
|
|
|
@ -515,7 +515,7 @@ static void fillLinearRange(SStreamFillSupporter* pFillSup, SStreamFillInfo* pFi
|
|||
cur.val = taosMemoryCalloc(1, pCell->bytes);
|
||||
QUERY_CHECK_NULL(cur.val, code, lino, _end, terrno);
|
||||
|
||||
taosGetLinearInterpolationVal(&cur, pCell->type, &start, pEnd, pCell->type);
|
||||
taosGetLinearInterpolationVal(&cur, pCell->type, &start, pEnd, pCell->type, typeGetTypeModFromColInfo(&pDstCol->info));
|
||||
code = colDataSetVal(pDstCol, index, (const char*)cur.val, false);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
||||
|
@ -1980,15 +1980,15 @@ static void copyFillValueInfo(SStreamFillSupporter* pFillSup, SStreamFillInfo* p
|
|||
SVariant* pVar = &(pValueCol->fillVal);
|
||||
if (pCell->type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float v = 0;
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else if (IS_FLOAT_TYPE(pCell->type)) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else if (IS_INTEGER_TYPE(pCell->type)) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i, 0);
|
||||
SET_TYPED_DATA(pCell->pData, pCell->type, v);
|
||||
} else {
|
||||
pCell->isNull = true;
|
||||
|
|
|
@ -85,33 +85,37 @@ static int32_t doSetUserSpecifiedValue(SColumnInfoData* pDst, SVariant* pVar, in
|
|||
bool isNull = (TSDB_DATA_TYPE_NULL == pVar->nType) ? true : false;
|
||||
if (pDst->info.type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float v = 0;
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->f);
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->f, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (pDst->info.type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->d);
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->d, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (IS_SIGNED_NUMERIC_TYPE(pDst->info.type) || pDst->info.type == TSDB_DATA_TYPE_BOOL) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(pDst->info.type)) {
|
||||
uint64_t v = 0;
|
||||
GET_TYPED_DATA(v, uint64_t, pVar->nType, &pVar->u);
|
||||
GET_TYPED_DATA(v, uint64_t, pVar->nType, &pVar->u, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->u);
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->u, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rowIndex, (const char*)&v, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (pDst->info.type == TSDB_DATA_TYPE_NCHAR || pDst->info.type == TSDB_DATA_TYPE_VARCHAR ||
|
||||
pDst->info.type == TSDB_DATA_TYPE_VARBINARY) {
|
||||
code = colDataSetVal(pDst, rowIndex, pVar->pz, isNull);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else if (pDst->info.type == TSDB_DATA_TYPE_DECIMAL64) {
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)&pVar->i, isNull);
|
||||
} else if (pDst->info.type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
code = colDataSetVal(pDst, rowIndex, (char*)pVar->pz, isNull);
|
||||
} else { // others data
|
||||
colDataSetNULL(pDst, rowIndex);
|
||||
}
|
||||
|
@ -232,7 +236,7 @@ static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock*
|
|||
|
||||
int64_t out = 0;
|
||||
point = (SPoint){.key = pFillInfo->currentKey, .val = &out};
|
||||
taosGetLinearInterpolationVal(&point, type, &point1, &point2, type);
|
||||
taosGetLinearInterpolationVal(&point, type, &point1, &point2, type, typeGetTypeModFromColInfo(&pDstCol->info));
|
||||
|
||||
code = colDataSetVal(pDstCol, index, (const char*)&out, false);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
@ -721,10 +725,10 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t ma
|
|||
}
|
||||
|
||||
void taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* point1, SPoint* point2,
|
||||
int32_t inputType) {
|
||||
int32_t inputType, STypeMod inputTypeMod) {
|
||||
double v1 = -1, v2 = -1;
|
||||
GET_TYPED_DATA(v1, double, inputType, point1->val);
|
||||
GET_TYPED_DATA(v2, double, inputType, point2->val);
|
||||
GET_TYPED_DATA(v1, double, inputType, point1->val, inputTypeMod);
|
||||
GET_TYPED_DATA(v2, double, inputType, point2->val, inputTypeMod);
|
||||
|
||||
double r = 0;
|
||||
if (!IS_BOOLEAN_TYPE(inputType)) {
|
||||
|
|
|
@ -193,7 +193,7 @@ static void tRowGetKeyFromColData(int64_t ts, SColumnInfoData* pPkCol, int32_t r
|
|||
|
||||
pKey->pks[0].type = t;
|
||||
if (IS_NUMERIC_TYPE(t)) {
|
||||
GET_TYPED_DATA(pKey->pks[0].val, int64_t, t, colDataGetNumData(pPkCol, rowIndex));
|
||||
valueSetDatum(pKey->pks, t, colDataGetData(pPkCol, rowIndex), tDataTypes[t].bytes);
|
||||
} else {
|
||||
char* p = colDataGetVarData(pPkCol, rowIndex);
|
||||
pKey->pks[0].pData = (uint8_t*)varDataVal(p);
|
||||
|
@ -215,7 +215,7 @@ static bool checkDuplicateTimestamps(STimeSliceOperatorInfo* pSliceInfo, SColumn
|
|||
if (IS_VAR_DATA_TYPE(pPkCol->info.type)) {
|
||||
cur.pks[0].pData = (uint8_t*)colDataGetVarData(pPkCol, curIndex);
|
||||
} else {
|
||||
memcpy(&cur.pks[0].val, colDataGetData(pPkCol, curIndex), pPkCol->info.bytes);
|
||||
valueSetDatum(cur.pks, pPkCol->info.type, colDataGetData(pPkCol, curIndex), pPkCol->info.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
if (pDst->info.type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float v = 0;
|
||||
if (!IS_VAR_DATA_TYPE(pVar->nType)) {
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->f);
|
||||
GET_TYPED_DATA(v, float, pVar->nType, &pVar->f, 0);
|
||||
} else {
|
||||
v = taosStr2Float(varDataVal(pVar->pz), NULL);
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
} else if (pDst->info.type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double v = 0;
|
||||
if (!IS_VAR_DATA_TYPE(pVar->nType)) {
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->d);
|
||||
GET_TYPED_DATA(v, double, pVar->nType, &pVar->d, 0);
|
||||
} else {
|
||||
v = taosStr2Double(varDataVal(pVar->pz), NULL);
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
} else if (IS_SIGNED_NUMERIC_TYPE(pDst->info.type)) {
|
||||
int64_t v = 0;
|
||||
if (!IS_VAR_DATA_TYPE(pVar->nType)) {
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i, 0);
|
||||
} else {
|
||||
v = taosStr2Int64(varDataVal(pVar->pz), NULL, 10);
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
} else if (IS_UNSIGNED_NUMERIC_TYPE(pDst->info.type)) {
|
||||
uint64_t v = 0;
|
||||
if (!IS_VAR_DATA_TYPE(pVar->nType)) {
|
||||
GET_TYPED_DATA(v, uint64_t, pVar->nType, &pVar->u);
|
||||
GET_TYPED_DATA(v, uint64_t, pVar->nType, &pVar->u, 0);
|
||||
} else {
|
||||
v = taosStr2UInt64(varDataVal(pVar->pz), NULL, 10);
|
||||
}
|
||||
|
@ -496,7 +496,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
} else if (IS_BOOLEAN_TYPE(pDst->info.type)) {
|
||||
bool v = false;
|
||||
if (!IS_VAR_DATA_TYPE(pVar->nType)) {
|
||||
GET_TYPED_DATA(v, bool, pVar->nType, &pVar->i);
|
||||
GET_TYPED_DATA(v, bool, pVar->nType, &pVar->i, 0);
|
||||
} else {
|
||||
v = taosStr2Int8(varDataVal(pVar->pz), NULL, 10);
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp
|
|||
|
||||
current.val = taosMemoryCalloc(pLinearInfo->bytes, 1);
|
||||
QUERY_CHECK_NULL(current.val, code, lino, _end, terrno);
|
||||
taosGetLinearInterpolationVal(¤t, pLinearInfo->type, &start, &end, pLinearInfo->type);
|
||||
taosGetLinearInterpolationVal(¤t, pLinearInfo->type, &start, &end, pLinearInfo->type, typeGetTypeModFromColInfo(&pDst->info));
|
||||
code = colDataSetVal(pDst, rows, (char*)current.val, false);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
||||
|
|
|
@ -236,12 +236,12 @@ void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY pr
|
|||
double v1 = 0, v2 = 0, v = 0;
|
||||
if (prevRowIndex == -1) {
|
||||
SGroupKeys* p = taosArrayGet(pPrevValues, index);
|
||||
GET_TYPED_DATA(v1, double, pColInfo->info.type, p->pData);
|
||||
GET_TYPED_DATA(v1, double, pColInfo->info.type, p->pData, typeGetTypeModFromColInfo(&pColInfo->info));
|
||||
} else {
|
||||
GET_TYPED_DATA(v1, double, pColInfo->info.type, colDataGetData(pColInfo, prevRowIndex));
|
||||
GET_TYPED_DATA(v1, double, pColInfo->info.type, colDataGetData(pColInfo, prevRowIndex), typeGetTypeModFromColInfo(&pColInfo->info));
|
||||
}
|
||||
|
||||
GET_TYPED_DATA(v2, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex));
|
||||
GET_TYPED_DATA(v2, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex), typeGetTypeModFromColInfo(&pColInfo->info));
|
||||
|
||||
#if 0
|
||||
if (functionId == FUNCTION_INTERP) {
|
||||
|
@ -271,7 +271,7 @@ void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY pr
|
|||
SPoint point = (SPoint){.key = windowKey, .val = &v};
|
||||
|
||||
if (!fmIsElapsedFunc(pCtx[k].functionId)) {
|
||||
taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE);
|
||||
taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE, 0);
|
||||
}
|
||||
|
||||
if (type == RESULT_ROW_START_INTERP) {
|
||||
|
|
|
@ -29,6 +29,7 @@ target_link_libraries(
|
|||
PRIVATE qcom
|
||||
PRIVATE scalar
|
||||
PRIVATE geometry
|
||||
PRIVATE decimal
|
||||
PRIVATE transport
|
||||
PUBLIC uv_a
|
||||
)
|
||||
|
|
|
@ -78,7 +78,7 @@ int32_t avgInvertFunction(SqlFunctionCtx* pCtx);
|
|||
#endif
|
||||
|
||||
int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx);
|
||||
int32_t getAvgInfoSize();
|
||||
int32_t getAvgInfoSize(SFunctionNode* pFunc);
|
||||
|
||||
bool getStdFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo);
|
||||
|
|
|
@ -90,6 +90,7 @@ extern "C" {
|
|||
#define FUNC_PARAM_SUPPORT_INTEGER_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(21)
|
||||
#define FUNC_PARAM_SUPPORT_NULL_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(22)
|
||||
#define FUNC_PARAM_SUPPORT_UNIX_TS_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(23)
|
||||
#define FUNC_PARAM_SUPPORT_DECIMAL_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(24)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ extern "C" {
|
|||
#include "tdigest.h"
|
||||
#include "functionResInfo.h"
|
||||
#include "tpercentile.h"
|
||||
#include "decimal.h"
|
||||
|
||||
#define USE_ARRAYLIST
|
||||
|
||||
|
@ -46,10 +47,68 @@ typedef struct SSumRes {
|
|||
bool overflow; // if overflow is true, dsum to be used for any type;
|
||||
} SSumRes;
|
||||
|
||||
typedef struct SDecimalSumRes {
|
||||
Decimal128 sum;
|
||||
int16_t type;
|
||||
int64_t prevTs;
|
||||
bool isPrevTsSet;
|
||||
bool overflow;
|
||||
uint32_t flag; // currently not used
|
||||
} SDecimalSumRes;
|
||||
|
||||
#define SUM_RES_GET_RES(pSumRes) ((SSumRes*)pSumRes)
|
||||
#define SUM_RES_GET_DECIMAL_RES(pSumRes) ((SDecimalSumRes*)pSumRes)
|
||||
|
||||
#define SUM_RES_GET_SIZE(type) IS_DECIMAL_TYPE(type) ? sizeof(SDecimalSumRes) : sizeof(SSumRes)
|
||||
|
||||
#define SUM_RES_SET_TYPE(pSumRes, inputType, _type) \
|
||||
do { \
|
||||
if (IS_DECIMAL_TYPE(inputType)) \
|
||||
SUM_RES_GET_DECIMAL_RES(pSumRes)->type = _type; \
|
||||
else \
|
||||
SUM_RES_GET_RES(pSumRes)->type = _type; \
|
||||
} while (0)
|
||||
|
||||
#define SUM_RES_GET_TYPE(pSumRes, inputType) \
|
||||
(IS_DECIMAL_TYPE(inputType) ? SUM_RES_GET_DECIMAL_RES(pSumRes)->type : SUM_RES_GET_RES(pSumRes)->type)
|
||||
#define SUM_RES_GET_PREV_TS(pSumRes, inputType) \
|
||||
(IS_DECIMAL_TYPE(inputType) ? SUM_RES_GET_DECIMAL_RES(pSumRes)->prevTs : SUM_RES_GET_RES(pSumRes)->prevTs)
|
||||
#define SUM_RES_GET_OVERFLOW(pSumRes, checkInputType, inputType) \
|
||||
(checkInputType && IS_DECIMAL_TYPE(inputType) ? SUM_RES_GET_DECIMAL_RES(pSumRes)->overflow \
|
||||
: SUM_RES_GET_RES(pSumRes)->overflow)
|
||||
|
||||
#define SUM_RES_GET_ISUM(pSumRes) (((SSumRes*)(pSumRes))->isum)
|
||||
#define SUM_RES_GET_USUM(pSumRes) (((SSumRes*)(pSumRes))->usum)
|
||||
#define SUM_RES_GET_DSUM(pSumRes) (((SSumRes*)(pSumRes))->dsum)
|
||||
#define SUM_RES_INC_ISUM(pSumRes, val) ((SSumRes*)(pSumRes))->isum += val
|
||||
#define SUM_RES_INC_USUM(pSumRes, val) ((SSumRes*)(pSumRes))->usum += val
|
||||
#define SUM_RES_INC_DSUM(pSumRes, val) ((SSumRes*)(pSumRes))->dsum += val
|
||||
|
||||
#define SUM_RES_GET_DECIMAL_SUM(pSumRes) ((SDecimalSumRes*)(pSumRes))->sum
|
||||
#define SUM_RES_INC_DECIMAL_SUM(pSumRes, pVal, type) \
|
||||
do { \
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); \
|
||||
int32_t wordNum = 0; \
|
||||
if (type == TSDB_DATA_TYPE_DECIMAL64) { \
|
||||
wordNum = DECIMAL_WORD_NUM(Decimal64); \
|
||||
overflow = decimal128AddCheckOverflow(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pVal, wordNum); \
|
||||
} else { \
|
||||
wordNum = DECIMAL_WORD_NUM(Decimal); \
|
||||
overflow = decimal128AddCheckOverflow(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pVal, wordNum); \
|
||||
} \
|
||||
pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pVal, wordNum); \
|
||||
if (overflow) break; \
|
||||
} while (0)
|
||||
|
||||
typedef struct SMinmaxResInfo {
|
||||
bool assign; // assign the first value or not
|
||||
int64_t v;
|
||||
char *str;
|
||||
union {
|
||||
struct {
|
||||
int64_t v;
|
||||
char* str;
|
||||
};
|
||||
int64_t dec[2]; // for decimal types
|
||||
};
|
||||
STuplePos tuplePos;
|
||||
|
||||
STuplePos nullTuplePos;
|
||||
|
@ -57,6 +116,17 @@ typedef struct SMinmaxResInfo {
|
|||
int16_t type;
|
||||
} SMinmaxResInfo;
|
||||
|
||||
typedef struct SOldMinMaxResInfo {
|
||||
bool assign; // assign the first value or not
|
||||
int64_t v;
|
||||
char* str;
|
||||
STuplePos tuplePos;
|
||||
|
||||
STuplePos nullTuplePos;
|
||||
bool nullTupleSaved;
|
||||
int16_t type;
|
||||
} SOldMinMaxResInfo;
|
||||
|
||||
typedef struct SStdRes {
|
||||
double result;
|
||||
int64_t count;
|
||||
|
@ -133,6 +203,55 @@ typedef struct SAvgRes {
|
|||
int16_t type; // store the original input type, used in merge function
|
||||
} SAvgRes;
|
||||
|
||||
typedef struct SDecimalAvgRes {
|
||||
Decimal128 avg;
|
||||
SDecimalSumRes sum;
|
||||
int64_t count;
|
||||
int16_t type; // store the original input type and scale, used in merge function
|
||||
uint8_t scale;
|
||||
} SDecimalAvgRes;
|
||||
|
||||
#define AVG_RES_GET_RES(pAvgRes) ((SAvgRes*)pAvgRes)
|
||||
#define AVG_RES_GET_DECIMAL_RES(pAvgRes) ((SDecimalAvgRes*)pAvgRes)
|
||||
#define AVG_RES_SET_TYPE(pAvgRes, inputType, _type) \
|
||||
do { \
|
||||
if (IS_DECIMAL_TYPE(inputType)) \
|
||||
AVG_RES_GET_DECIMAL_RES(pAvgRes)->type = _type; \
|
||||
else \
|
||||
AVG_RES_GET_RES(pAvgRes)->type = _type; \
|
||||
} while (0)
|
||||
|
||||
#define AVG_RES_SET_INPUT_SCALE(pAvgRes, _scale) \
|
||||
do { \
|
||||
AVG_RES_GET_DECIMAL_RES(pAvgRes)->scale = _scale; \
|
||||
} while (0)
|
||||
|
||||
#define AVG_RES_GET_INPUT_SCALE(pAvgRes) (AVG_RES_GET_DECIMAL_RES(pAvgRes)->scale)
|
||||
|
||||
#define AVG_RES_GET_TYPE(pAvgRes, inputType) \
|
||||
(IS_DECIMAL_TYPE(inputType) ? AVG_RES_GET_DECIMAL_RES(pAvgRes)->type : AVG_RES_GET_RES(pAvgRes)->type)
|
||||
|
||||
#define AVG_RES_GET_SIZE(inputType) (IS_DECIMAL_TYPE(inputType) ? sizeof(SDecimalAvgRes) : sizeof(SAvgRes))
|
||||
#define AVG_RES_GET_AVG(pAvgRes) (AVG_RES_GET_RES(pAvgRes)->result)
|
||||
#define AVG_RES_GET_SUM(pAvgRes) (AVG_RES_GET_RES(pAvgRes)->sum)
|
||||
#define AVG_RES_GET_COUNT(pAvgRes, checkInputType, inputType) \
|
||||
(checkInputType && IS_DECIMAL_TYPE(inputType) ? AVG_RES_GET_DECIMAL_RES(pAvgRes)->count \
|
||||
: AVG_RES_GET_RES(pAvgRes)->count)
|
||||
#define AVG_RES_INC_COUNT(pAvgRes, inputType, val) \
|
||||
do { \
|
||||
if (IS_DECIMAL_TYPE(inputType)) \
|
||||
AVG_RES_GET_DECIMAL_RES(pAvgRes)->count += val; \
|
||||
else \
|
||||
AVG_RES_GET_RES(pAvgRes)->count += val; \
|
||||
} while (0)
|
||||
|
||||
#define AVG_RES_GET_DECIMAL_AVG(pAvgRes) (((SDecimalAvgRes*)(pAvgRes))->avg)
|
||||
#define AVG_RES_GET_DECIMAL_SUM(pAvgRes) (((SDecimalAvgRes*)(pAvgRes))->sum)
|
||||
|
||||
#define AVG_RES_GET_SUM_OVERFLOW(pAvgRes, checkInputType, inputType) \
|
||||
checkInputType&& IS_DECIMAL_TYPE(inputType) \
|
||||
? SUM_RES_GET_OVERFLOW(&AVG_RES_GET_DECIMAL_SUM(pAvgRes), true, inputType) \
|
||||
: SUM_RES_GET_OVERFLOW(&AVG_RES_GET_SUM(pAvgRes), false, inputType)
|
||||
|
||||
// structs above are used in stream
|
||||
|
||||
|
@ -195,6 +314,7 @@ typedef struct tMemBucket {
|
|||
int16_t numOfSlots;
|
||||
int16_t type;
|
||||
int32_t bytes;
|
||||
STypeMod typeMod;
|
||||
int32_t total;
|
||||
int32_t elemPerPage; // number of elements for each object
|
||||
int32_t maxCapacity; // maximum allowed number of elements that can be sort directly to get the result
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
struct tMemBucket;
|
||||
|
||||
int32_t tMemBucketCreate(int32_t nElemSize, int16_t dataType, double minval, double maxval, bool hasWindowOrGroup,
|
||||
int32_t tMemBucketCreate(int32_t nElemSize, int16_t dataType, STypeMod typeMod, double minval, double maxval, bool hasWindowOrGroup,
|
||||
struct tMemBucket **pBucket, int32_t numOfElements);
|
||||
|
||||
void tMemBucketDestroy(struct tMemBucket **pBucket);
|
||||
|
|
|
@ -410,6 +410,11 @@ static bool paramSupportGeometry(uint64_t typeFlag) {
|
|||
FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_VAR_TYPE);
|
||||
}
|
||||
|
||||
static bool paramSupportDecimal(uint64_t typeFlag) {
|
||||
return FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_DECIMAL_TYPE) ||
|
||||
FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_ALL_TYPE);
|
||||
}
|
||||
|
||||
static bool paramSupportValueNode(uint64_t typeFlag) {
|
||||
return FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_VALUE_NODE) ||
|
||||
FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_EXPR_NODE);
|
||||
|
@ -502,6 +507,9 @@ static bool paramSupportDataType(SDataType* pDataType, uint64_t typeFlag) {
|
|||
return paramSupportVarBinary(typeFlag);
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return paramSupportGeometry(typeFlag);
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
return paramSupportDecimal(typeFlag);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -965,7 +973,35 @@ static int32_t translateMinMax(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
SDataType* dataType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0));
|
||||
uint8_t paraType = IS_NULL_TYPE(dataType->type) ? TSDB_DATA_TYPE_BIGINT : dataType->type;
|
||||
int32_t bytes = IS_STR_DATA_TYPE(paraType) ? dataType->bytes : tDataTypes[paraType].bytes;
|
||||
pFunc->node.resType = (SDataType){.bytes = bytes, .type = paraType};
|
||||
uint8_t prec = IS_DECIMAL_TYPE(paraType) ? dataType->precision : pFunc->node.resType.precision;
|
||||
pFunc->node.resType = (SDataType){.bytes = bytes, .type = paraType, .precision = prec, .scale = dataType->scale};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateAvg(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len));
|
||||
|
||||
uint8_t dt = TSDB_DATA_TYPE_DOUBLE, prec = 0, scale = 0;
|
||||
|
||||
bool isMergeFunc = pFunc->funcType == FUNCTION_TYPE_AVG_MERGE || pFunc->funcType == FUNCTION_TYPE_AVG_STATE_MERGE;
|
||||
SDataType* pInputDt = getSDataTypeFromNode(
|
||||
nodesListGetNode(isMergeFunc ? pFunc->pSrcFuncRef->pParameterList : pFunc->pParameterList, 0));
|
||||
pFunc->srcFuncInputType = *pInputDt;
|
||||
if (IS_DECIMAL_TYPE(pInputDt->type)) {
|
||||
SDataType sumDt = {.type = TSDB_DATA_TYPE_DECIMAL,
|
||||
.bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
|
||||
.precision = TSDB_DECIMAL_MAX_PRECISION,
|
||||
.scale = pInputDt->scale};
|
||||
SDataType countDt = {
|
||||
.type = TSDB_DATA_TYPE_BIGINT, .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .precision = 0, .scale = 0};
|
||||
SDataType avgDt = {0};
|
||||
int32_t code = decimalGetRetType(&sumDt, &countDt, OP_TYPE_DIV, &avgDt);
|
||||
if (code != 0) return code;
|
||||
dt = TSDB_DATA_TYPE_DECIMAL;
|
||||
prec = TSDB_DECIMAL_MAX_PRECISION;
|
||||
scale = avgDt.scale;
|
||||
}
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[dt].bytes, .type = dt, .precision = prec, .scale = scale};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1016,15 +1052,20 @@ static int32_t translateSum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
|
||||
uint8_t paraType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type;
|
||||
uint8_t resType = 0;
|
||||
uint8_t prec = 0, scale = 0;
|
||||
if (IS_SIGNED_NUMERIC_TYPE(paraType) || TSDB_DATA_TYPE_BOOL == paraType || IS_NULL_TYPE(paraType)) {
|
||||
resType = TSDB_DATA_TYPE_BIGINT;
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(paraType)) {
|
||||
resType = TSDB_DATA_TYPE_UBIGINT;
|
||||
} else if (IS_FLOAT_TYPE(paraType)) {
|
||||
resType = TSDB_DATA_TYPE_DOUBLE;
|
||||
} else if (IS_DECIMAL_TYPE(paraType)) {
|
||||
resType = TSDB_DATA_TYPE_DECIMAL;
|
||||
prec = TSDB_DECIMAL_MAX_PRECISION;
|
||||
scale = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.scale;
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType};
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType, .precision = prec, .scale = scale};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1650,8 +1691,12 @@ static int32_t translateOutVarchar(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
break;
|
||||
case FUNCTION_TYPE_AVG_PARTIAL:
|
||||
case FUNCTION_TYPE_AVG_STATE:
|
||||
pFunc->srcFuncInputType = ((SExprNode*)pFunc->pParameterList->pHead->pNode)->resType;
|
||||
bytes = getAvgInfoSize(pFunc) + VARSTR_HEADER_SIZE;
|
||||
break;
|
||||
case FUNCTION_TYPE_AVG_STATE_MERGE:
|
||||
bytes = getAvgInfoSize() + VARSTR_HEADER_SIZE;
|
||||
if (pFunc->pSrcFuncRef) pFunc->srcFuncInputType = pFunc->pSrcFuncRef->srcFuncInputType;
|
||||
bytes = getAvgInfoSize(pFunc) + VARSTR_HEADER_SIZE;
|
||||
break;
|
||||
case FUNCTION_TYPE_HISTOGRAM_PARTIAL:
|
||||
bytes = getHistogramInfoSize() + VARSTR_HEADER_SIZE;
|
||||
|
@ -1846,11 +1891,11 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
.outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_BIGINT_TYPE | FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_UBIGINT_TYPE}},
|
||||
.outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_BIGINT_TYPE | FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_UBIGINT_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE}},
|
||||
.translateFunc = translateSum,
|
||||
.dataRequiredFunc = statisDataRequired,
|
||||
.getEnvFunc = getSumFuncEnv,
|
||||
|
@ -1876,7 +1921,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
|
@ -1891,7 +1936,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.combineFunc = minCombine,
|
||||
.pPartialFunc = "min",
|
||||
.pStateFunc = "min",
|
||||
.pMergeFunc = "min"
|
||||
.pMergeFunc = "min",
|
||||
},
|
||||
{
|
||||
.name = "max",
|
||||
|
@ -1903,7 +1948,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
|
@ -1918,7 +1963,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.combineFunc = maxCombine,
|
||||
.pPartialFunc = "max",
|
||||
.pStateFunc = "max",
|
||||
.pMergeFunc = "max"
|
||||
.pMergeFunc = "max",
|
||||
},
|
||||
{
|
||||
.name = "stddev",
|
||||
|
@ -2044,12 +2089,12 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
.outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_DOUBLE_TYPE}},
|
||||
.translateFunc = translateOutDouble,
|
||||
.outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE}},
|
||||
.translateFunc = translateAvg,
|
||||
.dataRequiredFunc = statisDataRequired,
|
||||
.getEnvFunc = getAvgFuncEnv,
|
||||
.initFunc = avgFunctionSetup,
|
||||
|
@ -2075,7 +2120,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
|
@ -2106,7 +2151,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
.outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_DOUBLE_TYPE}},
|
||||
.translateFunc = translateOutDouble,
|
||||
.translateFunc = translateAvg,
|
||||
.getEnvFunc = getAvgFuncEnv,
|
||||
.initFunc = avgFunctionSetup,
|
||||
.processFunc = avgFunctionMerge,
|
||||
|
@ -4779,7 +4824,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.inputParaInfo[0][0] = {.isLastParam = true,
|
||||
.startParam = 1,
|
||||
.endParam = 1,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE,
|
||||
.validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE,
|
||||
.validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE,
|
||||
.paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE,
|
||||
.valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,},
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "builtinsimpl.h"
|
||||
#include "cJSON.h"
|
||||
#include "decimal.h"
|
||||
#include "function.h"
|
||||
#include "functionResInfoInt.h"
|
||||
#include "query.h"
|
||||
|
@ -105,6 +106,21 @@ typedef enum {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define LIST_ADD_DECIMAL_N(_res, _col, _start, _rows, _t, numOfElem) \
|
||||
do { \
|
||||
_t* d = (_t*)(_col->pData); \
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); \
|
||||
for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
|
||||
if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
|
||||
continue; \
|
||||
}; \
|
||||
overflow = overflow || decimal128AddCheckOverflow((Decimal*)_res, d + i, DECIMAL_WORD_NUM(_t)); \
|
||||
if (overflow) break; \
|
||||
pOps->add(_res, d + i, DECIMAL_WORD_NUM(_t)); \
|
||||
(numOfElem)++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem) \
|
||||
do { \
|
||||
_t* d = (_t*)(_col->pData); \
|
||||
|
@ -619,9 +635,10 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) {
|
|||
SInputColumnInfoData* pInput = &pCtx->input;
|
||||
SColumnDataAgg* pAgg = pInput->pColumnDataAgg[0];
|
||||
int32_t type = pInput->pData[0]->info.type;
|
||||
pCtx->inputType = type;
|
||||
|
||||
SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
pSumRes->type = type;
|
||||
void* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, type);
|
||||
|
||||
if (IS_NULL_TYPE(type)) {
|
||||
numOfElem = 0;
|
||||
|
@ -632,11 +649,19 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) {
|
|||
numOfElem = pInput->numOfRows - pAgg->numOfNull;
|
||||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
pSumRes->isum += pAgg->sum;
|
||||
SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
pSumRes->usum += pAgg->sum;
|
||||
SUM_RES_INC_USUM(pSumRes, pAgg->sum);
|
||||
} else if (IS_FLOAT_TYPE(type)) {
|
||||
pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
|
||||
SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
|
||||
&pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
|
||||
return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
}
|
||||
pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
|
||||
}
|
||||
} else { // computing based on the true data block
|
||||
SColumnInfoData* pCol = pInput->pData[0];
|
||||
|
@ -646,33 +671,42 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
|
||||
if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
|
||||
LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int8_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_SMALLINT) {
|
||||
LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_INT) {
|
||||
LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int32_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_BIGINT) {
|
||||
LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int64_t, numOfElem);
|
||||
}
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
if (type == TSDB_DATA_TYPE_UTINYINT) {
|
||||
LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint8_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_USMALLINT) {
|
||||
LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint16_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_UINT) {
|
||||
LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_UBIGINT) {
|
||||
LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
|
||||
} else if (type == TSDB_DATA_TYPE_FLOAT) {
|
||||
LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
|
||||
LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
|
||||
int32_t overflow = false;
|
||||
if (TSDB_DATA_TYPE_DECIMAL64 == type) {
|
||||
LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
|
||||
} else if (TSDB_DATA_TYPE_DECIMAL == type) {
|
||||
LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
|
||||
}
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
// check for overflow
|
||||
if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
|
||||
if (IS_FLOAT_TYPE(type) && (isinf(SUM_RES_GET_DSUM(pSumRes)) || isnan(SUM_RES_GET_DSUM(pSumRes)))) {
|
||||
numOfElem = 0;
|
||||
}
|
||||
|
||||
|
@ -750,26 +784,30 @@ int32_t sumInvertFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
|
||||
SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
|
||||
SSumRes* pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
|
||||
void* pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
|
||||
int16_t type = SUM_RES_GET_TYPE(pDBuf, pDestCtx->inputType);
|
||||
|
||||
SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
|
||||
SSumRes* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
|
||||
int16_t type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
|
||||
void* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
|
||||
type = (type == TSDB_DATA_TYPE_NULL) ? SUM_RES_GET_TYPE(pSBuf, pDestCtx->inputType) : type;
|
||||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
|
||||
pDBuf->isum += pSBuf->isum;
|
||||
SUM_RES_INC_ISUM(pDBuf, SUM_RES_GET_ISUM(pSBuf));
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
pDBuf->usum += pSBuf->usum;
|
||||
SUM_RES_INC_USUM(pDBuf, SUM_RES_GET_USUM(pSBuf));
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
bool overflow = false;
|
||||
SUM_RES_INC_DECIMAL_SUM(pDBuf, &SUM_RES_GET_DECIMAL_SUM(pSBuf), type);
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
|
||||
pDBuf->dsum += pSBuf->dsum;
|
||||
SUM_RES_INC_DSUM(pDBuf, SUM_RES_GET_DSUM(pSBuf));
|
||||
}
|
||||
pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
|
||||
pDResInfo->isNullRes &= pSResInfo->isNullRes;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(SSumRes);
|
||||
bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -824,6 +862,7 @@ int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultIn
|
|||
}
|
||||
|
||||
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
|
||||
COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
|
||||
pEnv->calcMemSize = sizeof(SMinmaxResInfo);
|
||||
return true;
|
||||
}
|
||||
|
@ -904,12 +943,18 @@ int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
colDataSetNULL(pCol, currentRow);
|
||||
}
|
||||
|
||||
taosMemoryFreeClear(pRes->str);
|
||||
if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
|
||||
if (pCtx->subsidiaries.num > 0) {
|
||||
if (pEntryInfo->numOfRes > 0) {
|
||||
code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
|
||||
|
@ -1037,7 +1082,6 @@ int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int3
|
|||
int16_t type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
|
||||
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
if (pSBuf->assign && (COMPARE_MINMAX_DATA(int64_t) || !pDBuf->assign)) {
|
||||
|
@ -1071,6 +1115,7 @@ int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int3
|
|||
pDBuf->assign = true;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
if (pSBuf->assign && (COMPARE_MINMAX_DATA(double) || !pDBuf->assign)) {
|
||||
pDBuf->v = pSBuf->v;
|
||||
|
@ -1079,12 +1124,28 @@ int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int3
|
|||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (pSBuf->assign && (strcmp((char*)&pDBuf->v, (char*)&pSBuf->v) || !pDBuf->assign)) {
|
||||
case TSDB_DATA_TYPE_DECIMAL64: {
|
||||
const SDecimalOps* pOps = getDecimalOps(type);
|
||||
if (pSBuf->assign && ((pOps->lt(&pDBuf->v, &pSBuf->v, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) || !pDBuf->assign)) {
|
||||
pDBuf->v = pSBuf->v;
|
||||
replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
|
||||
pDBuf->assign = true;
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
const SDecimalOps* pOps = getDecimalOps(type);
|
||||
if (pSBuf->assign && (pOps->lt(pDBuf->dec, pSBuf->dec, DECIMAL_WORD_NUM(Decimal)) ^ isMinFunc) || !pDBuf->assign) {
|
||||
memcpy(pDBuf->dec, pSBuf->dec, DECIMAL128_BYTES);
|
||||
replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
|
||||
pDBuf->assign = true;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
if (pSBuf->assign && (strcmp(pDBuf->str, pSBuf->str) || !pDBuf->assign)) {
|
||||
memcpy(pDBuf->str, pSBuf->str, varDataLen(pSBuf->str));
|
||||
replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
|
||||
pDBuf->assign = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
|
||||
|
@ -1532,8 +1593,10 @@ int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResult
|
|||
|
||||
SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
|
||||
|
||||
GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
|
||||
GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
|
||||
GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
|
||||
typeGetTypeModFromCol(pCtx->param[1].pCol));
|
||||
GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
|
||||
typeGetTypeModFromCol(pCtx->param[2].pCol));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1891,7 @@ int32_t percentileFunction(SqlFunctionCtx* pCtx) {
|
|||
pResInfo->complete = true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
code = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup,
|
||||
code = tMemBucketCreate(pCol->info.bytes, type, typeGetTypeModFromColInfo(&pCol->info), pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup,
|
||||
&pInfo->pMemBucket, pInfo->numOfElems);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
|
@ -1871,7 +1934,7 @@ int32_t percentileFunction(SqlFunctionCtx* pCtx) {
|
|||
char* data = colDataGetData(pCol, i);
|
||||
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
|
||||
if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
|
||||
SET_DOUBLE_VAL(&pInfo->minval, v);
|
||||
}
|
||||
|
@ -1926,7 +1989,7 @@ int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
|
||||
SVariant* pVal = &pCtx->param[i].param;
|
||||
|
||||
GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
|
||||
GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[i].pCol));
|
||||
|
||||
code = getPercentile((*pMemBucket), v, &ppInfo->result);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1958,7 +2021,7 @@ int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
} else {
|
||||
SVariant* pVal = &pCtx->param[1].param;
|
||||
|
||||
GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
|
||||
GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
|
||||
|
||||
code = getPercentile((*pMemBucket), v, &ppInfo->result);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -2027,7 +2090,7 @@ int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pRes
|
|||
|
||||
SVariant* pVal = &pCtx->param[1].param;
|
||||
pInfo->percent = 0;
|
||||
GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i);
|
||||
GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
|
||||
|
||||
if (pCtx->numOfParams == 2) {
|
||||
pInfo->algo = APERCT_ALGO_DEFAULT;
|
||||
|
@ -2074,7 +2137,7 @@ int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
double v = 0; // value
|
||||
int64_t w = 1; // weigth
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
|
||||
int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -2095,7 +2158,7 @@ int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
|
|||
char* data = colDataGetData(pCol, i);
|
||||
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
|
||||
int32_t code = tHistogramAdd(&pInfo->pHisto, v);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -2310,16 +2373,16 @@ static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal
|
|||
char numVal[8] = {0};
|
||||
switch (pkType) {
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
*(int32_t*)numVal = (int32_t)pVal->val;
|
||||
*(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
*(uint32_t*)numVal = (uint32_t)pVal->val;
|
||||
*(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
*(int64_t*)numVal = (int64_t)pVal->val;
|
||||
*(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
*(uint64_t*)numVal = (uint64_t)pVal->val;
|
||||
*(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -4146,7 +4209,7 @@ int32_t spreadFunction(SqlFunctionCtx* pCtx) {
|
|||
char* data = colDataGetData(pCol, i);
|
||||
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
|
||||
if (v < GET_DOUBLE_VAL(&pInfo->min)) {
|
||||
SET_DOUBLE_VAL(&pInfo->min, v);
|
||||
}
|
||||
|
@ -4701,7 +4764,7 @@ static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
|
|||
|
||||
char* data = colDataGetData(pCol, i);
|
||||
double v;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
|
||||
|
||||
for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
|
||||
if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
|
||||
|
@ -5338,7 +5401,7 @@ int32_t csumFunction(SqlFunctionCtx* pCtx) {
|
|||
char* data = colDataGetData(pInputCol, i);
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
int64_t v;
|
||||
GET_TYPED_DATA(v, int64_t, type, data);
|
||||
GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
pSumRes->isum += v;
|
||||
code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
|
@ -5346,7 +5409,7 @@ int32_t csumFunction(SqlFunctionCtx* pCtx) {
|
|||
}
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
uint64_t v;
|
||||
GET_TYPED_DATA(v, uint64_t, type, data);
|
||||
GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
pSumRes->usum += v;
|
||||
code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
|
@ -5354,7 +5417,7 @@ int32_t csumFunction(SqlFunctionCtx* pCtx) {
|
|||
}
|
||||
} else if (IS_FLOAT_TYPE(type)) {
|
||||
double v;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
pSumRes->dsum += v;
|
||||
// check for overflow
|
||||
if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
|
||||
|
@ -5440,7 +5503,7 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
char* data = colDataGetData(pInputCol, i);
|
||||
double v;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
|
||||
pInfo->points[pInfo->pos] = v;
|
||||
|
@ -6132,7 +6195,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
last->key = row.ts;
|
||||
|
||||
GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
|
||||
GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
pInfo->dOutput += twa_get_area(pCtx->start, *last);
|
||||
pInfo->win.skey = pCtx->start.key;
|
||||
|
@ -6154,7 +6217,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
last->key = row.ts;
|
||||
|
||||
GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
|
||||
GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
pInfo->win.skey = last->key;
|
||||
pInfo->numOfElems++;
|
||||
|
@ -6687,7 +6750,7 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
|
|||
}
|
||||
|
||||
char* d = row.pData;
|
||||
GET_TYPED_DATA(v, double, pInputCol->info.type, d);
|
||||
GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
int32_t pos = pCtx->offset + numOfElems;
|
||||
if (!pDerivInfo->valueSet) { // initial value is not set yet
|
||||
|
@ -6743,7 +6806,7 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
|
|||
}
|
||||
|
||||
char* d = row.pData;
|
||||
GET_TYPED_DATA(v, double, pInputCol->info.type, d);
|
||||
GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
int32_t pos = pCtx->offset + numOfElems;
|
||||
if (!pDerivInfo->valueSet) { // initial value is not set yet
|
||||
|
@ -6901,7 +6964,7 @@ int32_t irateFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
char* data = row.pData;
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
|
||||
|
||||
if (INT64_MIN == pRateInfo->lastKey) {
|
||||
doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
|
||||
|
|
|
@ -42,60 +42,74 @@
|
|||
} while (0)
|
||||
|
||||
// define signed number sum with check overflow
|
||||
#define CHECK_OVERFLOW_SUM_SIGNED(out, val) \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \
|
||||
out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val) { \
|
||||
double dsum = (double)out->sum.isum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.isum += val; \
|
||||
}
|
||||
#define CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, val) \
|
||||
do { \
|
||||
SAvgRes* out = pAvgRes; \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \
|
||||
out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val) { \
|
||||
double dsum = (double)out->sum.isum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.isum += val; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// val is big than INT64_MAX, val come from merge
|
||||
#define CHECK_OVERFLOW_SUM_SIGNED_BIG(out, val, big) \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \
|
||||
out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val || \
|
||||
big) { \
|
||||
double dsum = (double)out->sum.isum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.isum += val; \
|
||||
}
|
||||
#define CHECK_OVERFLOW_SUM_SIGNED_BIG(pAvgRes, val, big) \
|
||||
do { \
|
||||
SAvgRes* out = pAvgRes; \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \
|
||||
out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val || big) { \
|
||||
double dsum = (double)out->sum.isum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
SUM_RES_INC_ISUM(&AVG_RES_GET_SUM(out), val); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// define unsigned number sum with check overflow
|
||||
#define CHECK_OVERFLOW_SUM_UNSIGNED(out, val) \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (UINT64_MAX - out->sum.usum <= val) { \
|
||||
double dsum = (double)out->sum.usum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.usum += val; \
|
||||
}
|
||||
#define CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, val) \
|
||||
do { \
|
||||
SAvgRes* out = pAvgRes; \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (UINT64_MAX - out->sum.usum <= val) { \
|
||||
double dsum = (double)out->sum.usum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.usum += val; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// val is big than UINT64_MAX, val come from merge
|
||||
#define CHECK_OVERFLOW_SUM_UNSIGNED_BIG(out, val, big) \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (UINT64_MAX - out->sum.usum <= val || big) { \
|
||||
double dsum = (double)out->sum.usum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.usum += val; \
|
||||
}
|
||||
#define CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pAvgRes, val, big) \
|
||||
do { \
|
||||
SAvgRes* out = pAvgRes; \
|
||||
if (out->sum.overflow) { \
|
||||
out->sum.dsum += val; \
|
||||
} else if (UINT64_MAX - out->sum.usum <= val || big) { \
|
||||
double dsum = (double)out->sum.usum; \
|
||||
out->sum.overflow = true; \
|
||||
out->sum.dsum = dsum + val; \
|
||||
} else { \
|
||||
out->sum.usum += val; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int32_t getAvgInfoSize() { return (int32_t)sizeof(SAvgRes); }
|
||||
int32_t getAvgInfoSize(SFunctionNode* pFunc) {
|
||||
if (pFunc->pSrcFuncRef) return AVG_RES_GET_SIZE(pFunc->pSrcFuncRef->srcFuncInputType.type);
|
||||
return AVG_RES_GET_SIZE(pFunc->srcFuncInputType.type);
|
||||
}
|
||||
|
||||
bool getAvgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(SAvgRes);
|
||||
bool getAvgFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize =getAvgInfoSize(pFunc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -107,27 +121,33 @@ int32_t avgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo)
|
|||
return TSDB_CODE_FUNC_SETUP_ERROR;
|
||||
}
|
||||
|
||||
SAvgRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
|
||||
(void)memset(pRes, 0, sizeof(SAvgRes));
|
||||
void* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
|
||||
(void)memset(pRes, 0, pCtx->resDataInfo.interBufSize);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t calculateAvgBySMAInfo(SAvgRes* pRes, int32_t numOfRows, int32_t type, const SColumnDataAgg* pAgg) {
|
||||
static int32_t calculateAvgBySMAInfo(void* pRes, int32_t numOfRows, int32_t type, const SColumnDataAgg* pAgg, int32_t* pNumOfElem) {
|
||||
int32_t numOfElem = numOfRows - pAgg->numOfNull;
|
||||
|
||||
pRes->count += numOfElem;
|
||||
AVG_RES_INC_COUNT(pRes, type, numOfElem);
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, pAgg->sum);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, pAgg->sum);
|
||||
} else if (IS_FLOAT_TYPE(type)) {
|
||||
pRes->sum.dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
bool overflow = pAgg->overflow;
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes), &pAgg->decimal128Sum, TSDB_DATA_TYPE_DECIMAL);
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
}
|
||||
|
||||
return numOfElem;
|
||||
*pNumOfElem = numOfElem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputColumnInfoData *pInput, SAvgRes* pRes) {
|
||||
static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputColumnInfoData *pInput, void* pRes, int32_t* pNumOfElem) {
|
||||
int32_t start = pInput->startRowIndex;
|
||||
int32_t numOfRows = pInput->numOfRows;
|
||||
int32_t numOfElems = 0;
|
||||
|
@ -141,8 +161,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_TINYINT, 1);
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -156,8 +176,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_SMALLINT, 1);
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -170,8 +190,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_INT, 1);
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -185,8 +205,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_BIGINT, 1);
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -199,8 +219,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UTINYINT, 1);
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -214,8 +234,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_USMALLINT, 1);
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -228,8 +248,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UINT, 1);
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -243,8 +263,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i])
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UBIGINT, 1);
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -258,8 +278,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
pRes->sum.dsum += plist[i];
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_FLOAT, 1);
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -272,17 +292,32 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol
|
|||
}
|
||||
|
||||
numOfElems += 1;
|
||||
pRes->count += 1;
|
||||
pRes->sum.dsum += plist[i];
|
||||
AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_DOUBLE, 1);
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
const char* pDec = pCol->pData;
|
||||
for (int32_t i = start; i < numOfRows + start; ++i) {
|
||||
if (colDataIsNull_f(pCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
numOfElems += 1;
|
||||
AVG_RES_INC_COUNT(pRes, type, 1);
|
||||
bool overflow = false;
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes), (const void*)(pDec + i * tDataTypes[type].bytes), type);
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return numOfElems;
|
||||
*pNumOfElem = numOfElems;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
||||
|
@ -292,8 +327,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
SInputColumnInfoData* pInput = &pCtx->input;
|
||||
SColumnDataAgg* pAgg = pInput->pColumnDataAgg[0];
|
||||
int32_t type = pInput->pData[0]->info.type;
|
||||
pCtx->inputType = type;
|
||||
|
||||
SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
void* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
|
||||
// computing based on the true data block
|
||||
SColumnInfoData* pCol = pInput->pData[0];
|
||||
|
@ -305,13 +341,15 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
goto _over;
|
||||
}
|
||||
|
||||
pAvgRes->type = type;
|
||||
AVG_RES_SET_TYPE(pAvgRes, pCtx->inputType, type);
|
||||
if (IS_DECIMAL_TYPE(type)) AVG_RES_SET_INPUT_SCALE(pAvgRes, pInput->pData[0]->info.scale);
|
||||
|
||||
if (pInput->colDataSMAIsSet) { // try to use SMA if available
|
||||
numOfElem = calculateAvgBySMAInfo(pAvgRes, numOfRows, type, pAgg);
|
||||
int32_t code = calculateAvgBySMAInfo(pAvgRes, numOfRows, type, pAgg, &numOfElem);
|
||||
if (code != 0) return code;
|
||||
} else if (!pCol->hasNull) { // try to employ the simd instructions to speed up the loop
|
||||
numOfElem = pInput->numOfRows;
|
||||
pAvgRes->count += pInput->numOfRows;
|
||||
AVG_RES_INC_COUNT(pAvgRes, pCtx->inputType, pInput->numOfRows);
|
||||
|
||||
switch(type) {
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
|
@ -320,9 +358,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
if (type == TSDB_DATA_TYPE_TINYINT) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i])
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
|
||||
} else {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint8_t)plist[i])
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint8_t)plist[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -334,9 +372,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
if (type == TSDB_DATA_TYPE_SMALLINT) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i])
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
|
||||
} else {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint16_t)plist[i])
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint16_t)plist[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -348,9 +386,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
if (type == TSDB_DATA_TYPE_INT) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i])
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
|
||||
} else {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint32_t)plist[i])
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint32_t)plist[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -362,9 +400,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
if (type == TSDB_DATA_TYPE_BIGINT) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i])
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
|
||||
} else {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint64_t)plist[i])
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint64_t)plist[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -374,7 +412,7 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
const float* plist = (const float*) pCol->pData;
|
||||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
pAvgRes->sum.dsum += plist[i];
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pAvgRes), plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -382,15 +420,31 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
|||
const double* plist = (const double*)pCol->pData;
|
||||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
pAvgRes->sum.dsum += plist[i];
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pAvgRes), plist[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
case TSDB_DATA_TYPE_DECIMAL64: {
|
||||
const char* pDec = pCol->pData;
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
|
||||
bool overflow = false;
|
||||
if (type == TSDB_DATA_TYPE_DECIMAL64) {
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pAvgRes), (const void*)(pDec + i * tDataTypes[type].bytes),
|
||||
TSDB_DATA_TYPE_DECIMAL64);
|
||||
} else {
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pAvgRes), (const void*)(pDec + i * tDataTypes[type].bytes),
|
||||
TSDB_DATA_TYPE_DECIMAL);
|
||||
}
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
|
||||
}
|
||||
} else {
|
||||
numOfElem = doAddNumericVector(pCol, type, pInput, pAvgRes);
|
||||
int32_t code = doAddNumericVector(pCol, type, pInput, pAvgRes, &numOfElem);
|
||||
if (code) return code;
|
||||
}
|
||||
|
||||
_over:
|
||||
|
@ -399,23 +453,33 @@ _over:
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) {
|
||||
if (IS_NULL_TYPE(pInput->type)) {
|
||||
return;
|
||||
static int32_t avgTransferInfo(SqlFunctionCtx* pCtx, void* pInput, void* pOutput) {
|
||||
int32_t inputDT = pCtx->pExpr->pExpr->_function.pFunctNode->srcFuncInputType.type;
|
||||
int32_t type = AVG_RES_GET_TYPE(pInput, inputDT);
|
||||
pCtx->inputType = type;
|
||||
if (IS_NULL_TYPE(type)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pOutput->type = pInput->type;
|
||||
if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
|
||||
bool overflow = pInput->sum.overflow;
|
||||
CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, (overflow ? pInput->sum.dsum : pInput->sum.isum), overflow);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
|
||||
bool overflow = pInput->sum.overflow;
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, (overflow ? pInput->sum.dsum : pInput->sum.usum), overflow);
|
||||
|
||||
AVG_RES_SET_TYPE(pOutput, inputDT, type);
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
bool overflow = AVG_RES_GET_SUM_OVERFLOW(pInput, false, 0);
|
||||
CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, (overflow ? SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)) : SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pInput))), overflow);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
bool overflow = AVG_RES_GET_SUM_OVERFLOW(pInput, false, 0);
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, (overflow ? SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)) : SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pInput))), overflow);
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
AVG_RES_SET_INPUT_SCALE(pOutput, AVG_RES_GET_INPUT_SCALE(pInput));
|
||||
bool overflow = false;
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pOutput), &AVG_RES_GET_DECIMAL_SUM(pInput), TSDB_DATA_TYPE_DECIMAL);
|
||||
if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||
} else {
|
||||
pOutput->sum.dsum += pInput->sum.dsum;
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pOutput), SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)));
|
||||
}
|
||||
|
||||
pOutput->count += pInput->count;
|
||||
AVG_RES_INC_COUNT(pOutput, type, AVG_RES_GET_COUNT(pInput, true, type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t avgFunctionMerge(SqlFunctionCtx* pCtx) {
|
||||
|
@ -431,15 +495,16 @@ int32_t avgFunctionMerge(SqlFunctionCtx* pCtx) {
|
|||
return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
|
||||
}
|
||||
|
||||
SAvgRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
void* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
|
||||
int32_t start = pInput->startRowIndex;
|
||||
|
||||
for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
|
||||
if(colDataIsNull_s(pCol, i)) continue;
|
||||
char* data = colDataGetData(pCol, i);
|
||||
SAvgRes* pInputInfo = (SAvgRes*)varDataVal(data);
|
||||
avgTransferInfo(pInputInfo, pInfo);
|
||||
void* pInputInfo = varDataVal(data);
|
||||
int32_t code = avgTransferInfo(pCtx, pInputInfo, pInfo);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
|
||||
SET_VAL(GET_RES_INFO(pCtx), 1, 1);
|
||||
|
@ -514,20 +579,27 @@ int32_t avgInvertFunction(SqlFunctionCtx* pCtx) {
|
|||
|
||||
int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
|
||||
SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
|
||||
SAvgRes* pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
|
||||
void* pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
|
||||
int32_t type = AVG_RES_GET_TYPE(pDBuf, pDestCtx->inputType);
|
||||
|
||||
SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
|
||||
SAvgRes* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
|
||||
int16_t type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
|
||||
void* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
|
||||
type = (type == TSDB_DATA_TYPE_NULL) ? AVG_RES_GET_TYPE(pSBuf, pDestCtx->inputType) : type;
|
||||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pDBuf, pSBuf->sum.isum)
|
||||
CHECK_OVERFLOW_SUM_SIGNED(pDBuf, SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pSBuf)));
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pDBuf, pSBuf->sum.usum)
|
||||
CHECK_OVERFLOW_SUM_UNSIGNED(pDBuf, SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pSBuf)));
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
bool overflow = false;
|
||||
SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pDBuf), &SUM_RES_GET_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pSBuf)), type);
|
||||
if (overflow) {
|
||||
|
||||
}
|
||||
} else {
|
||||
pDBuf->sum.dsum += pSBuf->sum.dsum;
|
||||
SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pDBuf), SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pSBuf)));
|
||||
}
|
||||
pDBuf->count += pSBuf->count;
|
||||
AVG_RES_INC_COUNT(pDBuf, pDestCtx->inputType, AVG_RES_GET_COUNT(pSBuf, true, pDestCtx->inputType));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -535,24 +607,46 @@ int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
|
|||
int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
||||
SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
|
||||
|
||||
SAvgRes* pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
|
||||
int32_t type = pRes->type;
|
||||
void* pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
|
||||
int32_t type = AVG_RES_GET_TYPE(pRes, pCtx->inputType);
|
||||
int64_t count = AVG_RES_GET_COUNT(pRes, true, type);
|
||||
|
||||
if (pRes->count > 0) {
|
||||
if(pRes->sum.overflow) {
|
||||
// overflow flag set , use dsum
|
||||
pRes->result = pRes->sum.dsum / ((double)pRes->count);
|
||||
if (AVG_RES_GET_COUNT(pRes, true, pCtx->inputType) > 0) {
|
||||
|
||||
if(AVG_RES_GET_SUM_OVERFLOW(pRes, true, pCtx->inputType)) {
|
||||
AVG_RES_GET_AVG(pRes) = SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
|
||||
}else if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
pRes->result = pRes->sum.isum / ((double)pRes->count);
|
||||
AVG_RES_GET_AVG(pRes) = SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
pRes->result = pRes->sum.usum / ((double)pRes->count);
|
||||
AVG_RES_GET_AVG(pRes) = SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
|
||||
} else if (IS_DECIMAL_TYPE(type)) {
|
||||
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
|
||||
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||
SDataType sumDt = {.type = TSDB_DATA_TYPE_DECIMAL,
|
||||
.bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
|
||||
.precision = pCol->info.precision,
|
||||
.scale = AVG_RES_GET_INPUT_SCALE(pRes)};
|
||||
SDataType countDt = {
|
||||
.type = TSDB_DATA_TYPE_BIGINT, .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .precision = 0, .scale = 0};
|
||||
SDataType avgDt = {.type = TSDB_DATA_TYPE_DECIMAL,
|
||||
.bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
|
||||
.precision = pCol->info.precision,
|
||||
.scale = pCol->info.scale};
|
||||
int64_t count = AVG_RES_GET_COUNT(pRes, true, type);
|
||||
int32_t code =
|
||||
decimalOp(OP_TYPE_DIV, &sumDt, &countDt, &avgDt, &SUM_RES_GET_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes)),
|
||||
&count, &AVG_RES_GET_DECIMAL_AVG(pRes));
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
pRes->result = pRes->sum.dsum / ((double)pRes->count);
|
||||
AVG_RES_GET_AVG(pRes) = SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (pRes->count == 0 || isinf(pRes->result) || isnan(pRes->result)) {
|
||||
if (AVG_RES_GET_COUNT(pRes, true, pCtx->inputType) == 0) {
|
||||
pEntryInfo->numOfRes = 0;
|
||||
} else if (!IS_DECIMAL_TYPE(pCtx->inputType)) {
|
||||
if (isinf(AVG_RES_GET_AVG(pRes)) || isnan(AVG_RES_GET_AVG(pRes))) pEntryInfo->numOfRes = 0;
|
||||
} else {
|
||||
pEntryInfo->numOfRes = 1;
|
||||
}
|
||||
|
@ -562,8 +656,8 @@ int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
|
||||
int32_t avgPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
||||
SAvgRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
int32_t resultBytes = getAvgInfoSize();
|
||||
void* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||
int32_t resultBytes = AVG_RES_GET_SIZE(pCtx->inputType);
|
||||
char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (NULL == res) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "tdatablock.h"
|
||||
#include "tfunctionInt.h"
|
||||
#include "tglobal.h"
|
||||
#include "decimal.h"
|
||||
|
||||
#define __COMPARE_ACQUIRED_MAX(i, end, bm, _data, ctx, val, pos) \
|
||||
int32_t code = TSDB_CODE_SUCCESS; \
|
||||
|
@ -395,6 +396,40 @@ static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFu
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64: {
|
||||
const Decimal64* pData = (const Decimal64*)pCol->pData;
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
|
||||
int32_t code = 0;
|
||||
for (; i < end; ++i) {
|
||||
if (colDataIsNull_f(pCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
if (pOps->gt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
|
||||
pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
|
||||
if (pCtx->subsidiaries.num > 0) {
|
||||
code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
int32_t code = 0;
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
const Decimal128* pData = (const Decimal128*)pCol->pData;
|
||||
for (; i < end; ++i) {
|
||||
if (colDataIsNull_f(pCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
if (pOps->gt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
|
||||
memcpy(pBuf->dec, pData + i, pCol->info.bytes);
|
||||
if (pCtx->subsidiaries.num > 0) {
|
||||
code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
switch (pCol->info.type) {
|
||||
|
@ -458,6 +493,40 @@ static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFu
|
|||
__COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos)
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64: {
|
||||
const Decimal64* pData = (const Decimal64*)pCol->pData;
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
|
||||
int32_t code = 0;
|
||||
for (; i < end; ++i) {
|
||||
if (colDataIsNull_f(pCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
if (pOps->lt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
|
||||
pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
|
||||
if (pCtx->subsidiaries.num > 0) {
|
||||
code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DECIMAL: {
|
||||
int32_t code = 0;
|
||||
const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
const Decimal128* pData = (const Decimal128*)pCol->pData;
|
||||
for (; i < end; ++i) {
|
||||
if (colDataIsNull_f(pCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
if (pOps->lt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
|
||||
memcpy(pBuf->dec, pData + i, pCol->info.bytes);
|
||||
if (pCtx->subsidiaries.num > 0) {
|
||||
code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
|
@ -549,11 +618,18 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
}
|
||||
|
||||
int16_t index = 0;
|
||||
void* tval = (isMinFunc) ? &pInput->pColumnDataAgg[0]->min : &pInput->pColumnDataAgg[0]->max;
|
||||
void* tval = NULL;
|
||||
if (IS_DECIMAL_TYPE(type)) {
|
||||
tval = isMinFunc ? pInput->pColumnDataAgg[0]->decimal128Min : pInput->pColumnDataAgg[0]->decimal128Max;
|
||||
} else {
|
||||
tval = (isMinFunc) ? &pInput->pColumnDataAgg[0]->min : &pInput->pColumnDataAgg[0]->max;
|
||||
}
|
||||
|
||||
if (!pBuf->assign) {
|
||||
if (type == TSDB_DATA_TYPE_FLOAT) {
|
||||
GET_FLOAT_VAL(&pBuf->v) = GET_DOUBLE_VAL(tval);
|
||||
} else if (type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
memcpy(pBuf->dec, tval, pCol->info.bytes);
|
||||
} else {
|
||||
pBuf->v = GET_INT64_VAL(tval);
|
||||
}
|
||||
|
@ -562,7 +638,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
} else {
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type)) {
|
||||
int64_t prev = 0;
|
||||
GET_TYPED_DATA(prev, int64_t, type, &pBuf->v);
|
||||
GET_TYPED_DATA(prev, int64_t, type, &pBuf->v, 0);
|
||||
|
||||
int64_t val = GET_INT64_VAL(tval);
|
||||
if ((prev < val) ^ isMinFunc) {
|
||||
|
@ -571,7 +647,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
}
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
|
||||
uint64_t prev = 0;
|
||||
GET_TYPED_DATA(prev, uint64_t, type, &pBuf->v);
|
||||
GET_TYPED_DATA(prev, uint64_t, type, &pBuf->v, 0);
|
||||
|
||||
uint64_t val = GET_UINT64_VAL(tval);
|
||||
if ((prev < val) ^ isMinFunc) {
|
||||
|
@ -580,7 +656,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
}
|
||||
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double prev = 0;
|
||||
GET_TYPED_DATA(prev, double, type, &pBuf->v);
|
||||
GET_TYPED_DATA(prev, double, type, &pBuf->v, 0);
|
||||
|
||||
double val = GET_DOUBLE_VAL(tval);
|
||||
if ((prev < val) ^ isMinFunc) {
|
||||
|
@ -589,13 +665,25 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
}
|
||||
} else if (type == TSDB_DATA_TYPE_FLOAT) {
|
||||
float prev = 0;
|
||||
GET_TYPED_DATA(prev, float, type, &pBuf->v);
|
||||
GET_TYPED_DATA(prev, float, type, &pBuf->v, 0);
|
||||
|
||||
float val = GET_DOUBLE_VAL(tval);
|
||||
if ((prev < val) ^ isMinFunc) {
|
||||
GET_FLOAT_VAL(&pBuf->v) = val;
|
||||
code = saveRelatedTupleTag(pCtx, pInput, tval);
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_DECIMAL64) {
|
||||
const SDecimalOps* pOps = getDecimalOps(type);
|
||||
if (pOps->lt(&pBuf->v, tval, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) {
|
||||
DECIMAL64_SET_VALUE((Decimal64*)&pBuf->v, *(int64_t*)tval);
|
||||
code =saveRelatedTupleTag(pCtx, pInput, tval);
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_DECIMAL) {
|
||||
const SDecimalOps* pOps = getDecimalOps(type);
|
||||
if (pOps->lt(pBuf->dec, tval, DECIMAL_WORD_NUM(Decimal128)) ^ isMinFunc) {
|
||||
DECIMAL128_CLONE((Decimal128*)pBuf->dec, (Decimal128*)tval);
|
||||
code =saveRelatedTupleTag(pCtx, pInput, tval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,8 +700,8 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
int32_t threshold[] = {
|
||||
//NULL, BOOL, TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE, VARCHAR, TIMESTAMP, NCHAR,
|
||||
INT32_MAX, INT32_MAX, 32, 16, 8, 4, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX,
|
||||
// UTINYINT,USMALLINT, UINT, UBIGINT, JSON, VARBINARY, DECIMAL, BLOB, MEDIUMBLOB, BINARY
|
||||
32, 16, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX,
|
||||
// UTINYINT,USMALLINT, UINT, UBIGINT, JSON, VARBINARY, DECIMAL, BLOB, MEDIUMBLOB, BINARY, Decimal64
|
||||
32, 16, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -656,6 +744,12 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems)
|
|||
(void)memcpy(pBuf->str, colDataGetData(pCol, i), varDataTLen(colDataGetData(pCol, i)));
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
*(int64_t*)&pBuf->v = *(int64_t*)p;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
(void)memcpy(pBuf->dec, p, pCol->info.bytes);
|
||||
break;
|
||||
default:
|
||||
(void)memcpy(&pBuf->v, p, pCol->info.bytes);
|
||||
break;
|
||||
|
|
|
@ -436,6 +436,7 @@ int32_t createFunctionWithSrcFunc(const char* pName, const SFunctionNode* pSrcFu
|
|||
|
||||
(*ppFunc)->hasPk = pSrcFunc->hasPk;
|
||||
(*ppFunc)->pkBytes = pSrcFunc->pkBytes;
|
||||
(*ppFunc)->pSrcFuncRef = pSrcFunc;
|
||||
|
||||
(void)snprintf((*ppFunc)->functionName, sizeof((*ppFunc)->functionName), "%s", pName);
|
||||
(*ppFunc)->pParameterList = pParameterList;
|
||||
|
@ -646,7 +647,7 @@ static int32_t fmCreateStateMergeFunc(SFunctionNode* pFunc, SFunctionNode** pSta
|
|||
SNodeList* pParams = NULL;
|
||||
int32_t code = nodesCloneList(pFunc->pParameterList, &pParams);
|
||||
if (!pParams) return code;
|
||||
code = createFunction(funcMgtBuiltins[pFunc->funcId].pMergeFunc, pParams, pStateMergeFunc);
|
||||
code = createFunctionWithSrcFunc(funcMgtBuiltins[pFunc->funcId].pMergeFunc, pFunc, pParams, pStateMergeFunc);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
nodesDestroyList(pParams);
|
||||
return code;
|
||||
|
|
|
@ -143,7 +143,7 @@ int32_t findOnlyResult(tMemBucket *pMemBucket, double *result) {
|
|||
return TSDB_CODE_FUNC_PERCENTILE_ERROR;
|
||||
}
|
||||
|
||||
GET_TYPED_DATA(*result, double, pMemBucket->type, pPage->data);
|
||||
GET_TYPED_DATA(*result, double, pMemBucket->type, pPage->data, pMemBucket->typeMod);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ int32_t findOnlyResult(tMemBucket *pMemBucket, double *result) {
|
|||
|
||||
int32_t tBucketIntHash(tMemBucket *pBucket, const void *value, int32_t *index) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, pBucket->type, value);
|
||||
GET_TYPED_DATA(v, int64_t, pBucket->type, value, pBucket->typeMod);
|
||||
|
||||
*index = -1;
|
||||
|
||||
|
@ -186,7 +186,7 @@ int32_t tBucketIntHash(tMemBucket *pBucket, const void *value, int32_t *index) {
|
|||
|
||||
int32_t tBucketUintHash(tMemBucket *pBucket, const void *value, int32_t *index) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, uint64_t, pBucket->type, value);
|
||||
GET_TYPED_DATA(v, uint64_t, pBucket->type, value, pBucket->typeMod);
|
||||
|
||||
*index = -1;
|
||||
|
||||
|
@ -268,7 +268,7 @@ static void resetSlotInfo(tMemBucket *pBucket) {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t tMemBucketCreate(int32_t nElemSize, int16_t dataType, double minval, double maxval, bool hasWindowOrGroup,
|
||||
int32_t tMemBucketCreate(int32_t nElemSize, int16_t dataType, STypeMod typeMod, double minval, double maxval, bool hasWindowOrGroup,
|
||||
tMemBucket **pBucket, int32_t numOfElements) {
|
||||
*pBucket = (tMemBucket *)taosMemoryCalloc(1, sizeof(tMemBucket));
|
||||
if (*pBucket == NULL) {
|
||||
|
@ -286,6 +286,7 @@ int32_t tMemBucketCreate(int32_t nElemSize, int16_t dataType, double minval, dou
|
|||
(*pBucket)->bytes = nElemSize;
|
||||
(*pBucket)->total = 0;
|
||||
(*pBucket)->times = 1;
|
||||
(*pBucket)->typeMod = typeMod;
|
||||
|
||||
(*pBucket)->maxCapacity = 200000;
|
||||
(*pBucket)->groupPagesMap = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
||||
|
@ -353,10 +354,11 @@ void tMemBucketDestroy(tMemBucket **pBucket) {
|
|||
taosMemoryFreeClear(*pBucket);
|
||||
}
|
||||
|
||||
int32_t tMemBucketUpdateBoundingBox(MinMaxEntry *r, const char *data, int32_t dataType) {
|
||||
int32_t tMemBucketUpdateBoundingBox(MinMaxEntry *r, const char *data, tMemBucket* pBucket) {
|
||||
int32_t dataType = pBucket->type;
|
||||
if (IS_SIGNED_NUMERIC_TYPE(dataType)) {
|
||||
int64_t v = 0;
|
||||
GET_TYPED_DATA(v, int64_t, dataType, data);
|
||||
GET_TYPED_DATA(v, int64_t, dataType, data, pBucket->typeMod);
|
||||
|
||||
if (r->dMinVal > v) {
|
||||
r->dMinVal = v;
|
||||
|
@ -367,7 +369,7 @@ int32_t tMemBucketUpdateBoundingBox(MinMaxEntry *r, const char *data, int32_t da
|
|||
}
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(dataType)) {
|
||||
uint64_t v = 0;
|
||||
GET_TYPED_DATA(v, uint64_t, dataType, data);
|
||||
GET_TYPED_DATA(v, uint64_t, dataType, data, pBucket->typeMod);
|
||||
|
||||
if (r->u64MinVal > v) {
|
||||
r->u64MinVal = v;
|
||||
|
@ -378,7 +380,7 @@ int32_t tMemBucketUpdateBoundingBox(MinMaxEntry *r, const char *data, int32_t da
|
|||
}
|
||||
} else if (IS_FLOAT_TYPE(dataType)) {
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, dataType, data);
|
||||
GET_TYPED_DATA(v, double, dataType, data, pBucket->typeMod);
|
||||
|
||||
if (r->dMinVal > v) {
|
||||
r->dMinVal = v;
|
||||
|
@ -415,7 +417,7 @@ int32_t tMemBucketPut(tMemBucket *pBucket, const void *data, size_t size) {
|
|||
count += 1;
|
||||
|
||||
tMemBucketSlot *pSlot = &pBucket->pSlots[index];
|
||||
code = tMemBucketUpdateBoundingBox(&pSlot->range, d, pBucket->type);
|
||||
code = tMemBucketUpdateBoundingBox(&pSlot->range, d, pBucket);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
|
@ -572,8 +574,8 @@ int32_t getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction
|
|||
char *nextVal = thisVal + pMemBucket->bytes;
|
||||
|
||||
double td = 1.0, nd = 1.0;
|
||||
GET_TYPED_DATA(td, double, pMemBucket->type, thisVal);
|
||||
GET_TYPED_DATA(nd, double, pMemBucket->type, nextVal);
|
||||
GET_TYPED_DATA(td, double, pMemBucket->type, thisVal, pMemBucket->typeMod);
|
||||
GET_TYPED_DATA(nd, double, pMemBucket->type, nextVal, pMemBucket->typeMod);
|
||||
|
||||
*result = (1 - fraction) * td + fraction * nd;
|
||||
taosMemoryFreeClear(buffer);
|
||||
|
@ -586,7 +588,7 @@ int32_t getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction
|
|||
}
|
||||
// try next round
|
||||
tMemBucket *tmpBucket = NULL;
|
||||
int32_t code = tMemBucketCreate(pMemBucket->bytes, pMemBucket->type, pSlot->range.dMinVal, pSlot->range.dMaxVal,
|
||||
int32_t code = tMemBucketCreate(pMemBucket->bytes, pMemBucket->type, pMemBucket->typeMod, pSlot->range.dMinVal, pSlot->range.dMaxVal,
|
||||
false, &tmpBucket, pSlot->info.size);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
tMemBucketDestroy(&tmpBucket);
|
||||
|
|
|
@ -326,7 +326,7 @@ static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
|
|||
indexError("invalid length for node:%p, length: %d", node, LIST_LENGTH(nl->pNodeList));
|
||||
SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||
}
|
||||
SIF_ERR_RET(scalarGenerateSetFromList((void **)¶m->pFilter, node, nl->node.resType.type, 0));
|
||||
SIF_ERR_RET(scalarGenerateSetFromList((void **)¶m->pFilter, node, nl->node.resType.type, 0, 0));
|
||||
if (taosHashPut(ctx->pRes, &node, POINTER_BYTES, param, sizeof(*param))) {
|
||||
taosHashCleanup(param->pFilter);
|
||||
param->pFilter = NULL;
|
||||
|
|
|
@ -199,7 +199,14 @@ static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
|||
memcpy(pDst->datum.p, pSrc->datum.p, len);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
COPY_SCALAR_FIELD(datum.d);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
pDst->datum.p = taosMemCalloc(1, pSrc->node.resType.bytes);
|
||||
if (!pDst->datum.p) return terrno;
|
||||
memcpy(pDst->datum.p, pSrc->datum.p, pSrc->node.resType.bytes);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
case TSDB_DATA_TYPE_MEDIUMBLOB:
|
||||
default:
|
||||
|
@ -234,6 +241,7 @@ static int32_t functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst)
|
|||
COPY_SCALAR_FIELD(pkBytes);
|
||||
COPY_SCALAR_FIELD(hasOriginalFunc);
|
||||
COPY_SCALAR_FIELD(originalFuncId);
|
||||
COPY_OBJECT_FIELD(srcFuncInputType, sizeof(SDataType));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -4573,6 +4573,7 @@ static const char* jkFunctionPkBytes = "PkBytes";
|
|||
static const char* jkFunctionIsMergeFunc = "IsMergeFunc";
|
||||
static const char* jkFunctionMergeFuncOf = "MergeFuncOf";
|
||||
static const char* jkFunctionTrimType = "TrimType";
|
||||
static const char* jkFunctionSrcFuncInputDT = "SrcFuncInputDataType";
|
||||
|
||||
static int32_t functionNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SFunctionNode* pNode = (const SFunctionNode*)pObj;
|
||||
|
@ -4608,6 +4609,9 @@ static int32_t functionNodeToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddIntegerToObject(pJson, jkFunctionTrimType, pNode->trimType);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkFunctionSrcFuncInputDT, dataTypeToJson, &pNode->srcFuncInputType);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -4645,6 +4649,9 @@ static int32_t jsonToFunctionNode(const SJson* pJson, void* pObj) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
tjsonGetNumberValue(pJson, jkFunctionTrimType, pNode->trimType, code);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonToObject(pJson, jkFunctionSrcFuncInputDT, jsonToDataType, &pNode->srcFuncInputType);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -882,6 +882,11 @@ static int32_t datumToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
code = tlvEncodeBinary(pEncoder, VALUE_CODE_DATUM, pNode->datum.p, getJsonValueLen(pNode->datum.p));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
code = tlvEncodeBinary(pEncoder, VALUE_CODE_DATUM, pNode->datum.p, pNode->node.resType.bytes);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
code = tlvEncodeI64(pEncoder, VALUE_CODE_DATUM, pNode->datum.i);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
// todo
|
||||
default:
|
||||
|
@ -1000,6 +1005,17 @@ static int32_t msgToDatum(STlv* pTlv, void* pObj) {
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes);
|
||||
if (!pNode->datum.p) {
|
||||
code = terrno;
|
||||
break;
|
||||
}
|
||||
code = tlvDecodeBinary(pTlv, pNode->datum.p);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DECIMAL64:
|
||||
code = tlvDecodeI64(pTlv, &pNode->datum.i);
|
||||
*(int64_t*)&pNode->typeData = pNode->datum.i;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
// todo
|
||||
default:
|
||||
|
@ -1143,6 +1159,7 @@ enum {
|
|||
FUNCTION_CODE_IS_MERGE_FUNC,
|
||||
FUNCTION_CODE_MERGE_FUNC_OF,
|
||||
FUNCTION_CODE_TRIM_TYPE,
|
||||
FUNCTION_SRC_FUNC_INPUT_TYPE,
|
||||
};
|
||||
|
||||
static int32_t functionNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||
|
@ -1179,6 +1196,9 @@ static int32_t functionNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeEnum(pEncoder, FUNCTION_CODE_TRIM_TYPE, pNode->trimType);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeObj(pEncoder, FUNCTION_SRC_FUNC_INPUT_TYPE, dataTypeInlineToMsg, &pNode->srcFuncInputType);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -1223,6 +1243,8 @@ static int32_t msgToFunctionNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
case FUNCTION_CODE_TRIM_TYPE:
|
||||
code = tlvDecodeEnum(pTlv, &pNode->trimType, sizeof(pNode->trimType));
|
||||
break;
|
||||
case FUNCTION_SRC_FUNC_INPUT_TYPE:
|
||||
code = tlvDecodeObjFromTlv(pTlv, msgToDataTypeInline, &pNode->srcFuncInputType);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue