TD-13495 logic plan UT
This commit is contained in:
parent
83712ffd60
commit
6f555efeb1
|
@ -132,7 +132,7 @@ bool nodesEqualNode(const SNode* a, const SNode* b);
|
||||||
SNode* nodesCloneNode(const SNode* pNode);
|
SNode* nodesCloneNode(const SNode* pNode);
|
||||||
SNodeList* nodesCloneList(const SNodeList* pList);
|
SNodeList* nodesCloneList(const SNodeList* pList);
|
||||||
|
|
||||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
|
int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen);
|
||||||
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -30,6 +30,7 @@ void tjsonDelete(SJson* pJson);
|
||||||
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
|
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
|
||||||
|
|
||||||
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number);
|
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number);
|
||||||
|
int32_t tjsonAddDoubleToObject(SJson* pJson, const char* pName, const double number);
|
||||||
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal);
|
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal);
|
||||||
int32_t tjsonAddItemToObject(SJson* pJson, const char* pName, SJson* pItem);
|
int32_t tjsonAddItemToObject(SJson* pJson, const char* pName, SJson* pItem);
|
||||||
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
|
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
|
||||||
|
@ -42,6 +43,7 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj);
|
||||||
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
|
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
|
||||||
|
|
||||||
char* tjsonToString(const SJson* pJson);
|
char* tjsonToString(const SJson* pJson);
|
||||||
|
char* tjsonToUnformattedString(const SJson* pJson);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "querynodes.h"
|
#include "querynodes.h"
|
||||||
#include "taos.h"
|
#include "taos.h"
|
||||||
|
#include "taoserror.h"
|
||||||
|
|
||||||
#define COPY_SCALAR_FIELD(fldname) \
|
#define COPY_SCALAR_FIELD(fldname) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -57,14 +58,13 @@ static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
||||||
COPY_SCALAR_FIELD(type);
|
|
||||||
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
||||||
COPY_CHAR_ARRAY_FIELD(aliasName);
|
COPY_CHAR_ARRAY_FIELD(aliasName);
|
||||||
// COPY_NODE_LIST_FIELD(pAssociationList);
|
// COPY_NODE_LIST_FIELD(pAssociationList);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(colId);
|
COPY_SCALAR_FIELD(colId);
|
||||||
COPY_SCALAR_FIELD(colType);
|
COPY_SCALAR_FIELD(colType);
|
||||||
COPY_CHAR_ARRAY_FIELD(dbName);
|
COPY_CHAR_ARRAY_FIELD(dbName);
|
||||||
|
@ -76,7 +76,7 @@ static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_CHAR_POINT_FIELD(literal);
|
COPY_CHAR_POINT_FIELD(literal);
|
||||||
COPY_SCALAR_FIELD(isDuration);
|
COPY_SCALAR_FIELD(isDuration);
|
||||||
switch (pSrc->node.resType.type) {
|
switch (pSrc->node.resType.type) {
|
||||||
|
@ -119,7 +119,7 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(opType);
|
COPY_SCALAR_FIELD(opType);
|
||||||
COPY_NODE_FIELD(pLeft);
|
COPY_NODE_FIELD(pLeft);
|
||||||
COPY_NODE_FIELD(pRight);
|
COPY_NODE_FIELD(pRight);
|
||||||
|
@ -127,14 +127,14 @@ static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
|
static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(condType);
|
COPY_SCALAR_FIELD(condType);
|
||||||
COPY_NODE_LIST_FIELD(pParameterList);
|
COPY_NODE_LIST_FIELD(pParameterList);
|
||||||
return (SNode*)pDst;
|
return (SNode*)pDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_CHAR_ARRAY_FIELD(functionName);
|
COPY_CHAR_ARRAY_FIELD(functionName);
|
||||||
COPY_SCALAR_FIELD(funcId);
|
COPY_SCALAR_FIELD(funcId);
|
||||||
COPY_SCALAR_FIELD(funcType);
|
COPY_SCALAR_FIELD(funcType);
|
||||||
|
@ -142,12 +142,19 @@ static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
||||||
return (SNode*)pDst;
|
return (SNode*)pDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SNode* groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) {
|
||||||
|
COPY_SCALAR_FIELD(groupingSetType);
|
||||||
|
COPY_NODE_LIST_FIELD(pParameterList);
|
||||||
|
return (SNode*)pDst;
|
||||||
|
}
|
||||||
|
|
||||||
SNode* nodesCloneNode(const SNode* pNode) {
|
SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
if (NULL == pNode) {
|
if (NULL == pNode) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SNode* pDst = nodesMakeNode(nodeType(pNode));
|
SNode* pDst = nodesMakeNode(nodeType(pNode));
|
||||||
if (NULL == pDst) {
|
if (NULL == pDst) {
|
||||||
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
switch (nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
@ -164,7 +171,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
break;
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
default:
|
default:
|
||||||
|
@ -174,8 +183,13 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SNodeList* nodesCloneList(const SNodeList* pList) {
|
SNodeList* nodesCloneList(const SNodeList* pList) {
|
||||||
|
if (NULL == pList) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SNodeList* pDst = nodesMakeList();
|
SNodeList* pDst = nodesMakeList();
|
||||||
if (NULL == pDst) {
|
if (NULL == pDst) {
|
||||||
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
|
|
|
@ -26,27 +26,47 @@ static char* nodeName(ENodeType type) {
|
||||||
case QUERY_NODE_COLUMN:
|
case QUERY_NODE_COLUMN:
|
||||||
return "Column";
|
return "Column";
|
||||||
case QUERY_NODE_VALUE:
|
case QUERY_NODE_VALUE:
|
||||||
|
return "Value";
|
||||||
case QUERY_NODE_OPERATOR:
|
case QUERY_NODE_OPERATOR:
|
||||||
|
return "Operator";
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
return "LogicCondition";
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
|
return "Function";
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
|
return "RealTable";
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
|
return "TempTable";
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
return "JoinTable";
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return "GroupingSet";
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
|
return "OrderByExpr";
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
|
return "Limit";
|
||||||
case QUERY_NODE_STATE_WINDOW:
|
case QUERY_NODE_STATE_WINDOW:
|
||||||
|
return "StateWindow";
|
||||||
case QUERY_NODE_SESSION_WINDOW:
|
case QUERY_NODE_SESSION_WINDOW:
|
||||||
|
return "SessionWinow";
|
||||||
case QUERY_NODE_INTERVAL_WINDOW:
|
case QUERY_NODE_INTERVAL_WINDOW:
|
||||||
|
return "IntervalWindow";
|
||||||
case QUERY_NODE_NODE_LIST:
|
case QUERY_NODE_NODE_LIST:
|
||||||
|
return "NodeList";
|
||||||
case QUERY_NODE_FILL:
|
case QUERY_NODE_FILL:
|
||||||
|
return "Fill";
|
||||||
case QUERY_NODE_COLUMN_REF:
|
case QUERY_NODE_COLUMN_REF:
|
||||||
|
return "ColumnRef";
|
||||||
case QUERY_NODE_TARGET:
|
case QUERY_NODE_TARGET:
|
||||||
|
return "Target";
|
||||||
case QUERY_NODE_RAW_EXPR:
|
case QUERY_NODE_RAW_EXPR:
|
||||||
|
return "RawExpr";
|
||||||
case QUERY_NODE_SET_OPERATOR:
|
case QUERY_NODE_SET_OPERATOR:
|
||||||
|
return "SetOperator";
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
return "SelectStmt";
|
||||||
case QUERY_NODE_SHOW_STMT:
|
case QUERY_NODE_SHOW_STMT:
|
||||||
break;
|
return "ShowStmt";
|
||||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||||
return "LogicScan";
|
return "LogicScan";
|
||||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||||
|
@ -119,7 +139,7 @@ static int32_t logicPlanNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
static const char* jkScanLogicPlanScanCols = "ScanCols";
|
static const char* jkScanLogicPlanScanCols = "ScanCols";
|
||||||
static const char* jkScanLogicPlanTableMeta = "TableMeta";
|
static const char* jkScanLogicPlanTableMeta = "TableMeta";
|
||||||
|
|
||||||
static int32_t logicScanToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -135,7 +155,7 @@ static int32_t logicScanToJson(const void* pObj, SJson* pJson) {
|
||||||
|
|
||||||
static const char* jkProjectLogicPlanProjections = "Projections";
|
static const char* jkProjectLogicPlanProjections = "Projections";
|
||||||
|
|
||||||
static int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
|
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -149,7 +169,7 @@ static int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
|
||||||
static const char* jkJoinLogicPlanJoinType = "JoinType";
|
static const char* jkJoinLogicPlanJoinType = "JoinType";
|
||||||
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
|
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
|
||||||
|
|
||||||
static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
|
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -163,14 +183,14 @@ static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t logicFilterToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicFilterNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
return logicPlanNodeToJson(pObj, pJson);
|
return logicPlanNodeToJson(pObj, pJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
|
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
|
||||||
static const char* jkAggLogicPlanAggFuncs = "AggFuncs";
|
static const char* jkAggLogicPlanAggFuncs = "AggFuncs";
|
||||||
|
|
||||||
static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicAggNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
|
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -184,17 +204,291 @@ static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* jkDataTypeType = "Type";
|
||||||
|
static const char* jkDataTypePrecision = "Precision";
|
||||||
|
static const char* jkDataTypeScale = "Scale";
|
||||||
|
static const char* jkDataTypeDataBytes = "Bytes";
|
||||||
|
|
||||||
|
static int32_t dataTypeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SDataType* pNode = (const SDataType*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkDataTypeType, pNode->type);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypePrecision, pNode->precision);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypeScale, pNode->scale);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypeDataBytes, pNode->bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkExprDataType = "DataType";
|
||||||
|
static const char* jkExprAliasName = "AliasName";
|
||||||
|
|
||||||
|
static int32_t exprNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SExprNode* pNode = (const SExprNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddObject(pJson, jkExprDataType, dataTypeToJson, &pNode->resType);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkExprAliasName, pNode->aliasName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkColumnTableId = "TableId";
|
||||||
|
static const char* jkColumnColId = "ColId";
|
||||||
|
static const char* jkColumnColType = "ColType";
|
||||||
|
static const char* jkColumnDbName = "DbName";
|
||||||
|
static const char* jkColumnTableName = "TableName";
|
||||||
|
static const char* jkColumnTableAlias = "TableAlias";
|
||||||
|
static const char* jkColumnColName = "ColName";
|
||||||
|
|
||||||
|
static int32_t columnNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SColumnNode* pNode = (const SColumnNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnTableId, pNode->tableId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnColId, pNode->colId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnColType, pNode->colType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnDbName, pNode->dbName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnTableName, pNode->tableName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnTableAlias, pNode->tableAlias);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnColName, pNode->colName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef struct SValueNode {
|
||||||
|
// SExprNode node; // QUERY_NODE_VALUE
|
||||||
|
// char* ;
|
||||||
|
// bool ;
|
||||||
|
// union {
|
||||||
|
// bool b;
|
||||||
|
// int64_t i;
|
||||||
|
// uint64_t u;
|
||||||
|
// double d;
|
||||||
|
// char* p;
|
||||||
|
// } datum;
|
||||||
|
// } SValueNode;
|
||||||
|
|
||||||
|
static const char* jkValueLiteral = "Literal";
|
||||||
|
static const char* jkValueDuration = "Duration";
|
||||||
|
static const char* jkValueDatum = "Datum";
|
||||||
|
|
||||||
|
static int32_t valueNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SValueNode* pNode = (const SValueNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->literal);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->isDuration);
|
||||||
|
}
|
||||||
|
switch (pNode->node.resType.type) {
|
||||||
|
case TSDB_DATA_TYPE_NULL:
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.b);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_INT:
|
||||||
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.i);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_UINT:
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.u);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
|
code = tjsonAddDoubleToObject(pJson, jkValueDuration, pNode->datum.d);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARBINARY:
|
||||||
|
code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->datum.p);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_JSON:
|
||||||
|
case TSDB_DATA_TYPE_DECIMAL:
|
||||||
|
case TSDB_DATA_TYPE_BLOB:
|
||||||
|
// todo
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkOperatorType = "OpType";
|
||||||
|
static const char* jkOperatorLeft = "Left";
|
||||||
|
static const char* jkOperatorRight = "Right";
|
||||||
|
|
||||||
|
static int32_t operatorNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SOperatorNode* pNode = (const SOperatorNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkOperatorType, pNode->opType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkOperatorLeft, nodeToJson, pNode->pLeft);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkOperatorRight, nodeToJson, pNode->pRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkLogicCondType = "CondType";
|
||||||
|
static const char* jkLogicCondParameters = "Parameters";
|
||||||
|
|
||||||
|
static int32_t logicConditionNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SLogicConditionNode* pNode = (const SLogicConditionNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkLogicCondType, pNode->condType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkLogicCondParameters, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkFunctionName = "Name";
|
||||||
|
static const char* jkFunctionId = "Id";
|
||||||
|
static const char* jkFunctionType = "Type";
|
||||||
|
static const char* jkFunctionParameter = "Parameters";
|
||||||
|
|
||||||
|
static int32_t functionNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SFunctionNode* pNode = (const SFunctionNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkFunctionName, pNode->functionName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkFunctionId, pNode->funcId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkFunctionType, pNode->funcType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkFunctionParameter, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkGroupingSetType = "GroupingSetType";
|
||||||
|
static const char* jkGroupingSetParameter = "Parameters";
|
||||||
|
|
||||||
|
static int32_t groupingSetNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SGroupingSetNode* pNode = (const SGroupingSetNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkGroupingSetType, pNode->groupingSetType);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkGroupingSetParameter, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkSelectStmtDistinct = "Distinct";
|
||||||
|
static const char* jkSelectStmtProjections = "Projections";
|
||||||
|
static const char* jkSelectStmtFrom = "From";
|
||||||
|
static const char* jkSelectStmtWhere = "Where";
|
||||||
|
static const char* jkSelectStmtPartitionBy = "PartitionBy";
|
||||||
|
static const char* jkSelectStmtWindow = "Window";
|
||||||
|
static const char* jkSelectStmtGroupBy = "GroupBy";
|
||||||
|
static const char* jkSelectStmtHaving = "Having";
|
||||||
|
static const char* jkSelectStmtOrderBy = "OrderBy";
|
||||||
|
static const char* jkSelectStmtLimit = "Limit";
|
||||||
|
static const char* jkSelectStmtSlimit = "Slimit";
|
||||||
|
|
||||||
|
static int32_t selectStmtTojson(const void* pObj, SJson* pJson) {
|
||||||
|
const SSelectStmt* pNode = (const SSelectStmt*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkSelectStmtDistinct, pNode->isDistinct);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtProjections, nodeToJson, pNode->pProjectionList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtFrom, nodeToJson, pNode->pFromTable);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtWhere, nodeToJson, pNode->pWhere);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtPartitionBy, nodeToJson, pNode->pPartitionByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtWindow, nodeToJson, pNode->pWindow);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtGroupBy, nodeToJson, pNode->pGroupByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtHaving, nodeToJson, pNode->pHaving);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtOrderBy, nodeToJson, pNode->pOrderByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtLimit, nodeToJson, pNode->pLimit);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtSlimit, nodeToJson, pNode->pSlimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
switch (nodeType(pObj)) {
|
switch (nodeType(pObj)) {
|
||||||
case QUERY_NODE_COLUMN:
|
case QUERY_NODE_COLUMN:
|
||||||
|
return columnNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_VALUE:
|
case QUERY_NODE_VALUE:
|
||||||
|
return valueNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_OPERATOR:
|
case QUERY_NODE_OPERATOR:
|
||||||
|
return operatorNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
return logicConditionNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
|
return functionNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
break;
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return groupingSetNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
case QUERY_NODE_STATE_WINDOW:
|
case QUERY_NODE_STATE_WINDOW:
|
||||||
|
@ -206,19 +500,21 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
case QUERY_NODE_TARGET:
|
case QUERY_NODE_TARGET:
|
||||||
case QUERY_NODE_RAW_EXPR:
|
case QUERY_NODE_RAW_EXPR:
|
||||||
case QUERY_NODE_SET_OPERATOR:
|
case QUERY_NODE_SET_OPERATOR:
|
||||||
|
break;
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
return selectStmtTojson(pObj, pJson);
|
||||||
case QUERY_NODE_SHOW_STMT:
|
case QUERY_NODE_SHOW_STMT:
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||||
return logicScanToJson(pObj, pJson);
|
return logicScanNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||||
return logicJoinToJson(pObj, pJson);
|
return logicJoinNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_FILTER:
|
case QUERY_NODE_LOGIC_PLAN_FILTER:
|
||||||
return logicFilterToJson(pObj, pJson);
|
return logicFilterNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_AGG:
|
case QUERY_NODE_LOGIC_PLAN_AGG:
|
||||||
return logicAggToJson(pObj, pJson);
|
return logicAggNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
||||||
return logicProjectToJson(pObj, pJson);
|
return logicProjectNodeToJson(pObj, pJson);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +534,7 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen) {
|
||||||
if (NULL == pNode || NULL == pStr || NULL == pLen) {
|
if (NULL == pNode || NULL == pStr || NULL == pLen) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +551,7 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pStr = tjsonToString(pJson);
|
*pStr = format ? tjsonToString(pJson) : tjsonToUnformattedString(pJson);
|
||||||
tjsonDelete(pJson);
|
tjsonDelete(pJson);
|
||||||
|
|
||||||
*pLen = strlen(*pStr) + 1;
|
*pLen = strlen(*pStr) + 1;
|
||||||
|
|
|
@ -132,11 +132,22 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||||
pTarget->pTail->pNext = pSrc->pHead;
|
if (NULL == pTarget || NULL == pSrc) {
|
||||||
pSrc->pHead->pPrev = pTarget->pTail;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == pTarget->pHead) {
|
||||||
|
pTarget->pHead = pSrc->pHead;
|
||||||
|
} else {
|
||||||
|
pTarget->pTail->pNext = pSrc->pHead;
|
||||||
|
if (NULL != pSrc->pHead) {
|
||||||
|
pSrc->pHead->pPrev = pTarget->pTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
pTarget->pTail = pSrc->pTail;
|
pTarget->pTail = pSrc->pTail;
|
||||||
pTarget->length += pSrc->length;
|
pTarget->length += pSrc->length;
|
||||||
tfree(pSrc);
|
tfree(pSrc);
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +301,10 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char*
|
||||||
nodesDestroyList(cxt.pCols);
|
nodesDestroyList(cxt.pCols);
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
}
|
}
|
||||||
|
if (0 == LIST_LENGTH(cxt.pCols)) {
|
||||||
|
nodesDestroyList(cxt.pCols);
|
||||||
|
cxt.pCols = NULL;
|
||||||
|
}
|
||||||
*pCols = cxt.pCols;
|
*pCols = cxt.pCols;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,7 @@ static SNodeList* getProjectList(SNode* pNode) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, SColumnNode* pCol) {
|
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, bool isTag, SColumnNode* pCol) {
|
||||||
strcpy(pCol->dbName, pTable->table.dbName);
|
strcpy(pCol->dbName, pTable->table.dbName);
|
||||||
strcpy(pCol->tableAlias, pTable->table.tableAlias);
|
strcpy(pCol->tableAlias, pTable->table.tableAlias);
|
||||||
strcpy(pCol->tableName, pTable->table.tableName);
|
strcpy(pCol->tableName, pTable->table.tableName);
|
||||||
|
@ -359,7 +359,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p
|
||||||
}
|
}
|
||||||
pCol->tableId = pTable->pMeta->uid;
|
pCol->tableId = pTable->pMeta->uid;
|
||||||
pCol->colId = pColSchema->colId;
|
pCol->colId = pColSchema->colId;
|
||||||
// pCol->colType = pColSchema->type;
|
pCol->colType = isTag ? COLUMN_TYPE_TAG : COLUMN_TYPE_COLUMN;
|
||||||
pCol->node.resType.type = pColSchema->type;
|
pCol->node.resType.type = pColSchema->type;
|
||||||
pCol->node.resType.bytes = pColSchema->bytes;
|
pCol->node.resType.bytes = pColSchema->bytes;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol) {
|
||||||
return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, pCol);
|
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol);
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -408,7 +408,7 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
|
||||||
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
||||||
for (int32_t i = 0; i < nums; ++i) {
|
for (int32_t i = 0; i < nums; ++i) {
|
||||||
if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) {
|
if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) {
|
||||||
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, pCol);
|
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void generateTestT1(MockCatalogService* mcs) {
|
void generateTestT1(MockCatalogService* mcs) {
|
||||||
ITableBuilder& builder = mcs->createTableBuilder("test", "t1", TSDB_NORMAL_TABLE, 3)
|
ITableBuilder& builder = mcs->createTableBuilder("test", "t1", TSDB_NORMAL_TABLE, 4)
|
||||||
.setPrecision(TSDB_TIME_PRECISION_MILLI).setVgid(1).addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
.setPrecision(TSDB_TIME_PRECISION_MILLI).setVgid(1).addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
||||||
.addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20);
|
.addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20).addColumn("c3", TSDB_DATA_TYPE_BIGINT);
|
||||||
builder.done();
|
builder.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,20 @@
|
||||||
|
|
||||||
#define CHECK_ALLOC(p, res) \
|
#define CHECK_ALLOC(p, res) \
|
||||||
do { \
|
do { \
|
||||||
if (NULL == p) { \
|
if (NULL == (p)) { \
|
||||||
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
|
||||||
return res; \
|
return (res); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CHECK_CODE(exec, res) \
|
#define CHECK_CODE(exec, res) \
|
||||||
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__); \
|
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||||
pCxt->errCode = code; \
|
pCxt->errCode = code; \
|
||||||
return res; \
|
return (res); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -83,14 +83,30 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
|
||||||
return DEAL_RES_CONTINUE;
|
return DEAL_RES_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
|
typedef struct SNameExprCxt {
|
||||||
SNode* pNode;
|
int32_t planNodeId;
|
||||||
FOREACH(pNode, pExprs) {
|
int32_t rewriteId;
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_VALUE == nodeType(pNode)) {
|
} SNameExprCxt;
|
||||||
continue;
|
|
||||||
|
static EDealRes doNameExpr(SNode* pNode, void* pContext) {
|
||||||
|
switch (nodeType(pNode)) {
|
||||||
|
case QUERY_NODE_OPERATOR:
|
||||||
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
|
SNameExprCxt* pCxt = (SNameExprCxt*)pContext;
|
||||||
|
sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId++);
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
}
|
}
|
||||||
sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", planNodeId, rewriteId);
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
|
||||||
|
SNameExprCxt nameCxt = { .planNodeId = planNodeId, .rewriteId = rewriteId };
|
||||||
|
nodesWalkList(pExprs, doNameExpr, &nameCxt);
|
||||||
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
|
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
|
||||||
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
|
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
|
@ -135,12 +151,16 @@ 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, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
|
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
|
||||||
pScan->pScanCols = nodesCloneList(pCols);
|
if (NULL != pCols) {
|
||||||
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
pScan->pScanCols = nodesCloneList(pCols);
|
||||||
|
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
||||||
|
}
|
||||||
|
|
||||||
// set output
|
// set output
|
||||||
pScan->node.pTargets = nodesCloneList(pCols);
|
if (NULL != pCols) {
|
||||||
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
|
pScan->node.pTargets = nodesCloneList(pCols);
|
||||||
|
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
|
||||||
|
}
|
||||||
|
|
||||||
return (SLogicNode*)pScan;
|
return (SLogicNode*)pScan;
|
||||||
}
|
}
|
||||||
|
@ -173,8 +193,10 @@ static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin);
|
CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin);
|
||||||
|
|
||||||
// set on conditions
|
// set on conditions
|
||||||
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
if (NULL != pJoinTable->pOnCond) {
|
||||||
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
||||||
|
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
||||||
|
}
|
||||||
|
|
||||||
// set the output
|
// set the output
|
||||||
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
|
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
|
||||||
|
@ -220,35 +242,57 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SLogicNode* pC
|
||||||
return (SLogicNode*)pFilter;
|
return (SLogicNode*)pFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
|
typedef struct SCreateColumnCxt {
|
||||||
SNodeList* pList = nodesMakeList();
|
int32_t errCode;
|
||||||
CHECK_ALLOC(pList, NULL);
|
SNodeList* pList;
|
||||||
SNode* pNode;
|
} SCreateColumnCxt;
|
||||||
FOREACH(pNode, pExprs) {
|
|
||||||
if (QUERY_NODE_VALUE == nodeType(pNode)) {
|
static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
||||||
continue;
|
SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
|
||||||
} else if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
case QUERY_NODE_COLUMN: {
|
||||||
SNode* pCol = nodesCloneNode(pNode);
|
SNode* pCol = nodesCloneNode(pNode);
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, pCol)) {
|
||||||
goto error;
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pCol)) {
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
goto error;
|
}
|
||||||
}
|
case QUERY_NODE_OPERATOR:
|
||||||
} else {
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
SExprNode* pExpr = (SExprNode*)pNode;
|
SExprNode* pExpr = (SExprNode*)pNode;
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol) {
|
||||||
goto error;
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
pCol->node.resType = pExpr->resType;
|
pCol->node.resType = pExpr->resType;
|
||||||
strcpy(pCol->colName, pExpr->aliasName);
|
strcpy(pCol->colName, pExpr->aliasName);
|
||||||
|
if (TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, (SNode*)pCol)) {
|
||||||
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return pList;
|
|
||||||
error:
|
return DEAL_RES_CONTINUE;
|
||||||
nodesDestroyList(pList);
|
}
|
||||||
return NULL;
|
|
||||||
|
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
|
||||||
|
SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() };
|
||||||
|
if (NULL == cxt.pList) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nodesWalkList(pExprs, doCreateColumn, &cxt);
|
||||||
|
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||||
|
nodesDestroyList(cxt.pList);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return cxt.pList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
||||||
|
@ -263,24 +307,37 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
|
||||||
pAgg->node.id = pCxt->planNodeId++;
|
pAgg->node.id = pCxt->planNodeId++;
|
||||||
|
|
||||||
// set grouyp keys, agg funcs and having conditions
|
// set grouyp keys, agg funcs and having conditions
|
||||||
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
if (NULL != pSelect->pGroupByList) {
|
||||||
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
||||||
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
||||||
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
|
}
|
||||||
|
if (NULL != pAggFuncs) {
|
||||||
|
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
||||||
|
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
|
||||||
|
}
|
||||||
|
|
||||||
// rewrite the expression in subsequent clauses
|
// 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, 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);
|
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);
|
if (NULL != pSelect->pHaving) {
|
||||||
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
|
||||||
|
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
||||||
|
}
|
||||||
|
|
||||||
// set the output
|
// set the output
|
||||||
pAgg->node.pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
pAgg->node.pTargets = nodesMakeList();
|
||||||
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
||||||
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
|
if (NULL != pAgg->pGroupKeys) {
|
||||||
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
|
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
||||||
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
||||||
|
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
||||||
|
}
|
||||||
|
if (NULL != pAgg->pAggFuncs) {
|
||||||
|
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
|
||||||
|
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
|
||||||
|
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
||||||
|
}
|
||||||
|
|
||||||
return (SLogicNode*)pAgg;
|
return (SLogicNode*)pAgg;
|
||||||
}
|
}
|
||||||
|
@ -344,7 +401,7 @@ static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
||||||
SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 0 };
|
SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 };
|
||||||
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
||||||
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||||
nodesDestroyNode((SNode*)pRoot);
|
nodesDestroyNode((SNode*)pRoot);
|
||||||
|
|
|
@ -42,26 +42,28 @@ protected:
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
int32_t code = parser(&cxt_, &query_);
|
int32_t code = parser(&cxt_, &query_);
|
||||||
// cout << "parser return " << code << endl;
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] parser code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string syntaxTreeStr = toString(query_.pRoot, false);
|
||||||
|
|
||||||
SLogicNode* pLogicPlan = nullptr;
|
SLogicNode* pLogicPlan = nullptr;
|
||||||
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] plan code:" << tstrerror(code) << endl;
|
cout << "sql:[" << cxt_.pSql << "] plan code:" << code << ", strerror:" << tstrerror(code) << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char* pStr = NULL;
|
|
||||||
int32_t len = 0;
|
cout << "sql : [" << cxt_.pSql << "]" << endl;
|
||||||
code = nodesNodeToString((const SNode*)pLogicPlan, &pStr, &len);
|
cout << "syntax test : " << endl;
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
cout << syntaxTreeStr << endl;
|
||||||
cout << "sql:[" << cxt_.pSql << "] toString code:" << tstrerror(code) << endl;
|
// cout << "logic plan : " << endl;
|
||||||
return false;
|
// cout << toString((const SNode*)pLogicPlan) << endl;
|
||||||
}
|
cout << "unformatted logic plan : " << endl;
|
||||||
cout << "logic plan : " << endl;
|
cout << toString((const SNode*)pLogicPlan, false) << endl;
|
||||||
cout << pStr << endl;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +77,19 @@ private:
|
||||||
cxt_.msgLen = max_err_len;
|
cxt_.msgLen = max_err_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string toString(const SNode* pRoot, bool format = true) {
|
||||||
|
char* pStr = NULL;
|
||||||
|
int32_t len = 0;
|
||||||
|
int32_t code = nodesNodeToString(pRoot, format, &pStr, &len);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
cout << "sql:[" << cxt_.pSql << "] toString code:" << code << ", strerror:" << tstrerror(code) << endl;
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
string str(pStr);
|
||||||
|
tfree(pStr);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
string acctId_;
|
string acctId_;
|
||||||
string db_;
|
string db_;
|
||||||
char errMagBuf_[max_err_len];
|
char errMagBuf_[max_err_len];
|
||||||
|
@ -89,3 +104,19 @@ TEST_F(NewPlannerTest, simple) {
|
||||||
bind("SELECT * FROM t1");
|
bind("SELECT * FROM t1");
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(NewPlannerTest, groupBy) {
|
||||||
|
setDatabase("root", "test");
|
||||||
|
|
||||||
|
bind("SELECT count(*) FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1, count(*) FROM t1 GROUP BY c1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1 + c3, c1 + count(*) FROM t1 where c2 = 'abc' GROUP BY c1, c3");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1 + c3, count(*) FROM t1 where concat(c2, 'wwww') = 'abcwww' GROUP BY c1 + c3");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@ int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t
|
||||||
return tjsonAddStringToObject(pJson, pName, tmp);
|
return tjsonAddStringToObject(pJson, pName, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t tjsonAddDoubleToObject(SJson* pJson, const char* pName, const double number) {
|
||||||
|
return (NULL == cJSON_AddNumberToObject((cJSON*)pJson, pName, number) ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal) {
|
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);
|
return (NULL == cJSON_AddStringToObject((cJSON*)pJson, pName, pVal) ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -74,3 +78,7 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj) {
|
||||||
char* tjsonToString(const SJson* pJson) {
|
char* tjsonToString(const SJson* pJson) {
|
||||||
return cJSON_Print((cJSON*)pJson);
|
return cJSON_Print((cJSON*)pJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* tjsonToUnformattedString(const SJson* pJson) {
|
||||||
|
return cJSON_PrintUnformatted((cJSON*)pJson);
|
||||||
|
}
|
Loading…
Reference in New Issue