提交 013f8fed 编写于 作者: H Haojun Liao

[td-10564] 1. Enable and then refactor the parse the nested function in...

[td-10564] 1. Enable  and then refactor the parse the nested function in select clause. 2. Add some scalar string function in function module. 3. Add more test cases.
上级 55f3ac17
......@@ -221,7 +221,7 @@ typedef struct SScalarFunctionInfo {
char name[FUNCTIONS_NAME_MAX_LENGTH];
int8_t type; // scalar function or aggregation function
uint32_t functionId; // index of scalar function
void (*process)(const struct SScalarFuncParam *pInput, struct SScalarFuncParam* pOutput);
void (*process)(struct SScalarFuncParam* pOutput, size_t numOfInput, const struct SScalarFuncParam *pInput);
} SScalarFunctionInfo;
typedef struct SMultiFunctionsDesc {
......
......@@ -80,8 +80,7 @@ typedef struct SQueryStmtInfo {
SGroupbyExpr groupbyExpr; // groupby tags info
SArray * colList; // SArray<SColumn*>
SFieldInfo fieldsInfo;
SArray * exprList; // SArray<SExprInfo*>
SArray * exprList1; // final exprlist in case of arithmetic expression exists
SArray** exprList; // SArray<SExprInfo*>
SLimit limit;
SLimit slimit;
STagCond tagCond;
......@@ -112,6 +111,7 @@ typedef struct SQueryStmtInfo {
struct SQueryStmtInfo *pDownstream;
int32_t havingFieldNum;
SMultiFunctionsDesc info;
int32_t exprListLevelIndex;
} SQueryStmtInfo;
typedef struct SColumnIndex {
......@@ -165,7 +165,7 @@ void assignExprInfo(SExprInfo* dst, const SExprInfo* src);
void columnListCopy(SArray* dst, const SArray* src, uint64_t uid);
void columnListDestroy(SArray* pColumnList);
void dropAllExprInfo(SArray* pExprInfo);
void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel);
SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SColumnIndex* pColIndex, struct tExprNode* pParamExpr, SSchema* pResSchema, int16_t interSize);
int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy);
......
......@@ -140,8 +140,9 @@ do { \
#define FUNCTION_ROUND 4503
#define FUNCTION_LENGTH 4800
#define FUNCTION_LTRIM 4801
#define FUNCTION_RTRIM 4802
#define FUNCTION_CONCAT 4801
#define FUNCTION_LTRIM 4802
#define FUNCTION_RTRIM 4803
#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))
......
......@@ -12,10 +12,11 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <function.h>
#include "os.h"
#include "ttime.h"
#include "taosmsg.h"
#include "tglobal.h"
#include "ttime.h"
#include "exception.h"
#include "executorimpl.h"
......@@ -161,7 +162,7 @@ int64_t genQueryId(void) {
static int32_t getExprFunctionId(SExprInfo *pExprInfo) {
assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE);
return pExprInfo->pExpr->_node.functionId;
return pExprInfo->pExpr->_function.functionId;
}
static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
......@@ -1069,6 +1070,7 @@ void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlo
}
static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
#if 0
for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
pCtx[i].order = order;
pCtx[i].size = pBlock->info.rows;
......@@ -1079,7 +1081,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx,
if (pCtx[i].functionId == FUNCTION_ARITHM) {
// setArithParams((SScalarFunctionSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock);
} else {
SColIndex* pCol = &pOperator->pExpr[i].base.colInfo;
SColIndex* pCol = &pOperator->pExpr[i].base.pColumns->info.;
if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || (pCtx[i].functionId == FUNCTION_BLKINFO) ||
(TSDB_COL_IS_TAG(pCol->flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo;
......@@ -1087,7 +1089,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx,
// in case of the block distribution query, the inputBytes is not a constant value.
pCtx[i].pInput = p->pData;
assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);
assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type);
if (pCtx[i].functionId < 0) {
SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
......@@ -1112,7 +1114,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx,
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
pCtx[i].pInput = p->pData;
assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);
assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type);
for(int32_t j = 0; j < pBlock->info.rows; ++j) {
char* dst = p->pData + j * p->info.bytes;
taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
......@@ -1120,6 +1122,8 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx,
}
}
}
#endif
}
static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) {
......@@ -1170,11 +1174,11 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo,
continue;
}
SColIndex * pColIndex = &pExpr[k].base.colInfo;
SColIndex * pColIndex = NULL/*&pExpr[k].base.colInfo*/;
int16_t index = pColIndex->colIndex;
SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index);
assert(pColInfo->info.colId == pColIndex->colId && curTs != windowKey);
// assert(pColInfo->info.colId == pColIndex->info.colId && curTs != windowKey);
double v1 = 0, v2 = 0, v = 0;
if (prevRowIndex == -1) {
......@@ -1858,7 +1862,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr
for (int32_t i = 0; i < numOfOutput; ++i) {
SSqlExpr *pSqlExpr = &pExpr[i].base;
SQLFunctionCtx* pCtx = &pFuncCtx[i];
#if 0
SColIndex *pIndex = &pSqlExpr->colInfo;
if (TSDB_COL_REQ_NULL(pIndex->flag)) {
......@@ -1867,7 +1871,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr
} else {
pCtx->requireNull = false;
}
#endif
// pCtx->inputBytes = pSqlExpr->colBytes;
// pCtx->inputType = pSqlExpr->colType;
......@@ -2359,7 +2363,7 @@ bool onlyQueryTags(SQueryAttr* pQueryAttr) {
if (functionId != FUNCTION_TAGPRJ &&
functionId != FUNCTION_TID_TAG &&
(!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX)) &&
(!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX)) &&
(!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.pColumns->flag)))) {
return false;
}
......@@ -2879,7 +2883,7 @@ static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSData
int32_t numOfOutput = pTableScanInfo->numOfOutput;
for (int32_t i = 0; i < numOfOutput; ++i) {
int32_t functionId = pCtx[i].functionId;
int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->colId;
int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->info.colId;
// group by + first/last should not apply the first/last block filter
if (functionId < 0) {
......@@ -3211,7 +3215,7 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCt
}
// todo use tag column index to optimize performance
doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type,
doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->info.colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type,
pLocalExprInfo->base.resSchema.bytes);
if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type)
......@@ -3787,7 +3791,7 @@ void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx
int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
for (int32_t k = 0; k < numOfCols; ++k) {
SStddevInterResult* pres = taosArrayGet(p->pResult, k);
if (pres->colId == pExpr->colInfo.colId) {
if (pres->info.colId == pExpr->colInfo.colId) {
pCtx[i].param[0].arr = pres->pResult;
break;
}
......@@ -3819,7 +3823,7 @@ void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunction
int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
for (int32_t k = 0; k < numOfCols; ++k) {
SStddevInterResult* pres = taosArrayGet(p->pResult, k);
if (pres->colId == pExpr1->colInfo.colId) {
if (pres->info.colId == pExpr1->colInfo.colId) {
pCtx[i].param[0].arr = pres->pResult;
break;
}
......@@ -5041,7 +5045,7 @@ SArray* getOrderCheckColumns(SQueryAttr* pQuery) {
SSqlExpr* pExpr = &pQuery->pExpr1[j].base;
int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]);
if (index->colId == pExpr->colInfo.colId &&
if (index->colId == pExpr->pColumns->info.colId &&
(functionId == FUNCTION_PRJ || functionId == FUNCTION_TAG || functionId == FUNCTION_TS)) {
index->colIndex = j;
index->colId = pExpr->resSchema.colId;
......@@ -5073,8 +5077,8 @@ SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) {
// FUNCTION_TAG_DUMMY function needs to be ignored
if (index->colId == pExpr->pColumns->info.colId &&
((TSDB_COL_IS_TAG(pExpr->colInfo.flag) && functionId == FUNCTION_TAG) ||
(TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && functionId == FUNCTION_PRJ))) {
((TSDB_COL_IS_TAG(pExpr->pColumns->flag) && functionId == FUNCTION_TAG) ||
(TSDB_COL_IS_NORMAL_COL(pExpr->pColumns->flag) && functionId == FUNCTION_PRJ))) {
index->colIndex = j;
index->colId = pExpr->resSchema.colId;
found = true;
......@@ -5291,7 +5295,7 @@ SOperatorInfo *createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
pDataBlock->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
for(int32_t i = 0; i < numOfOutput; ++i) {
SColumnInfoData col = {{0}};
col.info.colId = pExpr[i].base.pColumns->colId;
col.info.colId = pExpr[i].base.pColumns->info.colId;
// col.info.bytes = pExpr[i].base.colBytes;
// col.info.type = pExpr[i].base.colType;
taosArrayPush(pDataBlock->pDataBlock, &col);
......@@ -6777,7 +6781,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
int16_t type = pExprInfo->base.resSchema.type;
for(int32_t i = 0; i < pQueryAttr->numOfTags; ++i) {
if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->colId) {
if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->info.colId) {
bytes = pQueryAttr->tagColList[i].bytes;
type = pQueryAttr->tagColList[i].type;
break;
......@@ -6809,10 +6813,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
output += sizeof(pQueryAttr->vgId);
char* data = NULL;
if (pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) {
if (pExprInfo->base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) {
data = tsdbGetTableName(item->pTable);
} else {
data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->colId, type, bytes);
data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->info.colId, type, bytes);
}
doSetTagValueToResultBuf(output, data, type, bytes);
......@@ -6848,10 +6852,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
type = pExprInfo[j].base.resSchema.type;
bytes = pExprInfo[j].base.resSchema.bytes;
if (pExprInfo[j].base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) {
if (pExprInfo[j].base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) {
data = tsdbGetTableName(item->pTable);
} else {
data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->colId, type, bytes);
data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->info.colId, type, bytes);
}
dst = pColInfo->pData + count * pExprInfo[j].base.resSchema.bytes;
......@@ -7047,20 +7051,20 @@ SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperat
static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
int32_t j = 0;
if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
if (TSDB_COL_IS_TAG(pExpr->pColumns->flag)) {
if (pExpr->pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) {
return TSDB_TBNAME_COLUMN_INDEX;
}
while(j < pTableInfo->numOfTags) {
if (pExpr->colInfo.colId == pTagCols[j].colId) {
if (pExpr->pColumns->info.colId == pTagCols[j].colId) {
return j;
}
j += 1;
}
} else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) { // user specified column data
} /*else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) { // user specified column data
return TSDB_UD_COLUMN_INDEX;
} else {
while (j < pTableInfo->numOfCols) {
......@@ -7070,7 +7074,7 @@ static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *p
j += 1;
}
}
}*/
return INT32_MIN; // return a less than TSDB_TBNAME_COLUMN_INDEX value
}
......@@ -7815,7 +7819,7 @@ int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t nu
// bytes = tDataTypes[type].bytes;
// } else {
// int32_t index = pExprs[i].base.colInfo.colIndex;
// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->colId);
// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->info.colId);
//
// type = prevExpr[index].base.resSchema.type;
// bytes = prevExpr[index].base.resSchema.bytes;
......@@ -7951,7 +7955,7 @@ static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) {
// }
// todo opt performance
SColIndex *pColIndex = &pSqlExprMsg->colInfo;
SColIndex *pColIndex = NULL;/*&pSqlExprMsg->colInfo;*/
if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
int32_t f = 0;
for (f = 0; f < pQueryAttr->numOfCols; ++f) {
......
......@@ -37,7 +37,7 @@ typedef struct SScalarFunctionSupport {
char** data;
} SScalarFunctionSupport;
extern struct SScalarFunctionInfo scalarFunc[5];
extern struct SScalarFunctionInfo scalarFunc[8];
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput,
void* param, char* (*getSourceDataBlock)(void*, const char*, int32_t));
......
......@@ -9,8 +9,9 @@ static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScal
dst->num = src->num;
}
static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
static void tceil(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assignBasicParaInfo(pOutput, pLeft);
assert(numOfInput == 1);
switch (pLeft->bytes) {
case TSDB_DATA_TYPE_FLOAT: {
......@@ -34,8 +35,9 @@ static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
}
}
static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
static void tfloor(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assignBasicParaInfo(pOutput, pLeft);
assert(numOfInput == 1);
switch (pLeft->bytes) {
case TSDB_DATA_TYPE_FLOAT: {
......@@ -61,8 +63,9 @@ static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
}
}
static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
static void _tabs(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assignBasicParaInfo(pOutput, pLeft);
assert(numOfInput == 1);
switch (pLeft->bytes) {
case TSDB_DATA_TYPE_FLOAT: {
......@@ -118,8 +121,9 @@ static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
}
}
static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
static void tround(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assignBasicParaInfo(pOutput, pLeft);
assert(numOfInput == 1);
switch (pLeft->bytes) {
case TSDB_DATA_TYPE_FLOAT: {
......@@ -143,7 +147,9 @@ static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
}
}
static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
static void tlength(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assert(numOfInput == 1);
int64_t* out = (int64_t*) pOutput->data;
char* s = pLeft->data;
......@@ -152,6 +158,46 @@ static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) {
}
}
static void tconcat(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
assert(numOfInput > 0);
int32_t rowLen = 0;
int32_t num = 1;
for(int32_t i = 0; i < numOfInput; ++i) {
rowLen += pLeft[i].bytes;
if (pLeft[i].num > 1) {
num = pLeft[i].num;
}
}
pOutput->data = realloc(pOutput->data, rowLen * num);
assert(pOutput->data);
char* rstart = pOutput->data;
for(int32_t i = 0; i < num; ++i) {
char* s = rstart;
varDataSetLen(s, 0);
for (int32_t j = 0; j < numOfInput; ++j) {
char* p1 = POINTER_SHIFT(pLeft[j].data, i * pLeft[j].bytes);
memcpy(varDataVal(s) + varDataLen(s), varDataVal(p1), varDataLen(p1));
varDataLen(s) += varDataLen(p1);
}
rstart += rowLen;
}
}
static void tltrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
}
static void trtrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
}
static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) {
switch(type) {
case TSDB_DATA_TYPE_TINYINT:
......@@ -256,7 +302,6 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa
_bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(pExprs->_node.optr);
SScalarFuncParam left = {0}, right = {0};
if (pLeft->nodeType == TEXPR_BINARYEXPR_NODE || pLeft->nodeType == TEXPR_UNARYEXPR_NODE) {
setScalarFuncParam(&left, leftOutput.type, leftOutput.bytes, leftOutput.data, leftOutput.num);
} else if (pLeft->nodeType == TEXPR_COL_NODE) {
......@@ -318,12 +363,15 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa
return 0;
}
SScalarFunctionInfo scalarFunc[5] = {
SScalarFunctionInfo scalarFunc[8] = {
{"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},
{"concat", FUNCTION_TYPE_SCALAR, FUNCTION_CONCAT, tconcat},
{"ltrim", FUNCTION_TYPE_SCALAR, FUNCTION_LTRIM, tltrim},
{"rtrim", FUNCTION_TYPE_SCALAR, FUNCTION_RTRIM, trtrim},
};
void setScalarFunctionSupp(struct SScalarFunctionSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
......
......@@ -31,7 +31,7 @@ SSchema *getTableTagSchema(const STableMeta* pTableMeta);
size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo);
SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema);
void addExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index, SExprInfo* pExprInfo);
void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level);
void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize);
SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index);
......
......@@ -202,7 +202,6 @@ SQueryStmtInfo *createQueryInfo() {
SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo));
pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField));
pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX;
pQueryInfo->limit.limit = -1;
......@@ -213,6 +212,13 @@ SQueryStmtInfo *createQueryInfo() {
pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->window = TSWINDOW_INITIALIZER;
pQueryInfo->exprList = calloc(10, POINTER_BYTES);
for(int32_t i = 0; i < 10; ++i) {
pQueryInfo->exprList[i] = taosArrayInit(4, POINTER_BYTES);
}
pQueryInfo->exprListLevelIndex = 0;
return pQueryInfo;
}
......@@ -221,14 +227,9 @@ static void destroyQueryInfoImpl(SQueryStmtInfo* pQueryInfo) {
cleanupColumnCond(&pQueryInfo->colCond);
cleanupFieldInfo(&pQueryInfo->fieldsInfo);
dropAllExprInfo(pQueryInfo->exprList);
dropAllExprInfo(pQueryInfo->exprList, 10);
pQueryInfo->exprList = NULL;
if (pQueryInfo->exprList1 != NULL) {
dropAllExprInfo(pQueryInfo->exprList1);
pQueryInfo->exprList1 = NULL;
}
columnListDestroy(pQueryInfo->colList);
pQueryInfo->colList = NULL;
......@@ -1707,18 +1708,27 @@ void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* f
}
}
SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) {
assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10);
return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex];
}
SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, SColumnIndex* pIndex,
SSchema* pColSchema, SSchema* pResultSchema, tExprNode* pExprNode, int32_t interSize, const char* token, bool finalResult) {
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex);
SExprInfo* pExpr = createExprInfo(pTableMetaInfo, functionId, pIndex, pExprNode, pResultSchema, interSize);
addExprInfo(pQueryInfo, outputColIndex, pExpr);
SArray* pExprList = getCurrentExprList(pQueryInfo);
addExprInfo(pExprList, outputColIndex, pExpr, pQueryInfo->exprListLevelIndex);
tstrncpy(pExpr->base.token, token, sizeof(pExpr->base.token));
uint64_t uid = pTableMetaInfo->pTableMeta->uid;
SArray* p = TSDB_COL_IS_TAG(pIndex->type)?pTableMetaInfo->tagColList:pQueryInfo->colList;
columnListInsert(p, uid, pColSchema, pIndex->type);
if (pIndex->columnIndex != COLUMN_INDEX_INITIAL_VAL) {
SArray* p = TSDB_COL_IS_TAG(pIndex->type) ? pTableMetaInfo->tagColList : pQueryInfo->colList;
columnListInsert(p, uid, pColSchema, pIndex->type);
}
pExpr->base.pColumns->flag = pIndex->type;
if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) {
......@@ -1792,7 +1802,8 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab
SExprInfo* pExpr = createExprInfo(pTableMetaInfo, FUNCTION_TS_DUMMY, &indexTS, NULL, &s, TSDB_KEYSIZE);
strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token));
addExprInfo(pQueryInfo, outputIndex, pExpr);
SArray* pExprList = getCurrentExprList(pQueryInfo);
addExprInfo(pExprList, outputIndex, pExpr, pQueryInfo->exprListLevelIndex);
SSchema* pSourceSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, indexTS.columnIndex);
columnListInsert(pQueryInfo->colList, pTableMetaInfo->pTableMeta->uid, pSourceSchema, TSDB_COL_NORMAL);
......@@ -1900,8 +1911,9 @@ static int32_t doHandleOneParam(SQueryStmtInfo *pQueryInfo, tSqlExprItem* pItem,
static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf);
static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf);
int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema,
tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) {
int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo,
SSchema* columnSchema, tExprNode** pNode, SColumnIndex* pIndex,
tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) {
const char* msg1 = "not support column types";
const char* msg2 = "invalid parameters";
const char* msg3 = "illegal column name";
......@@ -1926,11 +1938,20 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
return buildInvalidOperationMsg(pMsgBuf, msg6);
}
int32_t code = createComplexExpr(pQueryInfo, i, pParamElem, pMsgBuf);
SArray* pExprList = getCurrentExprList(pQueryInfo);
size_t n = taosArrayGetSize(pExprList);
// todo extract the table uid
pIndex->tableIndex = 0;
int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
SExprInfo** pLastExpr = taosArrayGetLast(pExprList);
*pNode = (*pLastExpr)->pExpr;
*(SSchema*) columnSchema = (*pLastExpr)->base.resSchema;
*pTableMetaInfo = getMetaInfo(pQueryInfo, 0);
} else {
if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) {
return buildInvalidOperationMsg(pMsgBuf, msg3);
......@@ -1945,36 +1966,20 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
*pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex);
*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;
SArray* pColumnList = taosArrayInit(4, sizeof(SColumn));
if (validateComplexExpr(pParamElem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
}
} else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) {
pIndex->tableIndex = 0; // todo set the correct table index
if (arithmeticType != NORMAL_ARITHMETIC) {
return buildInvalidOperationMsg(pMsgBuf, msg4);
}
*pTableMetaInfo = getMetaInfo(pQueryInfo, 0); // todo get the first table meta.
*columnSchema = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), "");
SToken* pExprToken = &pParamElem->pNode->exprToken;
int32_t len = MIN(TSDB_COL_NAME_LEN, pExprToken->n + 1);
tstrncpy(columnSchema->name, pExprToken->z, len);
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
taosArrayDestroy(colList);
tExprTreeDestroy(*pNode, NULL);
return buildInvalidOperationMsg(pMsgBuf, msg2);
SArray* pExprList = getCurrentExprList(pQueryInfo);
size_t n = taosArrayGetSize(pExprList);
int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pIndex->tableIndex = 0;
multiColumnListInsert(pQueryInfo, pColumnList, pMsgBuf);
taosArrayDestroy(colList);
taosArrayDestroy(pColumnList);
SExprInfo** pLastExpr = taosArrayGetLast(getCurrentExprList(pQueryInfo));
*pNode = (*pLastExpr)->pExpr;
*(SSchema*) columnSchema = (*pLastExpr)->base.resSchema;
*pTableMetaInfo = getMetaInfo(pQueryInfo, 0);
} else {
assert(0);
}
......@@ -1997,7 +2002,7 @@ static int32_t checkForkParam(tSqlExpr* pSqlExpr, size_t k, SMsgBuf* pMsgBuf) {
return TSDB_CODE_SUCCESS;
}
int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult, SMsgBuf* pMsgBuf) {
int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult, SMsgBuf* pMsgBuf) {
STableMetaInfo* pTableMetaInfo = NULL;
int32_t functionId = pItem->functionId;
int32_t code = TSDB_CODE_SUCCESS;
......@@ -2071,12 +2076,15 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);
tExprNode* pNode = NULL;
int32_t tokenId = pParamElem->pNode->tokenId;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
tExprNode* pNode = NULL;
int32_t tokenId = pParamElem->pNode->tokenId;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
SSchema columnSchema = {0};
code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem,pMsgBuf);
pQueryInfo->exprListLevelIndex += 1;
code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem, pMsgBuf);
pQueryInfo->exprListLevelIndex -= 1;
if (code != TSDB_CODE_SUCCESS) {
return code;
}
......@@ -2440,23 +2448,31 @@ static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr
}
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;
}
if (scalar) {
printf("scalar function found!\n");
// if (createComplexExpr(pQueryInfo, outputIndex, &item, pMsgBuf) != TSDB_CODE_SUCCESS) {
// return TSDB_CODE_TSC_INVALID_OPERATION;
// }
} else {
if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) {
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) {
// 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;
......@@ -2480,7 +2496,6 @@ int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) {
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;
......@@ -2491,6 +2506,7 @@ int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr,
int32_t type = pSqlExpr->type;
if (type == SQL_NODE_VALUE) {
// do nothing for scalar function, or maybe the evaluation can be done here
} else if (type == SQL_NODE_SQLFUNCTION) {
code = validateExprLeafFunctionNode(pQueryInfo, pSqlExpr, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
......@@ -2785,45 +2801,95 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
tExprNode* pLeft = NULL;
tExprNode* pRight= NULL;
if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
// assert it is a scalar function
*pExpr = calloc(1, sizeof(tExprNode));
(*pExpr)->nodeType = TEXPR_FUNCTION_NODE;
(*pExpr)->_function.num = 1;
(*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n);
SArray* pParamList = pSqlExpr->Expr.paramList;
size_t num = taosArrayGetSize(pParamList);
(*pExpr)->_function.pChild = calloc(num, POINTER_BYTES);
// 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;
// }
for(int32_t i = 0; i < num; ++i) {
tSqlExprItem* pItem = taosArrayGet(pParamList, i);
sqlExprToExprNode(&(((*pExpr)->_function.pChild)[0]), pItem->pNode, pQueryInfo, pCols, pMsgBuf);
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (pSqlExpr->type == SQL_NODE_EXPR) {
if (pSqlExpr->pLeft != NULL) {
int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
}
return TSDB_CODE_SUCCESS;
}
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (pSqlExpr->pLeft != NULL) {
int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
if (pSqlExpr->pRight != NULL) {
int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
tExprTreeDestroy(pLeft, NULL);
return ret;
}
}
}
if (pSqlExpr->pRight != NULL) {
int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
tExprTreeDestroy(pLeft, NULL);
return ret;
if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) {
*pExpr = calloc(1, sizeof(tExprNode));
return TSDB_CODE_SUCCESS;
}
}
} else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
SArray* pParamList = pSqlExpr->Expr.paramList;
if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) {
*pExpr = calloc(1, sizeof(tExprNode));
return TSDB_CODE_SUCCESS;
}
if (pParamList != NULL && taosArrayGetSize(pParamList) > 0) {
size_t num = taosArrayGetSize(pParamList);
tExprNode** p = calloc(num, POINTER_BYTES);
pQueryInfo->exprListLevelIndex += 1;
for(int32_t i = 0; i < num; ++i) {
tSqlExprItem* pItem = taosArrayGet(pParamList, i);
int32_t code = sqlExprToExprNode(&p[i], pItem->pNode, pQueryInfo, pCols, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
}
pQueryInfo->exprListLevelIndex -= 1;
bool scalar = false;
int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar);
if (functionId < 0) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo);
if (scalar) {
printf("scalar function found! %s\n", pSqlExpr->exprToken.z);
// Expression on the results of aggregation functions
*pExpr = calloc(1, sizeof(tExprNode));
(*pExpr)->nodeType = TEXPR_FUNCTION_NODE;
(*pExpr)->_function.pChild = p;
(*pExpr)->_function.functionId = functionId;
(*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n + 1);
return TSDB_CODE_SUCCESS;
} else {
printf("agg function found, %s\n", pSqlExpr->exprToken.z);
tSqlExprItem item = {.pNode = (tSqlExpr*)pSqlExpr, .aliasName = NULL, .functionId = functionId};
if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// convert the aggregate function to be the input data columns for the outer function.
}
}
}
if (pSqlExpr->pLeft == NULL) { // it is the leaf node
assert(pSqlExpr->pRight == NULL);
......@@ -2856,12 +2922,13 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
strncpy((*pExpr)->pSchema->name, pSqlExpr->exprToken.z, pSqlExpr->exprToken.n);
// set the input column data byte and type.
size_t size = taosArrayGetSize(pQueryInfo->exprList);
SArray* pExprList = getCurrentExprList(pQueryInfo);
size_t size = taosArrayGetSize(pExprList);
bool found = false;
uint64_t uid = 0;
for (int32_t i = 0; i < size; ++i) {
SExprInfo* p1 = taosArrayGetP(pQueryInfo->exprList, i);
SExprInfo* p1 = taosArrayGetP(pExprList, i);
if (strcmp((*pExpr)->pSchema->name, p1->base.resSchema.name) == 0) {
memcpy((*pExpr)->pSchema, &p1->base.resSchema, sizeof(SSchema));
......@@ -2982,9 +3049,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
int32_t arithmeticType = NON_ARITHMEIC_EXPR;
SArray* pColumnList = taosArrayInit(4, sizeof(SColumn));
if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
}
// if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) {
// return buildInvalidOperationMsg(pMsgBuf, msg1);
// }
if (arithmeticType == NORMAL_ARITHMETIC) {
// expr string is set as the parameter of function
......@@ -2999,8 +3066,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
return buildInvalidOperationMsg(pMsgBuf, msg2);
}
SExprInfo* pExpr = createBinaryExprInfo(pNode, &s);
addExprInfo(pQueryInfo, exprIndex, pExpr);
SExprInfo* pExpr = createBinaryExprInfo(pNode, &s);
SArray* pExprList = getCurrentExprList(pQueryInfo);
addExprInfo(pExprList, exprIndex, pExpr, pQueryInfo->exprListLevelIndex);
setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN);
// check for if there is a tag in the arithmetic express
......@@ -3026,7 +3094,11 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
// set the serialized binary string as the parameter of arithmetic expression
addExprInfoParam(&pExpr->base, c, TSDB_DATA_TYPE_BINARY, (int32_t)len);
addResColumnInfo(pQueryInfo, exprIndex, &pExpr->base.resSchema, pExpr);
// Need to be added to the final result list.
if (pQueryInfo->exprListLevelIndex == 0) {
addResColumnInfo(pQueryInfo, exprIndex, &pExpr->base.resSchema, pExpr);
}
tbufCloseWriter(&bw);
taosArrayDestroy(colList);
......@@ -3043,8 +3115,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex,
return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause");
}
SExprInfo* pExpr = createBinaryExprInfo(pNode, &s);
addExprInfo(pQueryInfo, exprIndex, pExpr);
SExprInfo* pExpr = createBinaryExprInfo(pNode, &s);
SArray* pExprList = getCurrentExprList(pQueryInfo);
addExprInfo(pExprList, exprIndex, pExpr, pQueryInfo->exprListLevelIndex);
setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN);
......@@ -3099,7 +3172,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
size_t numOfExpr = taosArrayGetSize(pSelNodeList);
for (int32_t i = 0; i < numOfExpr; ++i) {
int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo);
int32_t outputIndex = (int32_t) getNumOfExprs(pQueryInfo);
tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i);
int32_t type = pItem->pNode->type;
......@@ -3111,9 +3184,8 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
pQueryInfo->info.distinct = true;
}
bool scalarFunc = false;
if (type == SQL_NODE_SQLFUNCTION) {
bool scalarFunc = false;
pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &scalarFunc);
if (pItem->functionId == FUNCTION_INVALID_ID) {
int32_t functionId = FUNCTION_INVALID_ID;
......@@ -3123,15 +3195,17 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
}
pItem->functionId = functionId;
} else if (scalarFunc) {
if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
}
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
if ((code = addExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
if (scalarFunc) { // scalar function
if ((code = createComplexExpr(pQueryInfo, outputIndex, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
} else { // aggregate function
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
if ((code = addAggExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
}
} else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) {
// use the dynamic array list to decide if the function is valid or not
......@@ -3654,7 +3728,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
validateSqlNode(p, pQueryInfo, &buf);
}
SArray* functionList = extractFunctionIdList(pQueryInfo->exprList);
SArray* functionList = extractFunctionIdList(pQueryInfo->exprList[0]);
extractFunctionDesc(functionList, &pQueryInfo->info);
if ((code = checkForInvalidExpr(pQueryInfo, &buf)) != TSDB_CODE_SUCCESS) {
......
......@@ -19,7 +19,7 @@ SSchema* getTbnameColumnSchema() {
}
size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo) {
return taosArrayGetSize(pQueryInfo->exprList);
return taosArrayGetSize(pQueryInfo->exprList[0]);
}
SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
......@@ -104,7 +104,6 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
if (pParamExpr != NULL) {
pExpr->pExpr = createFunctionExprNode(functionId, NULL, pParamExpr, 1);
// pExpr->base.pColumns
// todo set the correct number of columns
} else if (pColIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
assert(pParamExpr == NULL);
......@@ -140,15 +139,17 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
return pExpr;
}
void addExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index, SExprInfo* pExprInfo) {
assert(pQueryInfo != NULL && pQueryInfo->exprList != NULL);
void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level) {
assert(pExprList != NULL );
int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList);
int32_t num = (int32_t) taosArrayGetSize(pExprList);
if (index == num) {
taosArrayPush(pQueryInfo->exprList, &pExprInfo);
taosArrayPush(pExprList, &pExprInfo);
} else {
taosArrayInsert(pQueryInfo->exprList, index, &pExprInfo);
taosArrayInsert(pExprList, index, &pExprInfo);
}
printf("add function, id:%d, level:%d\n", pExprInfo->pExpr->_function.functionId, level);
}
void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize) {
......@@ -176,10 +177,10 @@ void destroyExprInfo(SExprInfo* pExprInfo) {
tfree(pExprInfo);
}
void dropAllExprInfo(SArray* pExprInfo) {
static void dropOneLevelExprInfo(SArray* pExprInfo) {
size_t size = taosArrayGetSize(pExprInfo);
for(int32_t i = 0; i < size; ++i) {
for (int32_t i = 0; i < size; ++i) {
SExprInfo* pExpr = taosArrayGetP(pExprInfo, i);
destroyExprInfo(pExpr);
}
......@@ -187,6 +188,12 @@ void dropAllExprInfo(SArray* pExprInfo) {
taosArrayDestroy(pExprInfo);
}
void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel) {
for(int32_t i = 0; i < numOfLevel; ++i) {
dropOneLevelExprInfo(pExprInfo[i]);
}
}
void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) {
assert (pExpr != NULL || argument != NULL || bytes != 0);
......
......@@ -70,7 +70,7 @@ static SKeyword keywordTable[] = {
{"STAR", TK_STAR},
{"SLASH", TK_SLASH},
{"REM ", TK_REM},
{"CONCAT", TK_CONCAT},
{"||", TK_CONCAT},
{"UMINUS", TK_UMINUS},
{"UPLUS", TK_UPLUS},
{"BITNOT", TK_BITNOT},
......
......@@ -46,7 +46,7 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) {
SName* name = (SName*)taosArrayGet(req->pTableName, 0);
memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName));
pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 4 * sizeof(SSchema));
pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 6 * sizeof(SSchema));
strcpy(pTableMetaInfo->aliasName, name->tname);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
pTableMeta->tableType = TSDB_NORMAL_TABLE;
......@@ -99,6 +99,7 @@ void sqlCheck(const char* sql, bool valid) {
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
}
//TEST(testCase, validateAST_test) {
......@@ -125,7 +126,7 @@ void sqlCheck(const char* sql, bool valid) {
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -183,7 +184,7 @@ void sqlCheck(const char* sql, bool valid) {
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -229,7 +230,7 @@ void sqlCheck(const char* sql, bool valid) {
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -275,7 +276,7 @@ void sqlCheck(const char* sql, bool valid) {
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 4);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -320,7 +321,7 @@ void sqlCheck(const char* sql, bool valid) {
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -369,7 +370,7 @@ void sqlCheck(const char* sql, bool valid) {
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
// ASSERT_EQ(ret, 0);
//
// SArray* pExprList = pQueryInfo->exprList;
// SArray* pExprList = pQueryInfo->exprList[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
......@@ -395,236 +396,242 @@ void sqlCheck(const char* sql, bool valid) {
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(length(a+b)) from `t.1abc`", true);
// sqlCheck("select sum(sum(a+b)) from `t.1abc`", false);
// sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true);
// sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true);
// sqlCheck("select sum(length(sum(a))) from `t.1abc`", true);
sqlCheck("select concat(a,b) from `t.1abc`", true);
// sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true);
// sqlCheck("select length(length(length(a))) from `t.1abc`", true);
}
TEST(testCase, function_Test6) {
SSqlInfo info1 = doGenerateAST("select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)");
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), 5);
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_DOUBLE);
ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)");
ASSERT_EQ(p1->base.interBytes, 16);
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM);
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
tExprNode* pParam = p1->pExpr->_node.pLeft;
ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD);
ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE);
ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE);
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5);
SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1);
ASSERT_EQ(p2->base.pColumns->uid, 110);
ASSERT_EQ(p2->base.numOfParams, 0);
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)");
ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ(p2->base.token, "first(b*a)");
ASSERT_EQ(p2->base.interBytes, 24);
ASSERT_EQ(p2->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST);
ASSERT_TRUE(p2->pExpr->_node.pRight == NULL);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
TEST(testCase, function_Test7) {
SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)");
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), 2);
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+b)");
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ(p1->base.token, "count(a+b)");
ASSERT_EQ(p1->base.interBytes, 8);
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT);
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
tExprNode* pParam = p1->pExpr->_node.pLeft;
ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD);
ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE);
ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE);
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
TEST(testCase, function_Test8) {
SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
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), 2);
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
ASSERT_EQ(p1->base.pColumns->uid, 110);
ASSERT_EQ(p1->base.numOfParams, 1);
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
ASSERT_EQ(p1->base.interBytes, 16);
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
tExprNode* pParam = p1->pExpr->_node.pLeft;
ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE);
ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
TEST(testCase, invalid_sql_Test) {
char msg[128] = {0};
SMsgBuf buf;
buf.len = 128;
buf.buf = msg;
SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)");
ASSERT_EQ(info1.valid, true);
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_NE(ret, 0);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
//===============================================================================================================
info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)");
ASSERT_EQ(info1.valid, true);
pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
ASSERT_EQ(code, 0);
ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
ASSERT_EQ(ret, 0);
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
pQueryInfo = createQueryInfo();
setTableMetaInfo(pQueryInfo, &req);
pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
ASSERT_NE(ret, 0);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
\ No newline at end of file
//TEST(testCase, function_Test6) {
// SSqlInfo info1 = doGenerateAST("select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)");
// 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[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 5);
//
// 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_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)");
// ASSERT_EQ(p1->base.interBytes, 16);
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5);
//
// SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1);
// ASSERT_EQ(p2->base.pColumns->uid, 110);
// ASSERT_EQ(p2->base.numOfParams, 0);
// ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)");
// ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p2->base.token, "first(b*a)");
// ASSERT_EQ(p2->base.interBytes, 24);
// ASSERT_EQ(p2->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST);
// ASSERT_TRUE(p2->pExpr->_node.pRight == NULL);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test7) {
// SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)");
// 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[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 2);
//
// 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+b)");
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "count(a+b)");
// ASSERT_EQ(p1->base.interBytes, 8);
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test8) {
// SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
// 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[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 2);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
// ASSERT_EQ(p1->base.pColumns->uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 1);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.interBytes, 16);
//
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, invalid_sql_Test) {
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)");
// ASSERT_EQ(info1.valid, true);
//
// 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_NE(ret, 0);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
////===============================================================================================================
// info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)");
// ASSERT_EQ(info1.valid, true);
//
// pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
// ASSERT_NE(ret, 0);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
\ No newline at end of file
......@@ -66,65 +66,65 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) {
}
}
TEST(testCase, planner_test) {
SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
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), 2);
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
ASSERT_EQ(p1->base.pColumns->uid, 110);
ASSERT_EQ(p1->base.numOfParams, 1);
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
ASSERT_EQ(p1->base.interBytes, 16);
ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
tExprNode* pParam = p1->pExpr->_node.pLeft;
ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE);
ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
struct SQueryPlanNode* n = nullptr;
code = qCreateQueryPlan(pQueryInfo, &n);
char* str = NULL;
qQueryPlanToString(n, &str);
printf("%s\n", str);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
destroySqlInfo(&info1);
}
\ No newline at end of file
//TEST(testCase, planner_test) {
// SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)");
// 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[0];
// ASSERT_EQ(taosArrayGetSize(pExprList), 2);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
// ASSERT_EQ(p1->base.pColumns->uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 1);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.interBytes, 16);
//
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE);
// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
//
// struct SQueryPlanNode* n = nullptr;
// code = qCreateQueryPlan(pQueryInfo, &n);
//
// char* str = NULL;
// qQueryPlanToString(n, &str);
// printf("%s\n", str);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
\ No newline at end of file
......@@ -226,9 +226,9 @@ static SQueryPlanNode* doCreateQueryPlanForOneTableImpl(SQueryStmtInfo* pQueryIn
}
if (pQueryInfo->havingFieldNum > 0 || pQueryInfo->info.arithmeticOnAgg) {
int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1);
pNode =
createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, info, NULL);
// int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1);
// pNode =
// createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, info, NULL);
}
if (pQueryInfo->fillType != TSDB_FILL_NONE) {
......@@ -292,7 +292,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) {
SArray* exprList = taosArrayInit(4, POINTER_BYTES);
if (copyExprInfoList(exprList, pQueryInfo->exprList, uid, true) != 0) {
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
dropAllExprInfo(exprList);
// dropAllExprInfo(exprList);
exit(-1);
}
......@@ -308,7 +308,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) {
// 4. add the projection query node
SQueryPlanNode* pNode = doAddTableColumnNode(pQueryInfo, pTableMetaInfo, &info, exprList, tableColumnList);
columnListDestroy(tableColumnList);
dropAllExprInfo(exprList);
// dropAllExprInfo(exprList);
taosArrayPush(upstream, &pNode);
}
......@@ -316,7 +316,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) {
SQueryTableInfo info = {0};
int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList);
SQueryPlanNode* pNode = createQueryNode(QNODE_JOIN, "Join", upstream->pData, pQueryInfo->numOfTables,
pQueryInfo->exprList->pData, num, &info, NULL);
pQueryInfo->exprList[0]->pData, num, &info, NULL);
// 4. add the aggregation or projection execution node
pNode = doCreateQueryPlanForOneTableImpl(pQueryInfo, pNode, &info, pQueryInfo->exprList);
......@@ -338,7 +338,7 @@ static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) {
tfree(pQueryNode->info.name);
tfree(pQueryNode->tableInfo.tableName);
dropAllExprInfo(pQueryNode->pExpr);
// dropAllExprInfo(pQueryNode->pExpr);
if (pQueryNode->pPrevNodes != NULL) {
int32_t size = (int32_t) taosArrayGetSize(pQueryNode->pPrevNodes);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册