diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index aa0f1c9cff22bee78b1aa044d7ce165587f147ba..11b40326b971adf4759a7565ec48f844978cdb3b 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -129,13 +129,18 @@ typedef struct SColumn { SColumnFilterInfo *filterInfo; } SColumn; +typedef struct SExprFilter { + tSQLExpr *pExpr; //used for having parse + SArray *fp; + SColumn *pFilters; //having filter info +}SExprFilter; + typedef struct SInternalField { TAOS_FIELD field; bool visible; SExprInfo *pArithExprInfo; SSqlExpr *pSqlExpr; - tSQLExpr *pExpr; //used for having parse - SColumn *pFieldFilters; //having filter info + SExprFilter *pFieldFilters; } SInternalField; typedef struct SCond { diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 61d90598b488227b9d6b3f1177da7c7c1421306f..2b7a70de04f741a70462c76fd87dcc421f36e1f8 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -22,6 +22,7 @@ #include "tscUtil.h" #include "tschemautil.h" #include "tsclient.h" +#include "qutil.h" typedef struct SCompareParam { SLocalDataSource **pLocalData; @@ -1229,18 +1230,71 @@ static bool saveGroupResultInfo(SSqlObj *pSql) { return false; } -int32_t doHavingFilter(SQueryInfo* pQueryInfo) { + +bool doFilterFieldData(SQueryInfo* pQueryInfo, char *input, tFilePage* pOutput, SExprFilter* pFieldFilters, int16_t type, bool* notSkipped) { + bool qualified = false; + + for(int32_t k = 0; k < pFieldFilters->pFilters->numOfFilters; ++k) { + __filter_func_t fp = taosArrayGetP(pFieldFilters->fp, k); + SColumnFilterElem filterElem = {.filterInfo = pFieldFilters->pFilters->filterInfo[k]}; + + bool isnull = isNull(input, type); + if (isnull) { + if (fp == isNullOperator) { + qualified = true; + break; + } else { + continue; + } + } else { + if (fp == notNullOperator) { + qualified = true; + break; + } else if (fp == isNullOperator) { + continue; + } + } + + if (fp(&filterElem, input, input, type)) { + qualified = true; + break; + } + } + + *notSkipped = qualified; + + return TSDB_CODE_SUCCESS; +} + + +int32_t doHavingFilter(SQueryInfo* pQueryInfo, tFilePage* pOutput, bool* notSkipped) { + *notSkipped = true; + if (pQueryInfo->havingFieldNum <= 0) { return TSDB_CODE_SUCCESS; } + //int32_t exprNum = (int32_t) tscSqlExprNumOfExprs(pQueryInfo); + size_t numOfOutput = tscNumOfFields(pQueryInfo); for(int32_t i = 0; i < numOfOutput; ++i) { - SColumn* pFieldFilters = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pFieldFilters; - if (pFieldFilters != NULL) { + SInternalField* pInterField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i); + SExprFilter* pFieldFilters = pInterField->pFieldFilters; + + if (pFieldFilters == NULL) { continue; } - } + + int32_t type = pInterField->field.type; + + SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); + char* pInput = pOutput->data + pOutput->num* pExpr->offset; + + doFilterFieldData(pQueryInfo, pInput, pOutput, pFieldFilters, type, notSkipped); + if (!notSkipped) { + return TSDB_CODE_SUCCESS; + } + } return TSDB_CODE_SUCCESS; } @@ -1287,7 +1341,21 @@ bool genFinalResults(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool noMoreCurren doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalMerge->finalModel->rowSize); } - doHavingFilter(pQueryInfo); + bool notSkipped = true; + + doHavingFilter(pQueryInfo, pResBuf, ¬Skipped); + + if (!notSkipped) { + pRes->numOfRows = 0; + pLocalMerge->discard = !noMoreCurrentGroupRes; + + if (pLocalMerge->discard) { + SColumnModel *pInternModel = pLocalMerge->pDesc->pColumnModel; + tColModelAppend(pInternModel, pLocalMerge->discardData, pLocalMerge->pTempBuffer->data, 0, 1, 1); + } + + return notSkipped; + } // no interval query, no fill operation if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) { diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 588e9b18aafdc41994d5bde5020e44fa2dce20a3..0443c3cc5daaed207ef5d9700de15f1e10a83f7d 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -34,6 +34,7 @@ #include "tstoken.h" #include "tstrbuild.h" #include "ttokendef.h" +#include "qutil.h" #define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" @@ -6709,17 +6710,26 @@ static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { 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)); + SExprFilter* pFieldFilters = calloc(1, sizeof(SExprFilter)); if (pFieldFilters == NULL) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } - + + SColumn* pFilters = calloc(1, sizeof(SColumn)); + if (pFilters == NULL) { + tfree(pFieldFilters); + + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + pFieldFilters->pFilters = pFilters; pInfo->pFieldFilters = pFieldFilters; } + pInfo->pFieldFilters->pExpr = pExpr; + *interField = pInfo; return TSDB_CODE_SUCCESS; @@ -6731,7 +6741,7 @@ int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr for (int32_t i = pQueryInfo->havingFieldNum - 1; i >= 0; --i) { pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i); - if (0 == tSqlExprCompare(pInfo->pExpr, pExpr)) { + if (pInfo->pFieldFilters && 0 == tSqlExprCompare(pInfo->pFieldFilters->pExpr, pExpr)) { *pField = pInfo; return TSDB_CODE_SUCCESS; } @@ -6747,7 +6757,33 @@ int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr return TSDB_CODE_SUCCESS; } +static int32_t genExprFilter(SExprFilter * exprFilter) { + exprFilter->fp = taosArrayInit(4, sizeof(__filter_func_t)); + if (exprFilter->fp == NULL) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + for (int32_t i = 0; i < exprFilter->pFilters->numOfFilters; ++i) { + SColumnFilterInfo *filterInfo = &exprFilter->pFilters->filterInfo[i]; + + int32_t lower = filterInfo->lowerRelOptr; + int32_t upper = filterInfo->upperRelOptr; + if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) { + tscError("invalid rel optr"); + return TSDB_CODE_TSC_APP_ERROR; + } + + __filter_func_t ffp = getFilterOperator(lower, upper); + if (ffp == NULL) { + tscError("invalid filter info"); + return TSDB_CODE_TSC_APP_ERROR; + } + + taosArrayPush(exprFilter->fp, &ffp); + } + 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"; @@ -6768,7 +6804,7 @@ static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t return ret; } - pColumn = pInfo->pFieldFilters; + pColumn = pInfo->pFieldFilters->pFilters; // this is a new filter condition on this column if (pColumn->numOfFilters == 0) { @@ -6819,7 +6855,12 @@ static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t } } - return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pInfo->field.type, pExpr); + int32_t ret = doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pInfo->field.type, pExpr); + if (ret) { + return ret; + } + + return genExprFilter(pInfo->pFieldFilters); } int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, int32_t parentOptr) { diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index e0b3e8a565a675568b8cf698a742f8d74ea21efd..e725d0df1a19ec1ffbef0fb312a5626e0ce9119e 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1081,7 +1081,8 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) { } if (pInfo->pFieldFilters != NULL) { - tscColumnDestroy(pInfo->pFieldFilters); + tscColumnDestroy(pInfo->pFieldFilters->pFilters); + tfree(pInfo->pFieldFilters); } } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 7d171dff9abd7dfb8095a1712e67d250f5776895..05572acefded40a2471cff58e36d795d5f4d8887 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -213,9 +213,6 @@ bool doFilterData(SQuery *pQuery, int32_t elemPos) { return true; } -bool doFilterDataOnce() { - -} int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) { SQuery *pQuery = pRuntimeEnv->pQuery; diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index 029af0dcbbba28902406ae4a654f8dd01a55a46a..551a55999b16a380965c73c2e05a544e03805b06 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -296,6 +296,10 @@ static FORCE_INLINE int32_t tStrTokenCompare(SStrToken* left, SStrToken* right) int32_t tSqlExprCompare(tSQLExpr *left, tSQLExpr *right) { + if ((left == NULL && right) || (left && right == NULL)) { + return 1; + } + if (left->nSQLOptr != right->nSQLOptr) { return 1; }