提交 83d516af 编写于 作者: X Xiaoyu Wang

TD-13495 planner refactoring

上级 6b31e051
...@@ -62,6 +62,7 @@ typedef enum ENodeType { ...@@ -62,6 +62,7 @@ typedef enum ENodeType {
QUERY_NODE_NODE_LIST, QUERY_NODE_NODE_LIST,
QUERY_NODE_FILL, QUERY_NODE_FILL,
QUERY_NODE_COLUMN_REF, QUERY_NODE_COLUMN_REF,
QUERY_NODE_TARGET,
// Only be used in parser module. // Only be used in parser module.
QUERY_NODE_RAW_EXPR, QUERY_NODE_RAW_EXPR,
...@@ -93,7 +94,7 @@ typedef struct SListCell { ...@@ -93,7 +94,7 @@ typedef struct SListCell {
} SListCell; } SListCell;
typedef struct SNodeList { typedef struct SNodeList {
int16_t length; int32_t length;
SListCell* pHead; SListCell* pHead;
SListCell* pTail; SListCell* pTail;
} SNodeList; } SNodeList;
...@@ -103,6 +104,7 @@ void nodesDestroyNode(SNode* pNode); ...@@ -103,6 +104,7 @@ void nodesDestroyNode(SNode* pNode);
SNodeList* nodesMakeList(); SNodeList* nodesMakeList();
int32_t nodesListAppend(SNodeList* pList, SNode* pNode); int32_t nodesListAppend(SNodeList* pList, SNode* pNode);
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc);
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell); SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
SNode* nodesListGetNode(SNodeList* pList, int32_t index); SNode* nodesListGetNode(SNodeList* pList, int32_t index);
void nodesDestroyList(SNodeList* pList); void nodesDestroyList(SNodeList* pList);
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_PLANN_NODES_H_
#define _TD_PLANN_NODES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "querynodes.h"
typedef struct SLogicNode {
ENodeType type;
int32_t id;
SNodeList* pTargets; // SColumnNode
SNode* pConditions;
SNodeList* pChildren;
struct SLogicNode* pParent;
} SLogicNode;
typedef struct SScanLogicNode {
SLogicNode node;
SNodeList* pScanCols;
struct STableMeta* pMeta;
} SScanLogicNode;
typedef struct SJoinLogicNode {
SLogicNode node;
EJoinType joinType;
SNode* pOnConditions;
} SJoinLogicNode;
typedef struct SFilterLogicNode {
SLogicNode node;
} SFilterLogicNode;
typedef struct SAggLogicNode {
SLogicNode node;
SNodeList* pGroupKeys;
SNodeList* pAggFuncs;
} SAggLogicNode;
typedef struct SProjectLogicNode {
SLogicNode node;
SNodeList* pProjections;
} SProjectLogicNode;
#ifdef __cplusplus
}
#endif
#endif /*_TD_PLANN_NODES_H_*/
...@@ -62,8 +62,10 @@ typedef struct SColumnNode { ...@@ -62,8 +62,10 @@ typedef struct SColumnNode {
typedef struct SColumnRefNode { typedef struct SColumnRefNode {
ENodeType type; ENodeType type;
int32_t tupleId; SDataType dataType;
int32_t slotId; int16_t tupleId;
int16_t slotId;
int16_t columnId;
} SColumnRefNode; } SColumnRefNode;
typedef struct SValueNode { typedef struct SValueNode {
...@@ -106,6 +108,12 @@ typedef enum EOperatorType { ...@@ -106,6 +108,12 @@ typedef enum EOperatorType {
OP_TYPE_NMATCH, OP_TYPE_NMATCH,
OP_TYPE_IS_NULL, OP_TYPE_IS_NULL,
OP_TYPE_IS_NOT_NULL, OP_TYPE_IS_NOT_NULL,
OP_TYPE_IS_TRUE,
OP_TYPE_IS_FALSE,
OP_TYPE_IS_UNKNOWN,
OP_TYPE_IS_NOT_TRUE,
OP_TYPE_IS_NOT_FALSE,
OP_TYPE_IS_NOT_UNKNOWN,
// json operator // json operator
OP_TYPE_JSON_GET_VALUE, OP_TYPE_JSON_GET_VALUE,
...@@ -285,7 +293,7 @@ typedef enum ESqlClause { ...@@ -285,7 +293,7 @@ typedef enum ESqlClause {
void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext); void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext); void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, uint64_t tableId, bool realCol, SNodeList** pCols); int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, SNodeList** pCols);
typedef bool (*FFuncClassifier)(int32_t funcId); typedef bool (*FFuncClassifier)(int32_t funcId);
int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs); int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs);
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_NEW_PARSER_H_
#define _TD_NEW_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "parser.h"
typedef enum EStmtType {
STMT_TYPE_CMD = 1,
STMT_TYPE_QUERY
} EStmtType;
typedef struct SQuery {
EStmtType stmtType;
SNode* pRoot;
int32_t numOfResCols;
SSchema* pResSchema;
} SQuery;
int32_t parser(SParseContext* pParseCxt, SQuery* pQuery);
#ifdef __cplusplus
}
#endif
#endif /*_TD_NEW_PARSER_H_*/
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_UTIL_JSON_H_
#define _TD_UTIL_JSON_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "os.h"
typedef void SJson;
SJson* tjsonCreateObject();
void tjsonDelete(SJson* pJson);
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number);
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal);
int32_t tjsonAddItemToObject(SJson* pJson, const char* pName, SJson* pItem);
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
typedef int32_t (*FToJson)(const void* pObj, SJson* pJson);
int32_t tjsonAddObject(SJson* pJson, const char* pName, FToJson func, const void* pObj);
int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj);
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
char* tjsonToString(const SJson* pJson);
#ifdef __cplusplus
}
#endif
#endif /*_TD_UTIL_JSON_H_*/
...@@ -7,7 +7,7 @@ target_include_directories( ...@@ -7,7 +7,7 @@ target_include_directories(
) )
target_link_libraries( target_link_libraries(
nodes nodes
PRIVATE os util PRIVATE os util common qcom
) )
if(${BUILD_TEST}) if(${BUILD_TEST})
......
...@@ -13,11 +13,18 @@ ...@@ -13,11 +13,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "nodes.h" #include "plannodes.h"
#include "querynodes.h"
#include "query.h"
#include "taoserror.h"
#include "tjson.h"
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) { static int32_t nodeToJson(const void* pObj, SJson* pJson);
switch (nodeType(pNode)) {
static char* nodeName(ENodeType type) {
switch (type) {
case QUERY_NODE_COLUMN: case QUERY_NODE_COLUMN:
return "Column";
case QUERY_NODE_VALUE: case QUERY_NODE_VALUE:
case QUERY_NODE_OPERATOR: case QUERY_NODE_OPERATOR:
case QUERY_NODE_LOGIC_CONDITION: case QUERY_NODE_LOGIC_CONDITION:
...@@ -31,14 +38,230 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) { ...@@ -31,14 +38,230 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
case QUERY_NODE_STATE_WINDOW: case QUERY_NODE_STATE_WINDOW:
case QUERY_NODE_SESSION_WINDOW: case QUERY_NODE_SESSION_WINDOW:
case QUERY_NODE_INTERVAL_WINDOW: case QUERY_NODE_INTERVAL_WINDOW:
case QUERY_NODE_NODE_LIST:
case QUERY_NODE_FILL:
case QUERY_NODE_COLUMN_REF:
case QUERY_NODE_TARGET:
case QUERY_NODE_RAW_EXPR:
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
case QUERY_NODE_SHOW_STMT: case QUERY_NODE_SHOW_STMT:
break;
case QUERY_NODE_LOGIC_PLAN_SCAN:
return "LogicScan";
case QUERY_NODE_LOGIC_PLAN_JOIN:
return "LogicJoin";
case QUERY_NODE_LOGIC_PLAN_FILTER:
return "LogicFilter";
case QUERY_NODE_LOGIC_PLAN_AGG:
return "LogicAgg";
case QUERY_NODE_LOGIC_PLAN_PROJECT:
return "LogicProject";
default: default:
break; break;
} }
return "Unknown";
} }
int32_t nodesStringToNode(const char* pStr, SNode** pNode) { static int32_t addNodeList(SJson* pJson, const char* pName, FToJson func, const SNodeList* pList) {
if (LIST_LENGTH(pList) > 0) {
SJson* jList = tjsonAddArrayToObject(pJson, pName);
if (NULL == jList) {
return TSDB_CODE_OUT_OF_MEMORY;
}
SNode* pNode;
FOREACH(pNode, pList) {
int32_t code = tjsonAddItem(jList, func, pNode);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
}
return TSDB_CODE_SUCCESS;
}
static const char* jkTableMetaUid = "TableMetaUid";
static const char* jkTableMetaSuid = "TableMetaSuid";
static int32_t tableMetaToJson(const void* pObj, SJson* pJson) {
const STableMeta* pNode = (const STableMeta*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkTableMetaUid, pNode->uid);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkTableMetaSuid, pNode->suid);
}
return code;
}
static const char* jkLogicPlanId = "Id";
static const char* jkLogicPlanTargets = "Targets";
static const char* jkLogicPlanConditions = "Conditions";
static const char* jkLogicPlanChildren = "Children";
static int32_t logicPlanNodeToJson(const void* pObj, SJson* pJson) {
const SLogicNode* pNode = (const SLogicNode*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkLogicPlanId, pNode->id);
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkLogicPlanTargets, nodeToJson, pNode->pTargets);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkLogicPlanConditions, nodeToJson, pNode->pConditions);
}
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkLogicPlanChildren, nodeToJson, pNode->pChildren);
}
return code;
}
static const char* jkScanLogicPlanScanCols = "ScanCols";
static const char* jkScanLogicPlanTableMeta = "TableMeta";
static int32_t logicScanToJson(const void* pObj, SJson* pJson) {
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkScanLogicPlanScanCols, nodeToJson, pNode->pScanCols);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkScanLogicPlanTableMeta, tableMetaToJson, pNode->pMeta);
}
return code;
}
static const char* jkProjectLogicPlanProjections = "Projections";
static int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkProjectLogicPlanProjections, nodeToJson, pNode->pProjections);
}
return code;
}
static const char* jkJoinLogicPlanJoinType = "JoinType";
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinLogicPlanJoinType, pNode->joinType);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkJoinLogicPlanOnConditions, nodeToJson, pNode->pOnConditions);
}
return code;
}
static int32_t logicFilterToJson(const void* pObj, SJson* pJson) {
return logicPlanNodeToJson(pObj, pJson);
}
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
static const char* jkAggLogicPlanAggFuncs = "AggFuncs";
static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkAggLogicPlanGroupKeys, nodeToJson, pNode->pGroupKeys);
}
if (TSDB_CODE_SUCCESS == code) {
code = addNodeList(pJson, jkAggLogicPlanAggFuncs, nodeToJson, pNode->pAggFuncs);
}
return code;
}
static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
switch (nodeType(pObj)) {
case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE:
case QUERY_NODE_OPERATOR:
case QUERY_NODE_LOGIC_CONDITION:
case QUERY_NODE_FUNCTION:
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
case QUERY_NODE_JOIN_TABLE:
case QUERY_NODE_GROUPING_SET:
case QUERY_NODE_ORDER_BY_EXPR:
case QUERY_NODE_LIMIT:
case QUERY_NODE_STATE_WINDOW:
case QUERY_NODE_SESSION_WINDOW:
case QUERY_NODE_INTERVAL_WINDOW:
case QUERY_NODE_NODE_LIST:
case QUERY_NODE_FILL:
case QUERY_NODE_COLUMN_REF:
case QUERY_NODE_TARGET:
case QUERY_NODE_RAW_EXPR:
case QUERY_NODE_SET_OPERATOR:
case QUERY_NODE_SELECT_STMT:
case QUERY_NODE_SHOW_STMT:
break;
case QUERY_NODE_LOGIC_PLAN_SCAN:
return logicScanToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_JOIN:
return logicJoinToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_FILTER:
return logicFilterToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_AGG:
return logicAggToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_PROJECT:
return logicProjectToJson(pObj, pJson);
default:
break;
}
return TSDB_CODE_SUCCESS;
}
static const char* jkNodeType = "Type";
static int32_t nodeToJson(const void* pObj, SJson* pJson) {
const SNode* pNode = (const SNode*)pObj;
char* pNodeName = nodeName(nodeType(pNode));
int32_t code = tjsonAddStringToObject(pJson, jkNodeType, pNodeName);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, pNodeName, specificNodeToJson, pNode);
}
return code;
}
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
if (NULL == pNode || NULL == pStr || NULL == pLen) {
return TSDB_CODE_SUCCESS;
}
SJson* pJson = tjsonCreateObject();
if (NULL == pJson) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return TSDB_CODE_OUT_OF_MEMORY;
}
int32_t code = nodeToJson(pNode, pJson);
if (TSDB_CODE_SUCCESS != code) {
terrno = code;
return code;
}
*pStr = tjsonToString(pJson);
tjsonDelete(pJson);
*pLen = strlen(*pStr) + 1;
return TSDB_CODE_SUCCESS;
}
int32_t nodesStringToNode(const char* pStr, SNode** pNode) {
return TSDB_CODE_SUCCESS;
} }
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
#include "querynodes.h" #include "querynodes.h"
#include "nodesShowStmts.h" #include "plannodes.h"
#include "taos.h" #include "taos.h"
#include "taoserror.h" #include "taoserror.h"
#include "thash.h" #include "thash.h"
...@@ -68,8 +68,18 @@ SNode* nodesMakeNode(ENodeType type) { ...@@ -68,8 +68,18 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SSetOperator)); return makeNode(type, sizeof(SSetOperator));
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
return makeNode(type, sizeof(SSelectStmt)); return makeNode(type, sizeof(SSelectStmt));
case QUERY_NODE_SHOW_STMT: // case QUERY_NODE_SHOW_STMT:
return makeNode(type, sizeof(SShowStmt)); // return makeNode(type, sizeof(SShowStmt));
case QUERY_NODE_LOGIC_PLAN_SCAN:
return makeNode(type, sizeof(SScanLogicNode));
case QUERY_NODE_LOGIC_PLAN_JOIN:
return makeNode(type, sizeof(SJoinLogicNode));
case QUERY_NODE_LOGIC_PLAN_FILTER:
return makeNode(type, sizeof(SFilterLogicNode));
case QUERY_NODE_LOGIC_PLAN_AGG:
return makeNode(type, sizeof(SAggLogicNode));
case QUERY_NODE_LOGIC_PLAN_PROJECT:
return makeNode(type, sizeof(SProjectLogicNode));
default: default:
break; break;
} }
...@@ -121,6 +131,15 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) { ...@@ -121,6 +131,15 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
pTarget->pTail->pNext = pSrc->pHead;
pSrc->pHead->pPrev = pTarget->pTail;
pTarget->pTail = pSrc->pTail;
pTarget->length += pSrc->length;
tfree(pSrc);
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;
...@@ -129,6 +148,7 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) { ...@@ -129,6 +148,7 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
pCell->pNext->pPrev = pCell->pPrev; pCell->pNext->pPrev = pCell->pPrev;
} }
SListCell* pNext = pCell->pNext; SListCell* pNext = pCell->pNext;
nodesDestroyNode(pCell->pNode);
tfree(pCell); tfree(pCell);
--(pList->length); --(pList->length);
return pNext; return pNext;
...@@ -185,6 +205,14 @@ bool nodesIsComparisonOp(const SOperatorNode* pOp) { ...@@ -185,6 +205,14 @@ bool nodesIsComparisonOp(const SOperatorNode* pOp) {
case OP_TYPE_NOT_LIKE: case OP_TYPE_NOT_LIKE:
case OP_TYPE_MATCH: case OP_TYPE_MATCH:
case OP_TYPE_NMATCH: case OP_TYPE_NMATCH:
case OP_TYPE_IS_NULL:
case OP_TYPE_IS_NOT_NULL:
case OP_TYPE_IS_TRUE:
case OP_TYPE_IS_FALSE:
case OP_TYPE_IS_UNKNOWN:
case OP_TYPE_IS_NOT_TRUE:
case OP_TYPE_IS_NOT_FALSE:
case OP_TYPE_IS_NOT_UNKNOWN:
return true; return true;
default: default:
break; break;
...@@ -213,8 +241,7 @@ bool nodesIsTimelineQuery(const SNode* pQuery) { ...@@ -213,8 +241,7 @@ bool nodesIsTimelineQuery(const SNode* pQuery) {
typedef struct SCollectColumnsCxt { typedef struct SCollectColumnsCxt {
int32_t errCode; int32_t errCode;
uint64_t tableId; const char* pTableAlias;
bool realCol;
SNodeList* pCols; SNodeList* pCols;
SHashObj* pColIdHash; SHashObj* pColIdHash;
} SCollectColumnsCxt; } SCollectColumnsCxt;
...@@ -232,27 +259,24 @@ static EDealRes doCollect(SCollectColumnsCxt* pCxt, int32_t id, SNode* pNode) { ...@@ -232,27 +259,24 @@ static EDealRes doCollect(SCollectColumnsCxt* pCxt, int32_t id, SNode* pNode) {
static EDealRes collectColumns(SNode* pNode, void* pContext) { static EDealRes collectColumns(SNode* pNode, void* pContext) {
SCollectColumnsCxt* pCxt = (SCollectColumnsCxt*)pContext; SCollectColumnsCxt* pCxt = (SCollectColumnsCxt*)pContext;
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
if (pCxt->realCol && QUERY_NODE_COLUMN == nodeType(pNode)) {
SColumnNode* pCol = (SColumnNode*)pNode; SColumnNode* pCol = (SColumnNode*)pNode;
int32_t colId = pCol->colId; int32_t colId = pCol->colId;
if (pCxt->tableId == pCol->tableId && colId > 0) { if (0 == strcmp(pCxt->pTableAlias, pCol->tableAlias)) {
return doCollect(pCxt, colId, pNode); return doCollect(pCxt, colId, pNode);
} }
} else if (!pCxt->realCol && QUERY_NODE_COLUMN_REF == nodeType(pNode)) {
return doCollect(pCxt, ((SColumnRefNode*)pNode)->slotId, pNode);
} }
return DEAL_RES_CONTINUE; return DEAL_RES_CONTINUE;
} }
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, uint64_t tableId, bool realCol, SNodeList** pCols) { int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, SNodeList** pCols) {
if (NULL == pSelect || NULL == pCols) { if (NULL == pSelect || NULL == pCols) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
SCollectColumnsCxt cxt = { SCollectColumnsCxt cxt = {
.errCode = TSDB_CODE_SUCCESS, .errCode = TSDB_CODE_SUCCESS,
.realCol = realCol, .pTableAlias = pTableAlias,
.pCols = nodesMakeList(), .pCols = nodesMakeList(),
.pColIdHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK) .pColIdHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK)
}; };
...@@ -303,6 +327,12 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNod ...@@ -303,6 +327,12 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNod
nodesDestroyList(cxt.pFuncs); nodesDestroyList(cxt.pFuncs);
return cxt.errCode; return cxt.errCode;
} }
*pFuncs = cxt.pFuncs; if (LIST_LENGTH(cxt.pFuncs) > 0) {
*pFuncs = cxt.pFuncs;
} else {
nodesDestroyList(cxt.pFuncs);
*pFuncs = NULL;
}
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -13,27 +13,15 @@ ...@@ -13,27 +13,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _TD_AST_CREATE_FUNCS_H_ #ifndef _TD_PARSER_IMPL_H_
#define _TD_AST_CREATE_FUNCS_H_ #define _TD_PARSER_IMPL_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "querynodes.h" #include "querynodes.h"
#include "parser.h" #include "newParser.h"
typedef enum EStmtType {
STMT_TYPE_CMD = 1,
STMT_TYPE_QUERY
} EStmtType;
typedef struct SQuery {
EStmtType stmtType;
SNode* pRoot;
int32_t numOfResCols;
SSchema* pResSchema;
} SQuery;
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery); int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery); int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery);
...@@ -42,4 +30,4 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery); ...@@ -42,4 +30,4 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery);
} }
#endif #endif
#endif /*_TD_AST_CREATE_FUNCS_H_*/ #endif /*_TD_PARSER_IMPL_H_*/
...@@ -880,7 +880,6 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro ...@@ -880,7 +880,6 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
int32_t pos = getPositionValue(pVal); int32_t pos = getPositionValue(pVal);
if (pos < 0) { if (pos < 0) {
ERASE_NODE(pOrderByList); ERASE_NODE(pOrderByList);
nodesDestroyNode(pNode);
continue; continue;
} else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) { } else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT); return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
...@@ -1058,3 +1057,11 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) { ...@@ -1058,3 +1057,11 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
} }
return code; return code;
} }
int32_t parser(SParseContext* pParseCxt, SQuery* pQuery) {
int32_t code = doParse(pParseCxt, pQuery);
if (TSDB_CODE_SUCCESS == code) {
code = doTranslate(pParseCxt, pQuery);
}
return code;
}
...@@ -20,43 +20,10 @@ ...@@ -20,43 +20,10 @@
extern "C" { extern "C" {
#endif #endif
#include "querynodes.h" #include "plannodes.h"
#include "planner.h" #include "planner.h"
typedef struct SLogicNode { int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode);
ENodeType type;
int32_t id;
SNodeList* pTargets;
SNode* pConditions;
SNodeList* pChildren;
struct SLogicNode* pParent;
} SLogicNode;
typedef struct SScanLogicNode {
SLogicNode node;
SNodeList* pScanCols;
struct STableMeta* pMeta;
} SScanLogicNode;
typedef struct SJoinLogicNode {
SLogicNode node;
EJoinType joinType;
SNode* pOnConditions;
} SJoinLogicNode;
typedef struct SFilterLogicNode {
SLogicNode node;
} SFilterLogicNode;
typedef struct SAggLogicNode {
SLogicNode node;
SNodeList* pGroupKeys;
SNodeList* pAggFuncs;
} SAggLogicNode;
typedef struct SProjectLogicNode {
SLogicNode node;
} SProjectLogicNode;
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define CHECK_ALLOC(p, res) \ #define CHECK_ALLOC(p, res) \
do { \ do { \
if (NULL == p) { \ if (NULL == p) { \
printf("%s : %d\n", __FUNCTION__, __LINE__); \
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
return res; \ return res; \
} \ } \
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
do { \ do { \
int32_t code = exec; \ int32_t code = exec; \
if (TSDB_CODE_SUCCESS != code) { \ if (TSDB_CODE_SUCCESS != code) { \
printf("%s : %d\n", __FUNCTION__, __LINE__); \
pCxt->errCode = code; \ pCxt->errCode = code; \
return res; \ return res; \
} \ } \
...@@ -44,8 +46,7 @@ static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSele ...@@ -44,8 +46,7 @@ static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSele
typedef struct SRewriteExprCxt { typedef struct SRewriteExprCxt {
int32_t errCode; int32_t errCode;
int32_t planNodeId; SNodeList* pExprs;
SNodeList* pTargets;
} SRewriteExprCxt; } SRewriteExprCxt;
static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
...@@ -53,34 +54,44 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { ...@@ -53,34 +54,44 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
case QUERY_NODE_OPERATOR: case QUERY_NODE_OPERATOR:
case QUERY_NODE_LOGIC_CONDITION: case QUERY_NODE_LOGIC_CONDITION:
case QUERY_NODE_FUNCTION: { case QUERY_NODE_FUNCTION: {
SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
SNode* pExpr;
int32_t index = 0;
FOREACH(pExpr, pCxt->pExprs) {
if (nodesEqualNode(pExpr, *pNode)) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
return DEAL_RES_ERROR;
}
SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode);
pCol->node.resType = pToBeRewrittenExpr->resType;
strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName);
strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName);
nodesDestroyNode(*pNode);
*pNode = (SNode*)pCol;
return DEAL_RES_IGNORE_CHILD;
}
++index;
}
break; break;
} }
default: default:
break; break;
} }
SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
SNode* pTarget;
int32_t index = 0;
FOREACH(pTarget, pCxt->pTargets) {
if (nodesEqualNode(pTarget, *pNode)) {
SColumnRefNode* pCol = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
if (NULL == pCol) {
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
return DEAL_RES_ERROR;
}
pCol->tupleId = pCxt->planNodeId;
pCol->slotId = index;
nodesDestroyNode(*pNode);
*pNode = (SNode*)pCol;
return DEAL_RES_IGNORE_CHILD;
}
++index;
}
return DEAL_RES_CONTINUE; return DEAL_RES_CONTINUE;
} }
static int32_t rewriteExpr(int32_t planNodeId, SNodeList* pTargets, SSelectStmt* pSelect, ESqlClause clause) { static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = planNodeId, .pTargets = pTargets }; SNode* pNode;
FOREACH(pNode, pExprs) {
if (QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_VALUE == nodeType(pNode)) {
continue;
}
sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", planNodeId, rewriteId);
}
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt); nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
return cxt.errCode; return cxt.errCode;
} }
...@@ -114,23 +125,6 @@ error: ...@@ -114,23 +125,6 @@ error:
return pRoot; return pRoot;
} }
static SNodeList* createScanTargets(int32_t planNodeId, int32_t numOfScanCols) {
SNodeList* pTargets = nodesMakeList();
if (NULL == pTargets) {
return NULL;
}
for (int32_t i = 0; i < numOfScanCols; ++i) {
SColumnRefNode* pCol = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pTargets, (SNode*)pCol)) {
nodesDestroyList(pTargets);
return NULL;
}
pCol->tupleId = planNodeId;
pCol->slotId = i;
}
return pTargets;
}
static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) { static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) {
SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN); SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
CHECK_ALLOC(pScan, NULL); CHECK_ALLOC(pScan, NULL);
...@@ -140,22 +134,25 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, ...@@ -140,22 +134,25 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
// set columns to scan // set columns to scan
SNodeList* pCols = NULL; SNodeList* pCols = NULL;
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pScan->pMeta->uid, true, &pCols), (SLogicNode*)pScan); CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
pScan->pScanCols = nodesCloneList(pCols); pScan->pScanCols = nodesCloneList(pCols);
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan); CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
// pScanCols of SScanLogicNode is equivalent to pTargets of other logic nodes
CHECK_CODE(rewriteExpr(pScan->node.id, pScan->pScanCols, pSelect, SQL_CLAUSE_FROM), (SLogicNode*)pScan);
// set output // set output
pScan->node.pTargets = createScanTargets(pScan->node.id, LIST_LENGTH(pScan->pScanCols)); pScan->node.pTargets = nodesCloneList(pCols);
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan); CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
return (SLogicNode*)pScan; return (SLogicNode*)pScan;
} }
static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) { static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) {
return createQueryLogicNode(pCxt, pTable->pSubquery); SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery);
CHECK_ALLOC(pRoot, NULL);
SNode* pNode;
FOREACH(pNode, pRoot->pTargets) {
strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias);
}
return pRoot;
} }
static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) { static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) {
...@@ -179,12 +176,12 @@ static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, ...@@ -179,12 +176,12 @@ static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond); pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin); CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
// set the output and rewrite the expression in subsequent clauses with the output // set the output
SNodeList* pCols = NULL; pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, 0, false, &pCols), (SLogicNode*)pJoin);
pJoin->node.pTargets = nodesCloneList(pCols);
CHECK_ALLOC(pJoin->node.pTargets, (SLogicNode*)pJoin); CHECK_ALLOC(pJoin->node.pTargets, (SLogicNode*)pJoin);
CHECK_CODE(rewriteExpr(pJoin->node.id, pJoin->node.pTargets, pSelect, SQL_CLAUSE_FROM), (SLogicNode*)pJoin); SNodeList* pTargets = nodesCloneList(pRight->pTargets);
CHECK_ALLOC(pTargets, (SLogicNode*)pJoin);
nodesListAppendList(pJoin->node.pTargets, pTargets);
return (SLogicNode*)pJoin; return (SLogicNode*)pJoin;
} }
...@@ -203,7 +200,7 @@ static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSele ...@@ -203,7 +200,7 @@ static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSele
return NULL; return NULL;
} }
static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SLogicNode* pChild, SSelectStmt* pSelect) {
if (NULL == pSelect->pWhere) { if (NULL == pSelect->pWhere) {
return NULL; return NULL;
} }
...@@ -216,16 +213,44 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SSelectStmt* p ...@@ -216,16 +213,44 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SSelectStmt* p
pFilter->node.pConditions = nodesCloneNode(pSelect->pWhere); pFilter->node.pConditions = nodesCloneNode(pSelect->pWhere);
CHECK_ALLOC(pFilter->node.pConditions, (SLogicNode*)pFilter); CHECK_ALLOC(pFilter->node.pConditions, (SLogicNode*)pFilter);
// set the output and rewrite the expression in subsequent clauses with the output // set the output
SNodeList* pCols = NULL; pFilter->node.pTargets = nodesCloneList(pChild->pTargets);
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, 0, false, &pCols), (SLogicNode*)pFilter);
pFilter->node.pTargets = nodesCloneList(pCols);
CHECK_ALLOC(pFilter->node.pTargets, (SLogicNode*)pFilter); CHECK_ALLOC(pFilter->node.pTargets, (SLogicNode*)pFilter);
CHECK_CODE(rewriteExpr(pFilter->node.id, pFilter->node.pTargets, pSelect, SQL_CLAUSE_WHERE), (SLogicNode*)pFilter);
return (SLogicNode*)pFilter; return (SLogicNode*)pFilter;
} }
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
SNodeList* pList = nodesMakeList();
CHECK_ALLOC(pList, NULL);
SNode* pNode;
FOREACH(pNode, pExprs) {
if (QUERY_NODE_VALUE == nodeType(pNode)) {
continue;
} else if (QUERY_NODE_COLUMN == nodeType(pNode)) {
SNode* pCol = nodesCloneNode(pNode);
if (NULL == pCol) {
goto error;
}
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pCol)) {
goto error;
}
} else {
SExprNode* pExpr = (SExprNode*)pNode;
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
goto error;
}
pCol->node.resType = pExpr->resType;
strcpy(pCol->colName, pExpr->aliasName);
}
}
return pList;
error:
nodesDestroyList(pList);
return NULL;
}
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
SNodeList* pAggFuncs = NULL; SNodeList* pAggFuncs = NULL;
CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL); CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL);
...@@ -242,25 +267,54 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) ...@@ -242,25 +267,54 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg); CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
pAgg->pAggFuncs = nodesCloneList(pAggFuncs); pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg); CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
// rewrite the expression in subsequent clauses
CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving); pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg); CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
// set the output and rewrite the expression in subsequent clauses with the output // set the output
SNodeList* pCols = NULL; pAgg->node.pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_HAVING, 0, false, &pCols), (SLogicNode*)pAgg);
pAgg->node.pTargets = nodesCloneList(pCols);
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
CHECK_CODE(rewriteExpr(pAgg->node.id, pAgg->node.pTargets, pSelect, SQL_CLAUSE_HAVING), (SLogicNode*)pAgg); SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
nodesListAppendList(pAgg->node.pTargets, pTargets);
return (SLogicNode*)pAgg; return (SLogicNode*)pAgg;
} }
static SNodeList* createColumnByProjections(SPlanContext* pCxt, SNodeList* pExprs) {
SNodeList* pList = nodesMakeList();
CHECK_ALLOC(pList, NULL);
SNode* pNode;
FOREACH(pNode, pExprs) {
SExprNode* pExpr = (SExprNode*)pNode;
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
goto error;
}
pCol->node.resType = pExpr->resType;
strcpy(pCol->colName, pExpr->aliasName);
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, (SNode*)pCol)) {
goto error;
}
}
return pList;
error:
nodesDestroyList(pList);
return NULL;
}
static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT); SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
CHECK_ALLOC(pProject, NULL); CHECK_ALLOC(pProject, NULL);
pProject->node.id = pCxt->planNodeId++; pProject->node.id = pCxt->planNodeId++;
pProject->node.pTargets = nodesCloneList(pSelect->pProjectionList); pProject->pProjections = nodesCloneList(pSelect->pProjectionList);
pProject->node.pTargets = createColumnByProjections(pCxt,pSelect->pProjectionList);
CHECK_ALLOC(pProject->node.pTargets, (SLogicNode*)pProject); CHECK_ALLOC(pProject->node.pTargets, (SLogicNode*)pProject);
return (SLogicNode*)pProject; return (SLogicNode*)pProject;
...@@ -269,7 +323,7 @@ static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSele ...@@ -269,7 +323,7 @@ static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSele
static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable); SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable);
if (TSDB_CODE_SUCCESS == pCxt->errCode) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pRoot = pushLogicNode(pCxt, pRoot, createWhereFilterLogicNode(pCxt, pSelect)); pRoot = pushLogicNode(pCxt, pRoot, createWhereFilterLogicNode(pCxt, pRoot, pSelect));
} }
if (TSDB_CODE_SUCCESS == pCxt->errCode) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect)); pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect));
......
...@@ -13,7 +13,7 @@ ADD_EXECUTABLE(plannerTest ...@@ -13,7 +13,7 @@ ADD_EXECUTABLE(plannerTest
TARGET_LINK_LIBRARIES( TARGET_LINK_LIBRARIES(
plannerTest plannerTest
PUBLIC os util common planner parser catalog transport gtest function qcom PUBLIC os util common nodes planner parser catalog transport gtest function qcom
) )
TARGET_INCLUDE_DIRECTORIES( TARGET_INCLUDE_DIRECTORIES(
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <gtest/gtest.h>
#include "plannerImpl.h"
#include "newParser.h"
using namespace std;
using namespace testing;
class NewPlannerTest : public Test {
protected:
void setDatabase(const string& acctId, const string& db) {
acctId_ = acctId;
db_ = db;
}
void bind(const char* sql) {
reset();
cxt_.acctId = atoi(acctId_.c_str());
cxt_.db = db_.c_str();
sqlBuf_ = string(sql);
transform(sqlBuf_.begin(), sqlBuf_.end(), sqlBuf_.begin(), ::tolower);
cxt_.sqlLen = strlen(sql);
cxt_.pSql = sqlBuf_.c_str();
}
bool run() {
int32_t code = parser(&cxt_, &query_);
// cout << "parser return " << code << endl;
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] parser code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
return false;
}
SLogicNode* pLogicPlan = nullptr;
code = createLogicPlan(query_.pRoot, &pLogicPlan);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] plan code:" << tstrerror(code) << endl;
return false;
}
char* pStr = NULL;
int32_t len = 0;
code = nodesNodeToString((const SNode*)pLogicPlan, &pStr, &len);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] toString code:" << tstrerror(code) << endl;
return false;
}
cout << "logic plan : " << endl;
cout << pStr << endl;
return true;
}
private:
static const int max_err_len = 1024;
void reset() {
memset(&cxt_, 0, sizeof(cxt_));
memset(errMagBuf_, 0, max_err_len);
cxt_.pMsg = errMagBuf_;
cxt_.msgLen = max_err_len;
}
string acctId_;
string db_;
char errMagBuf_[max_err_len];
string sqlBuf_;
SParseContext cxt_;
SQuery query_;
};
TEST_F(NewPlannerTest, simple) {
setDatabase("root", "test");
bind("SELECT * FROM t1");
ASSERT_TRUE(run());
}
...@@ -10,7 +10,7 @@ target_link_libraries( ...@@ -10,7 +10,7 @@ target_link_libraries(
util util
PRIVATE os PRIVATE os
PUBLIC lz4_static PUBLIC lz4_static
PUBLIC api PUBLIC api cjson
) )
if(${BUILD_TEST}) if(${BUILD_TEST})
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tjson.h"
#include "taoserror.h"
#include "cJSON.h"
SJson* tjsonCreateObject() {
return cJSON_CreateObject();
}
void tjsonDelete(SJson* pJson) {
cJSON_Delete((cJSON*)pJson);
}
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number) {
char tmp[40] = {0};
snprintf(tmp, tListLen(tmp), "%"PRId64, number);
return tjsonAddStringToObject(pJson, pName, tmp);
}
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal) {
return (NULL == cJSON_AddStringToObject((cJSON*)pJson, pName, pVal) ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS);
}
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName) {
return cJSON_AddArrayToObject((cJSON*)pJson, pName);
}
int32_t tjsonAddItemToObject(SJson *pJson, const char* pName, SJson* pItem) {
return (cJSON_AddItemToObject((cJSON*)pJson, pName, pItem) ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED);
}
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem) {
return (cJSON_AddItemToArray((cJSON*)pJson, pItem) ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED);
}
int32_t tjsonAddObject(SJson* pJson, const char* pName, FToJson func, const void* pObj) {
if (NULL == pObj) {
return TSDB_CODE_SUCCESS;
}
SJson* pJobj = tjsonCreateObject();
if (NULL == pJobj || TSDB_CODE_SUCCESS != func(pObj, pJobj)) {
printf("%s:%d code = %d\n", __FUNCTION__, __LINE__, TSDB_CODE_FAILED);
tjsonDelete(pJobj);
return TSDB_CODE_FAILED;
}
return tjsonAddItemToObject(pJson, pName, pJobj);
}
int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj) {
SJson* pJobj = tjsonCreateObject();
if (NULL == pJobj || TSDB_CODE_SUCCESS != func(pObj, pJobj)) {
tjsonDelete(pJobj);
return TSDB_CODE_FAILED;
}
return tjsonAddItemToArray(pJson, pJobj);
}
char* tjsonToString(const SJson* pJson) {
return cJSON_Print((cJSON*)pJson);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册