提交 55f3ac17 编写于 作者: H Haojun Liao

[td-10564] refactor and add test cases.

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