提交 4c6dad1f 编写于 作者: H Haojun Liao

[td-10564]Fix bug in parser.

上级 86687338
......@@ -108,10 +108,10 @@ typedef struct SQueryStmtInfo {
SArray *pUdfInfo;
struct SQueryStmtInfo *sibling; // sibling
SArray *pUpstream; // SArray<struct SQueryStmtInfo>
struct SQueryStmtInfo *pDownstream;
SMultiFunctionsDesc info;
SArray *pUpstream; // SArray<struct SQueryStmtInfo>
int32_t havingFieldNum;
SMultiFunctionsDesc info;
int32_t exprListLevelIndex;
} SQueryStmtInfo;
......@@ -176,6 +176,7 @@ typedef struct SSourceParam {
SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, const char* funcName, SSourceParam* pSource, SSchema* pResSchema, int16_t interSize);
int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy);
int32_t getExprFunctionLevel(SQueryStmtInfo* pQueryInfo);
STableMetaInfo* getMetaInfo(SQueryStmtInfo* pQueryInfo, int32_t tableIndex);
SSchema *getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex);
......
......@@ -35,6 +35,11 @@
#define COLUMN_INDEX_INITIAL_VAL (-2)
#define COLUMN_INDEX_INITIALIZER { COLUMN_INDEX_INITIAL_VAL, COLUMN_INDEX_INITIAL_VAL }
static int32_t resColId = 5000;
int32_t getNewResColId() {
return resColId++;
}
static int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, bool outerQuery, SMsgBuf* pMsgBuf);
static int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema,
tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf);
......@@ -1562,6 +1567,15 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
for(int32_t i = 0; i < getExprFunctionLevel(pQueryInfo); ++i) {
SArray* functionList = extractFunctionList(pQueryInfo->exprList[i]);
extractFunctionDesc(functionList, &pQueryInfo->info);
if ((code = checkForInvalidExpr(pQueryInfo, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
}
return TSDB_CODE_SUCCESS; // Does not build query message here
}
......@@ -1603,7 +1617,11 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
size_t size = getNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < size; ++i) {
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
int32_t functionId = getExprFunctionId(pExpr);
if (pExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE) {
continue;
}
int32_t functionId = getExprFunctionId(pExpr);
if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.pColumns->flag)) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
}
......@@ -1669,11 +1687,6 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
}
}
static int32_t resColId = 5000;
int32_t getNewResColId() {
return resColId++;
}
int32_t addResColumnInfo(SQueryStmtInfo* pQueryInfo, int32_t outputIndex, SSchema* pSchema, SExprInfo* pSqlExpr) {
SInternalField* pInfo = insertFieldInfo(&pQueryInfo->fieldsInfo, outputIndex, pSchema);
pInfo->pExpr = pSqlExpr;
......@@ -1787,7 +1800,6 @@ static int32_t checkForAliasName(SMsgBuf* pMsgBuf, char* aliasName) {
return TSDB_CODE_SUCCESS;
}
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, bool* keepTableCols, SMsgBuf* pMsgBuf);
static int64_t getTickPerSecond(SVariant* pVariant, int32_t precision, int64_t* tickPerSec, SMsgBuf *pMsgBuf) {
......@@ -2600,15 +2612,15 @@ static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr
return TSDB_CODE_SUCCESS;
}
int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) {
static int32_t validateScalarFunctionParamNum(tSqlExpr* pSqlExpr, int32_t functionId, SMsgBuf* pMsgBuf) {
int32_t code = TSDB_CODE_SUCCESS;
switch (pItem->functionId) {
switch (functionId) {
case FUNCTION_CEIL: {
code = checkForkParam(pItem->pNode, 1, pMsgBuf);
code = checkForkParam(pSqlExpr, 1, pMsgBuf);
break;
}
case FUNCTION_LENGTH: {
code = checkForkParam(pItem->pNode, 1, pMsgBuf);
code = checkForkParam(pSqlExpr, 1, pMsgBuf);
break;
}
}
......@@ -2616,38 +2628,6 @@ int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) {
return code;
}
int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SArray* pList, int32_t* exprType, SMsgBuf* pMsgBuf) {
int32_t code = TSDB_CODE_SUCCESS;
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) {
// 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) {
return code;
}
} else if (type == SQL_NODE_EXPR) {
code = validateComplexExpr(pSqlExpr, pQueryInfo, pList, exprType, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
} else if (type == SQL_NODE_TABLE_COLUMN) {
code = validateExprLeafColumnNode(pQueryInfo, &pSqlExpr->columnName, pList, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
}
}
}
SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SColumnIndex* pColIndex, const char* aliasName, int32_t colId) {
STableMeta* pTableMeta = getMetaInfo(pQueryInfo, pColIndex->tableIndex)->pTableMeta;
......@@ -2888,57 +2868,6 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo,
return TSDB_CODE_SUCCESS;
}
int32_t validateComplexExpr(tSqlExpr * pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
int32_t code = TSDB_CODE_SUCCESS;
if (pExpr->type == SQL_NODE_SQLFUNCTION) {
return validateScalarFunctionParam(pQueryInfo, pExpr, pColList, type, pMsgBuf);
}
tSqlExpr* pLeft = pExpr->pLeft;
if (pLeft->type == SQL_NODE_EXPR) {
code = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
} else {
code = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
}
tSqlExpr* pRight = pExpr->pRight;
if (pRight->type == SQL_NODE_EXPR) {
code = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
} else {
code = validateExprLeafNode(pRight, pQueryInfo, pColList, type, pMsgBuf);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
}
// check divide by 0
if (pExpr->tokenId == TK_DIVIDE && pRight->type == SQL_NODE_VALUE) {
int32_t type1 = pRight->value.nType;
const char* msg1 = "invalid expr (divide by 0)";
if (type1 == TSDB_DATA_TYPE_DOUBLE && pRight->value.d < DBL_EPSILON) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
} else if (type1 == TSDB_DATA_TYPE_INT && pRight->value.i == 0) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
}
}
return TSDB_CODE_SUCCESS;
}
static uint64_t findTmpSourceColumnInNextLevel(SQueryStmtInfo* pQueryInfo, tExprNode *pExpr) {
// This function must be a aggregate function, so it must be in the next level
pQueryInfo->exprListLevelIndex += 1;
......@@ -3080,7 +3009,8 @@ int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SM
}
int32_t tokenId = pSqlExpr->tokenId;
if (pRight->type == SQL_NODE_VALUE && pRight->value.nType == TSDB_DATA_TYPE_DOUBLE && pRight->value.d == 0 && tokenId == TK_DIVIDE) {
if (pRight->type == SQL_NODE_VALUE && (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE || pRight->value.nType == TSDB_DATA_TYPE_INT) &&
pRight->value.d == 0 && tokenId == TK_DIVIDE) {
return buildInvalidOperationMsg(pMsgBuf, "invalid expression (divided by 0)");
}
......@@ -3098,6 +3028,20 @@ int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SM
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
} else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
bool scalar = false;
int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar);
if (functionId < 0) {
return buildInvalidOperationMsg(pMsgBuf, "invalid function name");
}
// do check the parameter number for scalar function
if (scalar) {
int32_t ret = validateScalarFunctionParamNum(pSqlExpr, functionId, pMsgBuf);
if (ret != TSDB_CODE_SUCCESS) {
return buildInvalidOperationMsg(pMsgBuf, "invalid number of function parameters");
}
}
}
return TSDB_CODE_SUCCESS;
......@@ -3379,14 +3323,14 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
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;
bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId);
if (!valid) {
if (pItem->functionId == FUNCTION_INVALID_ID) { // temporarily disable the udf
// int32_t functionId = FUNCTION_INVALID_ID;
// bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId);
// if (!valid) {
return buildInvalidOperationMsg(pMsgBuf, msg5);
}
// }
pItem->functionId = functionId;
// pItem->functionId = functionId;
}
if (scalarFunc) { // scalar function
......@@ -3920,12 +3864,6 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
validateSqlNode(p, pQueryInfo, &buf);
}
SArray* functionList = extractFunctionList(pQueryInfo->exprList[0]);
extractFunctionDesc(functionList, &pQueryInfo->info);
if ((code = checkForInvalidExpr(pQueryInfo, &buf)) != TSDB_CODE_SUCCESS) {
return code;
}
return code;
}
......@@ -223,7 +223,7 @@ void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t byt
}
int32_t getExprFunctionId(SExprInfo *pExprInfo) {
assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE);
assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE);
return 0;
}
......@@ -350,11 +350,16 @@ bool tscHasColumnFilter(SQueryStmtInfo* pQueryInfo) {
return false;
}
//void tscClearInterpInfo(SQueryStmtInfo* pQueryInfo) {
// if (!tscIsPointInterpQuery(pQueryInfo)) {
// return;
// }
//
// pQueryInfo->fillType = TSDB_FILL_NONE;
// tfree(pQueryInfo->fillVal);
//}
\ No newline at end of file
int32_t getExprFunctionLevel(SQueryStmtInfo* pQueryInfo) {
int32_t n = 10;
int32_t level = 0;
for(int32_t i = 0; i < n; ++i) {
SArray* pList = pQueryInfo->exprList[i];
if (taosArrayGetSize(pList) > 0) {
level += 1;
}
}
return level;
}
\ No newline at end of file
......@@ -412,6 +412,16 @@ TEST(testCase, function_Test10) {
sqlCheck("select block_dist() from `t.1abc`", true);
sqlCheck("select block_dist(a) from `t.1abc`", false);
sqlCheck("select count(*) from `t.1abc` interval(1s) group by a", false);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sqlCheck("select length119(a,b) from `t.1abc`", false);
sqlCheck("select length(a,b) from `t.1abc`", false);
sqlCheck("select block_dist() + 20 from `t.1abc`", false);
sqlCheck("select top(a, 20), count(b) from `t.1abc`", false);
sqlCheck("select count(b), c from `t.1abc`", false);
sqlCheck("select last_row(*), count(b) from `t.1abc`", false);
sqlCheck("select last_row(a, b) + 20 from `t.1abc`", false);
sqlCheck("select last_row(count(*)) from `t.1abc`", false);
}
TEST(testCase, function_Test6) {
......
......@@ -217,42 +217,12 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe
return pNode;
}
static int32_t getFunctionLevel(SQueryStmtInfo* pQueryInfo) {
int32_t n = 10;
int32_t level = 0;
for(int32_t i = 0; i < n; ++i) {
SArray* pList = pQueryInfo->exprList[i];
if (taosArrayGetSize(pList) > 0) {
level += 1;
}
}
return level;
}
static SQueryPlanNode* createOneQueryPlanNode(SArray* p, SQueryPlanNode* pNode, SExprInfo* pExpr, SQueryTableInfo* info) {
if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE) {
bool aggregateFunc = qIsAggregateFunction(pExpr->pExpr->_function.functionName);
if (aggregateFunc) {
int32_t numOfOutput = (int32_t)taosArrayGetSize(p);
return createQueryNode(QNODE_AGGREGATE, "Aggregate", &pNode, 1, p->pData, numOfOutput, info, NULL);
} else {
int32_t numOfOutput = (int32_t)taosArrayGetSize(p);
return createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, numOfOutput, info, NULL);
}
} else {
int32_t numOfOutput = (int32_t)taosArrayGetSize(p);
return createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, numOfOutput, info, NULL);
}
}
static SQueryPlanNode* doCreateQueryPlanForSingleTableImpl(SQueryStmtInfo* pQueryInfo, SQueryPlanNode* pNode, SQueryTableInfo* info) {
// group by column not by tag
size_t numOfGroupCols = taosArrayGetSize(pQueryInfo->groupbyExpr.columnInfo);
// check for aggregation
int32_t level = getFunctionLevel(pQueryInfo);
int32_t level = getExprFunctionLevel(pQueryInfo);
for(int32_t i = level - 1; i >= 0; --i) {
SArray* p = pQueryInfo->exprList[i];
......@@ -344,7 +314,7 @@ static bool isAllAggExpr(SArray* pList) {
static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo) {
assert(pQueryInfo != NULL);
size_t level = getFunctionLevel(pQueryInfo);
size_t level = getExprFunctionLevel(pQueryInfo);
for(int32_t i = 0; i < level - 1; ++i) {
SArray* p = pQueryInfo->exprList[i];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册