diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index f3bdbe2e8459c349ab235f2033def5c940354082..aa0f1c9cff22bee78b1aa044d7ce165587f147ba 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -116,13 +116,6 @@ typedef struct SColumnIndex { int16_t columnIndex; } SColumnIndex; -typedef struct SInternalField { - TAOS_FIELD field; - bool visible; - SExprInfo *pArithExprInfo; - SSqlExpr *pSqlExpr; - SColumn *pFieldFilters; -} SInternalField; typedef struct SFieldInfo { int16_t numOfOutput; // number of column in result @@ -136,6 +129,15 @@ typedef struct SColumn { SColumnFilterInfo *filterInfo; } SColumn; +typedef struct SInternalField { + TAOS_FIELD field; + bool visible; + SExprInfo *pArithExprInfo; + SSqlExpr *pSqlExpr; + tSQLExpr *pExpr; //used for having parse + SColumn *pFieldFilters; //having filter info +} SInternalField; + typedef struct SCond { uint64_t uid; int32_t len; // length of tag query condition data @@ -228,6 +230,7 @@ typedef struct SQueryInfo { int32_t round; // 0/1/.... int32_t bufLen; char* buf; + int32_t havingFieldNum; } SQueryInfo; typedef struct { diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 23fb0ab67cded77ff737fac4246343486e80eb95..61d90598b488227b9d6b3f1177da7c7c1421306f 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -1229,6 +1229,24 @@ static bool saveGroupResultInfo(SSqlObj *pSql) { return false; } +int32_t doHavingFilter(SQueryInfo* pQueryInfo) { + if (pQueryInfo->havingFieldNum <= 0) { + return TSDB_CODE_SUCCESS; + } + + size_t numOfOutput = tscNumOfFields(pQueryInfo); + for(int32_t i = 0; i < numOfOutput; ++i) { + SColumn* pFieldFilters = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pFieldFilters; + if (pFieldFilters != NULL) { + continue; + } + } + + return TSDB_CODE_SUCCESS; +} + + + /** * * @param pSql @@ -1269,6 +1287,8 @@ bool genFinalResults(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool noMoreCurren doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalMerge->finalModel->rowSize); } + doHavingFilter(pQueryInfo); + // no interval query, no fill operation if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) { genFinalResWithoutFill(pRes, pLocalMerge, pQueryInfo); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 9656aca2a798cf09bfa4787a93eacce9138245b4..588e9b18aafdc41994d5bde5020e44fa2dce20a3 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -3097,213 +3097,6 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd) return TSDB_CODE_SUCCESS; } -static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSQLExpr* pExpr, int32_t sqlOptr) { - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); - - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); - - const char* msg1 = "non binary column not support like operator"; - const char* msg2 = "binary column not support this operator"; - const char* msg3 = "bool column not support this operator"; - - SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex); - SColumnFilterInfo* pColFilter = NULL; - - /* - * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together - * the already existed condition. - */ - if (sqlOptr == TK_AND) { - // this is a new filter condition on this column - if (pColumn->numOfFilters == 0) { - pColFilter = addColumnFilterInfo(pColumn); - } else { // update the existed column filter information, find the filter info here - pColFilter = &pColumn->filterInfo[0]; - } - - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else if (sqlOptr == TK_OR) { - // TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2" - pColFilter = addColumnFilterInfo(pColumn); - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else { // error; - return TSDB_CODE_TSC_INVALID_SQL; - } - - pColFilter->filterstr = - ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); - - if (pColFilter->filterstr) { - if (pExpr->nSQLOptr != TK_EQ - && pExpr->nSQLOptr != TK_NE - && pExpr->nSQLOptr != TK_ISNULL - && pExpr->nSQLOptr != TK_NOTNULL - && pExpr->nSQLOptr != TK_LIKE - ) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); - } - } else { - if (pExpr->nSQLOptr == TK_LIKE) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if (pSchema->type == TSDB_DATA_TYPE_BOOL) { - if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); - } - } - } - - pColumn->colIndex = *pIndex; - return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pIndex, pExpr); -} - -int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr, int32_t parentOptr) { - if (pExpr == NULL || (*pExpr) == NULL) { - return TSDB_CODE_SUCCESS; - } - - const char* msg1 = "invalid having clause"; - - tSQLExpr* pLeft = (*pExpr)->pLeft; - tSQLExpr* pRight = (*pExpr)->pRight; - - if ((*pExpr)->nSQLOptr == TK_AND || (*pExpr)->nSQLOptr == TK_OR) { - int32_t ret = getHavingExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, (*pExpr)->nSQLOptr); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - - return getHavingExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, (*pExpr)->nSQLOptr); - } - - if ((pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE) && - (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE)) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if (pLeft->nSQLOptr >= TK_BOOL - && pLeft->nSQLOptr <= TK_BINARY - && pRight->nSQLOptr >= TK_BOOL - && pRight->nSQLOptr <= TK_BINARY) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - exchangeExpr(*pExpr); - - pLeft = (*pExpr)->pLeft; - pRight = (*pExpr)->pRight; - - if (!(pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE)) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if (!(pRight->nSQLOptr >= TK_BOOL && pRight->nSQLOptr <= TK_BINARY)) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if ((*pExpr)->nSQLOptr >= TK_BITAND) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if (pLeft->pParam == NULL || pLeft->pParam->nExpr < 1) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - for (int32_t i = 0; i < pLeft->pParam->nExpr; i++) { - tSqlExprItem* pParamElem = &(pLeft->pParam->a[i]); - if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if ((getColumnIndexByName(pCmd, &pParamElem->pNode->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS)) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - if (index.columnIndex <= 0 || - index.columnIndex >= tscGetNumOfColumns(pTableMeta)) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - } - - tSqlExprItem item = {.pNode = pLeft, .aliasName = NULL, .distinct = false}; - - int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); - - // ADD TRUE FOR TEST - if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_SQL; - } - - int32_t slot = tscNumOfFields(pQueryInfo) - 1; - SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot); - - if (pInfo->pFieldFilters == NULL) { - SColumn* pFieldFilters = calloc(1, sizeof(SColumn)); - if (pFieldFilters == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - pInfo->pFieldFilters = pFieldFilters; - } - - return handleExprInHavingClause(pCmd, pQueryInfo, pInfo->pFieldFilters, pExpr, parentOptr); -} - - - -int32_t parseHavingClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlCmd* pCmd) { - const char* msg1 = "having only works with group by"; - //const char* msg2 = "invalid column name in having clause"; - //const char* msg3 = "columns from one table allowed as having columns"; - //const char* msg4 = "no tag allowed in having clause"; - const char* msg5 = "invalid expression in having clause"; - -/* - const char* msg1 = "too many columns in group by clause"; - const char* msg4 = "join query does not support group by"; - const char* msg7 = "not support group by expression"; - const char* msg8 = "not allowed column type for group by"; - const char* msg9 = "tags not allowed for table query"; -*/ - - // todo : handle two tables situation - //STableMetaInfo* pTableMetaInfo = NULL; - - if (pExpr == NULL || (*pExpr) == NULL) { - return TSDB_CODE_SUCCESS; - } - - if (pQueryInfo->groupbyExpr.numOfGroupCols <= 0) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - - if ((*pExpr)->pLeft == NULL || (*pExpr)->pRight == NULL) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5); - } - - if (pQueryInfo->colList == NULL) { - pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); - } - - int32_t ret = 0; - - if ((ret = getHavingExpr(pCmd, pQueryInfo, pExpr, TK_AND)) != TSDB_CODE_SUCCESS) { - return ret; - } - - return TSDB_CODE_SUCCESS; -} - static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) { if (pColumn == NULL) { @@ -3328,15 +3121,11 @@ static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) { } static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnFilterInfo* pColumnFilter, - SColumnIndex* columnIndex, tSQLExpr* pExpr) { + int16_t colType, tSQLExpr* pExpr) { const char* msg = "not supported filter condition"; tSQLExpr* pRight = pExpr->pRight; - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, columnIndex->tableIndex); - SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex->columnIndex); - - int16_t colType = pSchema->type; if (colType >= TSDB_DATA_TYPE_TINYINT && colType <= TSDB_DATA_TYPE_BIGINT) { colType = TSDB_DATA_TYPE_BIGINT; } else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) { @@ -3649,7 +3438,10 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC } pColumn->colIndex = *pIndex; - return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pIndex, pExpr); + + int16_t colType = pSchema->type; + + return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, colType, pExpr); } static void relToString(tSQLExpr* pExpr, char** str) { @@ -6901,6 +6693,259 @@ static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { return TSDB_CODE_SUCCESS; } + + int32_t tscInsertExprFields(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SInternalField** interField) { + tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL, .distinct = false}; + + int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); + + // ADD TRUE FOR TEST + if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + ++pQueryInfo->havingFieldNum; + + int32_t slot = tscNumOfFields(pQueryInfo) - 1; + SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot); + pInfo->visible = false; + pInfo->pExpr = pExpr; + + if (pInfo->pFieldFilters == NULL) { + SColumn* pFieldFilters = calloc(1, sizeof(SColumn)); + if (pFieldFilters == NULL) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + pInfo->pFieldFilters = pFieldFilters; + } + + *interField = pInfo; + + return TSDB_CODE_SUCCESS; +} + +int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SInternalField** pField) { + SInternalField* pInfo = NULL; + + for (int32_t i = pQueryInfo->havingFieldNum - 1; i >= 0; --i) { + pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i); + + if (0 == tSqlExprCompare(pInfo->pExpr, pExpr)) { + *pField = pInfo; + return TSDB_CODE_SUCCESS; + } + } + + int32_t ret = tscInsertExprFields(pCmd, pQueryInfo, pExpr, &pInfo); + if (ret) { + return ret; + } + + *pField = pInfo; + + return TSDB_CODE_SUCCESS; +} + + + +static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, int32_t sqlOptr) { + const char* msg1 = "non binary column not support like operator"; + const char* msg2 = "invalid operator for binary column in having clause"; + const char* msg3 = "invalid operator for bool column in having clause"; + + SColumn* pColumn = NULL; + SColumnFilterInfo* pColFilter = NULL; + SInternalField* pInfo = NULL; + + /* + * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together + * the already existed condition. + */ + if (sqlOptr == TK_AND) { + int32_t ret = tscGetExprFilters(pCmd, pQueryInfo, pExpr->pLeft, &pInfo); + if (ret) { + return ret; + } + + pColumn = pInfo->pFieldFilters; + + // this is a new filter condition on this column + if (pColumn->numOfFilters == 0) { + pColFilter = addColumnFilterInfo(pColumn); + } else { // update the existed column filter information, find the filter info here + pColFilter = &pColumn->filterInfo[0]; + } + + if (pColFilter == NULL) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + } else if (sqlOptr == TK_OR) { + int32_t ret = tscInsertExprFields(pCmd, pQueryInfo, pExpr->pLeft, &pInfo); + if (ret) { + return ret; + } + + // TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2" + pColFilter = addColumnFilterInfo(pColumn); + if (pColFilter == NULL) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + } else { // error; + return TSDB_CODE_TSC_INVALID_SQL; + } + + pColFilter->filterstr = + ((pInfo->field.type == TSDB_DATA_TYPE_BINARY || pInfo->field.type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); + + if (pColFilter->filterstr) { + if (pExpr->nSQLOptr != TK_EQ + && pExpr->nSQLOptr != TK_NE + && pExpr->nSQLOptr != TK_ISNULL + && pExpr->nSQLOptr != TK_NOTNULL + && pExpr->nSQLOptr != TK_LIKE + ) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); + } + } else { + if (pExpr->nSQLOptr == TK_LIKE) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (pInfo->field.type == TSDB_DATA_TYPE_BOOL) { + if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); + } + } + } + + return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pInfo->field.type, pExpr); +} + +int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, int32_t parentOptr) { + if (pExpr == NULL) { + return TSDB_CODE_SUCCESS; + } + + const char* msg1 = "invalid having clause"; + + tSQLExpr* pLeft = pExpr->pLeft; + tSQLExpr* pRight = pExpr->pRight; + + if (pExpr->nSQLOptr == TK_AND || pExpr->nSQLOptr == TK_OR) { + int32_t ret = getHavingExpr(pCmd, pQueryInfo, pExpr->pLeft, pExpr->nSQLOptr); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + + return getHavingExpr(pCmd, pQueryInfo, pExpr->pRight, pExpr->nSQLOptr); + } + + if ((pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE) && + (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE)) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (pLeft->nSQLOptr >= TK_BOOL + && pLeft->nSQLOptr <= TK_BINARY + && pRight->nSQLOptr >= TK_BOOL + && pRight->nSQLOptr <= TK_BINARY) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + exchangeExpr(pExpr); + + pLeft = pExpr->pLeft; + pRight = pExpr->pRight; + + if (!(pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE)) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (!(pRight->nSQLOptr >= TK_BOOL && pRight->nSQLOptr <= TK_BINARY)) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (pExpr->nSQLOptr >= TK_BITAND) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (pLeft->pParam == NULL || pLeft->pParam->nExpr < 1) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + for (int32_t i = 0; i < pLeft->pParam->nExpr; i++) { + tSqlExprItem* pParamElem = &(pLeft->pParam->a[i]); + if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + SColumnIndex index = COLUMN_INDEX_INITIALIZER; + if ((getColumnIndexByName(pCmd, &pParamElem->pNode->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS)) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); + STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; + + if (index.columnIndex <= 0 || + index.columnIndex >= tscGetNumOfColumns(pTableMeta)) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + } + + return handleExprInHavingClause(pCmd, pQueryInfo, pExpr, parentOptr); +} + + + +int32_t parseHavingClause(SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SSqlCmd* pCmd) { + const char* msg1 = "having only works with group by"; + //const char* msg2 = "invalid column name in having clause"; + //const char* msg3 = "columns from one table allowed as having columns"; + //const char* msg4 = "no tag allowed in having clause"; + const char* msg5 = "invalid expression in having clause"; + +/* + const char* msg1 = "too many columns in group by clause"; + const char* msg4 = "join query does not support group by"; + const char* msg7 = "not support group by expression"; + const char* msg8 = "not allowed column type for group by"; + const char* msg9 = "tags not allowed for table query"; +*/ + + // todo : handle two tables situation + //STableMetaInfo* pTableMetaInfo = NULL; + + if (pExpr == NULL) { + return TSDB_CODE_SUCCESS; + } + + if (pQueryInfo->groupbyExpr.numOfGroupCols <= 0) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + + if (pExpr->pLeft == NULL || pExpr->pRight == NULL) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5); + } + + if (pQueryInfo->colList == NULL) { + pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); + } + + int32_t ret = 0; + + if ((ret = getHavingExpr(pCmd, pQueryInfo, pExpr, TK_AND)) != TSDB_CODE_SUCCESS) { + return ret; + } + + return TSDB_CODE_SUCCESS; +} + + + + + int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { assert(pQuerySql != NULL && (pQuerySql->from == NULL || taosArrayGetSize(pQuerySql->from) > 0)); @@ -7028,7 +7073,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { } // parse the having clause in the first place - if (parseHavingClause(pQueryInfo, &pQuerySql->pHaving, pCmd) != TSDB_CODE_SUCCESS) { + if (parseHavingClause(pQueryInfo, pQuerySql->pHaving, pCmd) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -7261,3 +7306,10 @@ bool hasNormalColumnFilter(SQueryInfo* pQueryInfo) { return false; } + + + + + + + diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index ef5e9170da258d6d6f221b1b5741315a3051fff9..e0b3e8a565a675568b8cf698a742f8d74ea21efd 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -956,6 +956,7 @@ SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { .pSqlExpr = NULL, .pArithExprInfo = NULL, .visible = true, + .pFieldFilters = NULL, }; info.field = *pField; @@ -968,6 +969,7 @@ SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_F .pSqlExpr = NULL, .pArithExprInfo = NULL, .visible = true, + .pFieldFilters = NULL, }; info.field = *field; @@ -1041,6 +1043,22 @@ int32_t tscGetResRowLength(SArray* pExprList) { return size; } +static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) { + for(int32_t i = 0; i < numOfFilters; ++i) { + if (pFilterInfo[i].filterstr) { + tfree(pFilterInfo[i].pz); + } + } + + tfree(pFilterInfo); +} + +static void tscColumnDestroy(SColumn* pCol) { + destroyFilterInfo(pCol->filterInfo, pCol->numOfFilters); + free(pCol); +} + + void tscFieldInfoClear(SFieldInfo* pFieldInfo) { if (pFieldInfo == NULL) { return; @@ -1298,15 +1316,7 @@ SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) { return taosArrayGetP(pColumnList, i); } -static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) { - for(int32_t i = 0; i < numOfFilters; ++i) { - if (pFilterInfo[i].filterstr) { - tfree(pFilterInfo[i].pz); - } - } - - tfree(pFilterInfo); -} + SColumn* tscColumnClone(const SColumn* src) { assert(src != NULL); @@ -1323,10 +1333,6 @@ SColumn* tscColumnClone(const SColumn* src) { return dst; } -static void tscColumnDestroy(SColumn* pCol) { - destroyFilterInfo(pCol->filterInfo, pCol->numOfFilters); - free(pCol); -} void tscColumnListCopy(SArray* dst, const SArray* src, int16_t tableIndex) { assert(src != NULL && dst != NULL); diff --git a/src/query/inc/qSqlparser.h b/src/query/inc/qSqlparser.h index 8efaa4cb21287d0308ce46382813f8d2ece4c529..08becde20ab131ff5a0ac54b58662e37fae3031f 100644 --- a/src/query/inc/qSqlparser.h +++ b/src/query/inc/qSqlparser.h @@ -233,6 +233,8 @@ SArray *tVariantListAppendToken(SArray *pList, SStrToken *pAliasToken, uint8_t s tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType); +int32_t tSqlExprCompare(tSQLExpr *left, tSQLExpr *right); + tSQLExpr *tSqlExprClone(tSQLExpr *pSrc); void tSqlExprDestroy(tSQLExpr *pExpr); diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index 658815adcf5bf27d39c41d30080fd4b8dbc6718b..029af0dcbbba28902406ae4a654f8dd01a55a46a 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -290,6 +290,58 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { } +static FORCE_INLINE int32_t tStrTokenCompare(SStrToken* left, SStrToken* right) { + return (left->type == right->type && left->n == right->n && strncasecmp(left->z, right->z, left->n) == 0) ? 0 : 1; +} + + +int32_t tSqlExprCompare(tSQLExpr *left, tSQLExpr *right) { + if (left->nSQLOptr != right->nSQLOptr) { + return 1; + } + + if ((left->pLeft && right->pLeft == NULL) + || (left->pLeft == NULL && right->pLeft) + || (left->pRight && right->pRight == NULL) + || (left->pRight == NULL && right->pRight) + || (left->pParam && right->pParam == NULL) + || (left->pParam == NULL && right->pParam)) { + return 1; + } + + if (tVariantCompare(&left->val, &right->val)) { + return 1; + } + + if (tStrTokenCompare(&left->colInfo, &right->colInfo)) { + return 1; + } + + if (left->pParam && left->pParam->nExpr != right->pParam->nExpr) { + return 1; + } + + for (int32_t i = 0; i < right->pParam->nExpr; i++) { + tSQLExpr* pSubLeft = left->pParam->a[i].pNode; + tSQLExpr* pSubRight = right->pParam->a[i].pNode; + + if (tSqlExprCompare(pSubLeft, pSubRight)) { + return 1; + } + } + + if (left->pLeft && tSqlExprCompare(left->pLeft, right->pLeft)) { + return 1; + } + + if (left->pRight && tSqlExprCompare(left->pRight, right->pRight)) { + return 1; + } + + return 0; +} + + tSQLExpr *tSqlExprClone(tSQLExpr *pSrc) { tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr));