first(*)/last(*) rewrite
This commit is contained in:
parent
fdbab777e5
commit
8ef6b184f2
|
@ -30,11 +30,19 @@ extern "C" {
|
|||
#define FOREACH(node, list) \
|
||||
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 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) \
|
||||
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); \
|
||||
|
@ -202,7 +210,9 @@ int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode);
|
|||
int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode);
|
||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
||||
int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc);
|
||||
int32_t nodesListPushFront(SNodeList* pList, SNodeptr pNode);
|
||||
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
|
||||
void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc);
|
||||
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index);
|
||||
void nodesDestroyList(SNodeList* pList);
|
||||
// Only clear the linked list structure, without releasing the elements inside
|
||||
|
|
|
@ -644,7 +644,7 @@ SNodeList* nodesMakeList() {
|
|||
|
||||
int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode) {
|
||||
if (NULL == pList || NULL == pNode) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
SListCell* p = taosMemoryCalloc(1, sizeof(SListCell));
|
||||
if (NULL == p) {
|
||||
|
@ -688,7 +688,7 @@ int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode) {
|
|||
|
||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||
if (NULL == pTarget || NULL == pSrc) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
if (NULL == pTarget->pHead) {
|
||||
|
@ -717,11 +717,34 @@ int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
|||
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) {
|
||||
if (NULL == pCell->pPrev) {
|
||||
pList->pHead = pCell->pNext;
|
||||
} else {
|
||||
pCell->pPrev->pNext = pCell->pNext;
|
||||
}
|
||||
if (NULL == pCell->pNext) {
|
||||
pList->pTail = pCell->pPrev;
|
||||
} else {
|
||||
pCell->pNext->pPrev = pCell->pPrev;
|
||||
}
|
||||
SListCell* pNext = pCell->pNext;
|
||||
|
@ -731,6 +754,24 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
|
|||
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) {
|
||||
SNode* node;
|
||||
FOREACH(node, pList) {
|
||||
|
|
|
@ -743,24 +743,99 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
|||
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 * ...
|
||||
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
|
||||
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;
|
||||
return createAllColumns(pCxt, &pSelect->pProjectionList);
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
|
@ -797,8 +872,8 @@ static int32_t getPositionValue(const SValueNode* pVal) {
|
|||
|
||||
static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) {
|
||||
*pOther = false;
|
||||
SNode* pNode;
|
||||
FOREACH(pNode, pOrderByList) {
|
||||
SNode* pNode = NULL;
|
||||
WHERE_EACH(pNode, pOrderByList) {
|
||||
SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr;
|
||||
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
|
||||
SValueNode* pVal = (SValueNode*)pExpr;
|
||||
|
@ -823,6 +898,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
|
|||
} else {
|
||||
*pOther = true;
|
||||
}
|
||||
WHERE_NEXT;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -845,11 +921,10 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
}
|
||||
|
||||
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
bool isSelectStar = false;
|
||||
int32_t code = translateStar(pCxt, pSelect, &isSelectStar);
|
||||
if (TSDB_CODE_SUCCESS == code && !isSelectStar) {
|
||||
pCxt->currClause = SQL_CLAUSE_SELECT;
|
||||
code = translateExprList(pCxt, pSelect->pProjectionList);
|
||||
pCxt->currClause = SQL_CLAUSE_SELECT;
|
||||
int32_t code = translateExprList(pCxt, pSelect->pProjectionList);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateStar(pCxt, pSelect);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
|
||||
|
@ -1829,10 +1904,13 @@ static int32_t getSmaIndexBuildAst(STranslateContext* pCxt, SCreateIndexStmt* pS
|
|||
pSelect->pFromTable = (SNode*)pTable;
|
||||
|
||||
pSelect->pProjectionList = nodesCloneList(pStmt->pOptions->pFuncs);
|
||||
if (NULL == pTable) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pSelect->pProjectionList || NULL == pFunc) {
|
||||
nodesDestroyNode(pSelect);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
strcpy(pFunc->functionName, "_wstartts");
|
||||
nodesListPushFront(pSelect->pProjectionList, pFunc);
|
||||
SNode* pProject = NULL;
|
||||
FOREACH(pProject, pSelect->pProjectionList) {
|
||||
sprintf(((SExprNode*)pProject)->aliasName, "#sma_%p", pProject);
|
||||
|
|
Loading…
Reference in New Issue