未验证 提交 08504bd9 编写于 作者: X Xiaoyu Wang 提交者: GitHub

Merge pull request #12030 from taosdata/feature/3.0_wxy

enh: refactor unit test of parser and planner
...@@ -22,19 +22,20 @@ extern "C" { ...@@ -22,19 +22,20 @@ extern "C" {
#include "tdef.h" #include "tdef.h"
#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type) #define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
#define setNodeType(nodeptr, type) (((SNode*)(nodeptr))->type = (type)) #define setNodeType(nodeptr, type) (((SNode*)(nodeptr))->type = (type))
#define LIST_LENGTH(l) (NULL != (l) ? (l)->length : 0) #define LIST_LENGTH(l) (NULL != (l) ? (l)->length : 0)
#define FOREACH(node, list) \ #define FOREACH(node, list) \
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext) for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
(NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext)
#define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode) #define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode)
#define INSERT_LIST(target, src) nodesListInsertList((target), cell, src) #define INSERT_LIST(target, src) nodesListInsertList((target), cell, src)
#define WHERE_EACH(node, list) \ #define WHERE_EACH(node, list) \
SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \ SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
while (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)) while (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false))
...@@ -43,16 +44,26 @@ extern "C" { ...@@ -43,16 +44,26 @@ extern "C" {
// only be use in WHERE_EACH // only be use in WHERE_EACH
#define ERASE_NODE(list) cell = nodesListErase((list), cell) #define ERASE_NODE(list) cell = nodesListErase((list), cell)
#define FORBOTH(node1, list1, node2, list2) \ #define FORBOTH(node1, list1, node2, list2) \
for (SListCell* cell1 = (NULL != (list1) ? (list1)->pHead : NULL), *cell2 = (NULL != (list2) ? (list2)->pHead : NULL); \ for (SListCell* cell1 = (NULL != (list1) ? (list1)->pHead : NULL), \
(NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), (NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), (node1 != NULL && node2 != NULL); \ *cell2 = (NULL != (list2) ? (list2)->pHead : NULL); \
cell1 = cell1->pNext, cell2 = cell2->pNext) (NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), \
(NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), \
(node1 != NULL && node2 != NULL); \
cell1 = cell1->pNext, cell2 = cell2->pNext)
#define REPLACE_LIST1_NODE(newNode) cell1->pNode = (SNode*)(newNode) #define REPLACE_LIST1_NODE(newNode) cell1->pNode = (SNode*)(newNode)
#define REPLACE_LIST2_NODE(newNode) cell2->pNode = (SNode*)(newNode) #define REPLACE_LIST2_NODE(newNode) cell2->pNode = (SNode*)(newNode)
#define FOREACH_FOR_REWRITE(node, list) \ #define FOREACH_FOR_REWRITE(node, list) \
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext) for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
#define DESTORY_LIST(list) \
do { \
nodesDestroyList(list); \
list = NULL; \
} while (0)
typedef enum ENodeType { typedef enum ENodeType {
// Syntax nodes are used in parser and planner module, and some are also used in executor module, such as COLUMN, // Syntax nodes are used in parser and planner module, and some are also used in executor module, such as COLUMN,
...@@ -202,7 +213,7 @@ typedef enum ENodeType { ...@@ -202,7 +213,7 @@ typedef enum ENodeType {
/** /**
* The first field of a node of any type is guaranteed to be the ENodeType. * The first field of a node of any type is guaranteed to be the ENodeType.
* Hence the type of any node can be gotten by casting it to SNode. * Hence the type of any node can be gotten by casting it to SNode.
*/ */
typedef struct SNode { typedef struct SNode {
ENodeType type; ENodeType type;
...@@ -211,41 +222,36 @@ typedef struct SNode { ...@@ -211,41 +222,36 @@ typedef struct SNode {
typedef struct SListCell { typedef struct SListCell {
struct SListCell* pPrev; struct SListCell* pPrev;
struct SListCell* pNext; struct SListCell* pNext;
SNode* pNode; SNode* pNode;
} SListCell; } SListCell;
typedef struct SNodeList { typedef struct SNodeList {
int32_t length; int32_t length;
SListCell* pHead; SListCell* pHead;
SListCell* pTail; SListCell* pTail;
} SNodeList; } SNodeList;
#define SNodeptr void* #define SNodeptr void*
SNodeptr nodesMakeNode(ENodeType type); SNodeptr nodesMakeNode(ENodeType type);
void nodesDestroyNode(SNodeptr pNode); void nodesDestroyNode(SNodeptr pNode);
SNodeList* nodesMakeList(); SNodeList* nodesMakeList();
int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode); int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode);
int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode); int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode);
int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode); int32_t nodesListMakeAppend(SNodeList** pList, SNodeptr pNode);
int32_t nodesListMakeStrictAppend(SNodeList** pList, SNodeptr pNode); int32_t nodesListMakeStrictAppend(SNodeList** pList, SNodeptr pNode);
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc); int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc);
int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc); int32_t nodesListStrictAppendList(SNodeList* pTarget, SNodeList* pSrc);
int32_t nodesListPushFront(SNodeList* pList, SNodeptr pNode); int32_t nodesListPushFront(SNodeList* pList, SNodeptr pNode);
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell); SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc); void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc);
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index); SNodeptr nodesListGetNode(SNodeList* pList, int32_t index);
void nodesDestroyList(SNodeList* pList); void nodesDestroyList(SNodeList* pList);
// Only clear the linked list structure, without releasing the elements inside // Only clear the linked list structure, without releasing the elements inside
void nodesClearList(SNodeList* pList); void nodesClearList(SNodeList* pList);
typedef enum EDealRes { typedef enum EDealRes { DEAL_RES_CONTINUE = 1, DEAL_RES_IGNORE_CHILD, DEAL_RES_ERROR, DEAL_RES_END } EDealRes;
DEAL_RES_CONTINUE = 1,
DEAL_RES_IGNORE_CHILD,
DEAL_RES_ERROR,
DEAL_RES_END
} EDealRes;
typedef EDealRes (*FNodeWalker)(SNode* pNode, void* pContext); typedef EDealRes (*FNodeWalker)(SNode* pNode, void* pContext);
void nodesWalkExpr(SNodeptr pNode, FNodeWalker walker, void* pContext); void nodesWalkExpr(SNodeptr pNode, FNodeWalker walker, void* pContext);
...@@ -261,18 +267,18 @@ void nodesRewriteExprsPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* ...@@ -261,18 +267,18 @@ void nodesRewriteExprsPostOrder(SNodeList* pList, FNodeRewriter rewriter, void*
bool nodesEqualNode(const SNodeptr a, const SNodeptr b); bool nodesEqualNode(const SNodeptr a, const SNodeptr b);
SNodeptr nodesCloneNode(const SNodeptr pNode); SNodeptr nodesCloneNode(const SNodeptr pNode);
SNodeList* nodesCloneList(const SNodeList* pList); SNodeList* nodesCloneList(const SNodeList* pList);
const char* nodesNodeName(ENodeType type); const char* nodesNodeName(ENodeType type);
int32_t nodesNodeToString(const SNodeptr pNode, bool format, char** pStr, int32_t* pLen); int32_t nodesNodeToString(const SNodeptr pNode, bool format, char** pStr, int32_t* pLen);
int32_t nodesStringToNode(const char* pStr, SNode** pNode); int32_t nodesStringToNode(const char* pStr, SNode** pNode);
int32_t nodesListToString(const SNodeList* pList, bool format, char** pStr, int32_t* pLen); int32_t nodesListToString(const SNodeList* pList, bool format, char** pStr, int32_t* pLen);
int32_t nodesStringToList(const char* pStr, SNodeList** pList); int32_t nodesStringToList(const char* pStr, SNodeList** pList);
int32_t nodesNodeToSQL(SNode *pNode, char *buf, int32_t bufSize, int32_t *len); int32_t nodesNodeToSQL(SNode* pNode, char* buf, int32_t bufSize, int32_t* len);
char *nodesGetNameFromColumnNode(SNode *pNode); char* nodesGetNameFromColumnNode(SNode* pNode);
int32_t nodesGetOutputNumFromSlotList(SNodeList* pSlots); int32_t nodesGetOutputNumFromSlotList(SNodeList* pSlots);
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -294,13 +294,14 @@ void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker wa ...@@ -294,13 +294,14 @@ void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker wa
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext); void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
typedef enum ECollectColType { COLLECT_COL_TYPE_COL = 1, COLLECT_COL_TYPE_TAG, COLLECT_COL_TYPE_ALL } ECollectColType; typedef enum ECollectColType { COLLECT_COL_TYPE_COL = 1, COLLECT_COL_TYPE_TAG, COLLECT_COL_TYPE_ALL } ECollectColType;
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, ECollectColType type, int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, ECollectColType type,
SNodeList** pCols); SNodeList** pCols);
typedef bool (*FFuncClassifier)(int32_t funcId); typedef bool (*FFuncClassifier)(int32_t funcId);
int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs); int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs);
int32_t nodesCollectSpecialNodes(SSelectStmt* pSelect, ESqlClause clause, ENodeType type, SNodeList** pNodes);
bool nodesIsExprNode(const SNode* pNode); bool nodesIsExprNode(const SNode* pNode);
bool nodesIsUnaryOp(const SOperatorNode* pOp); bool nodesIsUnaryOp(const SOperatorNode* pOp);
......
...@@ -588,6 +588,259 @@ static int32_t jsonToLogicSortNode(const SJson* pJson, void* pObj) { ...@@ -588,6 +588,259 @@ static int32_t jsonToLogicSortNode(const SJson* pJson, void* pObj) {
return code; return code;
} }
static const char* jkPartitionLogicPlanPartitionKeys = "PartitionKeys";
static int32_t logicPartitionNodeToJson(const void* pObj, SJson* pJson) {
const SPartitionLogicNode* pNode = (const SPartitionLogicNode*)pObj;
int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkPartitionLogicPlanPartitionKeys, pNode->pPartitionKeys);
}
return code;
}
static int32_t jsonToLogicPartitionNode(const SJson* pJson, void* pObj) {
SPartitionLogicNode* pNode = (SPartitionLogicNode*)pObj;
int32_t code = jsonToLogicPlanNode(pJson, pObj);
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkPartitionLogicPlanPartitionKeys, &pNode->pPartitionKeys);
}
return code;
}
static const char* jkSubplanIdQueryId = "QueryId";
static const char* jkSubplanIdGroupId = "GroupId";
static const char* jkSubplanIdSubplanId = "SubplanId";
static int32_t subplanIdToJson(const void* pObj, SJson* pJson) {
const SSubplanId* pNode = (const SSubplanId*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkSubplanIdQueryId, pNode->queryId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkSubplanIdGroupId, pNode->groupId);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkSubplanIdSubplanId, pNode->subplanId);
}
return code;
}
static int32_t jsonToSubplanId(const SJson* pJson, void* pObj) {
SSubplanId* pNode = (SSubplanId*)pObj;
int32_t code = tjsonGetUBigIntValue(pJson, jkSubplanIdQueryId, &pNode->queryId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkSubplanIdGroupId, &pNode->groupId);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkSubplanIdSubplanId, &pNode->subplanId);
}
return code;
}
static const char* jkEndPointFqdn = "Fqdn";
static const char* jkEndPointPort = "Port";
static int32_t epToJson(const void* pObj, SJson* pJson) {
const SEp* pNode = (const SEp*)pObj;
int32_t code = tjsonAddStringToObject(pJson, jkEndPointFqdn, pNode->fqdn);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkEndPointPort, pNode->port);
}
return code;
}
static int32_t jsonToEp(const SJson* pJson, void* pObj) {
SEp* pNode = (SEp*)pObj;
int32_t code = tjsonGetStringValue(pJson, jkEndPointFqdn, pNode->fqdn);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetSmallIntValue(pJson, jkEndPointPort, &pNode->port);
}
return code;
}
static const char* jkEpSetInUse = "InUse";
static const char* jkEpSetNumOfEps = "NumOfEps";
static const char* jkEpSetEps = "Eps";
static int32_t epSetToJson(const void* pObj, SJson* pJson) {
const SEpSet* pNode = (const SEpSet*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkEpSetInUse, pNode->inUse);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkEpSetNumOfEps, pNode->numOfEps);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddArray(pJson, jkEpSetEps, epToJson, pNode->eps, sizeof(SEp), pNode->numOfEps);
}
return code;
}
static int32_t jsonToEpSet(const SJson* pJson, void* pObj) {
SEpSet* pNode = (SEpSet*)pObj;
int32_t code = tjsonGetTinyIntValue(pJson, jkEpSetInUse, &pNode->inUse);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetTinyIntValue(pJson, jkEpSetNumOfEps, &pNode->numOfEps);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToArray(pJson, jkEpSetEps, jsonToEp, pNode->eps, sizeof(SEp));
}
return code;
}
static const char* jkVgroupInfoVgId = "VgId";
static const char* jkVgroupInfoHashBegin = "HashBegin";
static const char* jkVgroupInfoHashEnd = "HashEnd";
static const char* jkVgroupInfoEpSet = "EpSet";
static const char* jkVgroupInfoNumOfTable = "NumOfTable";
static int32_t vgroupInfoToJson(const void* pObj, SJson* pJson) {
const SVgroupInfo* pNode = (const SVgroupInfo*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkVgroupInfoVgId, pNode->vgId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoHashBegin, pNode->hashBegin);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoHashEnd, pNode->hashEnd);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkVgroupInfoEpSet, epSetToJson, &pNode->epSet);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoNumOfTable, pNode->numOfTable);
}
return code;
}
static int32_t jsonToVgroupInfo(const SJson* pJson, void* pObj) {
SVgroupInfo* pNode = (SVgroupInfo*)pObj;
int32_t code = tjsonGetIntValue(pJson, jkVgroupInfoVgId, &pNode->vgId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUIntValue(pJson, jkVgroupInfoHashBegin, &pNode->hashBegin);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUIntValue(pJson, jkVgroupInfoHashEnd, &pNode->hashEnd);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToObject(pJson, jkVgroupInfoEpSet, jsonToEpSet, &pNode->epSet);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkVgroupInfoNumOfTable, &pNode->numOfTable);
}
return code;
}
static const char* jkVgroupsInfoNum = "Num";
static const char* jkVgroupsInfoVgroups = "Vgroups";
static int32_t vgroupsInfoToJson(const void* pObj, SJson* pJson) {
const SVgroupsInfo* pNode = (const SVgroupsInfo*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkVgroupsInfoNum, pNode->numOfVgroups);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddArray(pJson, jkVgroupsInfoVgroups, vgroupInfoToJson, pNode->vgroups, sizeof(SVgroupInfo),
pNode->numOfVgroups);
}
return code;
}
static int32_t jsonToVgroupsInfo(const SJson* pJson, void* pObj) {
SVgroupsInfo* pNode = (SVgroupsInfo*)pObj;
int32_t code = tjsonGetIntValue(pJson, jkVgroupsInfoNum, &pNode->numOfVgroups);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToArray(pJson, jkVgroupsInfoVgroups, jsonToVgroupInfo, pNode->vgroups, sizeof(SVgroupInfo));
}
return code;
}
static const char* jkLogicSubplanId = "Id";
static const char* jkLogicSubplanChildren = "Children";
static const char* jkLogicSubplanRootNode = "RootNode";
static const char* jkLogicSubplanType = "SubplanType";
static const char* jkLogicSubplanVgroupsSize = "VgroupsSize";
static const char* jkLogicSubplanVgroups = "Vgroups";
static const char* jkLogicSubplanLevel = "Level";
static const char* jkLogicSubplanSplitFlag = "SplitFlag";
static int32_t logicSubplanToJson(const void* pObj, SJson* pJson) {
const SLogicSubplan* pNode = (const SLogicSubplan*)pObj;
int32_t code = tjsonAddObject(pJson, jkLogicSubplanId, subplanIdToJson, &pNode->id);
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkLogicSubplanChildren, pNode->pChildren);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkLogicSubplanRootNode, nodeToJson, pNode->pNode);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkLogicSubplanType, pNode->subplanType);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkLogicSubplanVgroupsSize, VGROUPS_INFO_SIZE(pNode->pVgroupList));
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkLogicSubplanVgroups, vgroupsInfoToJson, pNode->pVgroupList);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkLogicSubplanLevel, pNode->level);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkLogicSubplanSplitFlag, pNode->splitFlag);
}
return code;
}
static int32_t jsonToLogicSubplan(const SJson* pJson, void* pObj) {
SLogicSubplan* pNode = (SLogicSubplan*)pObj;
int32_t code = tjsonToObject(pJson, jkLogicSubplanId, jsonToSubplanId, &pNode->id);
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkLogicSubplanChildren, &pNode->pChildren);
}
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkLogicSubplanRootNode, (SNode**)&pNode->pNode);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetNumberValue(pJson, jkLogicSubplanType, pNode->subplanType);
}
int32_t objSize = 0;
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkLogicSubplanVgroupsSize, &objSize);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonMakeObject(pJson, jkLogicSubplanVgroups, jsonToVgroupsInfo, (void**)&pNode->pVgroupList, objSize);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkLogicSubplanLevel, &pNode->level);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkLogicSubplanSplitFlag, &pNode->splitFlag);
}
return code;
}
static const char* jkJoinLogicPlanJoinType = "JoinType"; static const char* jkJoinLogicPlanJoinType = "JoinType";
static const char* jkJoinLogicPlanOnConditions = "OnConditions"; static const char* jkJoinLogicPlanOnConditions = "OnConditions";
...@@ -837,63 +1090,6 @@ static int32_t physiStreamScanNodeToJson(const void* pObj, SJson* pJson) { retur ...@@ -837,63 +1090,6 @@ static int32_t physiStreamScanNodeToJson(const void* pObj, SJson* pJson) { retur
static int32_t jsonToPhysiStreamScanNode(const SJson* pJson, void* pObj) { return jsonToPhysiScanNode(pJson, pObj); } static int32_t jsonToPhysiStreamScanNode(const SJson* pJson, void* pObj) { return jsonToPhysiScanNode(pJson, pObj); }
static const char* jkEndPointFqdn = "Fqdn";
static const char* jkEndPointPort = "Port";
static int32_t epToJson(const void* pObj, SJson* pJson) {
const SEp* pNode = (const SEp*)pObj;
int32_t code = tjsonAddStringToObject(pJson, jkEndPointFqdn, pNode->fqdn);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkEndPointPort, pNode->port);
}
return code;
}
static int32_t jsonToEp(const SJson* pJson, void* pObj) {
SEp* pNode = (SEp*)pObj;
int32_t code = tjsonGetStringValue(pJson, jkEndPointFqdn, pNode->fqdn);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetSmallIntValue(pJson, jkEndPointPort, &pNode->port);
}
return code;
}
static const char* jkEpSetInUse = "InUse";
static const char* jkEpSetNumOfEps = "NumOfEps";
static const char* jkEpSetEps = "Eps";
static int32_t epSetToJson(const void* pObj, SJson* pJson) {
const SEpSet* pNode = (const SEpSet*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkEpSetInUse, pNode->inUse);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkEpSetNumOfEps, pNode->numOfEps);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddArray(pJson, jkEpSetEps, epToJson, pNode->eps, sizeof(SEp), pNode->numOfEps);
}
return code;
}
static int32_t jsonToEpSet(const SJson* pJson, void* pObj) {
SEpSet* pNode = (SEpSet*)pObj;
int32_t code = tjsonGetTinyIntValue(pJson, jkEpSetInUse, &pNode->inUse);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetTinyIntValue(pJson, jkEpSetNumOfEps, &pNode->numOfEps);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToArray(pJson, jkEpSetEps, jsonToEp, pNode->eps, sizeof(SEp));
}
return code;
}
static const char* jkSysTableScanPhysiPlanMnodeEpSet = "MnodeEpSet"; static const char* jkSysTableScanPhysiPlanMnodeEpSet = "MnodeEpSet";
static const char* jkSysTableScanPhysiPlanShowRewrite = "ShowRewrite"; static const char* jkSysTableScanPhysiPlanShowRewrite = "ShowRewrite";
static const char* jkSysTableScanPhysiPlanAccountId = "AccountId"; static const char* jkSysTableScanPhysiPlanAccountId = "AccountId";
...@@ -1342,38 +1538,6 @@ static int32_t physiDispatchNodeToJson(const void* pObj, SJson* pJson) { return ...@@ -1342,38 +1538,6 @@ static int32_t physiDispatchNodeToJson(const void* pObj, SJson* pJson) { return
static int32_t jsonToPhysiDispatchNode(const SJson* pJson, void* pObj) { return jsonToPhysicDataSinkNode(pJson, pObj); } static int32_t jsonToPhysiDispatchNode(const SJson* pJson, void* pObj) { return jsonToPhysicDataSinkNode(pJson, pObj); }
static const char* jkSubplanIdQueryId = "QueryId";
static const char* jkSubplanIdGroupId = "GroupId";
static const char* jkSubplanIdSubplanId = "SubplanId";
static int32_t subplanIdToJson(const void* pObj, SJson* pJson) {
const SSubplanId* pNode = (const SSubplanId*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkSubplanIdQueryId, pNode->queryId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkSubplanIdGroupId, pNode->groupId);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkSubplanIdSubplanId, pNode->subplanId);
}
return code;
}
static int32_t jsonToSubplanId(const SJson* pJson, void* pObj) {
SSubplanId* pNode = (SSubplanId*)pObj;
int32_t code = tjsonGetUBigIntValue(pJson, jkSubplanIdQueryId, &pNode->queryId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkSubplanIdGroupId, &pNode->groupId);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkSubplanIdSubplanId, &pNode->subplanId);
}
return code;
}
static const char* jkQueryNodeAddrId = "Id"; static const char* jkQueryNodeAddrId = "Id";
static const char* jkQueryNodeAddrInUse = "InUse"; static const char* jkQueryNodeAddrInUse = "InUse";
static const char* jkQueryNodeAddrNumOfEps = "NumOfEps"; static const char* jkQueryNodeAddrNumOfEps = "NumOfEps";
...@@ -1964,78 +2128,6 @@ static int32_t jsonToTableNode(const SJson* pJson, void* pObj) { ...@@ -1964,78 +2128,6 @@ static int32_t jsonToTableNode(const SJson* pJson, void* pObj) {
return code; return code;
} }
static const char* jkVgroupInfoVgId = "VgId";
static const char* jkVgroupInfoHashBegin = "HashBegin";
static const char* jkVgroupInfoHashEnd = "HashEnd";
static const char* jkVgroupInfoEpSet = "EpSet";
static const char* jkVgroupInfoNumOfTable = "NumOfTable";
static int32_t vgroupInfoToJson(const void* pObj, SJson* pJson) {
const SVgroupInfo* pNode = (const SVgroupInfo*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkVgroupInfoVgId, pNode->vgId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoHashBegin, pNode->hashBegin);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoHashEnd, pNode->hashEnd);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkVgroupInfoEpSet, epSetToJson, &pNode->epSet);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkVgroupInfoNumOfTable, pNode->numOfTable);
}
return code;
}
static int32_t jsonToVgroupInfo(const SJson* pJson, void* pObj) {
SVgroupInfo* pNode = (SVgroupInfo*)pObj;
int32_t code = tjsonGetIntValue(pJson, jkVgroupInfoVgId, &pNode->vgId);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUIntValue(pJson, jkVgroupInfoHashBegin, &pNode->hashBegin);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetUIntValue(pJson, jkVgroupInfoHashEnd, &pNode->hashEnd);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToObject(pJson, jkVgroupInfoEpSet, jsonToEpSet, &pNode->epSet);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkVgroupInfoNumOfTable, &pNode->numOfTable);
}
return code;
}
static const char* jkVgroupsInfoNum = "Num";
static const char* jkVgroupsInfoVgroups = "Vgroups";
static int32_t vgroupsInfoToJson(const void* pObj, SJson* pJson) {
const SVgroupsInfo* pNode = (const SVgroupsInfo*)pObj;
int32_t code = tjsonAddIntegerToObject(pJson, jkVgroupsInfoNum, pNode->numOfVgroups);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddArray(pJson, jkVgroupsInfoVgroups, vgroupInfoToJson, pNode->vgroups, sizeof(SVgroupInfo),
pNode->numOfVgroups);
}
return code;
}
static int32_t jsonToVgroupsInfo(const SJson* pJson, void* pObj) {
SVgroupsInfo* pNode = (SVgroupsInfo*)pObj;
int32_t code = tjsonGetIntValue(pJson, jkVgroupsInfoNum, &pNode->numOfVgroups);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToArray(pJson, jkVgroupsInfoVgroups, jsonToVgroupInfo, pNode->vgroups, sizeof(SVgroupInfo));
}
return code;
}
static const char* jkRealTableMetaSize = "MetaSize"; static const char* jkRealTableMetaSize = "MetaSize";
static const char* jkRealTableMeta = "Meta"; static const char* jkRealTableMeta = "Meta";
static const char* jkRealTableVgroupsInfoSize = "VgroupsInfoSize"; static const char* jkRealTableVgroupsInfoSize = "VgroupsInfoSize";
...@@ -2582,7 +2674,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { ...@@ -2582,7 +2674,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
break; break;
case QUERY_NODE_LOGIC_PLAN_SORT: case QUERY_NODE_LOGIC_PLAN_SORT:
return logicSortNodeToJson(pObj, pJson); return logicSortNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_PARTITION:
return logicPartitionNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_SUBPLAN: case QUERY_NODE_LOGIC_SUBPLAN:
return logicSubplanToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN: case QUERY_NODE_LOGIC_PLAN:
break; break;
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
...@@ -2667,6 +2762,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { ...@@ -2667,6 +2762,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToLogicProjectNode(pJson, pObj); return jsonToLogicProjectNode(pJson, pObj);
case QUERY_NODE_LOGIC_PLAN_SORT: case QUERY_NODE_LOGIC_PLAN_SORT:
return jsonToLogicSortNode(pJson, pObj); return jsonToLogicSortNode(pJson, pObj);
case QUERY_NODE_LOGIC_PLAN_PARTITION:
return jsonToLogicPartitionNode(pJson, pObj);
case QUERY_NODE_LOGIC_SUBPLAN:
return jsonToLogicSubplan(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
return jsonToPhysiTagScanNode(pJson, pObj); return jsonToPhysiTagScanNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
......
...@@ -1090,30 +1090,31 @@ static EDealRes collectColumns(SNode* pNode, void* pContext) { ...@@ -1090,30 +1090,31 @@ static EDealRes collectColumns(SNode* pNode, void* pContext) {
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, ECollectColType type, int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, ECollectColType type,
SNodeList** pCols) { SNodeList** pCols) {
if (NULL == pSelect || NULL == pCols) { if (NULL == pSelect || NULL == pCols) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_FAILED;
} }
SCollectColumnsCxt cxt = { SCollectColumnsCxt cxt = {
.errCode = TSDB_CODE_SUCCESS, .errCode = TSDB_CODE_SUCCESS,
.pTableAlias = pTableAlias, .pTableAlias = pTableAlias,
.collectType = type, .collectType = type,
.pCols = nodesMakeList(), .pCols = (NULL == *pCols ? nodesMakeList() : *pCols),
.pColHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK)}; .pColHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK)};
if (NULL == cxt.pCols || NULL == cxt.pColHash) { if (NULL == cxt.pCols || NULL == cxt.pColHash) {
return TSDB_CODE_OUT_OF_MEMORY; return TSDB_CODE_OUT_OF_MEMORY;
} }
*pCols = NULL;
nodesWalkSelectStmt(pSelect, clause, collectColumns, &cxt); nodesWalkSelectStmt(pSelect, clause, collectColumns, &cxt);
taosHashCleanup(cxt.pColHash); taosHashCleanup(cxt.pColHash);
if (TSDB_CODE_SUCCESS != cxt.errCode) { if (TSDB_CODE_SUCCESS != cxt.errCode) {
nodesDestroyList(cxt.pCols); nodesDestroyList(cxt.pCols);
return cxt.errCode; return cxt.errCode;
} }
if (0 == LIST_LENGTH(cxt.pCols)) { if (LIST_LENGTH(cxt.pCols) > 0) {
*pCols = cxt.pCols;
} else {
nodesDestroyList(cxt.pCols); nodesDestroyList(cxt.pCols);
cxt.pCols = NULL;
} }
*pCols = cxt.pCols;
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -1134,7 +1135,7 @@ static EDealRes collectFuncs(SNode* pNode, void* pContext) { ...@@ -1134,7 +1135,7 @@ static EDealRes collectFuncs(SNode* pNode, void* pContext) {
int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs) { int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs) {
if (NULL == pSelect || NULL == pFuncs) { if (NULL == pSelect || NULL == pFuncs) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_FAILED;
} }
SCollectFuncsCxt cxt = { SCollectFuncsCxt cxt = {
...@@ -1157,6 +1158,46 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNod ...@@ -1157,6 +1158,46 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNod
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
typedef struct SCollectSpecialNodesCxt {
int32_t errCode;
ENodeType type;
SNodeList* pNodes;
} SCollectSpecialNodesCxt;
static EDealRes collectSpecialNodes(SNode* pNode, void* pContext) {
SCollectSpecialNodesCxt* pCxt = (SCollectSpecialNodesCxt*)pContext;
if (pCxt->type == nodeType(pNode)) {
pCxt->errCode = nodesListStrictAppend(pCxt->pNodes, nodesCloneNode(pNode));
return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
}
return DEAL_RES_CONTINUE;
}
int32_t nodesCollectSpecialNodes(SSelectStmt* pSelect, ESqlClause clause, ENodeType type, SNodeList** pNodes) {
if (NULL == pSelect || NULL == pNodes) {
return TSDB_CODE_FAILED;
}
SCollectSpecialNodesCxt cxt = {
.errCode = TSDB_CODE_SUCCESS, .type = type, .pNodes = (NULL == *pNodes ? nodesMakeList() : *pNodes)};
if (NULL == cxt.pNodes) {
return TSDB_CODE_OUT_OF_MEMORY;
}
*pNodes = NULL;
nodesWalkSelectStmt(pSelect, SQL_CLAUSE_GROUP_BY, collectSpecialNodes, &cxt);
if (TSDB_CODE_SUCCESS != cxt.errCode) {
nodesDestroyList(cxt.pNodes);
return cxt.errCode;
}
if (LIST_LENGTH(cxt.pNodes) > 0) {
*pNodes = cxt.pNodes;
} else {
nodesDestroyList(cxt.pNodes);
}
return TSDB_CODE_SUCCESS;
}
char* getFillModeString(EFillMode mode) { char* getFillModeString(EFillMode mode) {
switch (mode) { switch (mode) {
case FILL_MODE_NONE: case FILL_MODE_NONE:
......
...@@ -30,9 +30,9 @@ typedef struct SAstCreateContext { ...@@ -30,9 +30,9 @@ typedef struct SAstCreateContext {
SParseContext* pQueryCxt; SParseContext* pQueryCxt;
SMsgBuf msgBuf; SMsgBuf msgBuf;
bool notSupport; bool notSupport;
bool valid;
SNode* pRootNode; SNode* pRootNode;
int16_t placeholderNo; int16_t placeholderNo;
int32_t errCode;
} SAstCreateContext; } SAstCreateContext;
typedef enum EDatabaseOptionType { typedef enum EDatabaseOptionType {
......
...@@ -23,13 +23,12 @@ ...@@ -23,13 +23,12 @@
} }
%syntax_error { %syntax_error {
if (pCxt->valid) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
if(TOKEN.z) { if(TOKEN.z) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z);
} else { } else {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL);
} }
pCxt->valid = false;
} }
} }
...@@ -42,8 +41,8 @@ ...@@ -42,8 +41,8 @@
%left NK_CONCAT. %left NK_CONCAT.
/************************************************ create/alter account *****************************************/ /************************************************ create/alter account *****************************************/
cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options. { pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options. { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
cmd ::= ALTER ACCOUNT NK_ID alter_account_options. { pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } cmd ::= ALTER ACCOUNT NK_ID alter_account_options. { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
%type account_options { int32_t } %type account_options { int32_t }
%destructor account_options { } %destructor account_options { }
...@@ -323,7 +322,7 @@ cmd ::= SHOW QNODES. ...@@ -323,7 +322,7 @@ cmd ::= SHOW QNODES.
cmd ::= SHOW FUNCTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_FUNCTIONS_STMT, NULL, NULL); } cmd ::= SHOW FUNCTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_FUNCTIONS_STMT, NULL, NULL); }
cmd ::= SHOW INDEXES FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, A, B); } cmd ::= SHOW INDEXES FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, A, B); }
cmd ::= SHOW STREAMS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT, NULL, NULL); } cmd ::= SHOW STREAMS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT, NULL, NULL); }
cmd ::= SHOW ACCOUNTS. { pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } cmd ::= SHOW ACCOUNTS. { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
cmd ::= SHOW APPS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT, NULL, NULL); } cmd ::= SHOW APPS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT, NULL, NULL); }
cmd ::= SHOW CONNECTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONNECTIONS_STMT, NULL, NULL); } cmd ::= SHOW CONNECTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONNECTIONS_STMT, NULL, NULL); }
cmd ::= SHOW LICENCE. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LICENCE_STMT, NULL, NULL); } cmd ::= SHOW LICENCE. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LICENCE_STMT, NULL, NULL); }
...@@ -491,7 +490,7 @@ signed_literal(A) ::= NK_STRING(B). ...@@ -491,7 +490,7 @@ signed_literal(A) ::= NK_STRING(B).
signed_literal(A) ::= NK_BOOL(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &B); } signed_literal(A) ::= NK_BOOL(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &B); }
signed_literal(A) ::= TIMESTAMP NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); } signed_literal(A) ::= TIMESTAMP NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); }
signed_literal(A) ::= duration_literal(B). { A = releaseRawExprNode(pCxt, B); } signed_literal(A) ::= duration_literal(B). { A = releaseRawExprNode(pCxt, B); }
signed_literal(A) ::= NULL. { A = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, NULL); } signed_literal(A) ::= NULL(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &B); }
signed_literal(A) ::= literal_func(B). { A = releaseRawExprNode(pCxt, B); } signed_literal(A) ::= literal_func(B). { A = releaseRawExprNode(pCxt, B); }
%type literal_list { SNodeList* } %type literal_list { SNodeList* }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define CHECK_OUT_OF_MEM(p) \ #define CHECK_OUT_OF_MEM(p) \
do { \ do { \
if (NULL == (p)) { \ if (NULL == (p)) { \
pCxt->valid = false; \ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "Out of memory"); \ snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "Out of memory"); \
return NULL; \ return NULL; \
} \ } \
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define CHECK_RAW_EXPR_NODE(node) \ #define CHECK_RAW_EXPR_NODE(node) \
do { \ do { \
if (NULL == (node) || QUERY_NODE_RAW_EXPR != nodeType(node)) { \ if (NULL == (node) || QUERY_NODE_RAW_EXPR != nodeType(node)) { \
pCxt->valid = false; \ pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR; \
return NULL; \ return NULL; \
} \ } \
} while (0) } while (0)
...@@ -42,9 +42,9 @@ void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt) { ...@@ -42,9 +42,9 @@ void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt) {
pCxt->msgBuf.buf = pParseCxt->pMsg; pCxt->msgBuf.buf = pParseCxt->pMsg;
pCxt->msgBuf.len = pParseCxt->msgLen; pCxt->msgBuf.len = pParseCxt->msgLen;
pCxt->notSupport = false; pCxt->notSupport = false;
pCxt->valid = true;
pCxt->pRootNode = NULL; pCxt->pRootNode = NULL;
pCxt->placeholderNo = 0; pCxt->placeholderNo = 0;
pCxt->errCode = TSDB_CODE_SUCCESS;
} }
static void copyStringFormStringToken(SToken* pToken, char* pBuf, int32_t len) { static void copyStringFormStringToken(SToken* pToken, char* pBuf, int32_t len) {
...@@ -63,42 +63,38 @@ static void trimEscape(SToken* pName) { ...@@ -63,42 +63,38 @@ static void trimEscape(SToken* pName) {
static bool checkUserName(SAstCreateContext* pCxt, SToken* pUserName) { static bool checkUserName(SAstCreateContext* pCxt, SToken* pUserName) {
if (NULL == pUserName) { if (NULL == pUserName) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
} else { } else {
if (pUserName->n >= TSDB_USER_LEN) { if (pUserName->n >= TSDB_USER_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
pCxt->valid = false;
} }
} }
if (pCxt->valid) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
trimEscape(pUserName); trimEscape(pUserName);
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkPassword(SAstCreateContext* pCxt, const SToken* pPasswordToken, char* pPassword) { static bool checkPassword(SAstCreateContext* pCxt, const SToken* pPasswordToken, char* pPassword) {
if (NULL == pPasswordToken) { if (NULL == pPasswordToken) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
} else if (pPasswordToken->n >= (TSDB_USET_PASSWORD_LEN - 2)) { } else if (pPasswordToken->n >= (TSDB_USET_PASSWORD_LEN - 2)) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
pCxt->valid = false;
} else { } else {
strncpy(pPassword, pPasswordToken->z, pPasswordToken->n); strncpy(pPassword, pPasswordToken->z, pPasswordToken->n);
strdequote(pPassword); strdequote(pPassword);
if (strtrim(pPassword) <= 0) { if (strtrim(pPassword) <= 0) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_PASSWD_EMPTY); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_PASSWD_EMPTY);
pCxt->valid = false;
} }
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, char* pFqdn, int32_t* pPort) { static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, char* pFqdn, int32_t* pPort) {
if (NULL == pEp) { if (NULL == pEp) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
} else if (pEp->n >= TSDB_FQDN_LEN + 2 + 6) { // format 'fqdn:port' } else if (pEp->n >= TSDB_FQDN_LEN + 2 + 6) { // format 'fqdn:port'
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
pCxt->valid = false;
} else { } else {
char ep[TSDB_FQDN_LEN + 2 + 6]; char ep[TSDB_FQDN_LEN + 2 + 6];
strncpy(ep, pEp->z, pEp->n); strncpy(ep, pEp->z, pEp->n);
...@@ -106,66 +102,59 @@ static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, ch ...@@ -106,66 +102,59 @@ static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, ch
strtrim(ep); strtrim(ep);
char* pColon = strchr(ep, ':'); char* pColon = strchr(ep, ':');
if (NULL == pColon) { if (NULL == pColon) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ENDPOINT); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ENDPOINT);
pCxt->valid = false;
} else { } else {
strncpy(pFqdn, ep, pColon - ep); strncpy(pFqdn, ep, pColon - ep);
*pPort = strtol(pColon + 1, NULL, 10); *pPort = strtol(pColon + 1, NULL, 10);
if (*pPort >= UINT16_MAX || *pPort <= 0) { if (*pPort >= UINT16_MAX || *pPort <= 0) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT);
pCxt->valid = false;
} }
} }
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkFqdn(SAstCreateContext* pCxt, const SToken* pFqdn) { static bool checkFqdn(SAstCreateContext* pCxt, const SToken* pFqdn) {
if (NULL == pFqdn) { if (NULL == pFqdn) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
} else { } else {
if (pFqdn->n >= TSDB_FQDN_LEN) { if (pFqdn->n >= TSDB_FQDN_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
pCxt->valid = false;
} }
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkPort(SAstCreateContext* pCxt, const SToken* pPortToken, int32_t* pPort) { static bool checkPort(SAstCreateContext* pCxt, const SToken* pPortToken, int32_t* pPort) {
if (NULL == pPortToken) { if (NULL == pPortToken) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
} else { } else {
*pPort = strtol(pPortToken->z, NULL, 10); *pPort = strtol(pPortToken->z, NULL, 10);
if (*pPort >= UINT16_MAX || *pPort <= 0) { if (*pPort >= UINT16_MAX || *pPort <= 0) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT);
pCxt->valid = false;
} }
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkDbName(SAstCreateContext* pCxt, SToken* pDbName, bool query) { static bool checkDbName(SAstCreateContext* pCxt, SToken* pDbName, bool query) {
if (NULL == pDbName) { if (NULL == pDbName) {
if (query && NULL == pCxt->pQueryCxt->db) { if (query && NULL == pCxt->pQueryCxt->db) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED);
pCxt->valid = false;
} }
} else { } else {
trimEscape(pDbName); trimEscape(pDbName);
if (pDbName->n >= TSDB_DB_NAME_LEN) { if (pDbName->n >= TSDB_DB_NAME_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pDbName->z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pDbName->z);
pCxt->valid = false;
} }
} }
return pCxt->valid; return TSDB_CODE_SUCCESS == pCxt->errCode;
} }
static bool checkTableName(SAstCreateContext* pCxt, SToken* pTableName) { static bool checkTableName(SAstCreateContext* pCxt, SToken* pTableName) {
trimEscape(pTableName); trimEscape(pTableName);
if (NULL != pTableName && pTableName->n >= TSDB_TABLE_NAME_LEN) { if (NULL != pTableName && pTableName->n >= TSDB_TABLE_NAME_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pTableName->z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pTableName->z);
pCxt->valid = false;
return false; return false;
} }
return true; return true;
...@@ -174,8 +163,7 @@ static bool checkTableName(SAstCreateContext* pCxt, SToken* pTableName) { ...@@ -174,8 +163,7 @@ static bool checkTableName(SAstCreateContext* pCxt, SToken* pTableName) {
static bool checkColumnName(SAstCreateContext* pCxt, SToken* pColumnName) { static bool checkColumnName(SAstCreateContext* pCxt, SToken* pColumnName) {
trimEscape(pColumnName); trimEscape(pColumnName);
if (NULL != pColumnName && pColumnName->n >= TSDB_COL_NAME_LEN) { if (NULL != pColumnName && pColumnName->n >= TSDB_COL_NAME_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pColumnName->z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pColumnName->z);
pCxt->valid = false;
return false; return false;
} }
return true; return true;
...@@ -184,8 +172,7 @@ static bool checkColumnName(SAstCreateContext* pCxt, SToken* pColumnName) { ...@@ -184,8 +172,7 @@ static bool checkColumnName(SAstCreateContext* pCxt, SToken* pColumnName) {
static bool checkIndexName(SAstCreateContext* pCxt, SToken* pIndexName) { static bool checkIndexName(SAstCreateContext* pCxt, SToken* pIndexName) {
trimEscape(pIndexName); trimEscape(pIndexName);
if (NULL != pIndexName && pIndexName->n >= TSDB_INDEX_NAME_LEN) { if (NULL != pIndexName && pIndexName->n >= TSDB_INDEX_NAME_LEN) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pIndexName->z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pIndexName->z);
pCxt->valid = false;
return false; return false;
} }
return true; return true;
...@@ -224,7 +211,7 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { ...@@ -224,7 +211,7 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) { if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
return nil_token; return nil_token;
} }
SRawExprNode* target = (SRawExprNode*)pNode; SRawExprNode* target = (SRawExprNode*)pNode;
...@@ -235,16 +222,12 @@ SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { ...@@ -235,16 +222,12 @@ SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) { SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) {
SNodeList* list = nodesMakeList(); SNodeList* list = nodesMakeList();
CHECK_OUT_OF_MEM(list); CHECK_OUT_OF_MEM(list);
if (TSDB_CODE_SUCCESS != nodesListAppend(list, pNode)) { pCxt->errCode = nodesListAppend(list, pNode);
pCxt->valid = false;
}
return list; return list;
} }
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) { SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) {
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pNode)) { pCxt->errCode = nodesListAppend(pList, pNode);
pCxt->valid = false;
}
return pList; return pList;
} }
...@@ -381,10 +364,10 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType d ...@@ -381,10 +364,10 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType d
strcpy(func->functionName, "cast"); strcpy(func->functionName, "cast");
func->node.resType = dt; func->node.resType = dt;
if (TSDB_DATA_TYPE_BINARY == dt.type) { if (TSDB_DATA_TYPE_BINARY == dt.type) {
func->node.resType.bytes += 2; func->node.resType.bytes += 2;
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) { } else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + 2; func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + 2;
} }
nodesListMakeAppend(&func->pParameterList, pExpr); nodesListMakeAppend(&func->pParameterList, pExpr);
return (SNode*)func; return (SNode*)func;
} }
...@@ -531,7 +514,7 @@ SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) { ...@@ -531,7 +514,7 @@ SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) {
} }
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) { SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
if (NULL == pNode || !pCxt->valid) { if (NULL == pNode || TSDB_CODE_SUCCESS != pCxt->errCode) {
return pNode; return pNode;
} }
int32_t len = TMIN(sizeof(((SExprNode*)pNode)->aliasName) - 1, pAlias->n); int32_t len = TMIN(sizeof(((SExprNode*)pNode)->aliasName) - 1, pAlias->n);
...@@ -995,7 +978,7 @@ static bool needDbShowStmt(ENodeType type) { ...@@ -995,7 +978,7 @@ static bool needDbShowStmt(ENodeType type) {
SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pDbName, SNode* pTbNamePattern) { SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pDbName, SNode* pTbNamePattern) {
if (needDbShowStmt(type) && NULL == pDbName && NULL == pCxt->pQueryCxt->db) { if (needDbShowStmt(type) && NULL == pDbName && NULL == pCxt->pQueryCxt->db) {
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "db not specified"); snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "db not specified");
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
return NULL; return NULL;
} }
SShowStmt* pStmt = nodesMakeNode(type); SShowStmt* pStmt = nodesMakeNode(type);
...@@ -1256,7 +1239,7 @@ SNode* createCompactStmt(SAstCreateContext* pCxt, SNodeList* pVgroups) { ...@@ -1256,7 +1239,7 @@ SNode* createCompactStmt(SAstCreateContext* pCxt, SNodeList* pVgroups) {
SNode* createCreateFunctionStmt(SAstCreateContext* pCxt, bool ignoreExists, bool aggFunc, const SToken* pFuncName, SNode* createCreateFunctionStmt(SAstCreateContext* pCxt, bool ignoreExists, bool aggFunc, const SToken* pFuncName,
const SToken* pLibPath, SDataType dataType, int32_t bufSize) { const SToken* pLibPath, SDataType dataType, int32_t bufSize) {
if (pLibPath->n <= 2) { if (pLibPath->n <= 2) {
pCxt->valid = false; pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
return NULL; return NULL;
} }
SCreateFunctionStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_FUNCTION_STMT); SCreateFunctionStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_FUNCTION_STMT);
......
...@@ -53,20 +53,20 @@ int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) { ...@@ -53,20 +53,20 @@ int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) {
} }
case TK_NK_ILLEGAL: { case TK_NK_ILLEGAL: {
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z); snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
cxt.valid = false; cxt.errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
goto abort_parse; goto abort_parse;
} }
case TK_NK_HEX: case TK_NK_HEX:
case TK_NK_OCT: case TK_NK_OCT:
case TK_NK_BIN: { case TK_NK_BIN: {
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z); snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z);
cxt.valid = false; cxt.errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
goto abort_parse; goto abort_parse;
} }
default: default:
Parse(pParser, t0.type, t0, &cxt); Parse(pParser, t0.type, t0, &cxt);
// ParseTrace(stdout, ""); // ParseTrace(stdout, "");
if (!cxt.valid) { if (TSDB_CODE_SUCCESS != cxt.errCode) {
goto abort_parse; goto abort_parse;
} }
} }
...@@ -74,7 +74,7 @@ int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) { ...@@ -74,7 +74,7 @@ int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) {
abort_parse: abort_parse:
ParseFree(pParser, (FFree)taosMemoryFree); ParseFree(pParser, (FFree)taosMemoryFree);
if (cxt.valid) { if (TSDB_CODE_SUCCESS == cxt.errCode) {
*pQuery = taosMemoryCalloc(1, sizeof(SQuery)); *pQuery = taosMemoryCalloc(1, sizeof(SQuery));
if (NULL == *pQuery) { if (NULL == *pQuery) {
return TSDB_CODE_OUT_OF_MEMORY; return TSDB_CODE_OUT_OF_MEMORY;
...@@ -82,5 +82,5 @@ abort_parse: ...@@ -82,5 +82,5 @@ abort_parse:
(*pQuery)->pRoot = cxt.pRootNode; (*pQuery)->pRoot = cxt.pRootNode;
(*pQuery)->placeholderNum = cxt.placeholderNo; (*pQuery)->placeholderNum = cxt.placeholderNo;
} }
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; return cxt.errCode;
} }
...@@ -208,6 +208,23 @@ static int32_t calcConstProjections(SCalcConstContext* pCxt, SNodeList* pProject ...@@ -208,6 +208,23 @@ static int32_t calcConstProjections(SCalcConstContext* pCxt, SNodeList* pProject
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
int32_t code = calcConstList(pSelect->pGroupByList);
if (TSDB_CODE_SUCCESS == code) {
SNode* pNode = NULL;
FOREACH(pNode, pSelect->pGroupByList) {
SNode* pGroupPara = NULL;
FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
return code;
}
}
}
DESTORY_LIST(pSelect->pGroupByList);
}
return code;
}
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) { static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
int32_t code = calcConstProjections(pCxt, pSelect->pProjectionList, subquery); int32_t code = calcConstProjections(pCxt, pSelect->pProjectionList, subquery);
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
......
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
#include "functionMgt.h" #include "functionMgt.h"
#include "parUtil.h" #include "parUtil.h"
#include "scalar.h" #include "scalar.h"
#include "systable.h"
#include "tglobal.h" #include "tglobal.h"
#include "ttime.h" #include "ttime.h"
#include "systable.h"
#define generateDealNodeErrMsg(pCxt, code, ...) \ #define generateDealNodeErrMsg(pCxt, code, ...) \
(pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, code, ##__VA_ARGS__) ? DEAL_RES_ERROR : DEAL_RES_ERROR) (pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, code, ##__VA_ARGS__), DEAL_RES_ERROR)
typedef struct STranslateContext { typedef struct STranslateContext {
SParseContext* pParseCxt; SParseContext* pParseCxt;
...@@ -1676,11 +1676,12 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete ...@@ -1676,11 +1676,12 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbName, SDatabaseOptions* pOptions, static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbName, SDatabaseOptions* pOptions) {
bool alter) {
int32_t daysPerFile = pOptions->daysPerFile; int32_t daysPerFile = pOptions->daysPerFile;
int32_t daysToKeep0 = pOptions->keep[0]; int32_t daysToKeep0 = pOptions->keep[0];
if (alter && (-1 == daysPerFile || -1 == daysToKeep0)) { if (-1 == daysPerFile && -1 == daysToKeep0) {
return TSDB_CODE_SUCCESS;
} else if (-1 == daysPerFile || -1 == daysToKeep0) {
SDbCfgInfo dbCfg; SDbCfgInfo dbCfg;
int32_t code = getDBCfg(pCxt, pDbName, &dbCfg); int32_t code = getDBCfg(pCxt, pDbName, &dbCfg);
if (TSDB_CODE_SUCCESS != code) { if (TSDB_CODE_SUCCESS != code) {
...@@ -1695,8 +1696,7 @@ static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbNa ...@@ -1695,8 +1696,7 @@ static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbNa
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName, SDatabaseOptions* pOptions, static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName, SDatabaseOptions* pOptions) {
bool alter) {
int32_t code = int32_t code =
checkRangeOption(pCxt, "buffer", pOptions->buffer, TSDB_MIN_BUFFER_PER_VNODE, TSDB_MAX_BUFFER_PER_VNODE); checkRangeOption(pCxt, "buffer", pOptions->buffer, TSDB_MIN_BUFFER_PER_VNODE, TSDB_MAX_BUFFER_PER_VNODE);
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
...@@ -1753,13 +1753,13 @@ static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName ...@@ -1753,13 +1753,13 @@ static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName
code = checkDbRetentionsOption(pCxt, pOptions->pRetentions); code = checkDbRetentionsOption(pCxt, pOptions->pRetentions);
} }
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = checkOptionsDependency(pCxt, pDbName, pOptions, alter); code = checkOptionsDependency(pCxt, pDbName, pOptions);
} }
return code; return code;
} }
static int32_t checkCreateDatabase(STranslateContext* pCxt, SCreateDatabaseStmt* pStmt) { static int32_t checkCreateDatabase(STranslateContext* pCxt, SCreateDatabaseStmt* pStmt) {
return checkDatabaseOptions(pCxt, pStmt->dbName, pStmt->pOptions, false); return checkDatabaseOptions(pCxt, pStmt->dbName, pStmt->pOptions);
} }
typedef int32_t (*FSerializeFunc)(void* pBuf, int32_t bufLen, void* pReq); typedef int32_t (*FSerializeFunc)(void* pBuf, int32_t bufLen, void* pReq);
...@@ -1826,7 +1826,7 @@ static void buildAlterDbReq(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt, ...@@ -1826,7 +1826,7 @@ static void buildAlterDbReq(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt,
} }
static int32_t translateAlterDatabase(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt) { static int32_t translateAlterDatabase(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt) {
int32_t code = checkDatabaseOptions(pCxt, pStmt->dbName, pStmt->pOptions, true); int32_t code = checkDatabaseOptions(pCxt, pStmt->dbName, pStmt->pOptions);
if (TSDB_CODE_SUCCESS != code) { if (TSDB_CODE_SUCCESS != code) {
return code; return code;
} }
......
...@@ -3021,11 +3021,11 @@ static YYACTIONTYPE yy_reduce( ...@@ -3021,11 +3021,11 @@ static YYACTIONTYPE yy_reduce(
/********** Begin reduce actions **********************************************/ /********** Begin reduce actions **********************************************/
YYMINORTYPE yylhsminor; YYMINORTYPE yylhsminor;
case 0: /* cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */ case 0: /* cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */
{ pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
yy_destructor(yypParser,232,&yymsp[0].minor); yy_destructor(yypParser,232,&yymsp[0].minor);
break; break;
case 1: /* cmd ::= ALTER ACCOUNT NK_ID alter_account_options */ case 1: /* cmd ::= ALTER ACCOUNT NK_ID alter_account_options */
{ pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
yy_destructor(yypParser,233,&yymsp[0].minor); yy_destructor(yypParser,233,&yymsp[0].minor);
break; break;
case 2: /* account_options ::= */ case 2: /* account_options ::= */
...@@ -3591,7 +3591,7 @@ static YYACTIONTYPE yy_reduce( ...@@ -3591,7 +3591,7 @@ static YYACTIONTYPE yy_reduce(
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT, NULL, NULL); } { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT, NULL, NULL); }
break; break;
case 178: /* cmd ::= SHOW ACCOUNTS */ case 178: /* cmd ::= SHOW ACCOUNTS */
{ pCxt->valid = false; generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); }
break; break;
case 179: /* cmd ::= SHOW APPS */ case 179: /* cmd ::= SHOW APPS */
{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT, NULL, NULL); } { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT, NULL, NULL); }
...@@ -3902,7 +3902,8 @@ static YYACTIONTYPE yy_reduce( ...@@ -3902,7 +3902,8 @@ static YYACTIONTYPE yy_reduce(
yymsp[0].minor.yy662 = yylhsminor.yy662; yymsp[0].minor.yy662 = yylhsminor.yy662;
break; break;
case 272: /* signed_literal ::= NULL */ case 272: /* signed_literal ::= NULL */
{ yymsp[0].minor.yy662 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, NULL); } { yylhsminor.yy662 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0); }
yymsp[0].minor.yy662 = yylhsminor.yy662;
break; break;
case 291: /* expression ::= NK_LP expression NK_RP */ case 291: /* expression ::= NK_LP expression NK_RP */
case 355: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==355); case 355: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==355);
...@@ -4352,13 +4353,12 @@ static void yy_syntax_error( ...@@ -4352,13 +4353,12 @@ static void yy_syntax_error(
#define TOKEN yyminor #define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/ /************ Begin %syntax_error code ****************************************/
if (pCxt->valid) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
if(TOKEN.z) { if(TOKEN.z) {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z);
} else { } else {
generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL); pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL);
} }
pCxt->valid = false;
} }
/************ End %syntax_error code ******************************************/ /************ End %syntax_error code ******************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
......
...@@ -24,4 +24,9 @@ if(${BUILD_WINGETOPT}) ...@@ -24,4 +24,9 @@ if(${BUILD_WINGETOPT})
PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src" PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
) )
target_link_libraries(parserTest PUBLIC wingetopt) target_link_libraries(parserTest PUBLIC wingetopt)
endif() endif()
\ No newline at end of file
add_test(
NAME parserTest
COMMAND parserTest
)
...@@ -155,16 +155,22 @@ int32_t __catalogGetDBVgInfo(SCatalog* pCtg, void* pRpc, const SEpSet* pMgmtEps, ...@@ -155,16 +155,22 @@ int32_t __catalogGetDBVgInfo(SCatalog* pCtg, void* pRpc, const SEpSet* pMgmtEps,
return 0; return 0;
} }
int32_t __catalogGetDBCfg(SCatalog* pCtg, void* pRpc, const SEpSet* pMgmtEps, const char* dbFName, SDbCfgInfo* pDbCfg) {
return 0;
}
void initMetaDataEnv() { void initMetaDataEnv() {
mockCatalogService.reset(new MockCatalogService()); mockCatalogService.reset(new MockCatalogService());
static Stub stub; static Stub stub;
stub.set(catalogGetHandle, __catalogGetHandle); stub.set(catalogGetHandle, __catalogGetHandle);
stub.set(catalogGetTableMeta, __catalogGetTableMeta); stub.set(catalogGetTableMeta, __catalogGetTableMeta);
stub.set(catalogGetSTableMeta, __catalogGetTableMeta);
stub.set(catalogGetTableHashVgroup, __catalogGetTableHashVgroup); stub.set(catalogGetTableHashVgroup, __catalogGetTableHashVgroup);
stub.set(catalogGetTableDistVgInfo, __catalogGetTableDistVgInfo); stub.set(catalogGetTableDistVgInfo, __catalogGetTableDistVgInfo);
stub.set(catalogGetDBVgVersion, __catalogGetDBVgVersion); stub.set(catalogGetDBVgVersion, __catalogGetDBVgVersion);
stub.set(catalogGetDBVgInfo, __catalogGetDBVgInfo); stub.set(catalogGetDBVgInfo, __catalogGetDBVgInfo);
stub.set(catalogGetDBCfg, __catalogGetDBCfg);
// { // {
// AddrAny any("libcatalog.so"); // AddrAny any("libcatalog.so");
// std::map<std::string,void*> result; // std::map<std::string,void*> result;
......
...@@ -111,9 +111,8 @@ class MockCatalogServiceImpl { ...@@ -111,9 +111,8 @@ class MockCatalogServiceImpl {
} }
int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const { int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const {
char db[TSDB_DB_NAME_LEN] = {0}; vgInfo->vgId = 1;
tNameGetDbName(pTableName, db); return TSDB_CODE_SUCCESS;
return copyTableVgroup(db, tNameGetTableName(pTableName), vgInfo);
} }
int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** vgList) const { int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** vgList) const {
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserExplainToSyncdbTest : public ParserTestBase {};
TEST_F(ParserExplainToSyncdbTest, explain) {
useDb("root", "test");
run("explain SELECT * FROM t1");
run("explain analyze SELECT * FROM t1");
run("explain analyze verbose true ratio 0.01 SELECT * FROM t1");
}
// todo kill connection
// todo kill query
// todo kill stream
// todo merge vgroup
// todo redistribute vgroup
// todo reset query cache
// todo syncdb
} // namespace ParserTest
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserInitialATest : public ParserTestBase {};
TEST_F(ParserInitialATest, alterAccount) {
useDb("root", "test");
run("alter account ac_wxy pass '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT);
}
TEST_F(ParserInitialATest, alterDnode) {
useDb("root", "test");
run("alter dnode 1 'resetLog'");
run("alter dnode 1 'debugFlag' '134'");
}
TEST_F(ParserInitialATest, alterDatabase) {
useDb("root", "test");
run("alter database wxy_db cachelast 1 fsync 200 wal 1");
}
// todo alter local
// todo alter stable
// todo alter table
TEST_F(ParserInitialATest, alterUser) {
useDb("root", "test");
run("alter user wxy pass '123456'");
run("alter user wxy privilege 'write'");
}
TEST_F(ParserInitialATest, bug001) {
useDb("root", "test");
run("alter database db wal 0 # td-14436", TSDB_CODE_PAR_SYNTAX_ERROR);
}
} // namespace ParserTest
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserInitialCTest : public ParserTestBase {};
// todo compact
TEST_F(ParserInitialCTest, createAccount) {
useDb("root", "test");
run("create account ac_wxy pass '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT);
}
TEST_F(ParserInitialCTest, createBnode) {
useDb("root", "test");
run("create bnode on dnode 1");
}
TEST_F(ParserInitialCTest, createDatabase) {
useDb("root", "test");
run("create database wxy_db");
run("create database if not exists wxy_db "
"cachelast 2 "
"comp 1 "
"days 100 "
"fsync 100 "
"maxrows 1000 "
"minrows 100 "
"keep 1440 "
"precision 'ms' "
"replica 3 "
"wal 2 "
"vgroups 100 "
"single_stable 0 "
"retentions 15s:7d,1m:21d,15m:5y");
run("create database if not exists wxy_db "
"days 100m "
"keep 1440m,300h,400d ");
}
TEST_F(ParserInitialCTest, createDnode) {
useDb("root", "test");
run("create dnode abc1 port 7000");
run("create dnode 1.1.1.1 port 9000");
}
// todo create function
TEST_F(ParserInitialCTest, createIndexSma) {
useDb("root", "test");
run("create sma index index1 on t1 function(max(c1), min(c3 + 10), sum(c4)) INTERVAL(10s)");
}
TEST_F(ParserInitialCTest, createMnode) {
useDb("root", "test");
run("create mnode on dnode 1");
}
TEST_F(ParserInitialCTest, createQnode) {
useDb("root", "test");
run("create qnode on dnode 1");
}
TEST_F(ParserInitialCTest, createSnode) {
useDb("root", "test");
run("create snode on dnode 1");
}
TEST_F(ParserInitialCTest, createStable) {
useDb("root", "test");
run("create stable t1(ts timestamp, c1 int) TAGS(id int)");
run("create stable if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 "
"SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), "
"c15 VARCHAR(50)) "
"TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, a5 FLOAT, a6 DOUBLE, a7 "
"BINARY(20), a8 SMALLINT, "
"a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), "
"a15 VARCHAR(50)) "
"TTL 100 COMMENT 'test create table' SMA(c1, c2, c3) ROLLUP (min) FILE_FACTOR 0.1 DELAY 2");
}
TEST_F(ParserInitialCTest, createStream) {
useDb("root", "test");
run("create stream s1 as select * from t1");
run("create stream if not exists s1 as select * from t1");
run("create stream s1 into st1 as select * from t1");
run("create stream if not exists s1 trigger window_close watermark 10s into st1 as select * from t1");
}
TEST_F(ParserInitialCTest, createTable) {
useDb("root", "test");
run("create table t1(ts timestamp, c1 int)");
run("create table if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 "
"SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 "
"NCHAR(30), "
"c15 VARCHAR(50)) "
"TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)");
run("create table if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 "
"SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 "
"NCHAR(30), "
"c15 VARCHAR(50)) "
"TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, "
"a5 FLOAT, a6 DOUBLE, a7 "
"BINARY(20), a8 SMALLINT, "
"a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 "
"TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), "
"a15 VARCHAR(50)) "
"TTL 100 COMMENT 'test create "
"table' SMA(c1, c2, c3) ROLLUP (min) FILE_FACTOR 0.1 DELAY 2");
run("create table if not exists t1 using st1 tags(1, 'wxy')");
run("create table "
"if not exists test.t1 using test.st1 (tag1, tag2) tags(1, 'abc') "
"if not exists test.t2 using test.st1 (tag1, tag2) tags(2, 'abc') "
"if not exists test.t3 using test.st1 (tag1, tag2) tags(3, 'abc') ");
}
TEST_F(ParserInitialCTest, createTopic) {
useDb("root", "test");
run("create topic tp1 as select * from t1");
run("create topic if not exists tp1 as select * from t1");
run("create topic tp1 as test");
run("create topic if not exists tp1 as test");
}
TEST_F(ParserInitialCTest, createUser) {
useDb("root", "test");
run("create user wxy pass '123456'");
}
} // namespace ParserTest
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserInitialDTest : public ParserTestBase {};
// todo delete
// todo desc
// todo describe
// todo drop account
TEST_F(ParserInitialDTest, dropBnode) {
useDb("root", "test");
run("drop bnode on dnode 1");
}
// todo drop database
// todo drop dnode
// todo drop function
TEST_F(ParserInitialDTest, dropIndex) {
useDb("root", "test");
run("drop index index1 on t1");
}
TEST_F(ParserInitialDTest, dropMnode) {
useDb("root", "test");
run("drop mnode on dnode 1");
}
TEST_F(ParserInitialDTest, dropQnode) {
useDb("root", "test");
run("drop qnode on dnode 1");
}
TEST_F(ParserInitialDTest, dropSnode) {
useDb("root", "test");
run("drop snode on dnode 1");
}
// todo drop stable
// todo drop stream
// todo drop table
TEST_F(ParserInitialDTest, dropTopic) {
useDb("root", "test");
run("drop topic tp1");
run("drop topic if exists tp1");
}
TEST_F(ParserInitialDTest, dropUser) {
useDb("root", "test");
run("drop user wxy");
}
} // namespace ParserTest
...@@ -111,6 +111,7 @@ class InsertTest : public Test { ...@@ -111,6 +111,7 @@ class InsertTest : public Test {
cxt_.pMsg = errMagBuf_; cxt_.pMsg = errMagBuf_;
cxt_.msgLen = max_err_len; cxt_.msgLen = max_err_len;
code_ = TSDB_CODE_SUCCESS; code_ = TSDB_CODE_SUCCESS;
res_ = nullptr;
} }
SVnodeModifOpStmt* getVnodeModifStmt(SQuery* pQuery) { return (SVnodeModifOpStmt*)pQuery->pRoot; } SVnodeModifOpStmt* getVnodeModifStmt(SQuery* pQuery) { return (SVnodeModifOpStmt*)pQuery->pRoot; }
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserSelectTest : public ParserTestBase {};
TEST_F(ParserSelectTest, basic) {
useDb("root", "test");
run("select * from t1");
run("select * from test.t1");
run("select ts, c1 from t1");
run("select ts, t.c1 from (select * from t1) t");
run("select * from t1 tt1, t1 tt2 where tt1.c1 = tt2.c1");
}
TEST_F(ParserSelectTest, constant) {
useDb("root", "test");
run("select 123, 20.4, 'abc', \"wxy\", timestamp '2022-02-09 17:30:20', true, false, 10s from t1");
run("select 1234567890123456789012345678901234567890, 20.1234567890123456789012345678901234567890, 'abc', \"wxy\", "
"timestamp '2022-02-09 17:30:20', true, false, 15s from t1");
run("select 123 + 45 from t1 where 2 - 1");
}
TEST_F(ParserSelectTest, expression) {
useDb("root", "test");
run("select ts + 10s, c1 + 10, concat(c2, 'abc') from t1");
run("select ts > 0, c1 < 20 and c2 = 'qaz' from t1");
run("select ts > 0, c1 between 10 and 20 and c2 = 'qaz' from t1");
}
TEST_F(ParserSelectTest, condition) {
useDb("root", "test");
run("select c1 from t1 where ts in (true, false)");
run("select * from t1 where c1 > 10 and c1 is not null");
}
TEST_F(ParserSelectTest, pseudoColumn) {
useDb("root", "test");
run("select _wstartts, _wendts, count(*) from t1 interval(10s)");
}
TEST_F(ParserSelectTest, multiResFunc) {
useDb("root", "test");
run("select last(*), first(*), last_row(*) from t1");
run("select last(c1, c2), first(t1.*), last_row(c3) from t1");
run("select last(t2.*), first(t1.c1, t2.*), last_row(t1.*, t2.*) from st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
}
TEST_F(ParserSelectTest, clause) {
useDb("root", "test");
// group by clause
run("select count(*) cnt from t1 where c1 > 0");
run("select count(*), c2 cnt from t1 where c1 > 0 group by c2");
run("select count(*) cnt from t1 where c1 > 0 group by c2 having count(c1) > 10");
run("select count(*), c1, c2 + 10, c1 + c2 cnt from t1 where c1 > 0 group by c2, c1");
run("select count(*), c1 + 10, c2 cnt from t1 where c1 > 0 group by c1 + 10, c2");
// order by clause
run("select count(*) cnt from t1 where c1 > 0 group by c2 order by cnt");
run("select count(*) cnt from t1 where c1 > 0 group by c2 order by 1");
// distinct clause
// run("select distinct c1, c2 from t1 where c1 > 0 order by c1");
// run("select distinct c1 + 10, c2 from t1 where c1 > 0 order by c1 + 10, c2");
// run("select distinct c1 + 10 cc1, c2 cc2 from t1 where c1 > 0 order by cc1, c2");
// run("select distinct count(c2) from t1 where c1 > 0 group by c1 order by count(c2)");
}
TEST_F(ParserSelectTest, window) {
useDb("root", "test");
run("select count(*) from t1 interval(10s)");
}
TEST_F(ParserSelectTest, semanticError) {
useDb("root", "test");
// TSDB_CODE_PAR_INVALID_COLUMN
run("select c1, cc1 from t1", TSDB_CODE_PAR_INVALID_COLUMN, PARSER_STAGE_TRANSLATE);
run("select t1.c1, t1.cc1 from t1", TSDB_CODE_PAR_INVALID_COLUMN, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_TABLE_NOT_EXIST
run("select * from t10", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
run("select * from test.t10", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
run("select t2.c1 from t1", TSDB_CODE_PAR_TABLE_NOT_EXIST, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_AMBIGUOUS_COLUMN
run("select c2 from t1 tt1, t1 tt2 where tt1.c1 = tt2.c1", TSDB_CODE_PAR_AMBIGUOUS_COLUMN, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
run("select timestamp '2010' from t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
run("select c2 from t1 tt1 join t1 tt2 on count(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION,
PARSER_STAGE_TRANSLATE);
run("select c2 from t1 where count(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, PARSER_STAGE_TRANSLATE);
run("select c2 from t1 group by count(*)", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT
run("select c2 from t1 order by 0", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, PARSER_STAGE_TRANSLATE);
run("select c2 from t1 order by 2", TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
run("select count(*) cnt from t1 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION, PARSER_STAGE_TRANSLATE);
run("select count(*) cnt from t1 group by c2 having c1 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
PARSER_STAGE_TRANSLATE);
run("select count(*), c1 cnt from t1 group by c2 having c2 > 0", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
PARSER_STAGE_TRANSLATE);
run("select count(*) cnt from t1 group by c2 having c2 > 0 order by c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION,
PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_NOT_SINGLE_GROUP
run("select count(*), c1 from t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
run("select count(*) from t1 order by c1", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
run("select c1 from t1 order by count(*)", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION
run("select distinct c1, c2 from t1 where c1 > 0 order by ts", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
PARSER_STAGE_TRANSLATE);
run("select distinct c1 from t1 where c1 > 0 order by count(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
PARSER_STAGE_TRANSLATE);
run("select distinct c2 from t1 where c1 > 0 order by count(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
PARSER_STAGE_TRANSLATE);
}
} // namespace ParserTest
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parTestUtil.h"
using namespace std;
namespace ParserTest {
class ParserShowToUseTest : public ParserTestBase {};
// todo show accounts
// todo show apps
// todo show connections
// todo show create database
// todo show create stable
// todo show create table
TEST_F(ParserShowToUseTest, showDatabases) {
useDb("root", "test");
run("show databases");
}
TEST_F(ParserShowToUseTest, showDnodes) {
useDb("root", "test");
run("show dnodes");
}
TEST_F(ParserShowToUseTest, showFunctions) {
useDb("root", "test");
run("show functions");
}
// todo show licence
TEST_F(ParserShowToUseTest, showIndexes) {
useDb("root", "test");
run("show indexes from t1");
run("show indexes from t1 from test");
}
TEST_F(ParserShowToUseTest, showMnodes) {
useDb("root", "test");
run("show mnodes");
}
TEST_F(ParserShowToUseTest, showModules) {
useDb("root", "test");
run("show modules");
}
TEST_F(ParserShowToUseTest, showQnodes) {
useDb("root", "test");
run("show qnodes");
}
// todo show queries
// todo show scores
TEST_F(ParserShowToUseTest, showStables) {
useDb("root", "test");
run("show stables");
run("show test.stables");
run("show stables like 'c%'");
run("show test.stables like 'c%'");
}
TEST_F(ParserShowToUseTest, showStreams) {
useDb("root", "test");
run("show streams");
}
TEST_F(ParserShowToUseTest, showTables) {
useDb("root", "test");
run("show tables");
run("show test.tables");
run("show tables like 'c%'");
run("show test.tables like 'c%'");
}
// todo show topics
TEST_F(ParserShowToUseTest, showUsers) {
useDb("root", "test");
run("show users");
}
// todo show variables
TEST_F(ParserShowToUseTest, showVgroups) {
useDb("root", "test");
run("show vgroups");
run("show test.vgroups");
}
// todo show vnodes
// todo split vgroup
TEST_F(ParserShowToUseTest, useDatabase) {
useDb("root", "test");
run("use wxy_db");
}
} // namespace ParserTest
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "parTestUtil.h" #include "parTestUtil.h"
#include "parToken.h" #include "parToken.h"
namespace ParserTest {
class ParserEnv : public testing::Environment { class ParserEnv : public testing::Environment {
public: public:
virtual void SetUp() { virtual void SetUp() {
...@@ -62,9 +64,11 @@ static void parseArg(int argc, char* argv[]) { ...@@ -62,9 +64,11 @@ static void parseArg(int argc, char* argv[]) {
} }
} }
} // namespace ParserTest
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
testing::AddGlobalTestEnvironment(new ParserEnv()); testing::AddGlobalTestEnvironment(new ParserTest::ParserEnv());
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
parseArg(argc, argv); ParserTest::parseArg(argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
...@@ -23,17 +23,30 @@ ...@@ -23,17 +23,30 @@
using namespace std; using namespace std;
using namespace testing; using namespace testing;
#define DO_WITH_THROW(func, ...) \ namespace ParserTest {
do { \
int32_t code__ = func(__VA_ARGS__); \ #define DO_WITH_THROW(func, ...) \
if (TSDB_CODE_SUCCESS != code__) { \ do { \
throw runtime_error("sql:[" + stmtEnv_.sql_ + "] " #func " code:" + to_string(code__) + \ int32_t code__ = func(__VA_ARGS__); \
", strerror:" + string(tstrerror(code__)) + ", msg:" + string(stmtEnv_.msgBuf_.data())); \ if (!checkResultCode(#func, code__)) { \
} \ if (TSDB_CODE_SUCCESS != code__) { \
throw runtime_error("sql:[" + stmtEnv_.sql_ + "] " #func " code:" + to_string(code__) + \
", strerror:" + string(tstrerror(code__)) + ", msg:" + string(stmtEnv_.msgBuf_.data())); \
} else { \
throw runtime_error("sql:[" + stmtEnv_.sql_ + "] " #func " expect " + to_string(stmtEnv_.expect_) + \
" actual " + to_string(code__)); \
} \
} else if (TSDB_CODE_SUCCESS != code__) { \
throw TerminateFlag(); \
} \
} while (0); } while (0);
bool g_isDump = false; bool g_isDump = false;
struct TerminateFlag : public exception {
const char* what() const throw() { return "success and terminate"; }
};
class ParserTestBaseImpl { class ParserTestBaseImpl {
public: public:
void useDb(const string& acctId, const string& db) { void useDb(const string& acctId, const string& db) {
...@@ -41,8 +54,8 @@ class ParserTestBaseImpl { ...@@ -41,8 +54,8 @@ class ParserTestBaseImpl {
caseEnv_.db_ = db; caseEnv_.db_ = db;
} }
void run(const string& sql) { void run(const string& sql, int32_t expect, ParserStage checkStage) {
reset(); reset(expect, checkStage);
try { try {
SParseContext cxt = {0}; SParseContext cxt = {0};
setParseContext(sql, &cxt); setParseContext(sql, &cxt);
...@@ -57,6 +70,9 @@ class ParserTestBaseImpl { ...@@ -57,6 +70,9 @@ class ParserTestBaseImpl {
if (g_isDump) { if (g_isDump) {
dump(); dump();
} }
} catch (const TerminateFlag& e) {
// success and terminate
return;
} catch (...) { } catch (...) {
dump(); dump();
throw; throw;
...@@ -72,6 +88,8 @@ class ParserTestBaseImpl { ...@@ -72,6 +88,8 @@ class ParserTestBaseImpl {
struct stmtEnv { struct stmtEnv {
string sql_; string sql_;
array<char, 1024> msgBuf_; array<char, 1024> msgBuf_;
int32_t expect_;
string checkFunc_;
}; };
struct stmtRes { struct stmtRes {
...@@ -80,9 +98,34 @@ class ParserTestBaseImpl { ...@@ -80,9 +98,34 @@ class ParserTestBaseImpl {
string calcConstAst_; string calcConstAst_;
}; };
void reset() { bool checkResultCode(const string& pFunc, int32_t resultCode) {
return !(stmtEnv_.checkFunc_.empty())
? (("*" == stmtEnv_.checkFunc_ || stmtEnv_.checkFunc_ == pFunc) ? stmtEnv_.expect_ == resultCode
: TSDB_CODE_SUCCESS == resultCode)
: true;
}
string stageFunc(ParserStage stage) {
switch (stage) {
case PARSER_STAGE_PARSE:
return "parse";
case PARSER_STAGE_TRANSLATE:
return "translate";
case PARSER_STAGE_CALC_CONST:
return "calculateConstant";
case PARSER_STAGE_ALL:
return "*";
default:
break;
}
return "unknown";
}
void reset(int32_t expect, ParserStage checkStage) {
stmtEnv_.sql_.clear(); stmtEnv_.sql_.clear();
stmtEnv_.msgBuf_.fill(0); stmtEnv_.msgBuf_.fill(0);
stmtEnv_.expect_ = expect;
stmtEnv_.checkFunc_ = stageFunc(checkStage);
res_.parsedAst_.clear(); res_.parsedAst_.clear();
res_.translatedAst_.clear(); res_.translatedAst_.clear();
...@@ -146,4 +189,8 @@ ParserTestBase::~ParserTestBase() {} ...@@ -146,4 +189,8 @@ ParserTestBase::~ParserTestBase() {}
void ParserTestBase::useDb(const std::string& acctId, const std::string& db) { impl_->useDb(acctId, db); } void ParserTestBase::useDb(const std::string& acctId, const std::string& db) { impl_->useDb(acctId, db); }
void ParserTestBase::run(const std::string& sql) { return impl_->run(sql); } void ParserTestBase::run(const std::string& sql, int32_t expect, ParserStage checkStage) {
return impl_->run(sql, expect, checkStage);
}
} // namespace ParserTest
...@@ -18,15 +18,21 @@ ...@@ -18,15 +18,21 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "taoserror.h"
namespace ParserTest {
class ParserTestBaseImpl; class ParserTestBaseImpl;
enum ParserStage { PARSER_STAGE_PARSE, PARSER_STAGE_TRANSLATE, PARSER_STAGE_CALC_CONST, PARSER_STAGE_ALL };
class ParserTestBase : public testing::Test { class ParserTestBase : public testing::Test {
public: public:
ParserTestBase(); ParserTestBase();
virtual ~ParserTestBase(); virtual ~ParserTestBase();
void useDb(const std::string& acctId, const std::string& db); void useDb(const std::string& acctId, const std::string& db);
void run(const std::string& sql); void run(const std::string& sql, int32_t expect = TSDB_CODE_SUCCESS, ParserStage checkStage = PARSER_STAGE_ALL);
private: private:
std::unique_ptr<ParserTestBaseImpl> impl_; std::unique_ptr<ParserTestBaseImpl> impl_;
...@@ -34,4 +40,6 @@ class ParserTestBase : public testing::Test { ...@@ -34,4 +40,6 @@ class ParserTestBase : public testing::Test {
extern bool g_isDump; extern bool g_isDump;
} // namespace ParserTest
#endif // PARSER_TEST_UTIL_H #endif // PARSER_TEST_UTIL_H
此差异已折叠。
...@@ -748,10 +748,10 @@ static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele ...@@ -748,10 +748,10 @@ static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele
SLogicNode* pRoot = NULL; SLogicNode* pRoot = NULL;
int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot); int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot);
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = createChildLogicNode(pCxt, pSelect, createWindowLogicNode, &pRoot); code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot);
} }
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot); code = createChildLogicNode(pCxt, pSelect, createWindowLogicNode, &pRoot);
} }
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot); code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot);
......
...@@ -520,6 +520,7 @@ static int32_t cpdPushCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild, SN ...@@ -520,6 +520,7 @@ static int32_t cpdPushCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild, SN
default: default:
break; break;
} }
planError("cpdPushCondToChild failed, invalid logic plan node %s", nodesNodeName(nodeType(pChild)));
return TSDB_CODE_PLAN_INTERNAL_ERROR; return TSDB_CODE_PLAN_INTERNAL_ERROR;
} }
......
...@@ -272,6 +272,7 @@ static EDealRes doSetSlotId(SNode* pNode, void* pContext) { ...@@ -272,6 +272,7 @@ static EDealRes doSetSlotId(SNode* pNode, void* pContext) {
} }
// pIndex is definitely not NULL, otherwise it is a bug // pIndex is definitely not NULL, otherwise it is a bug
if (NULL == pIndex) { if (NULL == pIndex) {
planError("doSetSlotId failed, invalid slot name %s", name);
pCxt->errCode = TSDB_CODE_PLAN_INTERNAL_ERROR; pCxt->errCode = TSDB_CODE_PLAN_INTERNAL_ERROR;
return DEAL_RES_ERROR; return DEAL_RES_ERROR;
} }
...@@ -435,12 +436,15 @@ static void vgroupInfoToNodeAddr(const SVgroupInfo* vg, SQueryNodeAddr* pNodeAdd ...@@ -435,12 +436,15 @@ static void vgroupInfoToNodeAddr(const SVgroupInfo* vg, SQueryNodeAddr* pNodeAdd
pNodeAddr->epSet = vg->epSet; pNodeAddr->epSet = vg->epSet;
} }
static int32_t createTagScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode, SPhysiNode** pPhyNode) { static int32_t createTagScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode,
SPhysiNode** pPhyNode) {
STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode( STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode(
pCxt, pScanLogicNode->pMeta->tableInfo.precision, (SLogicNode*)pScanLogicNode, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN); pCxt, pScanLogicNode->pMeta->tableInfo.precision, (SLogicNode*)pScanLogicNode, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN);
if (NULL == pTagScan) { if (NULL == pTagScan) {
return TSDB_CODE_OUT_OF_MEMORY; return TSDB_CODE_OUT_OF_MEMORY;
} }
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode);
return createScanPhysiNodeFinalize(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan, pPhyNode); return createScanPhysiNodeFinalize(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan, pPhyNode);
} }
...@@ -514,7 +518,7 @@ static int32_t createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, ...@@ -514,7 +518,7 @@ static int32_t createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
SPhysiNode** pPhyNode) { SPhysiNode** pPhyNode) {
switch (pScanLogicNode->scanType) { switch (pScanLogicNode->scanType) {
case SCAN_TYPE_TAG: case SCAN_TYPE_TAG:
return createTagScanPhysiNode(pCxt, pScanLogicNode, pPhyNode); return createTagScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
case SCAN_TYPE_TABLE: case SCAN_TYPE_TABLE:
return createTableScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode); return createTableScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
case SCAN_TYPE_SYSTEM_TABLE: case SCAN_TYPE_SYSTEM_TABLE:
......
...@@ -30,4 +30,9 @@ if(${BUILD_WINGETOPT}) ...@@ -30,4 +30,9 @@ if(${BUILD_WINGETOPT})
PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src" PUBLIC "${TD_SOURCE_DIR}/contrib/wingetopt/src"
) )
target_link_libraries(plannerTest PUBLIC wingetopt) target_link_libraries(plannerTest PUBLIC wingetopt)
endif() endif()
\ No newline at end of file
add_test(
NAME plannerTest
COMMAND plannerTest
)
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanBasicTest : public PlannerTestBase {};
TEST_F(PlanBasicTest, select) {
useDb("root", "test");
// run("select * from t1");
// run("select 1 from t1");
// run("select * from st1");
run("select 1 from st1");
}
TEST_F(PlanBasicTest, where) {
useDb("root", "test");
run("select * from t1 where c1 > 10");
}
TEST_F(PlanBasicTest, join) {
useDb("root", "test");
run("select t1.c1, t2.c2 from st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
run("select t1.c1, t2.c2 from st1s1 t1 join st1s2 t2 on t1.ts = t2.ts");
}
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanDistinctTest : public PlannerTestBase {};
TEST_F(PlanDistinctTest, basic) {
useDb("root", "test");
// distinct single col
run("select distinct c1 from t1");
// distinct col list
run("select distinct c1, c2 from t1");
}
TEST_F(PlanDistinctTest, expr) {
useDb("root", "test");
run("select distinct c1, c2 + 10 from t1");
}
TEST_F(PlanDistinctTest, withOrderBy) {
useDb("root", "test");
run("select distinct c1 + 10 a from t1 order by a");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanGroupByTest : public PlannerTestBase {};
TEST_F(PlanGroupByTest, basic) {
useDb("root", "test");
run("select count(*) from t1");
run("select c1, max(c3), min(c3), count(*) from t1 group by c1");
run("select c1 + c3, c1 + count(*) from t1 where c2 = 'abc' group by c1, c3");
run("select c1 + c3, sum(c4 * c5) from t1 where concat(c2, 'wwww') = 'abcwww' group by c1 + c3");
run("select sum(ceil(c1)) from t1 group by ceil(c1)");
}
TEST_F(PlanGroupByTest, withOrderBy) {
useDb("root", "test");
// order by aggfunc
run("select count(*), sum(c1) from t1 order by sum(c1)");
// order by alias of aggfunc
// run("select count(*), sum(c1) a from t1 order by a");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanIntervalTest : public PlannerTestBase {};
TEST_F(PlanIntervalTest, basic) {
useDb("root", "test");
run("select count(*) from t1 interval(10s)");
}
TEST_F(PlanIntervalTest, pseudoCol) {
useDb("root", "test");
run("select _wstartts, _wduration, _wendts, count(*) from t1 interval(10s)");
}
TEST_F(PlanIntervalTest, fill) {
useDb("root", "test");
run("select count(*) from t1 interval(10s) fill(linear)");
run("select count(*), sum(c1) from t1 interval(10s) fill(value, 10, 20)");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanJoinTest : public PlannerTestBase {};
TEST_F(PlanJoinTest, basic) {
useDb("root", "test");
run("select t1.c1, t2.c2 from st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
run("select t1.*, t2.* from st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
// run("select t1.c1, t2.c1 from st1s1 t1 join st1s2 t2 on t1.ts = t2.ts where t1.c1 > t2.c1 and t1.c2 = 'abc' and "
// "t2.c2 = 'qwe'");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanLimitTest : public PlannerTestBase {};
TEST_F(PlanLimitTest, limit) {
useDb("root", "test");
run("select * from t1 limit 2");
run("select * from t1 limit 5 offset 2");
run("select * from t1 limit 2, 5");
}
TEST_F(PlanLimitTest, slimit) {
useDb("root", "test");
run("select * from t1 partition by c1 slimit 2");
run("select * from t1 partition by c1 slimit 5 soffset 2");
run("select * from t1 partition by c1 slimit 2, 5");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanOrderByTest : public PlannerTestBase {};
TEST_F(PlanOrderByTest, basic) {
useDb("root", "test");
// order by key is in the projection list
run("select c1 from t1 order by c1");
// order by key is not in the projection list
run("select c1 from t1 order by c2");
}
TEST_F(PlanOrderByTest, expr) {
useDb("root", "test");
run("select * from t1 order by c1 + 10, c2");
}
TEST_F(PlanOrderByTest, nullsOrder) {
useDb("root", "test");
run("select * from t1 order by c1 desc nulls first");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanOtherTest : public PlannerTestBase {};
TEST_F(PlanOtherTest, createTopic) {
useDb("root", "test");
run("create topic tp as SELECT * FROM st1");
}
TEST_F(PlanOtherTest, createStream) {
useDb("root", "test");
run("create stream if not exists s1 trigger window_close watermark 10s into st1 as select count(*) from t1 "
"interval(10s)");
}
TEST_F(PlanOtherTest, createSmaIndex) {
useDb("root", "test");
run("create sma index index1 on t1 function(max(c1), min(c3 + 10), sum(c4)) interval(10s)");
}
TEST_F(PlanOtherTest, explain) {
useDb("root", "test");
run("explain SELECT * FROM t1");
run("explain analyze SELECT * FROM t1");
run("explain analyze verbose true ratio 0.01 SELECT * FROM t1");
}
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanPartitionByTest : public PlannerTestBase {};
TEST_F(PlanPartitionByTest, basic) {
useDb("root", "test");
run("select * from t1 partition by c1");
}
TEST_F(PlanPartitionByTest, withAggFunc) {
useDb("root", "test");
run("select count(*) from t1 partition by c1");
}
TEST_F(PlanPartitionByTest, withInterval) {
useDb("root", "test");
// normal/child table
run("select count(*) from t1 partition by c1 interval(10s)");
// super table
run("select count(*) from st1 partition by tag1, tag2 interval(10s)");
}
TEST_F(PlanPartitionByTest, withGroupBy) {
useDb("root", "test");
run("select count(*) from t1 partition by c1 group by c2");
}
...@@ -13,14 +13,15 @@ ...@@ -13,14 +13,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "parTestUtil.h" #include "planTestUtil.h"
#include "planner.h"
using namespace std; using namespace std;
class ParserAlterTest : public ParserTestBase {}; class PlanSessionTest : public PlannerTestBase {};
TEST_F(ParserAlterTest, stmt) { TEST_F(PlanSessionTest, basic) {
useDb("root", "test"); useDb("root", "test");
run("create database db1"); run("select count(*) from t1 session(ts, 10s)");
} }
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanStateTest : public PlannerTestBase {};
TEST_F(PlanStateTest, basic) {
useDb("root", "test");
run("select count(*) from t1 state_window(c1)");
}
TEST_F(PlanStateTest, stateExpr) {
useDb("root", "test");
run("select count(*) from t1 state_window(c1 + 10)");
}
...@@ -42,13 +42,13 @@ class PlanStmtTest : public PlannerTestBase { ...@@ -42,13 +42,13 @@ class PlanStmtTest : public PlannerTestBase {
// todo // todo
} }
private: private:
TAOS_MULTI_BIND* pBindParams_; TAOS_MULTI_BIND* pBindParams_;
int32_t paramNo_; int32_t paramNo_;
}; };
TEST_F(PlanStmtTest, stmt) { TEST_F(PlanStmtTest, stmt) {
useDb("root", "test"); useDb("root", "test");
run("SELECT * FROM t1 where c1 = ?"); run("select * from t1 where c1 = ?");
} }
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanSubqeuryTest : public PlannerTestBase {};
TEST_F(PlanSubqeuryTest, basic) {
useDb("root", "test");
run("select * from (select * from t1)");
}
TEST_F(PlanSubqeuryTest, doubleGroupBy) {
useDb("root", "test");
run("select count(*) from (select c1 + c3 a, c1 + count(*) b from t1 where c2 = 'abc' group by c1, c3) where a > 100 "
"group by b");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "planTestUtil.h"
#include "planner.h"
using namespace std;
class PlanSysTableTest : public PlannerTestBase {};
TEST_F(PlanSysTableTest, show) {
useDb("root", "test");
run("show tables");
run("show stables");
}
TEST_F(PlanSysTableTest, information) {
useDb("root", "information_schema");
run("show tables");
}
...@@ -106,6 +106,7 @@ class PlannerTestBaseImpl { ...@@ -106,6 +106,7 @@ class PlannerTestBaseImpl {
res_.splitLogicPlan_.clear(); res_.splitLogicPlan_.clear();
res_.scaledLogicPlan_.clear(); res_.scaledLogicPlan_.clear();
res_.physiPlan_.clear(); res_.physiPlan_.clear();
res_.physiSubplans_.clear();
} }
void dump() { void dump() {
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <gtest/gtest.h>
#include "cmdnodes.h"
#include "parser.h"
#include "planInt.h"
using namespace std;
using namespace testing;
class PlannerTest : public Test {
protected:
void setDatabase(const string& acctId, const string& db) {
acctId_ = acctId;
db_ = db;
}
void bind(const char* sql) {
reset();
cxt_.acctId = atoi(acctId_.c_str());
cxt_.db = db_.c_str();
sqlBuf_ = string(sql);
transform(sqlBuf_.begin(), sqlBuf_.end(), sqlBuf_.begin(), ::tolower);
cxt_.sqlLen = strlen(sql);
cxt_.pSql = sqlBuf_.c_str();
}
bool run(bool streamQuery = false) {
int32_t code = qParseQuerySql(&cxt_, &query_);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] qParseQuerySql code:" << code << ", strerror:" << tstrerror(code)
<< ", msg:" << errMagBuf_ << endl;
return false;
}
const string syntaxTreeStr = toString(query_->pRoot, false);
SLogicNode* pLogicNode = nullptr;
SPlanContext cxt = {0};
cxt.queryId = 1;
cxt.acctId = 0;
cxt.streamQuery = streamQuery;
setPlanContext(query_, &cxt);
code = createLogicPlan(&cxt, &pLogicNode);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] createLogicPlan code:" << code << ", strerror:" << tstrerror(code) << endl;
return false;
}
cout << "====================sql : [" << cxt_.pSql << "]" << endl;
cout << "syntax tree : " << endl;
cout << syntaxTreeStr << endl;
cout << "unformatted logic plan : " << endl;
cout << toString((const SNode*)pLogicNode, false) << endl;
code = optimizeLogicPlan(&cxt, pLogicNode);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] optimizeLogicPlan code:" << code << ", strerror:" << tstrerror(code) << endl;
return false;
}
SLogicSubplan* pLogicSubplan = nullptr;
code = splitLogicPlan(&cxt, pLogicNode, &pLogicSubplan);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] splitLogicPlan code:" << code << ", strerror:" << tstrerror(code) << endl;
return false;
}
SQueryLogicPlan* pLogicPlan = NULL;
code = scaleOutLogicPlan(&cxt, pLogicSubplan, &pLogicPlan);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] createPhysiPlan code:" << code << ", strerror:" << tstrerror(code) << endl;
return false;
}
SArray* pExecNodeList = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SQueryNodeAddr));
code = createPhysiPlan(&cxt, pLogicPlan, &plan_, pExecNodeList);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] createPhysiPlan code:" << code << ", strerror:" << tstrerror(code) << endl;
return false;
}
cout << "unformatted physical plan : " << endl;
cout << toString((const SNode*)plan_, false) << endl;
SNode* pNode;
FOREACH(pNode, plan_->pSubplans) {
SNode* pSubplan;
FOREACH(pSubplan, ((SNodeListNode*)pNode)->pNodeList) {
cout << "unformatted physical subplan : " << endl;
cout << toString(pSubplan, false) << endl;
}
}
return true;
}
private:
static const int max_err_len = 1024;
void setPlanContext(SQuery* pQuery, SPlanContext* pCxt) {
if (QUERY_NODE_CREATE_TOPIC_STMT == nodeType(pQuery->pRoot)) {
pCxt->pAstRoot = ((SCreateTopicStmt*)pQuery->pRoot)->pQuery;
pCxt->topicQuery = true;
} else if (QUERY_NODE_CREATE_INDEX_STMT == nodeType(pQuery->pRoot)) {
SMCreateSmaReq req = {0};
tDeserializeSMCreateSmaReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req);
nodesStringToNode(req.ast, &pCxt->pAstRoot);
pCxt->streamQuery = true;
} else if (QUERY_NODE_CREATE_STREAM_STMT == nodeType(pQuery->pRoot)) {
SCreateStreamStmt* pStmt = (SCreateStreamStmt*)pQuery->pRoot;
pCxt->pAstRoot = pStmt->pQuery;
pCxt->streamQuery = true;
pCxt->triggerType = pStmt->pOptions->triggerType;
pCxt->watermark = (NULL != pStmt->pOptions->pWatermark ? ((SValueNode*)pStmt->pOptions->pWatermark)->datum.i : 0);
} else {
pCxt->pAstRoot = pQuery->pRoot;
}
}
void reset() {
memset(&cxt_, 0, sizeof(cxt_));
memset(errMagBuf_, 0, max_err_len);
cxt_.pMsg = errMagBuf_;
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);
taosMemoryFreeClear(pStr);
return str;
}
string acctId_;
string db_;
char errMagBuf_[max_err_len];
string sqlBuf_;
SParseContext cxt_;
SQuery* query_;
SQueryPlan* plan_;
};
TEST_F(PlannerTest, selectBasic) {
setDatabase("root", "test");
bind("SELECT * FROM t1");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectConstant) {
setDatabase("root", "test");
bind("SELECT 2-1 FROM t1");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectStableBasic) {
setDatabase("root", "test");
bind("SELECT * FROM st1");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectJoin) {
setDatabase("root", "test");
bind("SELECT t1.c1, t2.c2 FROM st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
ASSERT_TRUE(run());
bind("SELECT t1.*, t2.* FROM st1s1 t1, st1s2 t2 where t1.ts = t2.ts");
ASSERT_TRUE(run());
bind(
"SELECT t1.c1, t2.c1 FROM st1s1 t1 join st1s2 t2 on t1.ts = t2.ts where t1.c1 > t2.c1 and t1.c2 = 'abc' and "
"t2.c2 = 'qwe'");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectGroupBy) {
setDatabase("root", "test");
bind("SELECT count(*) FROM t1");
ASSERT_TRUE(run());
bind("SELECT c1, max(c3), min(c3), 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, sum(c4 * c5) FROM t1 where concat(c2, 'wwww') = 'abcwww' GROUP BY c1 + c3");
ASSERT_TRUE(run());
bind("SELECT sum(ceil(c1)) FROM t1 GROUP BY ceil(c1)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectSubquery) {
setDatabase("root", "test");
bind(
"SELECT count(*) FROM (SELECT c1 + c3 a, c1 + count(*) b FROM t1 where c2 = 'abc' GROUP BY c1, c3) where a > 100 "
"group by b");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectInterval) {
setDatabase("root", "test");
bind("SELECT count(*) FROM t1 interval(10s)");
ASSERT_TRUE(run());
bind("SELECT _wstartts, _wduration, _wendts, count(*) FROM t1 interval(10s)");
ASSERT_TRUE(run());
bind("SELECT count(*) FROM t1 interval(10s) fill(linear)");
ASSERT_TRUE(run());
bind("SELECT count(*), sum(c1) FROM t1 interval(10s) fill(value, 10, 20)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectSessionWindow) {
setDatabase("root", "test");
bind("SELECT count(*) FROM t1 session(ts, 10s)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectStateWindow) {
setDatabase("root", "test");
bind("SELECT count(*) FROM t1 state_window(c1)");
ASSERT_TRUE(run());
bind("SELECT count(*) FROM t1 state_window(c1 + 10)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectPartitionBy) {
setDatabase("root", "test");
bind("SELECT * FROM t1 partition by c1");
ASSERT_TRUE(run());
bind("SELECT count(*) FROM t1 partition by c1");
ASSERT_TRUE(run());
bind("SELECT count(*) FROM t1 partition by c1 group by c2");
ASSERT_TRUE(run());
bind("SELECT count(*) FROM st1 partition by tag1, tag2 interval(10s)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectOrderBy) {
setDatabase("root", "test");
bind("SELECT c1 FROM t1 order by c1");
ASSERT_TRUE(run());
bind("SELECT c1 FROM t1 order by c2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 order by c1 + 10, c2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 order by c1 desc nulls first");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectGroupByOrderBy) {
setDatabase("root", "test");
bind("select count(*), sum(c1) from t1 order by sum(c1)");
ASSERT_TRUE(run());
bind("select count(*), sum(c1) a from t1 order by a");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectDistinct) {
setDatabase("root", "test");
bind("SELECT distinct c1 FROM t1");
ASSERT_TRUE(run());
bind("SELECT distinct c1, c2 + 10 FROM t1");
ASSERT_TRUE(run());
bind("SELECT distinct c1 + 10 a FROM t1 order by a");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectLimit) {
setDatabase("root", "test");
bind("SELECT * FROM t1 limit 2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 limit 5 offset 2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 limit 2, 5");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, selectSlimit) {
setDatabase("root", "test");
bind("SELECT * FROM t1 partition by c1 slimit 2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 partition by c1 slimit 5 soffset 2");
ASSERT_TRUE(run());
bind("SELECT * FROM t1 partition by c1 slimit 2, 5");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, showTables) {
setDatabase("root", "test");
bind("show tables");
ASSERT_TRUE(run());
setDatabase("root", "information_schema");
bind("show tables");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, showStables) {
setDatabase("root", "test");
bind("show stables");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, createTopic) {
setDatabase("root", "test");
bind("create topic tp as SELECT * FROM st1");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, createStream) {
setDatabase("root", "test");
bind(
"create stream if not exists s1 trigger window_close watermark 10s into st1 as select count(*) from t1 "
"interval(10s)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, createSmaIndex) {
setDatabase("root", "test");
bind("create sma index index1 on t1 function(max(c1), min(c3 + 10), sum(c4)) INTERVAL(10s)");
ASSERT_TRUE(run());
}
TEST_F(PlannerTest, explain) {
setDatabase("root", "test");
bind("explain SELECT * FROM t1");
ASSERT_TRUE(run());
bind("explain analyze SELECT * FROM t1");
ASSERT_TRUE(run());
bind("explain analyze verbose true ratio 0.01 SELECT * FROM t1");
ASSERT_TRUE(run());
}
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
# --- stable # --- stable
./test.sh -f tsim/stable/disk.sim ./test.sh -f tsim/stable/disk.sim
./test.sh -f tsim/stable/dnode3.sim #./test.sh -f tsim/stable/dnode3.sim
./test.sh -f tsim/stable/metrics.sim ./test.sh -f tsim/stable/metrics.sim
./test.sh -f tsim/stable/refcount.sim ./test.sh -f tsim/stable/refcount.sim
# ./test.sh -f tsim/stable/show.sim # ./test.sh -f tsim/stable/show.sim
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册