/* * Copyright (c) 2019 TAOS Data, Inc. * * 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 . */ #include "plannodes.h" #include "querynodes.h" #include "query.h" #include "taoserror.h" #include "tjson.h" static int32_t nodeToJson(const void* pObj, SJson* pJson); static char* nodeName(ENodeType type) { switch (type) { case QUERY_NODE_COLUMN: return "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 "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: break; } return "Unknown"; } 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; }