[td-10564] refactor and add test cases.
This commit is contained in:
parent
89e324c899
commit
55f3ac1701
|
@ -68,6 +68,13 @@ typedef struct SColumnInfoData {
|
|||
|
||||
//======================================================================================================================
|
||||
// the following structure shared by parser and executor
|
||||
typedef struct SColumn {
|
||||
uint64_t uid;
|
||||
char name[TSDB_COL_NAME_LEN];
|
||||
int8_t flag; // column type: normal column, tag, or user-input column (integer/float/string)
|
||||
SColumnInfo info;
|
||||
} SColumn;
|
||||
|
||||
typedef struct SLimit {
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
|
@ -89,8 +96,9 @@ typedef struct SGroupbyExpr {
|
|||
typedef struct SSqlExpr {
|
||||
char token[TSDB_COL_NAME_LEN]; // original token
|
||||
SSchema resSchema;
|
||||
SColIndex colInfo; // there may be mutiple input columns
|
||||
uint64_t uid; // table uid, todo refactor use the pointer
|
||||
|
||||
int32_t numOfCols;
|
||||
SColumn* pColumns; // data columns that are required by query
|
||||
int32_t interBytes; // inter result buffer size
|
||||
int16_t numOfParams; // argument value of each function
|
||||
SVariant param[3]; // parameters are not more than 3
|
||||
|
|
|
@ -161,6 +161,7 @@ enum {
|
|||
TEXPR_NODE_DUMMY = 0x0,
|
||||
TEXPR_BINARYEXPR_NODE= 0x1,
|
||||
TEXPR_UNARYEXPR_NODE = 0x2,
|
||||
TEXPR_FUNCTION_NODE = 0x3,
|
||||
TEXPR_COL_NODE = 0x4,
|
||||
TEXPR_VALUE_NODE = 0x8,
|
||||
};
|
||||
|
@ -169,10 +170,7 @@ typedef struct tExprNode {
|
|||
uint8_t nodeType;
|
||||
union {
|
||||
struct {
|
||||
union {
|
||||
int32_t optr; // binary operator
|
||||
int32_t functionId;// unary operator
|
||||
};
|
||||
int32_t optr; // binary operator
|
||||
void *info; // support filter operation on this expression only available for leaf node
|
||||
struct tExprNode *pLeft; // left child pointer
|
||||
struct tExprNode *pRight; // right child pointer
|
||||
|
@ -180,18 +178,32 @@ typedef struct tExprNode {
|
|||
|
||||
SSchema *pSchema;// column node
|
||||
struct SVariant *pVal; // value node
|
||||
|
||||
struct {// function node
|
||||
char *functionName;
|
||||
int32_t functionId;
|
||||
int32_t num;
|
||||
|
||||
// Note that the attribute of pChild is not the parameter of function, it is the columns that involved in the
|
||||
// calculation instead.
|
||||
// E.g., Cov(col1, col2), the column information, w.r.t. the col1 and col2, is kept in pChild nodes.
|
||||
// The concat function, concat(col1, col2), is a binary scalar
|
||||
// operator and is kept in the attribute of _node.
|
||||
struct tExprNode **pChild;
|
||||
} _function;
|
||||
};
|
||||
} tExprNode;
|
||||
|
||||
//TODO create?
|
||||
void exprTreeToBinary(SBufferWriter* bw, tExprNode* pExprTree);
|
||||
void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *));
|
||||
|
||||
typedef struct SAggFunctionInfo {
|
||||
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
||||
int8_t type; // Scalar function or aggregation function
|
||||
uint8_t functionId; // Function Id
|
||||
int8_t sFunctionId; // Transfer function for super table query
|
||||
uint16_t status;
|
||||
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
||||
int8_t type; // Scalar function or aggregation function
|
||||
uint32_t functionId; // Function Id
|
||||
int8_t sFunctionId; // Transfer function for super table query
|
||||
uint16_t status;
|
||||
|
||||
bool (*init)(SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment
|
||||
void (*addInput)(SQLFunctionCtx *pCtx);
|
||||
|
@ -203,13 +215,13 @@ typedef struct SAggFunctionInfo {
|
|||
int32_t (*dataReqFunc)(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId);
|
||||
} SAggFunctionInfo;
|
||||
|
||||
typedef struct SScalarFunctionInfo {
|
||||
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
||||
int8_t type; // scalar function or aggregation function
|
||||
uint8_t functionId; // index of scalar function
|
||||
struct SScalarFuncParam;
|
||||
|
||||
bool (*init)(SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment
|
||||
void (*addInput)(SQLFunctionCtx *pCtx);
|
||||
typedef struct SScalarFunctionInfo {
|
||||
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
||||
int8_t type; // scalar function or aggregation function
|
||||
uint32_t functionId; // index of scalar function
|
||||
void (*process)(const struct SScalarFuncParam *pInput, struct SScalarFuncParam* pOutput);
|
||||
} SScalarFunctionInfo;
|
||||
|
||||
typedef struct SMultiFunctionsDesc {
|
||||
|
@ -241,7 +253,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
|
|||
* @param len
|
||||
* @return
|
||||
*/
|
||||
int32_t qIsBuiltinFunction(const char* name, int32_t len);
|
||||
int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction);
|
||||
|
||||
bool qIsValidUdf(SArray* pUdfInfo, const char* name, int32_t len, int32_t* functionId);
|
||||
|
||||
|
|
|
@ -26,29 +26,6 @@ extern "C" {
|
|||
#include "tvariant.h"
|
||||
#include "function.h"
|
||||
|
||||
typedef struct SColumn {
|
||||
uint64_t tableUid;
|
||||
int32_t columnIndex;
|
||||
SColumnInfo info;
|
||||
} SColumn;
|
||||
|
||||
|
||||
|
||||
//typedef struct SInterval {
|
||||
// int32_t tz; // query client timezone
|
||||
// char intervalUnit;
|
||||
// char slidingUnit;
|
||||
// char offsetUnit;
|
||||
// int64_t interval;
|
||||
// int64_t sliding;
|
||||
// int64_t offset;
|
||||
//} SInterval;
|
||||
//
|
||||
//typedef struct SSessionWindow {
|
||||
// int64_t gap; // gap between two session window(in microseconds)
|
||||
// int32_t primaryColId; // primary timestamp column
|
||||
//} SSessionWindow;
|
||||
|
||||
typedef struct SField {
|
||||
char name[TSDB_COL_NAME_LEN];
|
||||
uint8_t type;
|
||||
|
@ -89,12 +66,6 @@ typedef struct STagCond {
|
|||
typedef struct STableMetaInfo {
|
||||
STableMeta *pTableMeta; // table meta, cached in client side and acquired by name
|
||||
SVgroupsInfo *vgroupList;
|
||||
|
||||
/*
|
||||
* 1. keep the vgroup index during the multi-vnode super table projection query
|
||||
* 2. keep the vgroup index for multi-vnode insertion
|
||||
*/
|
||||
int32_t vgroupIndex;
|
||||
SName name;
|
||||
char aliasName[TSDB_TABLE_NAME_LEN]; // alias name of table specified in query sql
|
||||
SArray *tagColList; // SArray<SColumn*>, involved tag columns
|
||||
|
|
|
@ -134,14 +134,14 @@ do { \
|
|||
#define TSDB_BINARY_OP_REMAINDER 4004
|
||||
#define TSDB_BINARY_OP_CONCAT 4005
|
||||
|
||||
#define TSDB_UNARY_OP_CEIL 4500
|
||||
#define TSDB_UNARY_OP_FLOOR 4501
|
||||
#define TSDB_UNARY_OP_ABS 4502
|
||||
#define TSDB_UNARY_OP_ROUND 4503
|
||||
#define FUNCTION_CEIL 4500
|
||||
#define FUNCTION_FLOOR 4501
|
||||
#define FUNCTION_ABS 4502
|
||||
#define FUNCTION_ROUND 4503
|
||||
|
||||
#define TSDB_UNARY_OP_LEN 4600
|
||||
#define TSDB_UNARY_OP_LTRIM 4601
|
||||
#define TSDB_UNARY_OP_RTRIM 4601
|
||||
#define FUNCTION_LENGTH 4800
|
||||
#define FUNCTION_LTRIM 4801
|
||||
#define FUNCTION_RTRIM 4802
|
||||
|
||||
#define IS_RELATION_OPTR(op) (((op) >= TSDB_RELATION_LESS) && ((op) < TSDB_RELATION_IN))
|
||||
#define IS_ARITHMETIC_OPTR(op) (((op) >= TSDB_BINARY_OP_ADD) && ((op) <= TSDB_BINARY_OP_REMAINDER))
|
||||
|
|
|
@ -1040,13 +1040,14 @@ static TSKEY getStartTsKey(SQueryAttr* pQueryAttr, STimeWindow* win, const TSKEY
|
|||
}
|
||||
|
||||
static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order);
|
||||
|
||||
static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
|
||||
for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
|
||||
pCtx[i].order = order;
|
||||
pCtx[i].size = pBlock->info.rows;
|
||||
pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
|
||||
|
||||
setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);
|
||||
setBlockStatisInfo(&pCtx[i], pBlock, NULL/*&pOperator->pExpr[i].base.colInfo*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2358,8 +2359,8 @@ bool onlyQueryTags(SQueryAttr* pQueryAttr) {
|
|||
|
||||
if (functionId != FUNCTION_TAGPRJ &&
|
||||
functionId != FUNCTION_TID_TAG &&
|
||||
(!(functionId == FUNCTION_COUNT && pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX)) &&
|
||||
(!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
|
||||
(!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX)) &&
|
||||
(!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.pColumns->flag)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2878,7 +2879,7 @@ static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSData
|
|||
int32_t numOfOutput = pTableScanInfo->numOfOutput;
|
||||
for (int32_t i = 0; i < numOfOutput; ++i) {
|
||||
int32_t functionId = pCtx[i].functionId;
|
||||
int32_t colId = pTableScanInfo->pExpr[i].base.colInfo.colId;
|
||||
int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->colId;
|
||||
|
||||
// group by + first/last should not apply the first/last block filter
|
||||
if (functionId < 0) {
|
||||
|
@ -3205,12 +3206,12 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCt
|
|||
SExprInfo* pLocalExprInfo = &pExpr[idx];
|
||||
|
||||
// ts_comp column required the tag value for join filter
|
||||
if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) {
|
||||
if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.pColumns->flag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo use tag column index to optimize performance
|
||||
doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type,
|
||||
doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type,
|
||||
pLocalExprInfo->base.resSchema.bytes);
|
||||
|
||||
if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type)
|
||||
|
@ -5071,7 +5072,7 @@ SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) {
|
|||
int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]);
|
||||
|
||||
// FUNCTION_TAG_DUMMY function needs to be ignored
|
||||
if (index->colId == pExpr->colInfo.colId &&
|
||||
if (index->colId == pExpr->pColumns->info.colId &&
|
||||
((TSDB_COL_IS_TAG(pExpr->colInfo.flag) && functionId == FUNCTION_TAG) ||
|
||||
(TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && functionId == FUNCTION_PRJ))) {
|
||||
index->colIndex = j;
|
||||
|
@ -5290,7 +5291,7 @@ SOperatorInfo *createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
|
|||
pDataBlock->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
|
||||
for(int32_t i = 0; i < numOfOutput; ++i) {
|
||||
SColumnInfoData col = {{0}};
|
||||
col.info.colId = pExpr[i].base.colInfo.colId;
|
||||
col.info.colId = pExpr[i].base.pColumns->colId;
|
||||
// col.info.bytes = pExpr[i].base.colBytes;
|
||||
// col.info.type = pExpr[i].base.colType;
|
||||
taosArrayPush(pDataBlock->pDataBlock, &col);
|
||||
|
@ -6776,7 +6777,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
|
|||
int16_t type = pExprInfo->base.resSchema.type;
|
||||
|
||||
for(int32_t i = 0; i < pQueryAttr->numOfTags; ++i) {
|
||||
if (pQueryAttr->tagColList[i].colId == pExprInfo->base.colInfo.colId) {
|
||||
if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->colId) {
|
||||
bytes = pQueryAttr->tagColList[i].bytes;
|
||||
type = pQueryAttr->tagColList[i].type;
|
||||
break;
|
||||
|
@ -6808,10 +6809,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
|
|||
output += sizeof(pQueryAttr->vgId);
|
||||
|
||||
char* data = NULL;
|
||||
if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
if (pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
data = tsdbGetTableName(item->pTable);
|
||||
} else {
|
||||
data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
|
||||
data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->colId, type, bytes);
|
||||
}
|
||||
|
||||
doSetTagValueToResultBuf(output, data, type, bytes);
|
||||
|
@ -6839,7 +6840,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
|
|||
int16_t type = 0, bytes = 0;
|
||||
for(int32_t j = 0; j < pOperator->numOfOutput; ++j) {
|
||||
// not assign value in case of user defined constant output column
|
||||
if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) {
|
||||
if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.pColumns->flag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -6847,10 +6848,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
|
|||
type = pExprInfo[j].base.resSchema.type;
|
||||
bytes = pExprInfo[j].base.resSchema.bytes;
|
||||
|
||||
if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
if (pExprInfo[j].base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
data = tsdbGetTableName(item->pTable);
|
||||
} else {
|
||||
data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes);
|
||||
data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->colId, type, bytes);
|
||||
}
|
||||
|
||||
dst = pColInfo->pData + count * pExprInfo[j].base.resSchema.bytes;
|
||||
|
@ -7310,9 +7311,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
|
|||
for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
|
||||
param->pExpr[i] = pExprMsg;
|
||||
|
||||
pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
|
||||
pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
|
||||
pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag);
|
||||
// pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
|
||||
// pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
|
||||
// pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag);
|
||||
// pExprMsg->colBytes = htons(pExprMsg->colBytes);
|
||||
// pExprMsg->colType = htons(pExprMsg->colType);
|
||||
|
||||
|
@ -7361,9 +7362,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
|
|||
for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
|
||||
param->pSecExpr[i] = pExprMsg;
|
||||
|
||||
pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
|
||||
pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
|
||||
pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag);
|
||||
// pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
|
||||
// pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
|
||||
// pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag);
|
||||
// pExprMsg->resType = htons(pExprMsg->resType);
|
||||
// pExprMsg->resBytes = htons(pExprMsg->resBytes);
|
||||
// pExprMsg->colBytes = htons(pExprMsg->colBytes);
|
||||
|
@ -7677,11 +7678,11 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp
|
|||
SSchema s = {.type=TSDB_DATA_TYPE_BINARY, .bytes=TSDB_MAX_BINARY_LEN};
|
||||
type = s.type;
|
||||
bytes = s.bytes;
|
||||
} else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && functionId == FUNCTION_TAGPRJ) { // parse the normal column
|
||||
} else if (pExprs[i].base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX && functionId == FUNCTION_TAGPRJ) { // parse the normal column
|
||||
SSchema* s = tGetTbnameColumnSchema();
|
||||
type = s->type;
|
||||
bytes = s->bytes;
|
||||
} else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) {
|
||||
} else if (pExprs[i].base.pColumns->info.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.pColumns->info.colId > TSDB_RES_COL_ID) {
|
||||
// it is a user-defined constant value column
|
||||
assert(functionId == FUNCTION_PRJ);
|
||||
|
||||
|
@ -7692,7 +7693,7 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp
|
|||
}
|
||||
} else {
|
||||
int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
|
||||
if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
|
||||
if (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag)) {
|
||||
if (j < TSDB_TBNAME_COLUMN_INDEX || j >= pTableInfo->numOfTags) {
|
||||
tfree(pExprs);
|
||||
return TSDB_CODE_QRY_INVALID_MSG;
|
||||
|
@ -7704,8 +7705,8 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp
|
|||
}
|
||||
}
|
||||
|
||||
if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
|
||||
SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j];
|
||||
if (pExprs[i].base.pColumns->info.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
|
||||
SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag))? &pTagCols[j]:&pTableInfo->colList[j];
|
||||
type = pCol->type;
|
||||
bytes = pCol->bytes;
|
||||
} else {
|
||||
|
@ -7814,7 +7815,7 @@ int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t nu
|
|||
// bytes = tDataTypes[type].bytes;
|
||||
// } else {
|
||||
// int32_t index = pExprs[i].base.colInfo.colIndex;
|
||||
// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.colInfo.colId);
|
||||
// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->colId);
|
||||
//
|
||||
// type = prevExpr[index].base.resSchema.type;
|
||||
// bytes = prevExpr[index].base.resSchema.bytes;
|
||||
|
@ -8083,7 +8084,7 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S
|
|||
pQueryAttr->resultRowSize += pExprs[col].base.resSchema.bytes;
|
||||
|
||||
// keep the tag length
|
||||
if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
|
||||
if (TSDB_COL_IS_TAG(pExprs[col].base.pColumns->flag)) {
|
||||
pQueryAttr->tagLen += pExprs[col].base.resSchema.bytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef struct SScalarFunctionSupport {
|
|||
char** data;
|
||||
} SScalarFunctionSupport;
|
||||
|
||||
extern struct SScalarFunctionInfo scalarFunc[1];
|
||||
extern struct SScalarFunctionInfo scalarFunc[5];
|
||||
|
||||
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput,
|
||||
void* param, char* (*getSourceDataBlock)(void*, const char*, int32_t));
|
||||
|
|
|
@ -543,8 +543,8 @@ struct SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, co
|
|||
pFillCol[i].col.offset = offset;
|
||||
pFillCol[i].col.colId = pExprInfo->base.resSchema.colId;
|
||||
pFillCol[i].tagIndex = -2;
|
||||
pFillCol[i].flag = pExprInfo->base.colInfo.flag; // always be the normal column for table query
|
||||
pFillCol[i].functionId = pExprInfo->pExpr->_node.functionId;
|
||||
pFillCol[i].flag = pExprInfo->base.pColumns->flag; // always be the normal column for table query
|
||||
pFillCol[i].functionId = pExprInfo->pExpr->_function.functionId;
|
||||
pFillCol[i].fillVal.i = fillVal[i];
|
||||
|
||||
offset += pExprInfo->base.resSchema.bytes;
|
||||
|
|
|
@ -30,11 +30,12 @@ static void doInitFunctionHashTable() {
|
|||
|
||||
static pthread_once_t functionHashTableInit = PTHREAD_ONCE_INIT;
|
||||
|
||||
int32_t qIsBuiltinFunction(const char* name, int32_t len) {
|
||||
int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction) {
|
||||
pthread_once(&functionHashTableInit, doInitFunctionHashTable);
|
||||
|
||||
SAggFunctionInfo** pInfo = taosHashGet(functionHashTable, name, len);
|
||||
if (pInfo != NULL) {
|
||||
*scalarFunction = ((*pInfo)->type == FUNCTION_TYPE_SCALAR);
|
||||
return (*pInfo)->functionId;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -2,6 +2,156 @@
|
|||
#include "tbinoperator.h"
|
||||
#include "tunaryoperator.h"
|
||||
|
||||
|
||||
static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScalarFuncParam* src) {
|
||||
dst->type = src->type;
|
||||
dst->bytes = src->bytes;
|
||||
dst->num = src->num;
|
||||
}
|
||||
|
||||
static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = ceilf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*)pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = ceil(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = floorf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = floor(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
int8_t* p = (int8_t*) pLeft->data;
|
||||
int8_t* out = (int8_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
int16_t* p = (int16_t*) pLeft->data;
|
||||
int16_t* out = (int16_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
int32_t* p = (int32_t*) pLeft->data;
|
||||
int32_t* out = (int32_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
int64_t* p = (int64_t*) pLeft->data;
|
||||
int64_t* out = (int64_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = roundf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = round(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
int64_t* out = (int64_t*) pOutput->data;
|
||||
char* s = pLeft->data;
|
||||
|
||||
for(int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = varDataLen(POINTER_SHIFT(s, i * pLeft->bytes));
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) {
|
||||
switch(type) {
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
|
@ -168,11 +318,12 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa
|
|||
return 0;
|
||||
}
|
||||
|
||||
SScalarFunctionInfo scalarFunc[1] = {
|
||||
{
|
||||
|
||||
},
|
||||
|
||||
SScalarFunctionInfo scalarFunc[5] = {
|
||||
{"ceil", FUNCTION_TYPE_SCALAR, FUNCTION_CEIL, tceil},
|
||||
{"floor", FUNCTION_TYPE_SCALAR, FUNCTION_FLOOR, tfloor},
|
||||
{"abs", FUNCTION_TYPE_SCALAR, FUNCTION_ABS, _tabs},
|
||||
{"round", FUNCTION_TYPE_SCALAR, FUNCTION_ROUND, tround},
|
||||
{"length", FUNCTION_TYPE_SCALAR, FUNCTION_LENGTH, tlength},
|
||||
};
|
||||
|
||||
void setScalarFunctionSupp(struct SScalarFunctionSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
|
||||
|
|
|
@ -1,171 +1,13 @@
|
|||
#include "tunaryoperator.h"
|
||||
|
||||
static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScalarFuncParam* src) {
|
||||
dst->type = src->type;
|
||||
dst->bytes = src->bytes;
|
||||
dst->num = src->num;
|
||||
}
|
||||
|
||||
static void tceil(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = ceilf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*)pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = ceil(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tfloor(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = floorf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = floor(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tabs(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
int8_t* p = (int8_t*) pLeft->data;
|
||||
int8_t* out = (int8_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
int16_t* p = (int16_t*) pLeft->data;
|
||||
int16_t* out = (int16_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
int32_t* p = (int32_t*) pLeft->data;
|
||||
int32_t* out = (int32_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
int64_t* p = (int64_t*) pLeft->data;
|
||||
int64_t* out = (int64_t*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = (p[i] > 0)? p[i]:-p[i];
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tround(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
assignBasicParaInfo(pOutput, pLeft);
|
||||
|
||||
switch (pLeft->bytes) {
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
float* p = (float*) pLeft->data;
|
||||
float* out = (float*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = roundf(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double* p = (double*) pLeft->data;
|
||||
double* out = (double*) pOutput->data;
|
||||
for (int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = round(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void tlen(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
|
||||
int64_t* out = (int64_t*) pOutput->data;
|
||||
char* s = pLeft->data;
|
||||
|
||||
for(int32_t i = 0; i < pLeft->num; ++i) {
|
||||
out[i] = varDataLen(POINTER_SHIFT(s, i * pLeft->bytes));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO dynamic define these functions
|
||||
_unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t operator) {
|
||||
switch(operator) {
|
||||
case TSDB_UNARY_OP_CEIL:
|
||||
return tceil;
|
||||
case TSDB_UNARY_OP_FLOOR:
|
||||
return tfloor;
|
||||
case TSDB_UNARY_OP_ROUND:
|
||||
return tround;
|
||||
case TSDB_UNARY_OP_ABS:
|
||||
return _tabs;
|
||||
case TSDB_UNARY_OP_LEN:
|
||||
return tlen;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
bool isStringOperatorFn(int32_t op) {
|
||||
return op == TSDB_UNARY_OP_LEN;
|
||||
return op == FUNCTION_LENGTH;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ extern "C" {
|
|||
|
||||
TAOS_FIELD createField(const SSchema* pSchema);
|
||||
SSchema createSchema(uint8_t type, int16_t bytes, int16_t colId, const char* name);
|
||||
void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema);
|
||||
|
||||
SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* field);
|
||||
int32_t getNumOfFields(SFieldInfo* pFieldInfo);
|
||||
|
@ -51,7 +52,7 @@ STableMetaInfo* addEmptyMetaInfo(SQueryStmtInfo* pQueryInfo);
|
|||
|
||||
void columnListCopyAll(SArray* dst, const SArray* src);
|
||||
|
||||
SColumn* columnListInsert(SArray* pColumnList, int32_t columnIndex, uint64_t uid, SSchema* pSchema);
|
||||
SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag);
|
||||
SColumn* insertPrimaryTsColumn(SArray* pColumnList, uint64_t tableUid);
|
||||
|
||||
void cleanupTagCond(STagCond* pTagCond);
|
||||
|
|
|
@ -327,7 +327,7 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SQueryStmtI
|
|||
int32_t startOffset = (int32_t) taosArrayGetSize(pQueryInfo->colList);
|
||||
|
||||
for(int32_t i = 0; i < pMeta->tableInfo.numOfColumns; ++i) {
|
||||
columnListInsert(pQueryInfo->colList, i + startOffset, pMeta->uid, &pMeta->schema[i]);
|
||||
columnListInsert(pQueryInfo->colList, pMeta->uid, &pMeta->schema[i], TSDB_COL_NORMAL);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -556,14 +556,14 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
|
|||
taosArrayPush(pGroupExpr->columnInfo, &colIndex);
|
||||
|
||||
index.columnIndex = relIndex;
|
||||
columnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMeta->uid, pSchema);
|
||||
columnListInsert(pTableMetaInfo->tagColList, pTableMeta->uid, pSchema, colIndex.flag);
|
||||
} else {
|
||||
// check if the column type is valid, here only support the bool/tinyint/smallint/bigint group by
|
||||
if (pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
columnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->uid, pSchema);
|
||||
columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL);
|
||||
|
||||
SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId };
|
||||
strncpy(colIndex.name, pSchema->name, tListLen(colIndex.name));
|
||||
|
@ -854,7 +854,7 @@ int32_t validateStateWindowNode(SQueryStmtInfo *pQueryInfo, SWindowStateVal* pWi
|
|||
return buildInvalidOperationMsg(pMsgBuf, msg2);
|
||||
}
|
||||
|
||||
columnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->uid, pSchema);
|
||||
columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL);
|
||||
SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId };
|
||||
|
||||
//TODO use group by routine? state window query not support stable query.
|
||||
|
@ -1114,7 +1114,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S
|
|||
pExpr = getExprInfo(pQueryInfo, pos);
|
||||
|
||||
// other tag are not allowed
|
||||
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
|
@ -1133,7 +1133,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S
|
|||
bool found = false;
|
||||
for (int32_t i = 0; i < getNumOfExprs(pQueryInfo); ++i) {
|
||||
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
|
||||
if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.pColumns->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1214,7 +1214,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S
|
|||
|
||||
pExpr = getExprInfo(pQueryInfo, pos);
|
||||
|
||||
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
}
|
||||
|
@ -1614,7 +1614,7 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
|
|||
for (int32_t i = 0; i < size; ++i) {
|
||||
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
|
||||
int32_t functionId = getExprFunctionId(pExpr);
|
||||
if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.colInfo.flag)) {
|
||||
if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.pColumns->flag)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
}
|
||||
|
@ -1718,15 +1718,15 @@ SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex,
|
|||
uint64_t uid = pTableMetaInfo->pTableMeta->uid;
|
||||
|
||||
SArray* p = TSDB_COL_IS_TAG(pIndex->type)?pTableMetaInfo->tagColList:pQueryInfo->colList;
|
||||
columnListInsert(p, pIndex->columnIndex, uid, pColSchema);
|
||||
columnListInsert(p, uid, pColSchema, pIndex->type);
|
||||
|
||||
pExpr->base.colInfo.flag = pIndex->type;
|
||||
pExpr->base.pColumns->flag = pIndex->type;
|
||||
if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) {
|
||||
insertPrimaryTsColumn(pQueryInfo->colList, uid);
|
||||
}
|
||||
|
||||
if (finalResult) {
|
||||
addResColumnInfo(pQueryInfo, outputColIndex, pColSchema, pExpr);
|
||||
addResColumnInfo(pQueryInfo, outputColIndex, pResultSchema, pExpr);
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
|
@ -1762,7 +1762,7 @@ static int32_t checkForAliasName(SMsgBuf* pMsgBuf, char* aliasName) {
|
|||
}
|
||||
|
||||
static int32_t validateComplexExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf);
|
||||
static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, uint64_t *uid, SMsgBuf* pMsgBuf);
|
||||
static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, SMsgBuf* pMsgBuf);
|
||||
|
||||
static int64_t getTickPerSecond(SVariant* pVariant, int32_t precision, int64_t* tickPerSec, SMsgBuf *pMsgBuf) {
|
||||
const char* msg10 = "derivative duration should be greater than 1 Second";
|
||||
|
@ -1795,7 +1795,7 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab
|
|||
addExprInfo(pQueryInfo, outputIndex, pExpr);
|
||||
|
||||
SSchema* pSourceSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, indexTS.columnIndex);
|
||||
columnListInsert(pQueryInfo->colList, indexTS.columnIndex, pTableMetaInfo->pTableMeta->uid, pSourceSchema);
|
||||
columnListInsert(pQueryInfo->colList, pTableMetaInfo->pTableMeta->uid, pSourceSchema, TSDB_COL_NORMAL);
|
||||
addResColumnInfo(pQueryInfo, outputIndex, &pExpr->base.resSchema, pExpr);
|
||||
}
|
||||
|
||||
|
@ -1898,6 +1898,7 @@ static int32_t doHandleOneParam(SQueryStmtInfo *pQueryInfo, tSqlExprItem* pItem,
|
|||
}
|
||||
|
||||
static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf);
|
||||
static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf);
|
||||
|
||||
int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema,
|
||||
tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) {
|
||||
|
@ -1906,24 +1907,47 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
|
|||
const char* msg3 = "illegal column name";
|
||||
const char* msg4 = "nested function is not supported";
|
||||
const char* msg5 = "functions applied to tags are not allowed";
|
||||
const char* msg6 = "aggregate function can not be nested in aggregate function";
|
||||
const char* msg7 = "invalid function name";
|
||||
|
||||
if (tokenId == TK_ALL || tokenId == TK_ID) { // simple parameter
|
||||
if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
// simple parameter or nested function
|
||||
// It is a parameter of a aggregate function, so it can not be still a aggregate function.
|
||||
// E.g., the sql statement of "select count(count(*)) from table_name" is invalid.
|
||||
tSqlExpr* pSqlExpr = pParamElem->pNode;
|
||||
if (pParamElem->pNode->type == SQL_NODE_SQLFUNCTION) {
|
||||
bool scalarFunc = false;
|
||||
pParamElem->functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalarFunc);
|
||||
if (pParamElem->functionId == FUNCTION_INVALID_ID) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg7);
|
||||
}
|
||||
|
||||
if (!scalarFunc) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg6);
|
||||
}
|
||||
|
||||
int32_t code = createComplexExpr(pQueryInfo, i, pParamElem, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
}
|
||||
|
||||
// functions can not be applied to tags
|
||||
if (TSDB_COL_IS_TAG(pIndex->type)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
// 2. check if sql function can be applied on this column data type
|
||||
*pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex);
|
||||
*columnSchema = *(SSchema*)getOneColumnSchema((*pTableMetaInfo)->pTableMeta, pIndex->columnIndex);
|
||||
}
|
||||
|
||||
// functions can not be applied to tags
|
||||
if (TSDB_COL_IS_TAG(pIndex->type)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg5);
|
||||
}
|
||||
|
||||
*pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex);
|
||||
|
||||
// 2. check if sql function can be applied on this column data type
|
||||
*columnSchema = *(SSchema*) getOneColumnSchema((*pTableMetaInfo)->pTableMeta, pIndex->columnIndex);
|
||||
} else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) {
|
||||
}else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) {
|
||||
int32_t arithmeticType = NON_ARITHMEIC_EXPR;
|
||||
SArray* pColumnList = taosArrayInit(4, sizeof(SColumnIndex));
|
||||
SArray* pColumnList = taosArrayInit(4, sizeof(SColumn));
|
||||
if (validateComplexExpr(pParamElem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
@ -1940,7 +1964,7 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
|
|||
tstrncpy(columnSchema->name, pExprToken->z, len);
|
||||
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
|
||||
int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, NULL, pMsgBuf);
|
||||
int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
taosArrayDestroy(colList);
|
||||
tExprTreeDestroy(*pNode, NULL);
|
||||
|
@ -2290,7 +2314,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
|
|||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
columnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex]);
|
||||
columnListInsert(pTableMetaInfo->tagColList, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex], TSDB_COL_TAG);
|
||||
SSchema* pTagSchema = getTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
|
||||
SSchema s = {0};
|
||||
|
@ -2337,6 +2361,8 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
default: {
|
||||
// pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||
// if (pUdfInfo == NULL) {
|
||||
|
@ -2380,6 +2406,110 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
static int32_t validateExprLeafColumnNode(SQueryStmtInfo *pQueryInfo, SToken* pColumnName, SArray* pList, SMsgBuf* pMsgBuf) {
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(pColumnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// if column is timestamp not support arithmetic, so return invalid sql
|
||||
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex);
|
||||
if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
SColumn c = {0};
|
||||
setColumn(&c, pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema);
|
||||
taosArrayPush(pList, &c);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SMsgBuf* pMsgBuf) {
|
||||
tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL};
|
||||
|
||||
// sql function list in selection clause.
|
||||
// Append the sqlExpr into exprList of pQueryInfo structure sequentially
|
||||
bool scalar = false;
|
||||
item.functionId = qIsBuiltinFunction(pExpr->Expr.operand.z, pExpr->Expr.operand.n, &scalar);
|
||||
if (item.functionId < 0) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo);
|
||||
if (addExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k)
|
||||
int32_t inc = (int32_t) getNumOfExprs(pQueryInfo) - outputIndex;
|
||||
if (inc > 1) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// Not supported data type in expression
|
||||
for(int32_t i = 0; i < inc; ++i) {
|
||||
SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex);
|
||||
int16_t t = p1->base.resSchema.type;
|
||||
if (t == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
switch (pItem->functionId) {
|
||||
case FUNCTION_CEIL: {
|
||||
code = checkForkParam(pItem->pNode, 1, pMsgBuf);
|
||||
break;
|
||||
}
|
||||
case FUNCTION_LENGTH: {
|
||||
code = checkForkParam(pItem->pNode, 1, pMsgBuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SArray* pList, int32_t* exprType, SMsgBuf* pMsgBuf) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
// more than one parameter for count() function
|
||||
|
||||
SArray* pParamList = pExpr->Expr.paramList;
|
||||
*exprType = NORMAL_ARITHMETIC;
|
||||
|
||||
for (int32_t i = 0; i < 1; ++i) {
|
||||
tSqlExprItem* pParamElem = taosArrayGet(pParamList, i);
|
||||
tSqlExpr* pSqlExpr = pParamElem->pNode;
|
||||
|
||||
int32_t type = pSqlExpr->type;
|
||||
if (type == SQL_NODE_VALUE) {
|
||||
} else if (type == SQL_NODE_SQLFUNCTION) {
|
||||
code = validateExprLeafFunctionNode(pQueryInfo, pSqlExpr, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else if (type == SQL_NODE_EXPR) {
|
||||
code = validateComplexExpr(pSqlExpr, pQueryInfo, pList, exprType, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else if (type == SQL_NODE_TABLE_COLUMN) {
|
||||
code = validateExprLeafColumnNode(pQueryInfo, &pSqlExpr->columnName, pList, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SColumnIndex* pColIndex, const char* aliasName, int32_t colId) {
|
||||
STableMeta* pTableMeta = getMetaInfo(pQueryInfo, pColIndex->tableIndex)->pTableMeta;
|
||||
|
||||
|
@ -2452,6 +2582,48 @@ static SSchema createConstantColumnSchema(SVariant* pVal, const SToken* exprStr,
|
|||
return s;
|
||||
}
|
||||
|
||||
static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, SColumnIndex* pIndex, int32_t startPos, bool outerQuery, SMsgBuf* pMsgBuf) {
|
||||
const char* msg3 = "tbname not allowed in outer query";
|
||||
|
||||
SSchema colSchema = {0};
|
||||
int32_t functionId = 0;
|
||||
|
||||
if (outerQuery) { // todo??
|
||||
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex);
|
||||
|
||||
bool existed = false;
|
||||
SSchema* pSchema = pTableMetaInfo->pTableMeta->schema;
|
||||
|
||||
int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
if (strncasecmp(pSchema[i].name, TSQL_TBNAME_L, tListLen(pSchema[i].name)) == 0) {
|
||||
existed = true;
|
||||
pIndex->columnIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!existed) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
}
|
||||
|
||||
colSchema = pSchema[pIndex->columnIndex];
|
||||
functionId = FUNCTION_PRJ;
|
||||
} else {
|
||||
colSchema = *getTbnameColumnSchema();
|
||||
functionId = FUNCTION_TAGPRJ;
|
||||
}
|
||||
|
||||
SSchema resultSchema = colSchema;
|
||||
resultSchema.colId = getNewResColId();
|
||||
|
||||
char rawName[TSDB_COL_NAME_LEN] = {0};
|
||||
setTokenAndResColumnName(pItem, resultSchema.name, rawName, sizeof(colSchema.name) - 1);
|
||||
|
||||
doAddOneExprInfo(pQueryInfo, startPos, functionId, pIndex, &colSchema, &resultSchema, NULL, 0, rawName, true);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, bool outerQuery, SMsgBuf* pMsgBuf) {
|
||||
const char* msg1 = "tag for normal table query is not allowed";
|
||||
const char* msg2 = "invalid column name";
|
||||
|
@ -2487,7 +2659,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
|
|||
if (pTableMeta->tableType != TSDB_TEMP_TABLE) {
|
||||
insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->uid);
|
||||
}
|
||||
} else if (tokenId == TK_STRING || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { // simple column projection query
|
||||
} else if (tokenId == TK_STRING || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { //constant value column
|
||||
SColumnIndex index = createConstantColumnIndex(&pQueryInfo->udColumnId);
|
||||
SSchema colSchema = createConstantColumnSchema(&pItem->pNode->value, &pItem->pNode->exprToken, pItem->aliasName);
|
||||
|
||||
|
@ -2498,49 +2670,14 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
|
|||
// NOTE: the first parameter is reserved for the tag column id during join query process.
|
||||
pExpr->base.numOfParams = 2;
|
||||
taosVariantAssign(&pExpr->base.param[1], &pItem->pNode->value);
|
||||
} else if (tokenId == TK_ID) {
|
||||
} else if (tokenId == TK_ID) { // column name
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(&pItem->pNode->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg2);
|
||||
}
|
||||
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
SSchema colSchema = {0};
|
||||
int32_t functionId = 0;
|
||||
|
||||
if (outerQuery) { // todo??
|
||||
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex);
|
||||
|
||||
bool existed = false;
|
||||
SSchema* pSchema = pTableMetaInfo->pTableMeta->schema;
|
||||
|
||||
int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
if (strncasecmp(pSchema[i].name, TSQL_TBNAME_L, tListLen(pSchema[i].name)) == 0) {
|
||||
existed = true;
|
||||
index.columnIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!existed) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
}
|
||||
|
||||
colSchema = pSchema[index.columnIndex];
|
||||
functionId = FUNCTION_PRJ;
|
||||
} else {
|
||||
colSchema = *getTbnameColumnSchema();
|
||||
functionId = FUNCTION_TAGPRJ;
|
||||
}
|
||||
|
||||
SSchema resultSchema = colSchema;
|
||||
resultSchema.colId = getNewResColId();
|
||||
|
||||
char rawName[TSDB_COL_NAME_LEN] = {0};
|
||||
setTokenAndResColumnName(pItem, resultSchema.name, rawName, sizeof(colSchema.name) - 1);
|
||||
|
||||
doAddOneExprInfo(pQueryInfo, startPos, functionId, &index, &colSchema, &resultSchema, NULL, 0, rawName, true);
|
||||
handleTbnameProjection(pQueryInfo, pItem, &index, startPos, outerQuery, pMsgBuf);
|
||||
} else {
|
||||
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex);
|
||||
if (TSDB_COL_IS_TAG(index.type) && UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
|
||||
|
@ -2562,8 +2699,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pList, int32_t* type, uint64_t* uid,
|
||||
SMsgBuf* pMsgBuf) {
|
||||
static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pList, int32_t* type, SMsgBuf* pMsgBuf) {
|
||||
if (pExpr->type == SQL_NODE_TABLE_COLUMN) {
|
||||
if (*type == NON_ARITHMEIC_EXPR) {
|
||||
*type = NORMAL_ARITHMETIC;
|
||||
|
@ -2571,21 +2707,10 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo,
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(&pExpr->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
int32_t code = validateExprLeafColumnNode(pQueryInfo, &pExpr->columnName, pList, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// if column is timestamp, bool, binary, nchar, not support arithmetic, so return invalid sql
|
||||
STableMeta* pTableMeta = getMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta;
|
||||
|
||||
SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex);
|
||||
if ((pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) || (pSchema->type == TSDB_DATA_TYPE_BOOL) ||
|
||||
(pSchema->type == TSDB_DATA_TYPE_BINARY) || (pSchema->type == TSDB_DATA_TYPE_NCHAR)) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
taosArrayPush(pList, &index);
|
||||
} else if ((pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.d) || isinf(pExpr->value.d))) ||
|
||||
pExpr->tokenId == TK_NULL) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
|
@ -2596,103 +2721,99 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo,
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL};
|
||||
|
||||
// sql function list in selection clause.
|
||||
// Append the sqlExpr into exprList of pQueryInfo structure sequentially
|
||||
item.functionId = qIsBuiltinFunction(pExpr->Expr.operand.z, pExpr->Expr.operand.n);
|
||||
if (item.functionId < 0) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
int32_t code = validateExprLeafFunctionNode(pQueryInfo, pExpr, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo);
|
||||
if (addExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k)
|
||||
int32_t inc = (int32_t) getNumOfExprs(pQueryInfo) - outputIndex;
|
||||
if (inc > 1) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// Not supported data type in arithmetic expression
|
||||
uint64_t id = -1;
|
||||
for(int32_t i = 0; i < inc; ++i) {
|
||||
SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex);
|
||||
|
||||
int16_t t = p1->base.resSchema.type;
|
||||
if (IS_VAR_DATA_TYPE(t) || t == TSDB_DATA_TYPE_BOOL || t == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
id = p1->base.uid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id != p1->base.uid) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
*uid = id;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t validateComplexExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) {
|
||||
int32_t validateComplexExpr(tSqlExpr * pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) {
|
||||
if (pExpr == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
tSqlExpr* pLeft = pExpr->pLeft;
|
||||
uint64_t uidLeft = 0;
|
||||
uint64_t uidRight = 0;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (pExpr->type == SQL_NODE_SQLFUNCTION) {
|
||||
return validateScalarFunctionParam(pQueryInfo, pExpr, pColList, type, pMsgBuf);
|
||||
}
|
||||
|
||||
tSqlExpr* pLeft = pExpr->pLeft;
|
||||
if (pLeft->type == SQL_NODE_EXPR) {
|
||||
int32_t ret = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
code = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
int32_t ret = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, &uidLeft, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
code = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
tSqlExpr* pRight = pExpr->pRight;
|
||||
if (pRight->type == SQL_NODE_EXPR) {
|
||||
int32_t ret = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
code = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
int32_t ret = validateExprLeafNode(pRight, pQueryInfo, pColList, type, &uidRight, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
code = validateExprLeafNode(pRight, pQueryInfo, pColList, type, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
// check divide by 0
|
||||
if (pExpr->tokenId == TK_DIVIDE && pRight->type == SQL_NODE_VALUE) {
|
||||
int32_t type1 = pRight->value.nType;
|
||||
const char* msg1 = "invalid expr (divide by 0)";
|
||||
|
||||
if (type1 == TSDB_DATA_TYPE_DOUBLE && pRight->value.d < DBL_EPSILON) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
} else if (type1 == TSDB_DATA_TYPE_INT && pRight->value.i == 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, uint64_t *uid, SMsgBuf* pMsgBuf) {
|
||||
int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, SMsgBuf* pMsgBuf) {
|
||||
tExprNode* pLeft = NULL;
|
||||
tExprNode* pRight= NULL;
|
||||
|
||||
if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
|
||||
// assert it is a scalar function
|
||||
*pExpr = calloc(1, sizeof(tExprNode));
|
||||
(*pExpr)->nodeType = TEXPR_FUNCTION_NODE;
|
||||
(*pExpr)->_function.num = 1;
|
||||
(*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n);
|
||||
|
||||
SArray* pParamList = pSqlExpr->Expr.paramList;
|
||||
size_t num = taosArrayGetSize(pParamList);
|
||||
(*pExpr)->_function.pChild = calloc(num, POINTER_BYTES);
|
||||
|
||||
for(int32_t i = 0; i < num; ++i) {
|
||||
tSqlExprItem* pItem = taosArrayGet(pParamList, i);
|
||||
sqlExprToExprNode(&(((*pExpr)->_function.pChild)[0]), pItem->pNode, pQueryInfo, pCols, pMsgBuf);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (pSqlExpr->pLeft != NULL) {
|
||||
int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, uid, pMsgBuf);
|
||||
int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSqlExpr->pRight != NULL) {
|
||||
int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, uid, pMsgBuf);
|
||||
int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
tExprTreeDestroy(pLeft, NULL);
|
||||
return ret;
|
||||
|
@ -2728,7 +2849,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
|
|||
}
|
||||
return ret;
|
||||
} else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
|
||||
// arithmetic expression on the results of aggregation functions
|
||||
// Expression on the results of aggregation functions
|
||||
*pExpr = calloc(1, sizeof(tExprNode));
|
||||
(*pExpr)->nodeType = TEXPR_COL_NODE;
|
||||
(*pExpr)->pSchema = calloc(1, sizeof(SSchema));
|
||||
|
@ -2737,19 +2858,28 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
|
|||
// set the input column data byte and type.
|
||||
size_t size = taosArrayGetSize(pQueryInfo->exprList);
|
||||
|
||||
bool found = false;
|
||||
uint64_t uid = 0;
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SExprInfo* p1 = taosArrayGetP(pQueryInfo->exprList, i);
|
||||
|
||||
if (strcmp((*pExpr)->pSchema->name, p1->base.resSchema.name) == 0) {
|
||||
memcpy((*pExpr)->pSchema, &p1->base.resSchema, sizeof(SSchema));
|
||||
if (uid != NULL) {
|
||||
*uid = p1->base.uid;
|
||||
}
|
||||
|
||||
found = true;
|
||||
uid = p1->base.pColumns->uid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression
|
||||
|
||||
assert(found);
|
||||
|
||||
if (pCols != NULL) { // record the involved columns
|
||||
SColumn c = {0};
|
||||
setColumn(&c, uid, NULL, TSDB_COL_NORMAL, (*pExpr)->pSchema);
|
||||
taosArrayPush(pCols, &c);
|
||||
}
|
||||
|
||||
} else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column expression
|
||||
int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
|
@ -2764,17 +2894,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
|
|||
|
||||
SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex);
|
||||
*(*pExpr)->pSchema = *pSchema;
|
||||
|
||||
if (pCols != NULL) { // record the involved columns
|
||||
SColIndex colIndex = {0};
|
||||
tstrncpy(colIndex.name, pSchema->name, sizeof(colIndex.name));
|
||||
colIndex.colId = pSchema->colId;
|
||||
colIndex.colIndex = index.columnIndex;
|
||||
colIndex.flag = index.type;
|
||||
|
||||
taosArrayPush(pCols, &colIndex);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else if (pSqlExpr->tokenId == TK_SET) {
|
||||
int32_t colType = -1;
|
||||
|
@ -2823,17 +2942,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
|
|||
|
||||
assert((*pExpr)->_node.optr != 0);
|
||||
|
||||
// check for dividing by 0
|
||||
if ((*pExpr)->_node.optr == TSDB_BINARY_OP_DIVIDE) {
|
||||
if (pRight->nodeType == TEXPR_VALUE_NODE) {
|
||||
if (pRight->pVal->nType == TSDB_DATA_TYPE_INT && pRight->pVal->i == 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, "invalid expr (divide by 0)");
|
||||
} else if (pRight->pVal->nType == TSDB_DATA_TYPE_FLOAT && pRight->pVal->d == 0) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, "invalid expr (divide by 0)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: binary|nchar data allows the >|< type filter
|
||||
if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) {
|
||||
if (pRight != NULL && pRight->nodeType == TEXPR_VALUE_NODE) {
|
||||
|
@ -2848,33 +2956,32 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
|
|||
}
|
||||
|
||||
static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf) {
|
||||
const char* msg3 = "tag columns can not be used in arithmetic expression";
|
||||
const char* msg1 = "tag can not be used in expression";
|
||||
|
||||
SColumnIndex* p1 = taosArrayGet(pColumnList, 0);
|
||||
STableMeta* pTableMeta = getMetaInfo(pQueryInfo, p1->tableIndex)->pTableMeta;
|
||||
SColumn* p1 = taosArrayGet(pColumnList, 0);
|
||||
|
||||
size_t numOfNode = taosArrayGetSize(pColumnList);
|
||||
for(int32_t k = 0; k < numOfNode; ++k) {
|
||||
SColumnIndex* pIndex = taosArrayGet(pColumnList, k);
|
||||
if (TSDB_COL_IS_TAG(pIndex->type)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg3);
|
||||
SColumn* p = taosArrayGet(pColumnList, k);
|
||||
if (TSDB_COL_IS_TAG(p->flag)) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
SSchema* ps = getOneColumnSchema(pTableMeta, pIndex->columnIndex);
|
||||
columnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->uid, ps);
|
||||
SSchema s = createSchema(p->info.type, p->info.bytes, p->info.colId, p->name);
|
||||
columnListInsert(pQueryInfo->colList, p->uid, &s, p->flag);
|
||||
}
|
||||
|
||||
insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->uid);
|
||||
insertPrimaryTsColumn(pQueryInfo->colList, p1->uid);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) {
|
||||
const char* msg1 = "invalid column name, illegal column type, or columns in arithmetic expression from two tables";
|
||||
const char* msg1 = "invalid column name, illegal column type, or columns in expression from two tables";
|
||||
const char* msg2 = "invalid arithmetic expression in select clause";
|
||||
const char* msg3 = "tag columns can not be used in arithmetic expression";
|
||||
|
||||
int32_t arithmeticType = NON_ARITHMEIC_EXPR;
|
||||
SArray* pColumnList = taosArrayInit(4, sizeof(SColumnIndex));
|
||||
|
||||
SArray* pColumnList = taosArrayInit(4, sizeof(SColumn));
|
||||
if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
@ -2884,8 +2991,8 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
|
|||
SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), "");
|
||||
|
||||
tExprNode* pNode = NULL;
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
|
||||
int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, colList, NULL, pMsgBuf);
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColumn));
|
||||
int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, colList, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
taosArrayDestroy(colList);
|
||||
tExprTreeDestroy(pNode, NULL);
|
||||
|
@ -2924,13 +3031,13 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
|
|||
tbufCloseWriter(&bw);
|
||||
taosArrayDestroy(colList);
|
||||
} else {
|
||||
SColumnIndex columnIndex = {0};
|
||||
|
||||
SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), "");
|
||||
addResColumnInfo(pQueryInfo, exprIndex, &s, NULL);
|
||||
|
||||
assert(taosArrayGetSize(pColumnList) == 0);
|
||||
|
||||
tExprNode* pNode = NULL;
|
||||
int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, NULL, NULL, pMsgBuf);
|
||||
int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, pColumnList, pMsgBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
tExprTreeDestroy(pNode, NULL);
|
||||
return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause");
|
||||
|
@ -2938,10 +3045,19 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
|
|||
|
||||
SExprInfo* pExpr = createBinaryExprInfo(pNode, &s);
|
||||
addExprInfo(pQueryInfo, exprIndex, pExpr);
|
||||
|
||||
setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN);
|
||||
|
||||
pExpr->base.numOfParams = 1;
|
||||
// extract columns according to the tExprNode tree
|
||||
size_t num = taosArrayGetSize(pColumnList);
|
||||
pExpr->base.pColumns = calloc(num, sizeof(SColumn));
|
||||
for(int32_t i = 0; i < num; ++i) {
|
||||
pExpr->base.pColumns[i] = *(SColumn*) taosArrayGet(pColumnList, i);
|
||||
}
|
||||
|
||||
pExpr->base.numOfCols = num;
|
||||
|
||||
pExpr->base.numOfParams = 1;
|
||||
SBufferWriter bw = tbufInitWriter(NULL, false);
|
||||
// TRY(0) {
|
||||
exprTreeToBinary(&bw, pExpr->pExpr);
|
||||
|
@ -2979,7 +3095,8 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
|
|||
return buildInvalidOperationMsg(pMsgBuf, msg1);
|
||||
}
|
||||
|
||||
size_t numOfExpr = taosArrayGetSize(pSelNodeList);
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
size_t numOfExpr = taosArrayGetSize(pSelNodeList);
|
||||
|
||||
for (int32_t i = 0; i < numOfExpr; ++i) {
|
||||
int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo);
|
||||
|
@ -2987,15 +3104,17 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
|
|||
int32_t type = pItem->pNode->type;
|
||||
|
||||
if (pItem->distinct) {
|
||||
if (i != 0/* || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR*/) {
|
||||
if (i != 0 || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR) {
|
||||
return buildInvalidOperationMsg(pMsgBuf, msg4);
|
||||
}
|
||||
|
||||
pQueryInfo->info.distinct = true;
|
||||
}
|
||||
|
||||
bool scalarFunc = false;
|
||||
|
||||
if (type == SQL_NODE_SQLFUNCTION) {
|
||||
pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||
pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &scalarFunc);
|
||||
if (pItem->functionId == FUNCTION_INVALID_ID) {
|
||||
int32_t functionId = FUNCTION_INVALID_ID;
|
||||
bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId);
|
||||
|
@ -3004,21 +3123,24 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
|
|||
}
|
||||
|
||||
pItem->functionId = functionId;
|
||||
} else if (scalarFunc) {
|
||||
if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
|
||||
if (addExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
if ((code = addExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) {
|
||||
// use the dynamic array list to decide if the function is valid or not
|
||||
// select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2
|
||||
if (addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
if ((code = addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else if (type == SQL_NODE_EXPR) {
|
||||
int32_t code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -177,7 +177,8 @@ int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMet
|
|||
}
|
||||
|
||||
// Let's assume that it is an UDF/UDAF, if it is not a built-in function.
|
||||
if (qIsBuiltinFunction(t->z, t->n) < 0) {
|
||||
bool scalarFunc = false;
|
||||
if (qIsBuiltinFunction(t->z, t->n, &scalarFunc) < 0) {
|
||||
char* fname = strndup(t->z, t->n);
|
||||
taosArrayPush(pMetaInfo->pUdf, &fname);
|
||||
}
|
||||
|
|
|
@ -513,6 +513,20 @@ SSchema createSchema(uint8_t type, int16_t bytes, int16_t colId, const char* nam
|
|||
return s;
|
||||
}
|
||||
|
||||
void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema) {
|
||||
pColumn->uid = uid;
|
||||
pColumn->flag = flag;
|
||||
pColumn->info.colId = pSchema->colId;
|
||||
pColumn->info.bytes = pSchema->bytes;
|
||||
pColumn->info.type = pSchema->type;
|
||||
|
||||
if (tableName != NULL) {
|
||||
snprintf(pColumn->name, tListLen(pColumn->name), "%s.%s", tableName, pSchema->name);
|
||||
} else {
|
||||
tstrncpy(pColumn->name, pSchema->name, tListLen(pColumn->name));
|
||||
}
|
||||
}
|
||||
|
||||
int32_t getNumOfFields(SFieldInfo* pFieldInfo) {
|
||||
return pFieldInfo->numOfOutput;
|
||||
}
|
||||
|
@ -701,7 +715,7 @@ int32_t columnExists(SArray* pColumnList, int32_t columnId, uint64_t uid) {
|
|||
int32_t i = 0;
|
||||
while (i < numOfCols) {
|
||||
SColumn* pCol = taosArrayGetP(pColumnList, i);
|
||||
if ((pCol->info.colId != columnId) || (pCol->tableUid != uid)) {
|
||||
if ((pCol->info.colId != columnId) || (pCol->uid != uid)) {
|
||||
++i;
|
||||
continue;
|
||||
} else {
|
||||
|
@ -716,64 +730,60 @@ int32_t columnExists(SArray* pColumnList, int32_t columnId, uint64_t uid) {
|
|||
return i;
|
||||
}
|
||||
|
||||
SColumn* columnListInsert(SArray* pColumnList, int32_t columnIndex, uint64_t uid, SSchema* pSchema) {
|
||||
static int32_t doFindPosition(const SArray* pColumnList, uint64_t uid, const SSchema* pSchema) {
|
||||
int32_t i = 0;
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pColumnList);
|
||||
while (i < numOfCols) {
|
||||
SColumn* pCol = taosArrayGetP(pColumnList, i);
|
||||
if (pCol->uid < uid) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pCol->info.colId < pSchema->colId) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag) {
|
||||
// ignore the tbname columnIndex to be inserted into source list
|
||||
if (columnIndex < 0) {
|
||||
assert(pSchema != NULL && pColumnList != NULL);
|
||||
|
||||
int32_t i = doFindPosition(pColumnList, uid, pSchema);
|
||||
size_t size = taosArrayGetSize(pColumnList);
|
||||
if (size > 0 && i < size) {
|
||||
SColumn* pCol = taosArrayGetP(pColumnList, i);
|
||||
if (pCol->uid == uid && pCol->info.colId == pSchema->colId) {
|
||||
return pCol;
|
||||
}
|
||||
}
|
||||
|
||||
SColumn* b = calloc(1, sizeof(SColumn));
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pColumnList);
|
||||
b->uid = uid;
|
||||
b->flag = flag;
|
||||
b->info.colId = pSchema->colId;
|
||||
b->info.bytes = pSchema->bytes;
|
||||
b->info.type = pSchema->type;
|
||||
tstrncpy(b->name, pSchema->name, tListLen(b->name));
|
||||
|
||||
int32_t i = 0;
|
||||
while (i < numOfCols) {
|
||||
SColumn* pCol = taosArrayGetP(pColumnList, i);
|
||||
if (pCol->columnIndex < columnIndex) {
|
||||
i++;
|
||||
} else if (pCol->tableUid < uid) {
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= numOfCols || numOfCols == 0) {
|
||||
SColumn* b = calloc(1, sizeof(SColumn));
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b->columnIndex = columnIndex;
|
||||
b->tableUid = uid;
|
||||
b->info.colId = pSchema->colId;
|
||||
b->info.bytes = pSchema->bytes;
|
||||
b->info.type = pSchema->type;
|
||||
|
||||
taosArrayInsert(pColumnList, i, &b);
|
||||
} else {
|
||||
SColumn* pCol = taosArrayGetP(pColumnList, i);
|
||||
|
||||
if (i < numOfCols && (pCol->columnIndex > columnIndex || pCol->tableUid != uid)) {
|
||||
SColumn* b = calloc(1, sizeof(SColumn));
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b->columnIndex = columnIndex;
|
||||
b->tableUid = uid;
|
||||
b->info.colId = pSchema->colId;
|
||||
b->info.bytes = pSchema->bytes;
|
||||
b->info.type = pSchema->type;
|
||||
|
||||
taosArrayInsert(pColumnList, i, &b);
|
||||
}
|
||||
}
|
||||
|
||||
return taosArrayGetP(pColumnList, i);
|
||||
taosArrayInsert(pColumnList, i, &b);
|
||||
return b;
|
||||
}
|
||||
|
||||
SColumn* insertPrimaryTsColumn(SArray* pColumnList, uint64_t tableUid) {
|
||||
SSchema s = {.type = TSDB_DATA_TYPE_TIMESTAMP, .bytes = TSDB_KEYSIZE, .colId = PRIMARYKEY_TIMESTAMP_COL_ID};
|
||||
return columnListInsert(pColumnList, PRIMARYKEY_TIMESTAMP_COL_ID, tableUid, &s);
|
||||
return columnListInsert(pColumnList, tableUid, &s, TSDB_COL_NORMAL);
|
||||
}
|
||||
|
||||
void columnCopy(SColumn* pDest, const SColumn* pSrc);
|
||||
|
@ -817,8 +827,7 @@ SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFil
|
|||
void columnCopy(SColumn* pDest, const SColumn* pSrc) {
|
||||
destroyFilterInfo(&pDest->info.flist);
|
||||
|
||||
pDest->columnIndex = pSrc->columnIndex;
|
||||
pDest->tableUid = pSrc->tableUid;
|
||||
pDest->uid = pSrc->uid;
|
||||
pDest->info.flist.numOfFilters = pSrc->info.flist.numOfFilters;
|
||||
pDest->info.flist.filterInfo = tFilterInfoDup(pSrc->info.flist.filterInfo, pSrc->info.flist.numOfFilters);
|
||||
pDest->info.type = pSrc->info.type;
|
||||
|
@ -844,7 +853,7 @@ void columnListCopy(SArray* dst, const SArray* src, uint64_t uid) {
|
|||
for (int32_t i = 0; i < num; ++i) {
|
||||
SColumn* pCol = taosArrayGetP(src, i);
|
||||
|
||||
if (pCol->tableUid == uid) {
|
||||
if (pCol->uid == uid) {
|
||||
SColumn* p = columnClone(pCol);
|
||||
taosArrayPush(dst, &p);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
|
|||
return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
|
||||
}
|
||||
|
||||
static tExprNode* createUnaryFunctionExprNode(int32_t functionId, SSchema* pSchema, tExprNode* pColumnNode) {
|
||||
static tExprNode* createFunctionExprNode(int32_t functionId, SSchema* pSchema, tExprNode* pColumnNode, int32_t numOfCols) {
|
||||
if (pColumnNode == NULL) {
|
||||
pColumnNode = calloc(1, sizeof(tExprNode));
|
||||
pColumnNode->nodeType = TEXPR_COL_NODE;
|
||||
|
@ -66,9 +66,10 @@ static tExprNode* createUnaryFunctionExprNode(int32_t functionId, SSchema* pSche
|
|||
}
|
||||
|
||||
tExprNode* pNode = calloc(1, sizeof(tExprNode));
|
||||
pNode->nodeType = TEXPR_UNARYEXPR_NODE;
|
||||
pNode->_node.functionId = functionId;
|
||||
pNode->_node.pLeft = pColumnNode;
|
||||
pNode->nodeType = TEXPR_FUNCTION_NODE;
|
||||
pNode->_function.functionId = functionId;
|
||||
pNode->_function.pChild = pColumnNode;
|
||||
pNode->_function.num = numOfCols;
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
@ -92,48 +93,50 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t uid = 0;
|
||||
if (pTableMetaInfo->pTableMeta) {
|
||||
uid = pTableMetaInfo->pTableMeta->uid;
|
||||
}
|
||||
|
||||
SSqlExpr* p = &pExpr->base;
|
||||
p->pColumns = calloc(1, sizeof(SColumn));
|
||||
p->numOfCols = 1;
|
||||
|
||||
if (pParamExpr != NULL) {
|
||||
pExpr->pExpr = createUnaryFunctionExprNode(functionId, NULL, pParamExpr);
|
||||
pExpr->pExpr = createFunctionExprNode(functionId, NULL, pParamExpr, 1);
|
||||
// pExpr->base.pColumns
|
||||
// todo set the correct number of columns
|
||||
} else if (pColIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
assert(pParamExpr == NULL);
|
||||
|
||||
SSchema* s = getTbnameColumnSchema();
|
||||
p->colInfo.colId = TSDB_TBNAME_COLUMN_INDEX;
|
||||
pExpr->pExpr = createUnaryFunctionExprNode(functionId, s, pParamExpr);
|
||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, s);
|
||||
|
||||
pExpr->pExpr = createFunctionExprNode(functionId, s, pParamExpr, 1);
|
||||
} else if (pColIndex->columnIndex <= TSDB_UD_COLUMN_INDEX || functionId == FUNCTION_BLKINFO) {
|
||||
assert(pParamExpr == NULL);
|
||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_UDC, pResSchema);
|
||||
|
||||
p->colInfo.colId = pColIndex->columnIndex;
|
||||
SSchema s = createSchema(pResSchema->type, pResSchema->bytes, pColIndex->columnIndex, pResSchema->name);
|
||||
pExpr->pExpr = createUnaryFunctionExprNode(functionId, &s, pParamExpr);
|
||||
pExpr->pExpr = createFunctionExprNode(functionId, &s, pParamExpr, 1);
|
||||
} else {
|
||||
int32_t len = tListLen(p->colInfo.name);
|
||||
if (TSDB_COL_IS_TAG(pColIndex->type)) {
|
||||
SSchema* pSchema = getTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
p->colInfo.colId = pSchema[pColIndex->columnIndex].colId;
|
||||
pExpr->pExpr = createUnaryFunctionExprNode(functionId, &pSchema[pColIndex->columnIndex], pParamExpr);
|
||||
snprintf(p->colInfo.name, len, "%s.%s", pTableMetaInfo->aliasName, pSchema[pColIndex->columnIndex].name);
|
||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, &pSchema[pColIndex->columnIndex]);
|
||||
pExpr->pExpr = createFunctionExprNode(functionId, &pSchema[pColIndex->columnIndex], pParamExpr, 1);
|
||||
} else if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
// in handling select database/version/server_status(), the pTableMeta is NULL
|
||||
SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, pColIndex->columnIndex);
|
||||
p->colInfo.colId = pSchema->colId;
|
||||
snprintf(p->colInfo.name, len, "%s.%s", pTableMetaInfo->aliasName, pSchema->name);
|
||||
setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, pSchema);
|
||||
|
||||
pExpr->pExpr = createUnaryFunctionExprNode(functionId, pSchema, pParamExpr);
|
||||
pExpr->pExpr = createFunctionExprNode(functionId, pSchema, pParamExpr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
p->colInfo.flag = pColIndex->type;
|
||||
p->colInfo.colIndex = pColIndex->columnIndex;
|
||||
p->pColumns->flag = pColIndex->type;
|
||||
p->interBytes = interSize;
|
||||
memcpy(&p->resSchema, pResSchema, sizeof(SSchema));
|
||||
|
||||
if (pTableMetaInfo->pTableMeta) {
|
||||
p->uid = pTableMetaInfo->pTableMeta->uid;
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
|
@ -152,10 +155,9 @@ void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int
|
|||
assert(pExprInfo != NULL);
|
||||
|
||||
SSqlExpr* pse = &pExprInfo->base;
|
||||
pExprInfo->pExpr->_node.functionId = functionId;
|
||||
pExprInfo->pExpr->_function.functionId = functionId;
|
||||
assert(0);
|
||||
|
||||
pse->colInfo.colIndex = srcColumnIndex;
|
||||
pse->colInfo.colId = colId;
|
||||
pse->resSchema.type = resType;
|
||||
pse->resSchema.bytes = resSize;
|
||||
}
|
||||
|
@ -198,7 +200,7 @@ void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t byt
|
|||
|
||||
int32_t getExprFunctionId(SExprInfo *pExprInfo) {
|
||||
assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE);
|
||||
return pExprInfo->pExpr->_node.functionId;
|
||||
return pExprInfo->pExpr->_function.functionId;
|
||||
}
|
||||
|
||||
void assignExprInfo(SExprInfo* dst, const SExprInfo* src) {
|
||||
|
@ -225,8 +227,9 @@ int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deep
|
|||
size_t size = taosArrayGetSize(src);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SExprInfo* pExpr = taosArrayGetP(src, i);
|
||||
uint64_t exprUid = pExpr->base.pColumns->uid;
|
||||
|
||||
if (pExpr->base.uid == uid) {
|
||||
if (exprUid == uid) {
|
||||
if (deepcopy) {
|
||||
SExprInfo* p1 = calloc(1, sizeof(SExprInfo));
|
||||
assignExprInfo(p1, pExpr);
|
||||
|
@ -300,7 +303,7 @@ SArray* extractFunctionIdList(SArray* pExprInfoList) {
|
|||
SArray* p = taosArrayInit(len, sizeof(int32_t));
|
||||
for(int32_t i = 0; i < len; ++i) {
|
||||
SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i);
|
||||
taosArrayPush(p, &pExprInfo->pExpr->_node.functionId);
|
||||
taosArrayPush(p, &pExprInfo->pExpr->_function.functionId);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
|
|
@ -50,7 +50,7 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) {
|
|||
strcpy(pTableMetaInfo->aliasName, name->tname);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
pTableMeta->tableType = TSDB_NORMAL_TABLE;
|
||||
pTableMeta->tableInfo.numOfColumns = 4;
|
||||
pTableMeta->tableInfo.numOfColumns = 6;
|
||||
pTableMeta->tableInfo.rowSize = 28;
|
||||
pTableMeta->uid = 110;
|
||||
|
||||
|
@ -61,12 +61,12 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) {
|
|||
setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1);
|
||||
setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2);
|
||||
setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3);
|
||||
|
||||
}
|
||||
setSchema(&pSchema[4], TSDB_DATA_TYPE_BINARY, 12, "c", 4);
|
||||
setSchema(&pSchema[5], TSDB_DATA_TYPE_BINARY, 44, "d", 5);
|
||||
}
|
||||
|
||||
TEST(testCase, validateAST_test) {
|
||||
SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where ts<now+2h and `col` < 20 + 99");
|
||||
void sqlCheck(const char* sql, bool valid) {
|
||||
SSqlInfo info1 = doGenerateAST(sql);
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
|
@ -89,268 +89,314 @@ TEST(testCase, validateAST_test) {
|
|||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111");
|
||||
ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a");
|
||||
ASSERT_EQ(p1->base.colInfo.colId, 1);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "a");
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
|
||||
SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
||||
ASSERT_EQ(p2->base.uid, 0);
|
||||
ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression.
|
||||
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22");
|
||||
|
||||
// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a");
|
||||
// ASSERT_EQ(p1->base.colInfo.colId, 1);
|
||||
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p2->base.token, "a+b + 22");
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3);
|
||||
if (valid) {
|
||||
ASSERT_EQ(ret, 0);
|
||||
} else {
|
||||
ASSERT_NE(ret, 0);
|
||||
}
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test) {
|
||||
SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SMsgBuf buf;
|
||||
buf.len = 128;
|
||||
buf.buf = msg;
|
||||
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SMetaReq req = {0};
|
||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
|
||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
setTableMetaInfo(pQueryInfo, &req);
|
||||
|
||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a)");
|
||||
ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a");
|
||||
ASSERT_EQ(p1->base.colInfo.colId, 1);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
||||
ASSERT_EQ(p1->base.interBytes, 8);
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test2) {
|
||||
SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
//TEST(testCase, validateAST_test) {
|
||||
// SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where ts<now+2h and `col` < 20 + 99");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->info.colId, 110);
|
||||
// ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111");
|
||||
// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
||||
// ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "a");
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
//
|
||||
// SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
||||
// ASSERT_EQ(p2->base.pColumns->uid, 0);
|
||||
// ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression.
|
||||
// ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
// ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22");
|
||||
//
|
||||
//// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a");
|
||||
//// ASSERT_EQ(p1->base.colInfo.colId, 1);
|
||||
//// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p2->base.token, "a+b + 22");
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
//
|
||||
//TEST(testCase, function_Test) {
|
||||
// SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
// ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a)");
|
||||
// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
||||
// ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
||||
// ASSERT_EQ(p1->base.interBytes, 8);
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
//
|
||||
//TEST(testCase, function_Test2) {
|
||||
// SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
// ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc");
|
||||
// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a");
|
||||
// ASSERT_EQ(p1->base.pColumns->info.colId, 1);
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
||||
// ASSERT_EQ(p1->base.interBytes, 8);
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
//
|
||||
//TEST(testCase, function_Test3) {
|
||||
// SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 4);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
// ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)");
|
||||
// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.ts");
|
||||
// ASSERT_EQ(p1->base.pColumns->info.colId, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "first(ts)");
|
||||
// ASSERT_EQ(p1->base.interBytes, 24);
|
||||
//
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 4);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
//
|
||||
//TEST(testCase, function_Test4) {
|
||||
// SSqlInfo info1 = doGenerateAST("select _block_dist() as a1 from `t.1abc`");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
// ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
||||
//// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
|
||||
//// ASSERT_EQ(p1->base.colInfo.colId, 0);
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "_block_dist()");
|
||||
// ASSERT_EQ(p1->base.interBytes, 0);
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1);
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
|
||||
char msg[128] = {0};
|
||||
SMsgBuf buf;
|
||||
buf.len = 128;
|
||||
buf.buf = msg;
|
||||
//TEST(testCase, function_Test5) {
|
||||
// //todo select concat(concat(a, b), concat(b, a)) from `t.1abc`;
|
||||
//
|
||||
// SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`");
|
||||
// ASSERT_EQ(info1.valid, true);
|
||||
//
|
||||
// char msg[128] = {0};
|
||||
// SMsgBuf buf;
|
||||
// buf.len = 128;
|
||||
// buf.buf = msg;
|
||||
//
|
||||
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
// ASSERT_EQ(code, 0);
|
||||
//
|
||||
// SMetaReq req = {0};
|
||||
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
//
|
||||
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
// setTableMetaInfo(pQueryInfo, &req);
|
||||
//
|
||||
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
// ASSERT_EQ(ret, 0);
|
||||
//
|
||||
// SArray* pExprList = pQueryInfo->exprList;
|
||||
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
//
|
||||
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
// ASSERT_EQ(p1->base.numOfCols, 2);
|
||||
// ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
//
|
||||
// ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
||||
//
|
||||
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
// ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)");
|
||||
// ASSERT_EQ(p1->base.interBytes, 0);
|
||||
//
|
||||
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
||||
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
//
|
||||
// destroyQueryInfo(pQueryInfo);
|
||||
// qParserClearupMetaRequestInfo(&req);
|
||||
// destroySqlInfo(&info1);
|
||||
//}
|
||||
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SMetaReq req = {0};
|
||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
|
||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
setTableMetaInfo(pQueryInfo, &req);
|
||||
|
||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc");
|
||||
ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a");
|
||||
ASSERT_EQ(p1->base.colInfo.colId, 1);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "count(a)");
|
||||
ASSERT_EQ(p1->base.interBytes, 8);
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test3) {
|
||||
SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SMsgBuf buf;
|
||||
buf.len = 128;
|
||||
buf.buf = msg;
|
||||
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SMetaReq req = {0};
|
||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
|
||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
setTableMetaInfo(pQueryInfo, &req);
|
||||
|
||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 4);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)");
|
||||
ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
|
||||
ASSERT_EQ(p1->base.colInfo.colId, 0);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "first(ts)");
|
||||
ASSERT_EQ(p1->base.interBytes, 24);
|
||||
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 4);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test4) {
|
||||
SSqlInfo info1 = doGenerateAST("select _block_dist() as a1 from `t.1abc`");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SMsgBuf buf;
|
||||
buf.len = 128;
|
||||
buf.buf = msg;
|
||||
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SMetaReq req = {0};
|
||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
|
||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
setTableMetaInfo(pQueryInfo, &req);
|
||||
|
||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 1);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
||||
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
|
||||
// ASSERT_EQ(p1->base.colInfo.colId, 0);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "_block_dist()");
|
||||
ASSERT_EQ(p1->base.interBytes, 0);
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1);
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test5) {
|
||||
SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SMsgBuf buf;
|
||||
buf.len = 128;
|
||||
buf.buf = msg;
|
||||
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SMetaReq req = {0};
|
||||
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
|
||||
|
||||
SQueryStmtInfo* pQueryInfo = createQueryInfo();
|
||||
setTableMetaInfo(pQueryInfo, &req);
|
||||
|
||||
SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
|
||||
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
|
||||
ASSERT_EQ(ret, 0);
|
||||
|
||||
SArray* pExprList = pQueryInfo->exprList;
|
||||
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 0);
|
||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
||||
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
|
||||
// ASSERT_EQ(p1->base.colInfo.colId, 0);
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)");
|
||||
ASSERT_EQ(p1->base.interBytes, 0);
|
||||
|
||||
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
|
||||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
qParserClearupMetaRequestInfo(&req);
|
||||
destroySqlInfo(&info1);
|
||||
TEST(testCase, function_Test10) {
|
||||
// sqlCheck("select c from `t.1abc`", true);
|
||||
// sqlCheck("select length(c) from `t.1abc`", true);
|
||||
sqlCheck("select sum(length(a+b)) from `t.1abc`", false);
|
||||
// sqlCheck("select sum(sum(a+b)) from `t.1abc`", false);
|
||||
}
|
||||
|
||||
TEST(testCase, function_Test6) {
|
||||
|
@ -382,15 +428,15 @@ TEST(testCase, function_Test6) {
|
|||
ASSERT_EQ(taosArrayGetSize(pExprList), 5);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)");
|
||||
ASSERT_EQ(p1->base.interBytes, 16);
|
||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
|
||||
ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_SUM);
|
||||
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM);
|
||||
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
|
||||
|
||||
tExprNode* pParam = p1->pExpr->_node.pLeft;
|
||||
|
@ -404,15 +450,15 @@ TEST(testCase, function_Test6) {
|
|||
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5);
|
||||
|
||||
SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
||||
ASSERT_EQ(p2->base.uid, 110);
|
||||
ASSERT_EQ(p2->base.pColumns->uid, 110);
|
||||
ASSERT_EQ(p2->base.numOfParams, 0);
|
||||
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)");
|
||||
ASSERT_EQ(p2->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p2->base.token, "first(b*a)");
|
||||
ASSERT_EQ(p2->base.interBytes, 24);
|
||||
ASSERT_EQ(p2->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
|
||||
ASSERT_EQ(p2->pExpr->_node.functionId, FUNCTION_FIRST);
|
||||
ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST);
|
||||
ASSERT_TRUE(p2->pExpr->_node.pRight == NULL);
|
||||
|
||||
destroyQueryInfo(pQueryInfo);
|
||||
|
@ -449,15 +495,15 @@ TEST(testCase, function_Test7) {
|
|||
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 0);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a+b)");
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "count(a+b)");
|
||||
ASSERT_EQ(p1->base.interBytes, 8);
|
||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
|
||||
ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_COUNT);
|
||||
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT);
|
||||
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
|
||||
|
||||
tExprNode* pParam = p1->pExpr->_node.pLeft;
|
||||
|
@ -504,16 +550,16 @@ TEST(testCase, function_Test8) {
|
|||
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
|
||||
ASSERT_EQ(p1->base.interBytes, 16);
|
||||
|
||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
|
||||
ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_TOP);
|
||||
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
|
||||
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
|
||||
|
||||
tExprNode* pParam = p1->pExpr->_node.pLeft;
|
||||
|
|
|
@ -95,16 +95,16 @@ TEST(testCase, planner_test) {
|
|||
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
|
||||
|
||||
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
|
||||
ASSERT_EQ(p1->base.uid, 110);
|
||||
ASSERT_EQ(p1->base.pColumns->uid, 110);
|
||||
ASSERT_EQ(p1->base.numOfParams, 1);
|
||||
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
|
||||
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
|
||||
ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
|
||||
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
|
||||
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
|
||||
ASSERT_EQ(p1->base.interBytes, 16);
|
||||
|
||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
|
||||
ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_TOP);
|
||||
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
|
||||
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
|
||||
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
|
||||
|
||||
tExprNode* pParam = p1->pExpr->_node.pLeft;
|
||||
|
|
|
@ -186,7 +186,7 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe
|
|||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumn* pCol = taosArrayGetP(tableCols, i);
|
||||
SColumnIndex index = {.tableIndex = 0, .columnIndex = pCol->columnIndex};
|
||||
SColumnIndex index = {.tableIndex = 0, /*.columnIndex = pCol->columnIndex*/};
|
||||
|
||||
SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, i);
|
||||
SSchema resultSchema = *pSchema;
|
||||
|
|
Loading…
Reference in New Issue