first(*)/last(*) rewrite
This commit is contained in:
parent
fdbab777e5
commit
8ef6b184f2
|
@ -30,11 +30,19 @@ extern "C" {
|
||||||
#define FOREACH(node, list) \
|
#define FOREACH(node, list) \
|
||||||
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext)
|
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext)
|
||||||
|
|
||||||
// only be use in FOREACH
|
|
||||||
#define ERASE_NODE(list) cell = nodesListErase(list, cell);
|
|
||||||
|
|
||||||
#define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode)
|
#define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode)
|
||||||
|
|
||||||
|
#define INSERT_LIST(target, src) nodesListInsertList((target), cell, src)
|
||||||
|
|
||||||
|
#define WHERE_EACH(node, list) \
|
||||||
|
SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
|
||||||
|
while (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false))
|
||||||
|
|
||||||
|
#define WHERE_NEXT cell = cell->pNext
|
||||||
|
|
||||||
|
// only be use in WHERE_EACH
|
||||||
|
#define ERASE_NODE(list) cell = nodesListErase((list), cell)
|
||||||
|
|
||||||
#define FORBOTH(node1, list1, node2, list2) \
|
#define FORBOTH(node1, list1, node2, list2) \
|
||||||
for (SListCell* cell1 = (NULL != (list1) ? (list1)->pHead : NULL), *cell2 = (NULL != (list2) ? (list2)->pHead : NULL); \
|
for (SListCell* cell1 = (NULL != (list1) ? (list1)->pHead : NULL), *cell2 = (NULL != (list2) ? (list2)->pHead : NULL); \
|
||||||
(NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), (NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), (node1 != NULL && node2 != NULL); \
|
(NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), (NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), (node1 != NULL && node2 != NULL); \
|
||||||
|
@ -202,7 +210,9 @@ int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode);
|
||||||
int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode);
|
int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode);
|
||||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
||||||
int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
||||||
|
int32_t nodesListPushFront(SNodeList* pList, SNodeptr pNode);
|
||||||
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
|
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
|
||||||
|
void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc);
|
||||||
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index);
|
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index);
|
||||||
void nodesDestroyList(SNodeList* pList);
|
void nodesDestroyList(SNodeList* pList);
|
||||||
// Only clear the linked list structure, without releasing the elements inside
|
// Only clear the linked list structure, without releasing the elements inside
|
||||||
|
|
|
@ -644,7 +644,7 @@ SNodeList* nodesMakeList() {
|
||||||
|
|
||||||
int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode) {
|
int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode) {
|
||||||
if (NULL == pList || NULL == pNode) {
|
if (NULL == pList || NULL == pNode) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
SListCell* p = taosMemoryCalloc(1, sizeof(SListCell));
|
SListCell* p = taosMemoryCalloc(1, sizeof(SListCell));
|
||||||
if (NULL == p) {
|
if (NULL == p) {
|
||||||
|
@ -688,7 +688,7 @@ int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode) {
|
||||||
|
|
||||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||||
if (NULL == pTarget || NULL == pSrc) {
|
if (NULL == pTarget || NULL == pSrc) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == pTarget->pHead) {
|
if (NULL == pTarget->pHead) {
|
||||||
|
@ -717,11 +717,34 @@ int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t nodesListPushFront(SNodeList* pList, SNodeptr pNode) {
|
||||||
|
if (NULL == pList || NULL == pNode) {
|
||||||
|
return TSDB_CODE_FAILED;
|
||||||
|
}
|
||||||
|
SListCell* p = taosMemoryCalloc(1, sizeof(SListCell));
|
||||||
|
if (NULL == p) {
|
||||||
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
p->pNode = pNode;
|
||||||
|
if (NULL != pList->pHead) {
|
||||||
|
pList->pHead->pPrev = p;
|
||||||
|
p->pNext = pList->pHead;
|
||||||
|
}
|
||||||
|
pList->pHead = p;
|
||||||
|
++(pList->length);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
|
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
|
||||||
if (NULL == pCell->pPrev) {
|
if (NULL == pCell->pPrev) {
|
||||||
pList->pHead = pCell->pNext;
|
pList->pHead = pCell->pNext;
|
||||||
} else {
|
} else {
|
||||||
pCell->pPrev->pNext = pCell->pNext;
|
pCell->pPrev->pNext = pCell->pNext;
|
||||||
|
}
|
||||||
|
if (NULL == pCell->pNext) {
|
||||||
|
pList->pTail = pCell->pPrev;
|
||||||
|
} else {
|
||||||
pCell->pNext->pPrev = pCell->pPrev;
|
pCell->pNext->pPrev = pCell->pPrev;
|
||||||
}
|
}
|
||||||
SListCell* pNext = pCell->pNext;
|
SListCell* pNext = pCell->pNext;
|
||||||
|
@ -731,6 +754,24 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
|
||||||
return pNext;
|
return pNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc) {
|
||||||
|
if (NULL == pTarget || NULL == pPos || NULL == pSrc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == pPos->pPrev) {
|
||||||
|
pTarget->pHead = pSrc->pHead;
|
||||||
|
} else {
|
||||||
|
pPos->pPrev->pNext = pSrc->pHead;
|
||||||
|
}
|
||||||
|
pSrc->pHead->pPrev = pPos->pPrev;
|
||||||
|
pSrc->pTail->pNext = pPos;
|
||||||
|
pPos->pPrev = pSrc->pTail;
|
||||||
|
|
||||||
|
pTarget->length += pSrc->length;
|
||||||
|
taosMemoryFreeClear(pSrc);
|
||||||
|
}
|
||||||
|
|
||||||
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index) {
|
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index) {
|
||||||
SNode* node;
|
SNode* node;
|
||||||
FOREACH(node, pList) {
|
FOREACH(node, pList) {
|
||||||
|
|
|
@ -743,24 +743,99 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool* pIsSelectStar) {
|
static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
|
||||||
|
*pCols = nodesMakeList();
|
||||||
|
if (NULL == *pCols) {
|
||||||
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
|
||||||
|
size_t nums = taosArrayGetSize(pTables);
|
||||||
|
for (size_t i = 0; i < nums; ++i) {
|
||||||
|
STableNode* pTable = taosArrayGetP(pTables, i);
|
||||||
|
int32_t code = createColumnNodeByTable(pCxt, pTable, *pCols);
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isFirstLastFunc(SFunctionNode* pFunc) {
|
||||||
|
return (FUNCTION_TYPE_FIRST == pFunc->funcType || FUNCTION_TYPE_LAST == pFunc->funcType);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isFirstLastStar(SNode* pNode) {
|
||||||
|
if (QUERY_NODE_FUNCTION != nodeType(pNode) || !isFirstLastFunc((SFunctionNode*)pNode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
|
||||||
|
if (LIST_LENGTH(pParameterList) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SNode* pParam = nodesListGetNode(pParameterList, 0);
|
||||||
|
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SNode* createFirstLastFunc(SFunctionNode* pSrcFunc, SColumnNode* pCol) {
|
||||||
|
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pFunc->pParameterList = nodesMakeList();
|
||||||
|
if (NULL == pFunc->pParameterList || TSDB_CODE_SUCCESS != nodesListAppend(pFunc->pParameterList, pCol)) {
|
||||||
|
nodesDestroyNode(pFunc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = pCol->node.resType;
|
||||||
|
pFunc->funcId = pSrcFunc->funcId;
|
||||||
|
pFunc->funcType = pSrcFunc->funcType;
|
||||||
|
strcpy(pFunc->functionName, pSrcFunc->functionName);
|
||||||
|
snprintf(pFunc->node.aliasName, sizeof(pFunc->node.aliasName), (FUNCTION_TYPE_FIRST == pSrcFunc->funcType ? "first(%s)" : "last(%s)"), pCol->colName);
|
||||||
|
|
||||||
|
return (SNode*)pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t createFirstLastAllCols(STranslateContext* pCxt, SFunctionNode* pSrcFunc, SNodeList** pOutput) {
|
||||||
|
SNodeList* pCols = NULL;
|
||||||
|
if (TSDB_CODE_SUCCESS != createAllColumns(pCxt, &pCols)) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNodeList* pFuncs = nodesMakeList();
|
||||||
|
if (NULL == pFuncs) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
SNode* pCol = NULL;
|
||||||
|
FOREACH(pCol, pCols) {
|
||||||
|
if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pFuncs, createFirstLastFunc(pSrcFunc, (SColumnNode*)pCol))) {
|
||||||
|
nodesDestroyNode(pFuncs);
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pOutput = pFuncs;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
if (NULL == pSelect->pProjectionList) { // select * ...
|
if (NULL == pSelect->pProjectionList) { // select * ...
|
||||||
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
|
return createAllColumns(pCxt, &pSelect->pProjectionList);
|
||||||
size_t nums = taosArrayGetSize(pTables);
|
|
||||||
pSelect->pProjectionList = nodesMakeList();
|
|
||||||
if (NULL == pSelect->pProjectionList) {
|
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < nums; ++i) {
|
|
||||||
STableNode* pTable = taosArrayGetP(pTables, i);
|
|
||||||
int32_t code = createColumnNodeByTable(pCxt, pTable, pSelect->pProjectionList);
|
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pIsSelectStar = true;
|
|
||||||
} else {
|
} else {
|
||||||
// todo : t.*
|
// todo : t.*
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
WHERE_EACH(pNode, pSelect->pProjectionList) {
|
||||||
|
if (isFirstLastStar(pNode)) {
|
||||||
|
SNodeList* pFuncs = NULL;
|
||||||
|
if (TSDB_CODE_SUCCESS != createFirstLastAllCols(pCxt, (SFunctionNode*)pNode, &pFuncs)) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
INSERT_LIST(pSelect->pProjectionList, pFuncs);
|
||||||
|
ERASE_NODE(pSelect->pProjectionList);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
WHERE_NEXT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -797,8 +872,8 @@ static int32_t getPositionValue(const SValueNode* pVal) {
|
||||||
|
|
||||||
static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) {
|
static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) {
|
||||||
*pOther = false;
|
*pOther = false;
|
||||||
SNode* pNode;
|
SNode* pNode = NULL;
|
||||||
FOREACH(pNode, pOrderByList) {
|
WHERE_EACH(pNode, pOrderByList) {
|
||||||
SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr;
|
SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr;
|
||||||
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
|
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
|
||||||
SValueNode* pVal = (SValueNode*)pExpr;
|
SValueNode* pVal = (SValueNode*)pExpr;
|
||||||
|
@ -823,6 +898,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
|
||||||
} else {
|
} else {
|
||||||
*pOther = true;
|
*pOther = true;
|
||||||
}
|
}
|
||||||
|
WHERE_NEXT;
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -845,11 +921,10 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
bool isSelectStar = false;
|
pCxt->currClause = SQL_CLAUSE_SELECT;
|
||||||
int32_t code = translateStar(pCxt, pSelect, &isSelectStar);
|
int32_t code = translateExprList(pCxt, pSelect->pProjectionList);
|
||||||
if (TSDB_CODE_SUCCESS == code && !isSelectStar) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
pCxt->currClause = SQL_CLAUSE_SELECT;
|
code = translateStar(pCxt, pSelect);
|
||||||
code = translateExprList(pCxt, pSelect->pProjectionList);
|
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
|
code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
|
||||||
|
@ -1829,10 +1904,13 @@ static int32_t getSmaIndexBuildAst(STranslateContext* pCxt, SCreateIndexStmt* pS
|
||||||
pSelect->pFromTable = (SNode*)pTable;
|
pSelect->pFromTable = (SNode*)pTable;
|
||||||
|
|
||||||
pSelect->pProjectionList = nodesCloneList(pStmt->pOptions->pFuncs);
|
pSelect->pProjectionList = nodesCloneList(pStmt->pOptions->pFuncs);
|
||||||
if (NULL == pTable) {
|
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pSelect->pProjectionList || NULL == pFunc) {
|
||||||
nodesDestroyNode(pSelect);
|
nodesDestroyNode(pSelect);
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
strcpy(pFunc->functionName, "_wstartts");
|
||||||
|
nodesListPushFront(pSelect->pProjectionList, pFunc);
|
||||||
SNode* pProject = NULL;
|
SNode* pProject = NULL;
|
||||||
FOREACH(pProject, pSelect->pProjectionList) {
|
FOREACH(pProject, pSelect->pProjectionList) {
|
||||||
sprintf(((SExprNode*)pProject)->aliasName, "#sma_%p", pProject);
|
sprintf(((SExprNode*)pProject)->aliasName, "#sma_%p", pProject);
|
||||||
|
|
Loading…
Reference in New Issue