diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index fab97bdf5a..ab6bfa6c23 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -3502,6 +3502,8 @@ enum { TSQL_EXPR_TBNAME = 8, }; +#define GET_MIXED_TYPE(t) ((t) > TSQL_EXPR_COLUMN || (t) == (TSQL_EXPR_TS|TSQL_EXPR_TAG)) + static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); @@ -4103,10 +4105,9 @@ static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t } static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr, tSqlExpr** columnExpr) { + int32_t* type, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { const char* msg1 = "table query cannot use tags filter"; const char* msg2 = "illegal column name"; - const char* msg3 = "only one query time range allowed"; const char* msg4 = "too many join tables"; const char* msg5 = "not support ordinary column join"; const char* msg6 = "only one query condition on tbname allowed"; @@ -4196,11 +4197,11 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql */ tSqlExprDestroy(*pExpr); } else { - ret = setExprToCond(&pCondExpr->pTimewindow, *pExpr, msg3, parentOptr, pQueryInfo->msg); + ret = setNormalExprToCond(tsExpr, *pExpr, parentOptr); } *pExpr = NULL; // remove this expression - *type |= TSQL_EXPR_TAG; + *type |= TSQL_EXPR_TS; } else if (index.columnIndex >= tscGetNumOfColumns(pTableMeta) || index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { // query on tags, check for tag query condition if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { @@ -4260,16 +4261,19 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql } int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr, tSqlExpr** columnExpr) { + int32_t* type, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { if (pExpr == NULL) { return TSDB_CODE_SUCCESS; } tSqlExpr *columnLeft = NULL; tSqlExpr *columnRight = NULL; + tSqlExpr *tsLeft = NULL; + tSqlExpr *tsRight = NULL; + int32_t ret = 0; - const char* msg1 = "query condition between columns and tags/timestamp must use 'AND'"; + const char* msg1 = "query condition between columns and tags and timestamp must use 'AND'"; if ((*pExpr)->flags & (1 << EXPR_FLAG_TS_ERROR)) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -4286,12 +4290,12 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr int32_t rightType = 0; if (!tSqlExprIsParentOfLeaf(*pExpr)) { - ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId, &columnLeft); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId, &columnLeft, &tsLeft); if (ret != TSDB_CODE_SUCCESS) { goto err_ret; } - ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId, &columnRight); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId, &columnRight, &tsRight); if (ret != TSDB_CODE_SUCCESS) { goto err_ret; } @@ -4300,7 +4304,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr * if left child and right child do not belong to the same group, the sub * expression is not valid for parent node, it must be TK_AND operator. */ - if (((leftType != rightType) || (leftType == (TSQL_EXPR_COLUMN|TSQL_EXPR_TAG ))) && (*pExpr)->tokenId == TK_OR) { + if (((leftType != rightType) || GET_MIXED_TYPE(leftType)) && ((*pExpr)->tokenId == TK_OR)) { ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); goto err_ret; } @@ -4313,6 +4317,14 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr *columnExpr = columnLeft ? columnLeft : columnRight; } + if (tsLeft && tsRight) { + setNormalExprToCond(&tsLeft, tsRight, (*pExpr)->tokenId); + + *tsExpr = tsLeft; + } else { + *tsExpr = tsLeft ? tsLeft : tsRight; + } + *type = leftType|rightType; return TSDB_CODE_SUCCESS; @@ -4330,7 +4342,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr goto err_ret; } - ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, parentOptr, columnExpr); + ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, parentOptr, columnExpr, tsExpr); if (ret) { goto err_ret; } @@ -4466,11 +4478,59 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, return TSDB_CODE_SUCCESS; } +int32_t mergeTimeRange(SSqlCmd* pCmd, STimeWindow* res, STimeWindow* win, int32_t optr) { + const char* msg0 = "only one time stamp window allowed"; -static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { +#define SET_EMPTY_RANGE(w) do { (w)->skey = INT64_MAX; (w)->ekey = INT64_MIN; } while (0) +#define IS_EMPTY_RANGE(w) ((w)->skey == INT64_MAX && (w)->ekey == INT64_MIN) + + if (optr == TSDB_RELATION_AND) { + if (res->skey > win->ekey || win->skey > res->ekey) { + SET_EMPTY_RANGE(res); + return TSDB_CODE_SUCCESS; + } + + if (res->skey < win->skey) { + res->skey = win->skey; + } + + if (res->ekey > win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; + } + + if (res->skey > win->ekey || win->skey > res->ekey) { + if (IS_EMPTY_RANGE(res)) { + res->skey = win->skey; + res->ekey = win->ekey; + return TSDB_CODE_SUCCESS; + } + + if (IS_EMPTY_RANGE(win)) { + return TSDB_CODE_SUCCESS; + } + + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); + } + + if (res->skey > win->skey) { + res->skey = win->skey; + } + + if (res->ekey < win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; +} + + +static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, STimeWindow* win) { const char* msg0 = "invalid timestamp or operator for timestamp"; - const char* msg1 = "only one time stamp window allowed"; int32_t code = 0; + STimeWindow win2 = {.skey = INT64_MIN, .ekey = INT64_MAX}; if (pExpr == NULL) { return TSDB_CODE_SUCCESS; @@ -4478,15 +4538,25 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE if (!tSqlExprIsParentOfLeaf(pExpr)) { if (pExpr->tokenId == TK_OR) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft, win); + if (code) { + return code; + } + + code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight, &win2); + if (code) { + return code; + } + + return mergeTimeRange(pCmd, win, &win2, TSDB_RELATION_OR); } - code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); + code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft, win); if (code) { return code; } - return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); + return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight, win); } else { SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { @@ -4498,19 +4568,11 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE tSqlExpr* pRight = pExpr->pRight; - STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; - if (getTimeRange(&win, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { + if (getTimeRange(&win2, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); } - // update the timestamp query range - if (pQueryInfo->window.skey < win.skey) { - pQueryInfo->window.skey = win.skey; - } - - if (pQueryInfo->window.ekey > win.ekey) { - pQueryInfo->window.ekey = win.ekey; - } + return mergeTimeRange(pCmd, win, &win2, TSDB_RELATION_AND); } return TSDB_CODE_SUCCESS; @@ -4859,12 +4921,11 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } int32_t type = 0; - if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId, &condExpr.pColumnCond)) != TSDB_CODE_SUCCESS) { + if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId, &condExpr.pColumnCond, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { return ret; } tSqlExprCompact(pExpr); - tSqlExprCompact(&condExpr.pColumnCond); // after expression compact, the expression tree is only include tag query condition condExpr.pTagCond = (*pExpr); @@ -4875,7 +4936,12 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } // 2. get the query time range - if ((ret = getTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { + STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; + if ((ret = getTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow, &win)) != TSDB_CODE_SUCCESS) { + return ret; + } + + if ((ret = mergeTimeRange(&pSql->cmd, &pQueryInfo->window,&win, TSDB_RELATION_AND)) != TSDB_CODE_SUCCESS) { return ret; } diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 156445ec36..76945c50b5 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2580,7 +2580,7 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool uint32_t size = tscGetTableMetaMaxSize(); if (pTableMetaInfo->pTableMeta == NULL) { - pTableMetaInfo->pTableMeta = calloc(1, size); + pTableMetaInfo->pTableMeta = malloc(size); pTableMetaInfo->tableMetaSize = size; } else if (pTableMetaInfo->tableMetaSize < size) { char *tmp = realloc(pTableMetaInfo->pTableMeta, size); diff --git a/tests/script/general/parser/condition.sim b/tests/script/general/parser/condition.sim index 85c9d8c2ce..6b10101eaa 100644 --- a/tests/script/general/parser/condition.sim +++ b/tests/script/general/parser/condition.sim @@ -93,9 +93,6 @@ sql_error select * from stb1 where c8 in (1,2); sql_error select * from stb1 where t3 in (3); sql_error select * from stb1 where t2 in (3.0); sql_error select ts,c1,c7 from stb1 where c7 > false -sql_error select ts,c1,c7 from stb1 where ts != '2021-05-05 18:19:27' -sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:20.000'; -sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:20.000' and ts != '2021-05-05 18:19:22.000'; sql_error select * from stb1 where c1 > NULL; sql_error select * from stb1 where c1 = NULL; sql_error select * from stb1 where c1 LIKE '%1'; @@ -1369,6 +1366,9 @@ if $data00 != @21-05-05 18:19:08.000@ then endi print "ts test" +sql_error select ts,c1,c7 from stb1 where ts != '2021-05-05 18:19:27' +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts < '2021-05-05 18:19:02.000'; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:20.000' and ts != '2021-05-05 18:19:22.000'; print "tbname test" @@ -1401,9 +1401,10 @@ print "join test" print "column&ts test" +sql_error select count(*) from stb1 where ts > 0 or c1 > 0; print "column&tbname test" - +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0; print "column&tag test" @@ -1458,8 +1459,11 @@ endi print "column&join test" print "ts&tbname test" +sql_error select count(*) from stb1 where ts > 0 or tbname like 'tb%'; print "ts&tag test" +sql_error select count(*) from stb1 where ts > 0 or t1 > 0; + sql select * from stb2 where t1!=1 and t2=2 and t3 in ('2021-05-05 18:58:58.000') and ts < '2021-05-05 18:19:13.000'; if $rows != 2 then return -1 @@ -1483,8 +1487,12 @@ print "tag&join test" print "column&ts&tbname test" +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0 or ts > 0; print "column&ts&tag test" +sql_error select count(*) from stb1 where t1 > 0 or c1 > 0 or ts > 0; +sql_error select count(*) from stb1 where c1 > 0 or t1 > 0 or ts > 0; + sql select * from stb1 where (t1 > 0 or t1 > 2 ) and ts > '2021-05-05 18:19:10.000' and (c1 > 1 or c1 > 3) and (c6 > 40 or c6 < 30) and (c8 like '%3' or c8 like '_4') and (c9 like '1%' or c9 like '6%' or (c9 like '%3' and c9 != '23')) and ts > '2021-05-05 18:19:22.000' and ts <= '2021-05-05 18:19:26.000'; if $rows != 1 then return -1 @@ -1502,10 +1510,13 @@ endi print "column&ts&join test" print "column&tbname&tag test" +sql_error select count(*) from stb1 where c1 > 0 or tbname in ('tb1') or t1 > 0; print "column&tbname&join test" print "column&tag&join test" print "ts&tbname&tag test" +sql_error select count(*) from stb1 where ts > 0 or tbname in ('tb1') or t1 > 0; + print "ts&tbname&join test" print "ts&tag&join test" print "tbname&tag&join test" @@ -1514,11 +1525,9 @@ print "tbname&tag&join test" print "column&ts&tbname&tag test" -# select * from stb1 where (tbname like 'tb%' or ts > '2021-05-05 18:19:01.000') and (t1 > 5 or t1 < 4) and c1 > 0; -#=> select * from stb1 where (ts > '2021-05-05 18:19:01.000') and (tbname like 'tb%' or (t1 > 5 or t1 < 4)) and c1 > 0; -# select * from stb1 where (ts > '2021-05-05 18:19:01.000') and (ts > '2021-05-05 18:19:02.000' or t1 > 3) and (t1 > 5 or t1 < 4) and c1 > 0; -#=> select * from stb1 where (ts > '2021-05-05 18:19:01.000' or ts > '2021-05-05 18:19:02.000') and t1 > 3 and (t1 > 5 or t1 < 4) and c1 > 0; -#select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:20.000'; +sql_error select * from stb1 where (tbname like 'tb%' or ts > '2021-05-05 18:19:01.000') and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select * from stb1 where (ts > '2021-05-05 18:19:01.000') and (ts > '2021-05-05 18:19:02.000' or t1 > 3) and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:20.000' and col > 0 and t1 > 0; print "column&ts&tbname&join test"