support having
This commit is contained in:
parent
a18b6723d3
commit
a83cbb75d6
|
@ -129,13 +129,18 @@ typedef struct SColumn {
|
||||||
SColumnFilterInfo *filterInfo;
|
SColumnFilterInfo *filterInfo;
|
||||||
} SColumn;
|
} SColumn;
|
||||||
|
|
||||||
|
typedef struct SExprFilter {
|
||||||
|
tSQLExpr *pExpr; //used for having parse
|
||||||
|
SArray *fp;
|
||||||
|
SColumn *pFilters; //having filter info
|
||||||
|
}SExprFilter;
|
||||||
|
|
||||||
typedef struct SInternalField {
|
typedef struct SInternalField {
|
||||||
TAOS_FIELD field;
|
TAOS_FIELD field;
|
||||||
bool visible;
|
bool visible;
|
||||||
SExprInfo *pArithExprInfo;
|
SExprInfo *pArithExprInfo;
|
||||||
SSqlExpr *pSqlExpr;
|
SSqlExpr *pSqlExpr;
|
||||||
tSQLExpr *pExpr; //used for having parse
|
SExprFilter *pFieldFilters;
|
||||||
SColumn *pFieldFilters; //having filter info
|
|
||||||
} SInternalField;
|
} SInternalField;
|
||||||
|
|
||||||
typedef struct SCond {
|
typedef struct SCond {
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "tscUtil.h"
|
#include "tscUtil.h"
|
||||||
#include "tschemautil.h"
|
#include "tschemautil.h"
|
||||||
#include "tsclient.h"
|
#include "tsclient.h"
|
||||||
|
#include "qutil.h"
|
||||||
|
|
||||||
typedef struct SCompareParam {
|
typedef struct SCompareParam {
|
||||||
SLocalDataSource **pLocalData;
|
SLocalDataSource **pLocalData;
|
||||||
|
@ -1229,18 +1230,71 @@ static bool saveGroupResultInfo(SSqlObj *pSql) {
|
||||||
return false;
|
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) {
|
if (pQueryInfo->havingFieldNum <= 0) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//int32_t exprNum = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
|
||||||
|
|
||||||
size_t numOfOutput = tscNumOfFields(pQueryInfo);
|
size_t numOfOutput = tscNumOfFields(pQueryInfo);
|
||||||
for(int32_t i = 0; i < numOfOutput; ++i) {
|
for(int32_t i = 0; i < numOfOutput; ++i) {
|
||||||
SColumn* pFieldFilters = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pFieldFilters;
|
SInternalField* pInterField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
|
||||||
if (pFieldFilters != NULL) {
|
SExprFilter* pFieldFilters = pInterField->pFieldFilters;
|
||||||
|
|
||||||
|
if (pFieldFilters == NULL) {
|
||||||
continue;
|
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;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1341,21 @@ bool genFinalResults(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool noMoreCurren
|
||||||
doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalMerge->finalModel->rowSize);
|
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
|
// no interval query, no fill operation
|
||||||
if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) {
|
if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "tstoken.h"
|
#include "tstoken.h"
|
||||||
#include "tstrbuild.h"
|
#include "tstrbuild.h"
|
||||||
#include "ttokendef.h"
|
#include "ttokendef.h"
|
||||||
|
#include "qutil.h"
|
||||||
|
|
||||||
#define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0"
|
#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;
|
int32_t slot = tscNumOfFields(pQueryInfo) - 1;
|
||||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot);
|
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot);
|
||||||
pInfo->visible = false;
|
pInfo->visible = false;
|
||||||
pInfo->pExpr = pExpr;
|
|
||||||
|
|
||||||
if (pInfo->pFieldFilters == NULL) {
|
if (pInfo->pFieldFilters == NULL) {
|
||||||
SColumn* pFieldFilters = calloc(1, sizeof(SColumn));
|
SExprFilter* pFieldFilters = calloc(1, sizeof(SExprFilter));
|
||||||
if (pFieldFilters == NULL) {
|
if (pFieldFilters == NULL) {
|
||||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
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 = pFieldFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pInfo->pFieldFilters->pExpr = pExpr;
|
||||||
|
|
||||||
*interField = pInfo;
|
*interField = pInfo;
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
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) {
|
for (int32_t i = pQueryInfo->havingFieldNum - 1; i >= 0; --i) {
|
||||||
pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
|
pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
|
||||||
|
|
||||||
if (0 == tSqlExprCompare(pInfo->pExpr, pExpr)) {
|
if (pInfo->pFieldFilters && 0 == tSqlExprCompare(pInfo->pFieldFilters->pExpr, pExpr)) {
|
||||||
*pField = pInfo;
|
*pField = pInfo;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -6747,7 +6757,33 @@ int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr
|
||||||
return TSDB_CODE_SUCCESS;
|
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) {
|
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* msg1 = "non binary column not support like operator";
|
||||||
|
@ -6768,7 +6804,7 @@ static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pColumn = pInfo->pFieldFilters;
|
pColumn = pInfo->pFieldFilters->pFilters;
|
||||||
|
|
||||||
// this is a new filter condition on this column
|
// this is a new filter condition on this column
|
||||||
if (pColumn->numOfFilters == 0) {
|
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) {
|
int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, int32_t parentOptr) {
|
||||||
|
|
|
@ -1081,7 +1081,8 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pInfo->pFieldFilters != NULL) {
|
if (pInfo->pFieldFilters != NULL) {
|
||||||
tscColumnDestroy(pInfo->pFieldFilters);
|
tscColumnDestroy(pInfo->pFieldFilters->pFilters);
|
||||||
|
tfree(pInfo->pFieldFilters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,9 +213,6 @@ bool doFilterData(SQuery *pQuery, int32_t elemPos) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doFilterDataOnce() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) {
|
int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) {
|
||||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||||
|
|
|
@ -296,6 +296,10 @@ static FORCE_INLINE int32_t tStrTokenCompare(SStrToken* left, SStrToken* right)
|
||||||
|
|
||||||
|
|
||||||
int32_t tSqlExprCompare(tSQLExpr *left, tSQLExpr *right) {
|
int32_t tSqlExprCompare(tSQLExpr *left, tSQLExpr *right) {
|
||||||
|
if ((left == NULL && right) || (left && right == NULL)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (left->nSQLOptr != right->nSQLOptr) {
|
if (left->nSQLOptr != right->nSQLOptr) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue