Merge remote-tracking branch 'origin/3.0' into fix/dnode
This commit is contained in:
commit
5959cc2d42
|
@ -185,6 +185,8 @@ bool fmIsUserDefinedFunc(int32_t funcId);
|
|||
bool fmIsDistExecFunc(int32_t funcId);
|
||||
bool fmIsForbidFillFunc(int32_t funcId);
|
||||
bool fmIsForbidStreamFunc(int32_t funcId);
|
||||
bool fmIsForbidWindowFunc(int32_t funcId);
|
||||
bool fmIsForbidGroupByFunc(int32_t funcId);
|
||||
bool fmIsIntervalInterpoFunc(int32_t funcId);
|
||||
|
||||
int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);
|
||||
|
|
|
@ -102,6 +102,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_EXPLAIN_OPTIONS,
|
||||
QUERY_NODE_STREAM_OPTIONS,
|
||||
QUERY_NODE_LEFT_VALUE,
|
||||
QUERY_NODE_COLUMN_REF,
|
||||
|
||||
// Statement nodes are used in parser and planner module.
|
||||
QUERY_NODE_SET_OPERATOR,
|
||||
|
|
|
@ -65,11 +65,16 @@ typedef struct SColumnNode {
|
|||
char tableName[TSDB_TABLE_NAME_LEN];
|
||||
char tableAlias[TSDB_TABLE_NAME_LEN];
|
||||
char colName[TSDB_COL_NAME_LEN];
|
||||
SNode* pProjectRef;
|
||||
// SNode* pProjectRef;
|
||||
int16_t dataBlockId;
|
||||
int16_t slotId;
|
||||
} SColumnNode;
|
||||
|
||||
typedef struct SColumnRefNode {
|
||||
ENodeType type;
|
||||
char colName[TSDB_COL_NAME_LEN];
|
||||
} SColumnRefNode;
|
||||
|
||||
typedef struct STargetNode {
|
||||
ENodeType type;
|
||||
int16_t dataBlockId;
|
||||
|
@ -247,6 +252,8 @@ typedef struct SSelectStmt {
|
|||
bool hasIndefiniteRowsFunc;
|
||||
bool hasSelectFunc;
|
||||
bool hasSelectValFunc;
|
||||
bool hasUniqueFunc;
|
||||
bool hasTailFunc;
|
||||
} SSelectStmt;
|
||||
|
||||
typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType;
|
||||
|
@ -374,6 +381,9 @@ bool nodesIsComparisonOp(const SOperatorNode* pOp);
|
|||
bool nodesIsJsonOp(const SOperatorNode* pOp);
|
||||
bool nodesIsRegularOp(const SOperatorNode* pOp);
|
||||
|
||||
bool nodesExprHasColumn(SNode* pNode);
|
||||
bool nodesExprsHasColumn(SNodeList* pList);
|
||||
|
||||
void* nodesGetValueFromNode(SValueNode* pNode);
|
||||
int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value);
|
||||
char* nodesGetStrValueFromNode(SValueNode* pNode);
|
||||
|
|
|
@ -658,6 +658,9 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG TAOS_DEF_ERROR_CODE(0, 0x2656)
|
||||
#define TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x2657)
|
||||
#define TSDB_CODE_PAR_INVALID_WINDOW_PC TAOS_DEF_ERROR_CODE(0, 0x2658)
|
||||
#define TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x2659)
|
||||
#define TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x265A)
|
||||
#define TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x265B)
|
||||
|
||||
//planner
|
||||
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
||||
|
|
|
@ -392,10 +392,8 @@ SOperatorInfo* createMultiwaySortMergeOperatorInfo(SOperatorInfo** downStreams,
|
|||
|
||||
pInfo->bufPageSize = getProperSortPageSize(rowSize);
|
||||
|
||||
uint32_t numOfSources = taosArrayGetSize(pSortInfo);
|
||||
numOfSources = TMAX(4, numOfSources);
|
||||
|
||||
pInfo->sortBufSize = numOfSources * pInfo->bufPageSize;
|
||||
// one additional is reserved for merged result.
|
||||
pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1);
|
||||
|
||||
pOperator->fpSet =
|
||||
createOperatorFpSet(doOpenMultiwaySortMergeOperator, doMultiwaySortMerge, NULL, NULL,
|
||||
|
|
|
@ -195,6 +195,11 @@ static int32_t doAddToBuf(SSDataBlock* pDataBlock, SSortHandle* pHandle) {
|
|||
return doAddNewExternalMemSource(pHandle->pBuf, pHandle->pOrderedSource, pBlock, &pHandle->sourceId);
|
||||
}
|
||||
|
||||
static void setCurrentSourceIsDone(SSortSource* pSource, SSortHandle* pHandle) {
|
||||
pSource->src.rowIndex = -1;
|
||||
++pHandle->numOfCompletedSources;
|
||||
}
|
||||
|
||||
static int32_t sortComparInit(SMsortComparParam* cmpParam, SArray* pSources, int32_t startIndex, int32_t endIndex, SSortHandle* pHandle) {
|
||||
cmpParam->pSources = taosArrayGet(pSources, startIndex);
|
||||
cmpParam->numOfSources = (endIndex - startIndex + 1);
|
||||
|
@ -205,8 +210,10 @@ static int32_t sortComparInit(SMsortComparParam* cmpParam, SArray* pSources, int
|
|||
for (int32_t i = 0; i < cmpParam->numOfSources; ++i) {
|
||||
SSortSource* pSource = cmpParam->pSources[i];
|
||||
|
||||
// set current source is done
|
||||
if (taosArrayGetSize(pSource->pageIdList) == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
setCurrentSourceIsDone(pSource, pHandle);
|
||||
continue;
|
||||
}
|
||||
|
||||
SPageInfo* pPgInfo = *(SPageInfo**)taosArrayGet(pSource->pageIdList, pSource->pageIndex);
|
||||
|
@ -233,10 +240,9 @@ static int32_t sortComparInit(SMsortComparParam* cmpParam, SArray* pSources, int
|
|||
SSortSource* pSource = cmpParam->pSources[i];
|
||||
pSource->src.pBlock = pHandle->fetchfp(pSource->param);
|
||||
|
||||
// set current source id done
|
||||
// set current source is done
|
||||
if (pSource->src.pBlock == NULL) {
|
||||
pSource->src.rowIndex = -1;
|
||||
++pHandle->numOfCompletedSources;
|
||||
setCurrentSourceIsDone(pSource, pHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ extern "C" {
|
|||
#define FUNC_MGT_FORBID_FILL_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(15)
|
||||
#define FUNC_MGT_INTERVAL_INTERPO_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(16)
|
||||
#define FUNC_MGT_FORBID_STREAM_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(17)
|
||||
#define FUNC_MGT_FORBID_WINDOW_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(18)
|
||||
#define FUNC_MGT_FORBID_GROUP_BY_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(19)
|
||||
|
||||
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
||||
|
||||
|
|
|
@ -1086,8 +1086,8 @@ static int32_t translateUnique(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
}
|
||||
|
||||
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
if (QUERY_NODE_COLUMN != nodeType(pPara)) {
|
||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of UNIQUE can only be columns");
|
||||
if (!nodesExprHasColumn(pPara)) {
|
||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of UNIQUE must contain columns");
|
||||
}
|
||||
|
||||
pFunc->node.resType = ((SExprNode*)pPara)->resType;
|
||||
|
@ -2114,7 +2114,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "tail",
|
||||
.type = FUNCTION_TYPE_TAIL,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
|
||||
.translateFunc = translateTail,
|
||||
.getEnvFunc = getTailFuncEnv,
|
||||
.initFunc = tailFunctionSetup,
|
||||
|
@ -2124,7 +2124,8 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "unique",
|
||||
.type = FUNCTION_TYPE_UNIQUE,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC |
|
||||
FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
|
||||
.translateFunc = translateUnique,
|
||||
.getEnvFunc = getUniqueFuncEnv,
|
||||
.initFunc = uniqueFunctionSetup,
|
||||
|
|
|
@ -165,6 +165,10 @@ bool fmIsIntervalInterpoFunc(int32_t funcId) { return isSpecificClassifyFunc(fun
|
|||
|
||||
bool fmIsForbidStreamFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORBID_STREAM_FUNC); }
|
||||
|
||||
bool fmIsForbidWindowFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORBID_WINDOW_FUNC); }
|
||||
|
||||
bool fmIsForbidGroupByFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORBID_GROUP_BY_FUNC); }
|
||||
|
||||
void fmFuncMgtDestroy() {
|
||||
void* m = gFunMgtService.pFuncNameHashTable;
|
||||
if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) {
|
||||
|
@ -206,7 +210,7 @@ bool fmIsInvertible(int32_t funcId) {
|
|||
return res;
|
||||
}
|
||||
|
||||
//function has same input/output type
|
||||
// function has same input/output type
|
||||
bool fmIsSameInOutType(int32_t funcId) {
|
||||
bool res = false;
|
||||
switch (funcMgtBuiltins[funcId].type) {
|
||||
|
@ -301,7 +305,7 @@ static int32_t createMergeFunction(const SFunctionNode* pSrcFunc, const SFunctio
|
|||
nodesDestroyList(pParameterList);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
//overwrite function restype set by translate function
|
||||
// overwrite function restype set by translate function
|
||||
if (fmIsSameInOutType(pSrcFunc->funcId)) {
|
||||
(*pMergeFunc)->node.resType = pSrcFunc->node.resType;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,8 @@ SNode* nodesMakeNode(ENodeType type) {
|
|||
return makeNode(type, sizeof(SStreamOptions));
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return makeNode(type, sizeof(SLeftValueNode));
|
||||
case QUERY_NODE_COLUMN_REF:
|
||||
return makeNode(type, sizeof(SColumnDefNode));
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return makeNode(type, sizeof(SSetOperator));
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -1463,6 +1465,26 @@ int32_t nodesCollectSpecialNodes(SSelectStmt* pSelect, ESqlClause clause, ENodeT
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EDealRes hasColumn(SNode* pNode, void* pContext) {
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||
*(bool*)pContext = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
bool nodesExprHasColumn(SNode* pNode) {
|
||||
bool hasCol = false;
|
||||
nodesWalkExprPostOrder(pNode, hasColumn, &hasCol);
|
||||
return hasCol;
|
||||
}
|
||||
|
||||
bool nodesExprsHasColumn(SNodeList* pList) {
|
||||
bool hasCol = false;
|
||||
nodesWalkExprsPostOrder(pList, hasColumn, &hasCol);
|
||||
return hasCol;
|
||||
}
|
||||
|
||||
char* nodesGetFillModeString(EFillMode mode) {
|
||||
switch (mode) {
|
||||
case FILL_MODE_NONE:
|
||||
|
|
|
@ -648,6 +648,8 @@ SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrder
|
|||
CHECK_PARSER_STATUS(pCxt);
|
||||
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
||||
((SSelectStmt*)pStmt)->pOrderByList = pOrderByList;
|
||||
} else {
|
||||
((SSetOperator*)pStmt)->pOrderByList = pOrderByList;
|
||||
}
|
||||
return pStmt;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef struct STranslateContext {
|
|||
int32_t currLevel;
|
||||
ESqlClause currClause;
|
||||
SSelectStmt* pCurrSelectStmt;
|
||||
SSetOperator* pCurrSetOperator;
|
||||
SCmdMsgInfo* pCmdMsg;
|
||||
SHashObj* pDbs;
|
||||
SHashObj* pTables;
|
||||
|
@ -432,7 +433,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p
|
|||
static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) {
|
||||
SColumnNode* pCol = *pColRef;
|
||||
|
||||
pCol->pProjectRef = (SNode*)pExpr;
|
||||
// pCol->pProjectRef = (SNode*)pExpr;
|
||||
if (NULL == pExpr->pAssociation) {
|
||||
pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
|
||||
}
|
||||
|
@ -613,17 +614,36 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod
|
|||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static bool translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** pCol) {
|
||||
SNodeList* pProjectionList = pCxt->pCurrSelectStmt->pProjectionList;
|
||||
static SNodeList* getProjectListFromCxt(STranslateContext* pCxt) {
|
||||
if (NULL != pCxt->pCurrSelectStmt) {
|
||||
return pCxt->pCurrSelectStmt->pProjectionList;
|
||||
} else if (NULL != pCxt->pCurrSetOperator) {
|
||||
return pCxt->pCurrSetOperator->pProjectionList;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** pCol, bool* pFound) {
|
||||
SNodeList* pProjectionList = getProjectListFromCxt(pCxt);
|
||||
SNode* pNode;
|
||||
FOREACH(pNode, pProjectionList) {
|
||||
SExprNode* pExpr = (SExprNode*)pNode;
|
||||
if (0 == strcmp((*pCol)->colName, pExpr->aliasName)) {
|
||||
setColumnInfoByExpr(NULL, pExpr, pCol);
|
||||
return true;
|
||||
SColumnRefNode* pColRef = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
|
||||
if (NULL == pColRef) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
strcpy(pColRef->colName, pExpr->aliasName);
|
||||
nodesDestroyNode(*(SNode**)pCol);
|
||||
*(SNode**)pCol = (SNode*)pColRef;
|
||||
*pFound = true;
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
*pFound = false;
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) {
|
||||
|
@ -638,9 +658,11 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) {
|
|||
} else {
|
||||
bool found = false;
|
||||
if (SQL_CLAUSE_ORDER_BY == pCxt->currClause) {
|
||||
found = translateColumnUseAlias(pCxt, pCol);
|
||||
res = translateColumnUseAlias(pCxt, pCol, &found);
|
||||
}
|
||||
if (DEAL_RES_ERROR != res && !found) {
|
||||
res = translateColumnWithoutPrefix(pCxt, pCol);
|
||||
}
|
||||
res = (found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1098,11 +1120,43 @@ static int32_t translateWindowPseudoColumnFunc(STranslateContext* pCxt, SFunctio
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForbidWindowFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
if (!fmIsForbidWindowFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (NULL != pCxt->pCurrSelectStmt->pWindow) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC, pFunc->functionName);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForbidStreamFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
if (!fmIsForbidStreamFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (pCxt->createStream) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC, pFunc->functionName);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForbidGroupByFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
if (!fmIsForbidGroupByFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (NULL != pCxt->pCurrSelectStmt->pGroupByList) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC, pFunc->functionName);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void setFuncClassification(SSelectStmt* pSelect, SFunctionNode* pFunc) {
|
||||
if (NULL != pSelect) {
|
||||
pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId);
|
||||
pSelect->hasRepeatScanFuncs = pSelect->hasRepeatScanFuncs ? true : fmIsRepeatScanFunc(pFunc->funcId);
|
||||
pSelect->hasIndefiniteRowsFunc = pSelect->hasIndefiniteRowsFunc ? true : fmIsIndefiniteRowsFunc(pFunc->funcId);
|
||||
pSelect->hasUniqueFunc = pSelect->hasUniqueFunc ? true : (FUNCTION_TYPE_UNIQUE == pFunc->funcType);
|
||||
pSelect->hasTailFunc = pSelect->hasTailFunc ? true : (FUNCTION_TYPE_TAIL == pFunc->funcType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1130,6 +1184,15 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = translateWindowPseudoColumnFunc(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = translateForbidWindowFunc(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = translateForbidStreamFunc(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = translateForbidGroupByFunc(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
setFuncClassification(pCxt->pCurrSelectStmt, pFunc);
|
||||
}
|
||||
|
@ -1762,11 +1825,11 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
|
|||
} else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
|
||||
} else {
|
||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
SColumnRefNode* pCol = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
|
||||
if (NULL == pCol) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
|
||||
}
|
||||
setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), &pCol);
|
||||
strcpy(pCol->colName, ((SExprNode*)nodesListGetNode(pProjectionList, pos - 1))->aliasName);
|
||||
((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol;
|
||||
nodesDestroyNode(pExpr);
|
||||
}
|
||||
|
@ -1781,9 +1844,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
|
|||
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
bool other;
|
||||
int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (!other) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -1792,6 +1853,7 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -2116,6 +2178,172 @@ static int32_t rewriteTimelineFunc(STranslateContext* pCxt, SSelectStmt* pSelect
|
|||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
typedef struct SRwriteUniqueCxt {
|
||||
STranslateContext* pTranslateCxt;
|
||||
SNode* pExpr;
|
||||
} SRwriteUniqueCxt;
|
||||
|
||||
static EDealRes rewriteSeletcValueFunc(STranslateContext* pCxt, SNode** pNode) {
|
||||
SFunctionNode* pFirst = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFirst) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
strcpy(pFirst->functionName, "first");
|
||||
TSWAP(pFirst->pParameterList, ((SFunctionNode*)*pNode)->pParameterList);
|
||||
strcpy(pFirst->node.aliasName, ((SExprNode*)*pNode)->aliasName);
|
||||
nodesDestroyNode(*pNode);
|
||||
*pNode = (SNode*)pFirst;
|
||||
pCxt->errCode = fmGetFuncInfo(pFirst, pCxt->msgBuf.buf, pCxt->msgBuf.len);
|
||||
pCxt->pCurrSelectStmt->hasAggFuncs = true;
|
||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
static EDealRes rewriteUniqueFunc(SNode** pNode, void* pContext) {
|
||||
SRwriteUniqueCxt* pCxt = pContext;
|
||||
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
|
||||
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
NODES_CLEAR_LIST(pFunc->pParameterList);
|
||||
strcpy(((SExprNode*)pExpr)->aliasName, ((SExprNode*)*pNode)->aliasName);
|
||||
nodesDestroyNode(*pNode);
|
||||
*pNode = pExpr;
|
||||
pCxt->pExpr = pExpr;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
} else if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
|
||||
return rewriteSeletcValueFunc(pCxt->pTranslateCxt, pNode);
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static SNode* createGroupingSet(SNode* pExpr) {
|
||||
SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
|
||||
if (NULL == pGroupingSet) {
|
||||
return NULL;
|
||||
}
|
||||
pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
|
||||
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, nodesCloneNode(pExpr))) {
|
||||
nodesDestroyNode((SNode*)pGroupingSet);
|
||||
return NULL;
|
||||
}
|
||||
return (SNode*)pGroupingSet;
|
||||
}
|
||||
|
||||
static int32_t rewriteUniqueStmt(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (!pSelect->hasUniqueFunc) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SRwriteUniqueCxt cxt = {.pTranslateCxt = pCxt, .pExpr = NULL};
|
||||
nodesRewriteExprs(pSelect->pProjectionList, rewriteUniqueFunc, &cxt);
|
||||
if (TSDB_CODE_SUCCESS == cxt.pTranslateCxt->errCode) {
|
||||
cxt.pTranslateCxt->errCode = nodesListMakeStrictAppend(&pSelect->pGroupByList, createGroupingSet(cxt.pExpr));
|
||||
}
|
||||
pSelect->hasIndefiniteRowsFunc = false;
|
||||
return cxt.pTranslateCxt->errCode;
|
||||
}
|
||||
|
||||
typedef struct SRwriteTailCxt {
|
||||
STranslateContext* pTranslateCxt;
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
} SRwriteTailCxt;
|
||||
|
||||
static EDealRes rewriteTailFunc(SNode** pNode, void* pContext) {
|
||||
SRwriteTailCxt* pCxt = pContext;
|
||||
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
if (FUNCTION_TYPE_TAIL == pFunc->funcType) {
|
||||
pCxt->limit = ((SValueNode*)nodesListGetNode(pFunc->pParameterList, 1))->datum.i;
|
||||
if (3 == LIST_LENGTH(pFunc->pParameterList)) {
|
||||
pCxt->offset = ((SValueNode*)nodesListGetNode(pFunc->pParameterList, 2))->datum.i;
|
||||
}
|
||||
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
strcpy(((SExprNode*)pExpr)->aliasName, ((SExprNode*)*pNode)->aliasName);
|
||||
NODES_CLEAR_LIST(pFunc->pParameterList);
|
||||
nodesDestroyNode(*pNode);
|
||||
*pNode = pExpr;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t createLimieNode(SRwriteTailCxt* pCxt, SLimitNode** pOutput) {
|
||||
*pOutput = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT);
|
||||
if (NULL == *pOutput) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
(*pOutput)->limit = pCxt->limit;
|
||||
(*pOutput)->offset = pCxt->offset;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static SNode* createOrderByExpr(STranslateContext* pCxt) {
|
||||
SOrderByExprNode* pOrder = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR);
|
||||
if (NULL == pOrder) {
|
||||
return NULL;
|
||||
}
|
||||
pCxt->errCode = createPrimaryKeyCol(pCxt, &pOrder->pExpr);
|
||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||
nodesDestroyNode((SNode*)pOrder);
|
||||
return NULL;
|
||||
}
|
||||
pOrder->order = ORDER_DESC;
|
||||
pOrder->nullOrder = NULL_ORDER_FIRST;
|
||||
return (SNode*)pOrder;
|
||||
}
|
||||
|
||||
static int32_t rewriteTailStmt(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (!pSelect->hasTailFunc) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SRwriteTailCxt cxt = {.pTranslateCxt = pCxt, .limit = -1, .offset = -1};
|
||||
nodesRewriteExprs(pSelect->pProjectionList, rewriteTailFunc, &cxt);
|
||||
int32_t code = nodesListMakeStrictAppend(&pSelect->pOrderByList, createOrderByExpr(pCxt));
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createLimieNode(&cxt, &pSelect->pLimit);
|
||||
}
|
||||
pSelect->hasIndefiniteRowsFunc = false;
|
||||
return code;
|
||||
}
|
||||
|
||||
typedef struct SReplaceOrderByAliasCxt {
|
||||
STranslateContext* pTranslateCxt;
|
||||
SNodeList* pProjectionList;
|
||||
} SReplaceOrderByAliasCxt;
|
||||
|
||||
static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) {
|
||||
SReplaceOrderByAliasCxt* pCxt = pContext;
|
||||
if (QUERY_NODE_COLUMN_REF == nodeType(*pNode)) {
|
||||
SNodeList* pProjectionList = pCxt->pProjectionList;
|
||||
SNode* pProject = NULL;
|
||||
FOREACH(pProject, pProjectionList) {
|
||||
SExprNode* pExpr = (SExprNode*)pProject;
|
||||
if (0 == strcmp(((SColumnRefNode*)*pNode)->colName, pExpr->aliasName)) {
|
||||
SNode* pNew = nodesCloneNode(pProject);
|
||||
if (NULL == pNew) {
|
||||
pCxt->pTranslateCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
nodesDestroyNode(*pNode);
|
||||
*pNode = pNew;
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t replaceOrderByAlias(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList) {
|
||||
SReplaceOrderByAliasCxt cxt = {.pTranslateCxt = pCxt, .pProjectionList = pProjectionList};
|
||||
nodesRewriteExprsPostOrder(pOrderByList, replaceOrderByAliasImpl, &cxt);
|
||||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
pCxt->pCurrSelectStmt = pSelect;
|
||||
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
|
||||
|
@ -2147,9 +2375,18 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = checkLimit(pCxt, pSelect);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = rewriteUniqueStmt(pCxt, pSelect);
|
||||
}
|
||||
// if (TSDB_CODE_SUCCESS == code) {
|
||||
// code = rewriteTailStmt(pCxt, pSelect);
|
||||
// }
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = rewriteTimelineFunc(pCxt, pSelect);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = replaceOrderByAlias(pCxt, pSelect->pProjectionList, pSelect->pOrderByList);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -2186,7 +2423,7 @@ static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType d
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateSetOperatorImpl(STranslateContext* pCxt, SSetOperator* pSetOperator) {
|
||||
static int32_t translateSetOperProject(STranslateContext* pCxt, SSetOperator* pSetOperator) {
|
||||
SNodeList* pLeftProjections = getProjectList(pSetOperator->pLeft);
|
||||
SNodeList* pRightProjections = getProjectList(pSetOperator->pRight);
|
||||
if (LIST_LENGTH(pLeftProjections) != LIST_LENGTH(pRightProjections)) {
|
||||
|
@ -2221,6 +2458,23 @@ static uint8_t calcSetOperatorPrecision(SSetOperator* pSetOperator) {
|
|||
return calcPrecision(getStmtPrecision(pSetOperator->pLeft), getStmtPrecision(pSetOperator->pRight));
|
||||
}
|
||||
|
||||
static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pSetOperator) {
|
||||
bool other;
|
||||
int32_t code = translateOrderByPosition(pCxt, pSetOperator->pProjectionList, pSetOperator->pOrderByList, &other);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (other) {
|
||||
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
|
||||
pCxt->pCurrSelectStmt = NULL;
|
||||
pCxt->pCurrSetOperator = pSetOperator;
|
||||
code = translateExprList(pCxt, pSetOperator->pOrderByList);
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = replaceOrderByAlias(pCxt, pSetOperator->pProjectionList, pSetOperator->pOrderByList);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateSetOperator(STranslateContext* pCxt, SSetOperator* pSetOperator) {
|
||||
int32_t code = translateQuery(pCxt, pSetOperator->pLeft);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -2231,7 +2485,10 @@ static int32_t translateSetOperator(STranslateContext* pCxt, SSetOperator* pSetO
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pSetOperator->precision = calcSetOperatorPrecision(pSetOperator);
|
||||
code = translateSetOperatorImpl(pCxt, pSetOperator);
|
||||
code = translateSetOperProject(pCxt, pSetOperator);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateSetOperOrderBy(pCxt, pSetOperator);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -185,9 +185,15 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
|||
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
|
||||
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
|
||||
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
|
||||
return "%s function not allowed in fill query";
|
||||
return "%s function does not supportted in fill query";
|
||||
case TSDB_CODE_PAR_INVALID_WINDOW_PC:
|
||||
return "_WSTARTTS, _WENDTS and _WDURATION can only be used in window queries";
|
||||
return "_WSTARTTS, _WENDTS and _WDURATION can only be used in window query";
|
||||
case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
|
||||
return "%s function does not supportted in time window query";
|
||||
case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
|
||||
return "%s function does not supportted in stream query";
|
||||
case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
|
||||
return "%s function does not supportted in group query";
|
||||
case TSDB_CODE_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
default:
|
||||
|
|
|
@ -285,7 +285,7 @@ class MockCatalogServiceImpl {
|
|||
}
|
||||
|
||||
void createSmaIndex(const SMCreateSmaReq* pReq) {
|
||||
STableIndexInfo info;
|
||||
STableIndexInfo info = {0};
|
||||
info.intervalUnit = pReq->intervalUnit;
|
||||
info.slidingUnit = pReq->slidingUnit;
|
||||
info.interval = pReq->interval;
|
||||
|
|
|
@ -528,6 +528,12 @@ TEST_F(ParserInitialCTest, createStream) {
|
|||
clearCreateStreamReq();
|
||||
}
|
||||
|
||||
TEST_F(ParserInitialCTest, createStreamSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("CREATE STREAM s1 AS SELECT PERCENTILE(c1, 30) FROM t1", TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
|
||||
TEST_F(ParserInitialCTest, createTable) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
|
|
@ -161,6 +161,40 @@ TEST_F(ParserSelectTest, useDefinedFunc) {
|
|||
run("SELECT udf2(c1) FROM t1 GROUP BY c2");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, uniqueFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT UNIQUE(c1) FROM t1");
|
||||
|
||||
run("SELECT UNIQUE(c2 + 10) FROM t1 WHERE c1 > 10");
|
||||
|
||||
run("SELECT UNIQUE(c2 + 10), ts, c2 FROM t1 WHERE c1 > 10");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, uniqueFuncSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT UNIQUE(c1) FROM t1 INTERVAL(10S)", TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC);
|
||||
|
||||
run("SELECT UNIQUE(c1) FROM t1 GROUP BY c2", TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, tailFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT TAIL(c1, 10) FROM t1");
|
||||
|
||||
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, tailFuncSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT TAIL(c1, 10) FROM t1 INTERVAL(10S)", TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC);
|
||||
|
||||
run("SELECT TAIL(c1, 10) FROM t1 GROUP BY c2", TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, groupBy) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
@ -328,6 +362,8 @@ TEST_F(ParserSelectTest, setOperator) {
|
|||
run("(SELECT * FROM t1) UNION ALL (SELECT * FROM t1)");
|
||||
|
||||
run("SELECT c1 FROM (SELECT c1 FROM t1 UNION ALL SELECT c1 FROM t1)");
|
||||
|
||||
run("SELECT c1, c2 FROM t1 UNION ALL SELECT c1 as a, c2 as b FROM t1 ORDER BY c1");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, informationSchema) {
|
||||
|
|
|
@ -537,10 +537,12 @@ static int32_t stbSplCreateMergeKeys(SNodeList* pSortKeys, SNodeList* pTargets,
|
|||
SNode* pNode = NULL;
|
||||
FOREACH(pNode, pSortKeys) {
|
||||
SOrderByExprNode* pSortKey = (SOrderByExprNode*)pNode;
|
||||
SExprNode* pSortExpr = (SExprNode*)pSortKey->pExpr;
|
||||
SNode* pTarget = NULL;
|
||||
bool found = false;
|
||||
FOREACH(pTarget, pTargets) {
|
||||
if (0 == strcmp(((SExprNode*)pSortKey->pExpr)->aliasName, ((SColumnNode*)pTarget)->colName)) {
|
||||
if ((QUERY_NODE_COLUMN == nodeType(pSortExpr) && nodesEqualNode((SNode*)pSortExpr, pTarget)) ||
|
||||
(0 == strcmp(pSortExpr->aliasName, ((SColumnNode*)pTarget)->colName))) {
|
||||
code = nodesListMakeStrictAppend(&pMergeKeys, stbSplCreateOrderByExpr(pSortKey, pTarget));
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
break;
|
||||
|
@ -549,7 +551,7 @@ static int32_t stbSplCreateMergeKeys(SNodeList* pSortKeys, SNodeList* pTargets,
|
|||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code && !found) {
|
||||
SNode* pCol = stbSplCreateColumnNode((SExprNode*)pSortKey->pExpr);
|
||||
SNode* pCol = stbSplCreateColumnNode(pSortExpr);
|
||||
code = nodesListMakeStrictAppend(&pMergeKeys, stbSplCreateOrderByExpr(pSortKey, pCol));
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodesListStrictAppend(pTargets, pCol);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
static void dumpQueryPlan(SQueryPlan* pPlan) {
|
||||
char* pStr = NULL;
|
||||
nodesNodeToString((SNode*)pPlan, false, &pStr, NULL);
|
||||
planDebugL("Query Plan: %s", pStr);
|
||||
planDebugL("QID:0x%" PRIx64 " Query Plan: %s", pPlan->queryId, pStr);
|
||||
taosMemoryFree(pStr);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,3 +53,23 @@ TEST_F(PlanBasicTest, func) {
|
|||
|
||||
run("SELECT TOP(c1, 60) FROM t1");
|
||||
}
|
||||
|
||||
TEST_F(PlanBasicTest, uniqueFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT UNIQUE(c1) FROM t1");
|
||||
|
||||
run("SELECT UNIQUE(c2 + 10) FROM t1 WHERE c1 > 10");
|
||||
|
||||
run("SELECT UNIQUE(c2 + 10), ts, c2 FROM t1 WHERE c1 > 10");
|
||||
|
||||
run("SELECT UNIQUE(c1) a FROM t1 ORDER BY a");
|
||||
}
|
||||
|
||||
TEST_F(PlanBasicTest, tailFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT TAIL(c1, 10) FROM t1");
|
||||
|
||||
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10");
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ TEST_F(PlanOrderByTest, basic) {
|
|||
run("SELECT c1 FROM t1 ORDER BY c1");
|
||||
// ORDER BY key is not in the projection list
|
||||
run("SELECT c1 FROM t1 ORDER BY c2");
|
||||
|
||||
run("SELECT c1 AS a FROM t1 ORDER BY a");
|
||||
|
||||
run("SELECT c1 + 10 AS a FROM t1 ORDER BY a");
|
||||
}
|
||||
|
||||
TEST_F(PlanOrderByTest, expr) {
|
||||
|
@ -41,6 +45,12 @@ TEST_F(PlanOrderByTest, nullsOrder) {
|
|||
run("SELECT * FROM t1 ORDER BY c1 DESC NULLS FIRST");
|
||||
}
|
||||
|
||||
TEST_F(PlanOrderByTest, withGroupBy) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT SUM(c1) AS a FROM t1 GROUP BY c2 ORDER BY a");
|
||||
}
|
||||
|
||||
TEST_F(PlanOrderByTest, stable) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
@ -51,4 +61,6 @@ TEST_F(PlanOrderByTest, stable) {
|
|||
run("SELECT c2 FROM st1 ORDER BY c1");
|
||||
|
||||
run("SELECT c2 FROM st1 PARTITION BY c2 ORDER BY c1");
|
||||
|
||||
run("SELECT c1 AS a FROM st1 ORDER BY a");
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ class PlanSetOpTest : public PlannerTestBase {};
|
|||
TEST_F(PlanSetOpTest, unionAll) {
|
||||
useDb("root", "test");
|
||||
|
||||
// sql 1: single UNION ALL operator
|
||||
// single UNION ALL operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20");
|
||||
// sql 2: multi UNION ALL operator
|
||||
// multi UNION ALL operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 "
|
||||
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 "
|
||||
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 30");
|
||||
|
@ -46,6 +46,14 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) {
|
|||
run("SELECT ts FROM (SELECT ts FROM st1) UNION ALL SELECT ts FROM (SELECT ts FROM st1)");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionAllWithOrderBy) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 ORDER BY c1");
|
||||
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 ORDER BY 1");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, union) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
|
|
@ -946,8 +946,7 @@ int32_t taosGetFqdn(char *fqdn) {
|
|||
#endif // __APPLE__
|
||||
int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
|
||||
if (!result) {
|
||||
// printf("failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret));
|
||||
assert(0);
|
||||
fprintf(stderr,"failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ class TDTestCase:
|
|||
def check_tail_table(self , tbname , col_name , tail_rows , offset):
|
||||
tail_sql = f"select tail({col_name} , {tail_rows} , {offset}) from {tbname}"
|
||||
equal_sql = f"select {col_name} from (select ts , {col_name} from {tbname} order by ts desc limit {tail_rows} offset {offset}) order by ts"
|
||||
#equal_sql = f"select {col_name} from {tbname} order by ts desc limit {tail_rows} offset {offset}"
|
||||
tdSql.query(tail_sql)
|
||||
tail_result = tdSql.queryResult
|
||||
|
||||
|
@ -293,22 +294,22 @@ class TDTestCase:
|
|||
tdSql.checkData(0, 0, None)
|
||||
tdSql.checkData(1, 0, None)
|
||||
|
||||
tdSql.query("select tail(c1,3,2) from ct4 where c1 >2 ")
|
||||
tdSql.checkData(0, 0, 7)
|
||||
tdSql.query("select tail(c1,3,2) from ct4 where c1 >2 order by 1")
|
||||
tdSql.checkData(0, 0, 5)
|
||||
tdSql.checkData(1, 0, 6)
|
||||
tdSql.checkData(2, 0, 5)
|
||||
tdSql.checkData(2, 0, 7)
|
||||
|
||||
tdSql.query("select tail(c1,2,1) from ct4 where c2 between 0 and 99999")
|
||||
tdSql.checkData(0, 0, 2)
|
||||
tdSql.checkData(1, 0, 1)
|
||||
tdSql.query("select tail(c1,2,1) from ct4 where c2 between 0 and 99999 order by 1")
|
||||
tdSql.checkData(0, 0, 1)
|
||||
tdSql.checkData(1, 0, 2)
|
||||
|
||||
# tail with union all
|
||||
tdSql.query("select tail(c1,2,1) from ct4 union all select c1 from ct1")
|
||||
tdSql.checkRows(15)
|
||||
tdSql.query("select tail(c1,2,1) from ct4 union all select c1 from ct2")
|
||||
tdSql.query("select tail(c1,2,1) from ct4 union all select c1 from ct2 order by 1")
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkData(0, 0, 1)
|
||||
tdSql.checkData(1, 0, 0)
|
||||
tdSql.checkData(0, 0, 0)
|
||||
tdSql.checkData(1, 0, 1)
|
||||
tdSql.query("select tail(c2,2,1) from ct4 union all select abs(c2)/2 from ct4")
|
||||
tdSql.checkRows(14)
|
||||
|
||||
|
@ -334,18 +335,18 @@ class TDTestCase:
|
|||
tdSql.execute(f" insert into ttb1 values({ts_value} , {i})")
|
||||
tdSql.execute(f" insert into ttb2 values({ts_value} , {i})")
|
||||
|
||||
tdSql.query("select tail(tb2.num,3,2) from tb1, tb2 where tb1.ts=tb2.ts ")
|
||||
tdSql.query("select tail(tb2.num,3,2) from tb1, tb2 where tb1.ts=tb2.ts order by 1 desc")
|
||||
tdSql.checkRows(3)
|
||||
tdSql.checkData(0,0,5)
|
||||
tdSql.checkData(0,0,7)
|
||||
tdSql.checkData(1,0,6)
|
||||
tdSql.checkData(2,0,7)
|
||||
tdSql.checkData(2,0,5)
|
||||
|
||||
# nest query
|
||||
# tdSql.query("select tail(c1,2) from (select c1 from ct1)")
|
||||
tdSql.query("select c1 from (select tail(c1,2) c1 from ct4)")
|
||||
tdSql.query("select c1 from (select tail(c1,2) c1 from ct4) order by 1 nulls first")
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkData(0, 0, 0)
|
||||
tdSql.checkData(1, 0, None)
|
||||
tdSql.checkData(0, 0, None)
|
||||
tdSql.checkData(1, 0, 0)
|
||||
|
||||
tdSql.query("select sum(c1) from (select tail(c1,2) c1 from ct1)")
|
||||
tdSql.checkRows(1)
|
||||
|
|
|
@ -93,8 +93,8 @@ class TDTestCase:
|
|||
"select unique(c1) , min(c1) from t1",
|
||||
"select unique(c1) , spread(c1) from t1",
|
||||
"select unique(c1) , diff(c1) from t1",
|
||||
"select unique(c1) , abs(c1) from t1",
|
||||
"select unique(c1) , c1 from t1",
|
||||
#"select unique(c1) , abs(c1) from t1", # support
|
||||
#"select unique(c1) , c1 from t1",
|
||||
"select unique from stb1 partition by tbname",
|
||||
"select unique(123--123)==1 from stb1 partition by tbname",
|
||||
"select unique(123) from stb1 partition by tbname",
|
||||
|
@ -104,21 +104,21 @@ class TDTestCase:
|
|||
"select unique(c1 ,c2 ) from stb1 partition by tbname",
|
||||
"select unique(c1 ,NULL) from stb1 partition by tbname",
|
||||
"select unique(,) from stb1 partition by tbname;",
|
||||
"select unique(floor(c1) ab from stb1 partition by tbname)",
|
||||
"select unique(c1) as int from stb1 partition by tbname",
|
||||
#"select unique(floor(c1) ab from stb1 partition by tbname)", # support
|
||||
#"select unique(c1) as int from stb1 partition by tbname",
|
||||
"select unique('c1') from stb1 partition by tbname",
|
||||
"select unique(NULL) from stb1 partition by tbname",
|
||||
"select unique('') from stb1 partition by tbname",
|
||||
"select unique(c%) from stb1 partition by tbname",
|
||||
#"select unique(t1) from stb1 partition by tbname",
|
||||
#"select unique(t1) from stb1 partition by tbname", # support
|
||||
"select unique(True) from stb1 partition by tbname",
|
||||
"select unique(c1) , count(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , avg(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , min(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , spread(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , diff(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , abs(c1) from stb1 partition by tbname",
|
||||
"select unique(c1) , c1 from stb1 partition by tbname"
|
||||
#"select unique(c1) , abs(c1) from stb1 partition by tbname", # support
|
||||
#"select unique(c1) , c1 from stb1 partition by tbname" # support
|
||||
|
||||
]
|
||||
for error_sql in error_sql_lists:
|
||||
|
@ -198,7 +198,7 @@ class TDTestCase:
|
|||
unique_datas = []
|
||||
for elem in unique_result:
|
||||
unique_datas.append(elem[0])
|
||||
|
||||
unique_datas.sort(key=lambda x: (x is None, x))
|
||||
|
||||
tdSql.query(origin_sql)
|
||||
origin_result = tdSql.queryResult
|
||||
|
@ -212,6 +212,7 @@ class TDTestCase:
|
|||
continue
|
||||
else:
|
||||
pre_unique.append(elem)
|
||||
pre_unique.sort(key=lambda x: (x is None, x))
|
||||
|
||||
if pre_unique == unique_datas:
|
||||
tdLog.info(" unique query check pass , unique sql is: %s" %unique_sql)
|
||||
|
@ -266,16 +267,16 @@ class TDTestCase:
|
|||
tdSql.checkRows(10)
|
||||
|
||||
tdSql.error("select unique(c1),tbname from ct1")
|
||||
tdSql.error("select unique(c1),t1 from ct1")
|
||||
#tdSql.error("select unique(c1),t1 from ct1") #support
|
||||
|
||||
# unique with common col
|
||||
tdSql.error("select unique(c1) ,ts from ct1")
|
||||
tdSql.error("select unique(c1) ,c1 from ct1")
|
||||
#tdSql.error("select unique(c1) ,ts from ct1")
|
||||
#tdSql.error("select unique(c1) ,c1 from ct1")
|
||||
|
||||
# unique with scalar function
|
||||
tdSql.error("select unique(c1) ,abs(c1) from ct1")
|
||||
#tdSql.error("select unique(c1) ,abs(c1) from ct1")
|
||||
tdSql.error("select unique(c1) , unique(c2) from ct1")
|
||||
tdSql.error("select unique(c1) , abs(c2)+2 from ct1")
|
||||
#tdSql.error("select unique(c1) , abs(c2)+2 from ct1")
|
||||
|
||||
|
||||
# unique with aggregate function
|
||||
|
@ -288,13 +289,13 @@ class TDTestCase:
|
|||
tdSql.query("select unique(c1) from ct4 where c1 is null")
|
||||
tdSql.checkData(0, 0, None)
|
||||
|
||||
tdSql.query("select unique(c1) from ct4 where c1 >2 ")
|
||||
tdSql.checkData(0, 0, 8)
|
||||
tdSql.checkData(1, 0, 7)
|
||||
tdSql.checkData(2, 0, 6)
|
||||
tdSql.checkData(5, 0, 3)
|
||||
tdSql.query("select unique(c1) from ct4 where c1 >2 order by 1")
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.checkData(1, 0, 4)
|
||||
tdSql.checkData(2, 0, 5)
|
||||
tdSql.checkData(5, 0, 8)
|
||||
|
||||
tdSql.query("select unique(c1) from ct4 where c2 between 0 and 99999")
|
||||
tdSql.query("select unique(c1) from ct4 where c2 between 0 and 99999 order by 1 desc")
|
||||
tdSql.checkData(0, 0, 8)
|
||||
tdSql.checkData(1, 0, 7)
|
||||
tdSql.checkData(2, 0, 6)
|
||||
|
@ -335,23 +336,23 @@ class TDTestCase:
|
|||
tdSql.execute(f" insert into ttb1 values({ts_value} , {i})")
|
||||
tdSql.execute(f" insert into ttb2 values({ts_value} , {i})")
|
||||
|
||||
tdSql.query("select unique(tb2.num) from tb1, tb2 where tb1.ts=tb2.ts ")
|
||||
tdSql.query("select unique(tb2.num) from tb1, tb2 where tb1.ts=tb2.ts order by 1")
|
||||
tdSql.checkRows(10)
|
||||
tdSql.checkData(0,0,0)
|
||||
tdSql.checkData(1,0,1)
|
||||
tdSql.checkData(2,0,2)
|
||||
tdSql.checkData(9,0,9)
|
||||
|
||||
tdSql.query("select unique(tb2.num) from tb1, tb2 where tb1.ts=tb2.ts union all select unique(tb1.num) from tb1, tb2 where tb1.ts=tb2.ts ")
|
||||
tdSql.query("select unique(tb2.num) from tb1, tb2 where tb1.ts=tb2.ts union all select unique(tb1.num) from tb1, tb2 where tb1.ts=tb2.ts order by 1")
|
||||
tdSql.checkRows(20)
|
||||
tdSql.checkData(0,0,0)
|
||||
tdSql.checkData(1,0,1)
|
||||
tdSql.checkData(2,0,2)
|
||||
tdSql.checkData(9,0,9)
|
||||
tdSql.checkData(2,0,1)
|
||||
tdSql.checkData(4,0,2)
|
||||
tdSql.checkData(18,0,9)
|
||||
|
||||
# nest query
|
||||
# tdSql.query("select unique(c1) from (select c1 from ct1)")
|
||||
tdSql.query("select c1 from (select unique(c1) c1 from ct4)")
|
||||
tdSql.query("select c1 from (select unique(c1) c1 from ct4) order by 1 desc nulls first")
|
||||
tdSql.checkRows(10)
|
||||
tdSql.checkData(0, 0, None)
|
||||
tdSql.checkData(1, 0, 8)
|
||||
|
@ -366,7 +367,7 @@ class TDTestCase:
|
|||
tdSql.checkData(0, 0, 45)
|
||||
tdSql.checkData(1, 0, 45)
|
||||
|
||||
tdSql.query("select 1-abs(c1) from (select unique(c1) c1 from ct4)")
|
||||
tdSql.query("select 1-abs(c1) from (select unique(c1) c1 from ct4) order by 1 nulls first")
|
||||
tdSql.checkRows(10)
|
||||
tdSql.checkData(0, 0, None)
|
||||
tdSql.checkData(1, 0, -7.000000000)
|
||||
|
@ -421,7 +422,7 @@ class TDTestCase:
|
|||
f"insert into sub1_bound values ( now()+1s, 2147483648, 9223372036854775808, 32768, 128, 3.40E+38, 1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )"
|
||||
)
|
||||
|
||||
tdSql.query("select unique(c2) from sub1_bound")
|
||||
tdSql.query("select unique(c2) from sub1_bound order by 1 desc")
|
||||
tdSql.checkRows(5)
|
||||
tdSql.checkData(0,0,9223372036854775807)
|
||||
|
||||
|
|
Loading…
Reference in New Issue