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);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -30,6 +30,7 @@ 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 tjsonAddDoubleToObject(SJson* pJson, const char* pName, const double 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);
|
||||
|
@ -42,6 +43,7 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj);
|
|||
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
|
||||
|
||||
char* tjsonToString(const SJson* pJson);
|
||||
char* tjsonToUnformattedString(const SJson* pJson);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "querynodes.h"
|
||||
#include "taos.h"
|
||||
#include "taoserror.h"
|
||||
|
||||
#define COPY_SCALAR_FIELD(fldname) \
|
||||
do { \
|
||||
|
@ -57,14 +58,13 @@ static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {
|
|||
}
|
||||
|
||||
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
||||
COPY_SCALAR_FIELD(type);
|
||||
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
||||
COPY_CHAR_ARRAY_FIELD(aliasName);
|
||||
// COPY_NODE_LIST_FIELD(pAssociationList);
|
||||
}
|
||||
|
||||
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(colType);
|
||||
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) {
|
||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
||||
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||
COPY_CHAR_POINT_FIELD(literal);
|
||||
COPY_SCALAR_FIELD(isDuration);
|
||||
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) {
|
||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
||||
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||
COPY_SCALAR_FIELD(opType);
|
||||
COPY_NODE_FIELD(pLeft);
|
||||
COPY_NODE_FIELD(pRight);
|
||||
|
@ -127,14 +127,14 @@ static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* 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_NODE_LIST_FIELD(pParameterList);
|
||||
return (SNode*)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_SCALAR_FIELD(funcId);
|
||||
COPY_SCALAR_FIELD(funcType);
|
||||
|
@ -142,12 +142,19 @@ static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* 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) {
|
||||
if (NULL == pNode) {
|
||||
return NULL;
|
||||
}
|
||||
SNode* pDst = nodesMakeNode(nodeType(pNode));
|
||||
if (NULL == pDst) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
switch (nodeType(pNode)) {
|
||||
|
@ -164,7 +171,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
|||
case QUERY_NODE_REAL_TABLE:
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
break;
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
case QUERY_NODE_LIMIT:
|
||||
default:
|
||||
|
@ -174,8 +183,13 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
|||
}
|
||||
|
||||
SNodeList* nodesCloneList(const SNodeList* pList) {
|
||||
if (NULL == pList) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SNodeList* pDst = nodesMakeList();
|
||||
if (NULL == pDst) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
SNode* pNode;
|
||||
|
|
|
@ -26,27 +26,47 @@ static char* nodeName(ENodeType type) {
|
|||
case QUERY_NODE_COLUMN:
|
||||
return "Column";
|
||||
case QUERY_NODE_VALUE:
|
||||
return "Value";
|
||||
case QUERY_NODE_OPERATOR:
|
||||
return "Operator";
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
return "LogicCondition";
|
||||
case QUERY_NODE_FUNCTION:
|
||||
return "Function";
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
return "RealTable";
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
return "TempTable";
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
return "JoinTable";
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
return "GroupingSet";
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
return "OrderByExpr";
|
||||
case QUERY_NODE_LIMIT:
|
||||
return "Limit";
|
||||
case QUERY_NODE_STATE_WINDOW:
|
||||
return "StateWindow";
|
||||
case QUERY_NODE_SESSION_WINDOW:
|
||||
return "SessionWinow";
|
||||
case QUERY_NODE_INTERVAL_WINDOW:
|
||||
return "IntervalWindow";
|
||||
case QUERY_NODE_NODE_LIST:
|
||||
return "NodeList";
|
||||
case QUERY_NODE_FILL:
|
||||
return "Fill";
|
||||
case QUERY_NODE_COLUMN_REF:
|
||||
return "ColumnRef";
|
||||
case QUERY_NODE_TARGET:
|
||||
return "Target";
|
||||
case QUERY_NODE_RAW_EXPR:
|
||||
return "RawExpr";
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return "SetOperator";
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
return "SelectStmt";
|
||||
case QUERY_NODE_SHOW_STMT:
|
||||
break;
|
||||
return "ShowStmt";
|
||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||
return "LogicScan";
|
||||
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* 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;
|
||||
|
||||
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 int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
|
||||
static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
|
||||
|
||||
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* 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;
|
||||
|
||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||
|
@ -163,14 +183,14 @@ static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t logicFilterToJson(const void* pObj, SJson* pJson) {
|
||||
static int32_t logicFilterNodeToJson(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) {
|
||||
static int32_t logicAggNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
|
||||
|
||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||
|
@ -184,17 +204,291 @@ static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
|
|||
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) {
|
||||
switch (nodeType(pObj)) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
return columnNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_VALUE:
|
||||
return valueNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_OPERATOR:
|
||||
return operatorNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
return logicConditionNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_FUNCTION:
|
||||
return functionNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
break;
|
||||
case QUERY_NODE_GROUPING_SET:
|
||||
return groupingSetNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
case QUERY_NODE_LIMIT:
|
||||
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_RAW_EXPR:
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
break;
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
return selectStmtTojson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_STMT:
|
||||
break;
|
||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||
return logicScanToJson(pObj, pJson);
|
||||
return logicScanNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||
return logicJoinToJson(pObj, pJson);
|
||||
return logicJoinNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_FILTER:
|
||||
return logicFilterToJson(pObj, pJson);
|
||||
return logicFilterNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_AGG:
|
||||
return logicAggToJson(pObj, pJson);
|
||||
return logicAggNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
||||
return logicProjectToJson(pObj, pJson);
|
||||
return logicProjectNodeToJson(pObj, pJson);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -238,7 +534,7 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) {
|
|||
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) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -255,7 +551,7 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
|||
return code;
|
||||
}
|
||||
|
||||
*pStr = tjsonToString(pJson);
|
||||
*pStr = format ? tjsonToString(pJson) : tjsonToUnformattedString(pJson);
|
||||
tjsonDelete(pJson);
|
||||
|
||||
*pLen = strlen(*pStr) + 1;
|
||||
|
|
|
@ -132,11 +132,22 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) {
|
|||
}
|
||||
|
||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||
pTarget->pTail->pNext = pSrc->pHead;
|
||||
pSrc->pHead->pPrev = pTarget->pTail;
|
||||
if (NULL == pTarget || NULL == pSrc) {
|
||||
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->length += pSrc->length;
|
||||
tfree(pSrc);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -290,6 +301,10 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char*
|
|||
nodesDestroyList(cxt.pCols);
|
||||
return cxt.errCode;
|
||||
}
|
||||
if (0 == LIST_LENGTH(cxt.pCols)) {
|
||||
nodesDestroyList(cxt.pCols);
|
||||
cxt.pCols = NULL;
|
||||
}
|
||||
*pCols = cxt.pCols;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -349,7 +349,7 @@ static SNodeList* getProjectList(SNode* pNode) {
|
|||
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->tableAlias, pTable->table.tableAlias);
|
||||
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->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.bytes = pColSchema->bytes;
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode
|
|||
if (NULL == pCol) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
|
@ -408,7 +408,7 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
|
|||
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
||||
for (int32_t i = 0; i < nums; ++i) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
namespace {
|
||||
|
||||
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)
|
||||
.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();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,20 +18,20 @@
|
|||
|
||||
#define CHECK_ALLOC(p, res) \
|
||||
do { \
|
||||
if (NULL == p) { \
|
||||
if (NULL == (p)) { \
|
||||
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
|
||||
return res; \
|
||||
return (res); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_CODE(exec, res) \
|
||||
do { \
|
||||
int32_t code = exec; \
|
||||
int32_t code = (exec); \
|
||||
if (TSDB_CODE_SUCCESS != code) { \
|
||||
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||
pCxt->errCode = code; \
|
||||
return res; \
|
||||
return (res); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -83,14 +83,30 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
|
|||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
|
||||
SNode* pNode;
|
||||
FOREACH(pNode, pExprs) {
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_VALUE == nodeType(pNode)) {
|
||||
continue;
|
||||
typedef struct SNameExprCxt {
|
||||
int32_t planNodeId;
|
||||
int32_t rewriteId;
|
||||
} SNameExprCxt;
|
||||
|
||||
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 };
|
||||
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
|
||||
return cxt.errCode;
|
||||
|
@ -135,12 +151,16 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
|||
// set columns to scan
|
||||
SNodeList* pCols = NULL;
|
||||
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
|
||||
pScan->pScanCols = nodesCloneList(pCols);
|
||||
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
||||
if (NULL != pCols) {
|
||||
pScan->pScanCols = nodesCloneList(pCols);
|
||||
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
||||
}
|
||||
|
||||
// set output
|
||||
pScan->node.pTargets = nodesCloneList(pCols);
|
||||
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
|
||||
if (NULL != pCols) {
|
||||
pScan->node.pTargets = nodesCloneList(pCols);
|
||||
CHECK_ALLOC(pScan->node.pTargets, (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);
|
||||
|
||||
// set on conditions
|
||||
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
||||
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
||||
if (NULL != pJoinTable->pOnCond) {
|
||||
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
||||
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
||||
}
|
||||
|
||||
// set the output
|
||||
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
|
||||
|
@ -220,35 +242,57 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SLogicNode* pC
|
|||
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)) {
|
||||
typedef struct SCreateColumnCxt {
|
||||
int32_t errCode;
|
||||
SNodeList* pList;
|
||||
} SCreateColumnCxt;
|
||||
|
||||
static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
||||
SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
|
||||
switch (nodeType(pNode)) {
|
||||
case QUERY_NODE_COLUMN: {
|
||||
SNode* pCol = nodesCloneNode(pNode);
|
||||
if (NULL == pCol) {
|
||||
goto error;
|
||||
if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, pCol)) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pCol)) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
case QUERY_NODE_OPERATOR:
|
||||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
case QUERY_NODE_FUNCTION: {
|
||||
SExprNode* pExpr = (SExprNode*)pNode;
|
||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
if (NULL == pCol) {
|
||||
goto error;
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
pCol->node.resType = pExpr->resType;
|
||||
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:
|
||||
nodesDestroyList(pList);
|
||||
return NULL;
|
||||
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -263,24 +307,37 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
|
|||
pAgg->node.id = pCxt->planNodeId++;
|
||||
|
||||
// set grouyp keys, agg funcs and having conditions
|
||||
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
||||
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
||||
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
||||
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
|
||||
if (NULL != pSelect->pGroupByList) {
|
||||
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
||||
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
||||
}
|
||||
if (NULL != pAggFuncs) {
|
||||
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
||||
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);
|
||||
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
||||
if (NULL != pSelect->pHaving) {
|
||||
pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
|
||||
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
||||
}
|
||||
|
||||
// set the output
|
||||
pAgg->node.pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
||||
pAgg->node.pTargets = nodesMakeList();
|
||||
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
||||
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
|
||||
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
|
||||
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
||||
if (NULL != pAgg->pGroupKeys) {
|
||||
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
||||
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;
|
||||
}
|
||||
|
@ -344,7 +401,7 @@ static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
|
|||
}
|
||||
|
||||
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);
|
||||
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||
nodesDestroyNode((SNode*)pRoot);
|
||||
|
|
|
@ -42,26 +42,28 @@ protected:
|
|||
|
||||
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;
|
||||
cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const string syntaxTreeStr = toString(query_.pRoot, false);
|
||||
|
||||
SLogicNode* pLogicPlan = nullptr;
|
||||
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
cout << "sql : [" << cxt_.pSql << "]" << endl;
|
||||
cout << "syntax test : " << endl;
|
||||
cout << syntaxTreeStr << endl;
|
||||
// cout << "logic plan : " << endl;
|
||||
// cout << toString((const SNode*)pLogicPlan) << endl;
|
||||
cout << "unformatted logic plan : " << endl;
|
||||
cout << toString((const SNode*)pLogicPlan, false) << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -75,6 +77,19 @@ private:
|
|||
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 db_;
|
||||
char errMagBuf_[max_err_len];
|
||||
|
@ -89,3 +104,19 @@ TEST_F(NewPlannerTest, simple) {
|
|||
bind("SELECT * FROM t1");
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
return cJSON_Print((cJSON*)pJson);
|
||||
}
|
||||
|
||||
char* tjsonToUnformattedString(const SJson* pJson) {
|
||||
return cJSON_PrintUnformatted((cJSON*)pJson);
|
||||
}
|
Loading…
Reference in New Issue