提交 cdfe9929 编写于 作者: X Xiaoyu Wang

feat: fill physical plan

上级 91335405
......@@ -28,15 +28,16 @@ typedef int64_t tb_uid_t;
#define TSWINDOW_INITIALIZER ((STimeWindow){INT64_MIN, INT64_MAX})
#define TSWINDOW_DESC_INITIALIZER ((STimeWindow){INT64_MAX, INT64_MIN})
#define IS_TSWINDOW_SPECIFIED(win) (((win).skey != INT64_MIN) || ((win).ekey != INT64_MAX))
#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey))
typedef enum {
TSDB_SUPER_TABLE = 1, // super table
TSDB_CHILD_TABLE = 2, // table created from super table
TSDB_NORMAL_TABLE = 3, // ordinary table
TSDB_STREAM_TABLE = 4, // table created from stream computing
TSDB_TEMP_TABLE = 5, // temp table created by nest query
TSDB_SUPER_TABLE = 1, // super table
TSDB_CHILD_TABLE = 2, // table created from super table
TSDB_NORMAL_TABLE = 3, // ordinary table
TSDB_STREAM_TABLE = 4, // table created from stream computing
TSDB_TEMP_TABLE = 5, // temp table created by nest query
TSDB_SYSTEM_TABLE = 6,
TSDB_TABLE_MAX = 7
TSDB_TABLE_MAX = 7
} ETableType;
typedef enum {
......@@ -86,7 +87,7 @@ typedef enum {
extern char *qtypeStr[];
#define TSDB_PORT_HTTP 11
#define TSDB_PORT_HTTP 11
#undef TD_DEBUG_PRINT_ROW
......
......@@ -110,10 +110,11 @@ typedef struct SWindowLogicNode {
} SWindowLogicNode;
typedef struct SFillLogicNode {
SLogicNode node;
EFillMode mode;
SNode* pWStartTs;
SNode* pValues; // SNodeListNode
SLogicNode node;
EFillMode mode;
SNode* pWStartTs;
SNode* pValues; // SNodeListNode
STimeWindow timeRange;
} SFillLogicNode;
typedef struct SSortLogicNode {
......@@ -274,11 +275,12 @@ typedef struct SIntervalPhysiNode {
} SIntervalPhysiNode;
typedef struct SFillPhysiNode {
SPhysiNode node;
EFillMode mode;
SNode* pWStartTs; // SColumnNode
SNode* pValues; // SNodeListNode
SNodeList* pTargets;
SPhysiNode node;
EFillMode mode;
SNode* pWStartTs; // SColumnNode
SNode* pValues; // SNodeListNode
SNodeList* pTargets;
STimeWindow timeRange;
} SFillPhysiNode;
typedef struct SMultiTableIntervalPhysiNode {
......
......@@ -209,10 +209,11 @@ typedef enum EFillMode {
} EFillMode;
typedef struct SFillNode {
ENodeType type; // QUERY_NODE_FILL
EFillMode mode;
SNode* pValues; // SNodeListNode
SNode* pWStartTs; // _wstartts pseudo column
ENodeType type; // QUERY_NODE_FILL
EFillMode mode;
SNode* pValues; // SNodeListNode
SNode* pWStartTs; // _wstartts pseudo column
STimeWindow timeRange;
} SFillNode;
typedef struct SSelectStmt {
......
......@@ -619,9 +619,12 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_BY TAOS_DEF_ERROR_CODE(0, 0x2638)
#define TSDB_CODE_PAR_INVALID_TOPIC_QUERY TAOS_DEF_ERROR_CODE(0, 0x2639)
#define TSDB_CODE_PAR_INVALID_DROP_STABLE TAOS_DEF_ERROR_CODE(0, 0x263A)
#define TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE TAOS_DEF_ERROR_CODE(0, 0x263B)
//planner
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
#define TSDB_CODE_PLAN_EXPECTED_TS_EQUAL TAOS_DEF_ERROR_CODE(0, 0x2701)
#define TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN TAOS_DEF_ERROR_CODE(0, 0x2702)
//function
#define TSDB_CODE_FUNC_FUNTION_ERROR TAOS_DEF_ERROR_CODE(0, 0x2800)
......
......@@ -41,8 +41,6 @@
#define SET_MAIN_SCAN_FLAG(runtime) ((runtime)->scanFlag = MAIN_SCAN)
#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN)
#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey))
#define SDATA_BLOCK_INITIALIZER \
(SDataBlockInfo) { {0}, 0 }
......
......@@ -571,6 +571,8 @@ static int32_t jsonToLogicProjectNode(const SJson* pJson, void* pObj) {
static const char* jkFillLogicPlanMode = "Mode";
static const char* jkFillLogicPlanWStartTs = "WStartTs";
static const char* jkFillLogicPlanValues = "Values";
static const char* jkFillLogicPlanStartTime = "StartTime";
static const char* jkFillLogicPlanEndTime = "EndTime";
static int32_t logicFillNodeToJson(const void* pObj, SJson* pJson) {
const SFillLogicNode* pNode = (const SFillLogicNode*)pObj;
......@@ -585,6 +587,12 @@ static int32_t logicFillNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkFillLogicPlanValues, nodeToJson, pNode->pValues);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillLogicPlanStartTime, pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillLogicPlanEndTime, pNode->timeRange.ekey);
}
return code;
}
......@@ -602,6 +610,12 @@ static int32_t jsonToLogicFillNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkFillLogicPlanValues, &pNode->pValues);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillLogicPlanStartTime, &pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillLogicPlanEndTime, &pNode->timeRange.ekey);
}
return code;
}
......@@ -1475,6 +1489,8 @@ static const char* jkFillPhysiPlanMode = "Mode";
static const char* jkFillPhysiPlanWStartTs = "WStartTs";
static const char* jkFillPhysiPlanValues = "Values";
static const char* jkFillPhysiPlanTargets = "Targets";
static const char* jkFillPhysiPlanStartTime = "StartTime";
static const char* jkFillPhysiPlanEndTime = "EndTime";
static int32_t physiFillNodeToJson(const void* pObj, SJson* pJson) {
const SFillPhysiNode* pNode = (const SFillPhysiNode*)pObj;
......@@ -1492,6 +1508,12 @@ static int32_t physiFillNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = nodeListToJson(pJson, jkFillPhysiPlanTargets, pNode->pTargets);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillPhysiPlanStartTime, pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillPhysiPlanEndTime, pNode->timeRange.ekey);
}
return code;
}
......@@ -1512,6 +1534,12 @@ static int32_t jsonToPhysiFillNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeList(pJson, jkFillPhysiPlanTargets, &pNode->pTargets);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillPhysiPlanStartTime, &pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillPhysiPlanEndTime, &pNode->timeRange.ekey);
}
return code;
}
......@@ -2409,6 +2437,8 @@ static int32_t jsonToNodeListNode(const SJson* pJson, void* pObj) {
static const char* jkFillMode = "Mode";
static const char* jkFillValues = "Values";
static const char* jkFillWStartTs = "WStartTs";
static const char* jkFillStartTime = "StartTime";
static const char* jkFillEndTime = "EndTime";
static int32_t fillNodeToJson(const void* pObj, SJson* pJson) {
const SFillNode* pNode = (const SFillNode*)pObj;
......@@ -2420,6 +2450,12 @@ static int32_t fillNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkFillWStartTs, nodeToJson, pNode->pWStartTs);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillStartTime, pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillEndTime, pNode->timeRange.ekey);
}
return code;
}
......@@ -2434,6 +2470,12 @@ static int32_t jsonToFillNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkFillWStartTs, &pNode->pWStartTs);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillStartTime, &pNode->timeRange.skey);
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillEndTime, &pNode->timeRange.ekey);
}
return code;
}
......
......@@ -17,6 +17,7 @@
#include "catalog.h"
#include "cmdnodes.h"
#include "filter.h"
#include "functionMgt.h"
#include "parUtil.h"
#include "scalar.h"
......@@ -468,19 +469,19 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
pVal->datum.b = (0 == strcasecmp(pVal->literal, "true"));
*(bool*)&pVal->typeData = pVal->datum.b;
break;
case TSDB_DATA_TYPE_TINYINT:{
case TSDB_DATA_TYPE_TINYINT: {
char* endPtr = NULL;
pVal->datum.i = strtoll(pVal->literal, &endPtr, 10);
*(int8_t*)&pVal->typeData = pVal->datum.i;
break;
}
case TSDB_DATA_TYPE_SMALLINT:{
case TSDB_DATA_TYPE_SMALLINT: {
char* endPtr = NULL;
pVal->datum.i = strtoll(pVal->literal, &endPtr, 10);
*(int16_t*)&pVal->typeData = pVal->datum.i;
break;
}
case TSDB_DATA_TYPE_INT:{
case TSDB_DATA_TYPE_INT: {
char* endPtr = NULL;
pVal->datum.i = strtoll(pVal->literal, &endPtr, 10);
*(int32_t*)&pVal->typeData = pVal->datum.i;
......@@ -489,43 +490,43 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
case TSDB_DATA_TYPE_BIGINT: {
char* endPtr = NULL;
pVal->datum.i = strtoll(pVal->literal, &endPtr, 10);
*(int64_t*)&pVal->typeData = pVal->datum.i;
*(int64_t*)&pVal->typeData = pVal->datum.i;
break;
}
case TSDB_DATA_TYPE_UTINYINT:{
case TSDB_DATA_TYPE_UTINYINT: {
char* endPtr = NULL;
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
*(uint8_t*)&pVal->typeData = pVal->datum.u;
*(uint8_t*)&pVal->typeData = pVal->datum.u;
break;
}
case TSDB_DATA_TYPE_USMALLINT:{
case TSDB_DATA_TYPE_USMALLINT: {
char* endPtr = NULL;
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
*(uint16_t*)&pVal->typeData = pVal->datum.u;
*(uint16_t*)&pVal->typeData = pVal->datum.u;
break;
}
case TSDB_DATA_TYPE_UINT:{
case TSDB_DATA_TYPE_UINT: {
char* endPtr = NULL;
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
*(uint32_t*)&pVal->typeData = pVal->datum.u;
*(uint32_t*)&pVal->typeData = pVal->datum.u;
break;
}
case TSDB_DATA_TYPE_UBIGINT: {
char* endPtr = NULL;
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
*(uint64_t*)&pVal->typeData = pVal->datum.u;
*(uint64_t*)&pVal->typeData = pVal->datum.u;
break;
}
case TSDB_DATA_TYPE_FLOAT:{
case TSDB_DATA_TYPE_FLOAT: {
char* endPtr = NULL;
pVal->datum.d = strtold(pVal->literal, &endPtr);
*(float*)&pVal->typeData = pVal->datum.d;
*(float*)&pVal->typeData = pVal->datum.d;
break;
}
case TSDB_DATA_TYPE_DOUBLE: {
char* endPtr = NULL;
pVal->datum.d = strtold(pVal->literal, &endPtr);
*(double*)&pVal->typeData = pVal->datum.d;
*(double*)&pVal->typeData = pVal->datum.d;
break;
}
case TSDB_DATA_TYPE_VARCHAR:
......@@ -543,7 +544,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
TSDB_CODE_SUCCESS) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
}
*(int64_t*)&pVal->typeData = pVal->datum.i;
*(int64_t*)&pVal->typeData = pVal->datum.i;
break;
}
case TSDB_DATA_TYPE_NCHAR:
......@@ -1244,6 +1245,113 @@ static int32_t translateGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
return TSDB_CODE_SUCCESS;
}
static EDealRes isPrimaryKeyCondImpl(SNode* pNode, void* pContext) {
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
*((bool*)pContext) = ((PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pNode)->colId) ? true : false);
return *((bool*)pContext) ? DEAL_RES_CONTINUE : DEAL_RES_END;
}
return DEAL_RES_CONTINUE;
}
static bool isPrimaryKeyCond(SNode* pNode) {
bool isPrimaryKeyCond = false;
nodesWalkExpr(pNode, isPrimaryKeyCondImpl, &isPrimaryKeyCond);
return isPrimaryKeyCond;
}
static int32_t getTimeRangeFromLogicCond(STranslateContext* pCxt, SLogicConditionNode* pLogicCond,
STimeWindow* pTimeRange) {
SNodeList* pPrimaryKeyConds = NULL;
SNode* pCond = NULL;
FOREACH(pCond, pLogicCond->pParameterList) {
if (isPrimaryKeyCond(pCond)) {
if (TSDB_CODE_SUCCESS != nodesListMakeAppend(&pPrimaryKeyConds, pCond)) {
nodesClearList(pPrimaryKeyConds);
return TSDB_CODE_OUT_OF_MEMORY;
}
}
}
if (NULL == pPrimaryKeyConds) {
*pTimeRange = TSWINDOW_INITIALIZER;
return TSDB_CODE_SUCCESS;
}
SLogicConditionNode* pPrimaryKeyLogicCond = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION);
if (NULL == pPrimaryKeyLogicCond) {
nodesClearList(pPrimaryKeyConds);
return TSDB_CODE_OUT_OF_MEMORY;
}
pPrimaryKeyLogicCond->condType = LOGIC_COND_TYPE_AND;
pPrimaryKeyLogicCond->pParameterList = pPrimaryKeyConds;
bool isStrict = false;
int32_t code = filterGetTimeRange((SNode*)pPrimaryKeyLogicCond, pTimeRange, &isStrict);
nodesClearList(pPrimaryKeyConds);
pPrimaryKeyLogicCond->pParameterList = NULL;
nodesDestroyNode(pPrimaryKeyLogicCond);
return code;
}
static int32_t getTimeRange(STranslateContext* pCxt, SNode* pWhere, STimeWindow* pTimeRange) {
if (NULL == pWhere) {
*pTimeRange = TSWINDOW_INITIALIZER;
return TSDB_CODE_SUCCESS;
}
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pWhere) &&
LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)pWhere)->condType) {
return getTimeRangeFromLogicCond(pCxt, (SLogicConditionNode*)pWhere, pTimeRange);
}
if (isPrimaryKeyCond(pWhere)) {
bool isStrict = false;
return filterGetTimeRange(pWhere, pTimeRange, &isStrict);
} else {
*pTimeRange = TSWINDOW_INITIALIZER;
}
return TSDB_CODE_SUCCESS;
}
static int32_t checkFill(STranslateContext* pCxt, SIntervalWindowNode* pInterval) {
SFillNode* pFill = (SFillNode*)pInterval->pFill;
if (TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_INITIALIZER) ||
TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_DESC_INITIALIZER)) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE);
}
int64_t timeRange = TABS(pFill->timeRange.skey - pFill->timeRange.ekey);
int64_t intervalRange = 0;
SValueNode* pInter = (SValueNode*)pInterval->pInterval;
if (TIME_IS_VAR_DURATION(pInter->unit)) {
int64_t f = 1;
if (pInter->unit == 'n') {
f = 30L * MILLISECOND_PER_DAY;
} else if (pInter->unit == 'y') {
f = 365L * MILLISECOND_PER_DAY;
}
intervalRange = pInter->datum.i * f;
} else {
intervalRange = pInter->datum.i;
}
if ((timeRange == 0) || (timeRange / intervalRange) >= MAX_INTERVAL_TIME_WINDOW) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE);
}
return TSDB_CODE_SUCCESS;
}
static int32_t translateFill(STranslateContext* pCxt, SNode* pWhere, SIntervalWindowNode* pInterval) {
if (NULL == pInterval->pFill) {
return TSDB_CODE_SUCCESS;
}
int32_t code = getTimeRange(pCxt, pWhere, &(((SFillNode*)pInterval->pFill)->timeRange));
if (TSDB_CODE_SUCCESS == code) {
code = checkFill(pCxt, pInterval);
}
return code;
}
static int64_t getMonthsFromTimeVal(int64_t val, int32_t fromPrecision, char unit) {
int64_t days = convertTimeFromPrecisionToUnit(val, fromPrecision, 'd');
switch (unit) {
......@@ -1266,7 +1374,7 @@ static int64_t getMonthsFromTimeVal(int64_t val, int32_t fromPrecision, char uni
return -1;
}
static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode* pInterval) {
static int32_t checkIntervalWindow(STranslateContext* pCxt, SNode* pWhere, SIntervalWindowNode* pInterval) {
uint8_t precision = ((SColumnNode*)pInterval->pCol)->node.resType.precision;
SValueNode* pInter = (SValueNode*)pInterval->pInterval;
......@@ -1308,7 +1416,7 @@ static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode*
}
}
return TSDB_CODE_SUCCESS;
return translateFill(pCxt, pWhere, pInterval);
}
static EDealRes checkStateExpr(SNode* pNode, void* pContext) {
......@@ -1345,28 +1453,28 @@ static int32_t checkSessionWindow(STranslateContext* pCxt, SSessionWindowNode* p
return TSDB_CODE_SUCCESS;
}
static int32_t checkWindow(STranslateContext* pCxt, SNode* pWindow) {
switch (nodeType(pWindow)) {
static int32_t checkWindow(STranslateContext* pCxt, SSelectStmt* pSelect) {
switch (nodeType(pSelect->pWindow)) {
case QUERY_NODE_STATE_WINDOW:
return checkStateWindow(pCxt, (SStateWindowNode*)pWindow);
return checkStateWindow(pCxt, (SStateWindowNode*)pSelect->pWindow);
case QUERY_NODE_SESSION_WINDOW:
return checkSessionWindow(pCxt, (SSessionWindowNode*)pWindow);
return checkSessionWindow(pCxt, (SSessionWindowNode*)pSelect->pWindow);
case QUERY_NODE_INTERVAL_WINDOW:
return checkIntervalWindow(pCxt, (SIntervalWindowNode*)pWindow);
return checkIntervalWindow(pCxt, pSelect->pWhere, (SIntervalWindowNode*)pSelect->pWindow);
default:
break;
}
return TSDB_CODE_SUCCESS;
}
static int32_t translateWindow(STranslateContext* pCxt, SNode* pWindow) {
if (NULL == pWindow) {
static int32_t translateWindow(STranslateContext* pCxt, SSelectStmt* pSelect) {
if (NULL == pSelect->pWindow) {
return TSDB_CODE_SUCCESS;
}
pCxt->currClause = SQL_CLAUSE_WINDOW;
int32_t code = translateExpr(pCxt, pWindow);
int32_t code = translateExpr(pCxt, pSelect->pWindow);
if (TSDB_CODE_SUCCESS == code) {
code = checkWindow(pCxt, pWindow);
code = checkWindow(pCxt, pSelect);
}
return code;
}
......@@ -1485,7 +1593,7 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
code = translatePartitionBy(pCxt, pSelect->pPartitionByList);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateWindow(pCxt, pSelect->pWindow);
code = translateWindow(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateGroupBy(pCxt, pSelect);
......
......@@ -128,6 +128,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "Invalid topic query";
case TSDB_CODE_PAR_INVALID_DROP_STABLE:
return "Cannot drop super table in batch";
case TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE:
return "start(end) time of query range required or time range too large";
case TSDB_CODE_OUT_OF_MEMORY:
return "Out of memory";
default:
......@@ -140,7 +142,6 @@ int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...) {
va_start(vArgList, errCode);
vsnprintf(pBuf->buf, pBuf->len, getSyntaxErrFormat(errCode), vArgList);
va_end(vArgList);
terrno = errCode;
return errCode;
}
......
......@@ -32,7 +32,7 @@ TEST_F(ParserSelectTest, basic) {
run("SELECT ts, t.c1 FROM (SELECT * FROM t1) t");
run("SELECT * FROM t1 tt1, t1 tt2 where tt1.c1 = tt2.c1");
run("SELECT * FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1");
}
TEST_F(ParserSelectTest, constant) {
......@@ -43,7 +43,7 @@ TEST_F(ParserSelectTest, constant) {
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");
run("SELECT 123 + 45 FROM t1 WHERE 2 - 1");
}
TEST_F(ParserSelectTest, expression) {
......@@ -59,9 +59,9 @@ TEST_F(ParserSelectTest, expression) {
TEST_F(ParserSelectTest, condition) {
useDb("root", "test");
run("SELECT c1 FROM t1 where ts in (true, false)");
run("SELECT c1 FROM t1 WHERE ts in (true, false)");
run("SELECT * FROM t1 where c1 > 10 and c1 is not null");
run("SELECT * FROM t1 WHERE c1 > 10 and c1 is not null");
}
TEST_F(ParserSelectTest, pseudoColumn) {
......@@ -77,7 +77,7 @@ TEST_F(ParserSelectTest, multiResFunc) {
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");
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, timelineFunc) {
......@@ -96,29 +96,29 @@ TEST_F(ParserSelectTest, clause) {
useDb("root", "test");
// group by clause
run("SELECT COUNT(*) cnt FROM t1 where c1 > 0");
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(*), 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(*) 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, 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");
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 cnt");
run("SELECT COUNT(*) cnt FROM t1 where c1 > 0 group by c2 order by 1");
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, 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, 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 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)");
// run("SELECT distinct COUNT(c2) FROM t1 WHERE c1 > 0 group by c1 order by COUNT(c2)");
}
// INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
......@@ -133,7 +133,8 @@ TEST_F(ParserSelectTest, interval) {
// INTERVAL(interval_val, interval_offset) SLIDING (sliding_val)
run("SELECT COUNT(*) FROM t1 INTERVAL(10s, 5s) SLIDING(7s)");
// INTERVAL(interval_val) FILL(NONE)
run("SELECT COUNT(*) FROM t1 INTERVAL(10s) FILL(NONE)");
run("SELECT COUNT(*) FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' "
"INTERVAL(10s) FILL(NONE)");
}
TEST_F(ParserSelectTest, semanticError) {
......@@ -152,7 +153,7 @@ TEST_F(ParserSelectTest, semanticError) {
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);
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);
......@@ -161,7 +162,7 @@ TEST_F(ParserSelectTest, semanticError) {
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 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);
......@@ -190,13 +191,13 @@ TEST_F(ParserSelectTest, semanticError) {
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,
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,
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,
run("SELECT distinct c2 FROM t1 WHERE c1 > 0 order by COUNT(c2)", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION,
PARSER_STAGE_TRANSLATE);
}
......
......@@ -21,6 +21,7 @@ extern "C" {
#endif
#include "planner.h"
#include "taoserror.h"
#define QUERY_POLICY_VNODE 1
#define QUERY_POLICY_HYBRID 2
......@@ -33,6 +34,8 @@ extern "C" {
#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__)
#define planTrace(param, ...) qTrace("PLAN: " param, __VA_ARGS__)
int32_t generateUsageErrMsg(char* pBuf, int32_t len, int32_t errCode, ...);
int32_t createLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode);
int32_t optimizeLogicPlan(SPlanContext* pCxt, SLogicNode* pLogicNode);
int32_t splitLogicPlan(SPlanContext* pCxt, SLogicNode* pLogicNode, SLogicSubplan** pLogicSubplan);
......
......@@ -597,6 +597,7 @@ static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_WINDOW, NULL, COLLECT_COL_TYPE_ALL, &pFill->node.pTargets);
pFill->mode = pFillNode->mode;
pFill->timeRange = pFillNode->timeRange;
pFill->pValues = nodesCloneNode(pFillNode->pValues);
pFill->pWStartTs = nodesCloneNode(pFillNode->pWStartTs);
if ((NULL != pFillNode->pValues && NULL == pFill->pValues) || NULL == pFill->pWStartTs) {
......
......@@ -554,22 +554,19 @@ static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
snprintf(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, "l.ts = r.ts is expected in join expression");
return TSDB_CODE_FAILED;
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
}
return TSDB_CODE_SUCCESS;
}
static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SLogicConditionNode* pOnCond) {
if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
snprintf(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, "l.ts = r.ts is expected in join expression");
return TSDB_CODE_FAILED;
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
}
SNode* pCond = NULL;
FOREACH(pCond, pOnCond->pParameterList) {
if (!cpdIsPrimaryKeyEqualCond(pJoin, pCond)) {
snprintf(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, "l.ts = r.ts is expected in join expression");
return TSDB_CODE_FAILED;
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
}
}
return TSDB_CODE_SUCCESS;
......@@ -577,8 +574,7 @@ static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin,
static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
if (NULL == pJoin->pOnConditions) {
snprintf(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, "not support cross join");
return TSDB_CODE_FAILED;
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
}
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions)) {
return cpdCheckLogicCond(pCxt, pJoin, (SLogicConditionNode*)pJoin->pOnConditions);
......
......@@ -1037,6 +1037,9 @@ static int32_t createFillPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
return TSDB_CODE_OUT_OF_MEMORY;
}
pFill->mode = pFillNode->mode;
pFill->timeRange = pFillNode->timeRange;
SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc);
int32_t code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pFillNode->node.pTargets, &pFill->pTargets);
if (TSDB_CODE_SUCCESS == code) {
......
/*
* 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 "planInt.h"
static char* getUsageErrFormat(int32_t errCode) {
switch (errCode) {
case TSDB_CODE_PLAN_EXPECTED_TS_EQUAL:
return "l.ts = r.ts is expected in join expression";
case TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN:
return "not support cross join";
default:
break;
}
return "Unknown error";
}
int32_t generateUsageErrMsg(char* pBuf, int32_t len, int32_t errCode, ...) {
va_list vArgList;
va_start(vArgList, errCode);
vsnprintf(pBuf, len, getUsageErrFormat(errCode), vArgList);
va_end(vArgList);
return errCode;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* 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.
*
......@@ -20,30 +20,32 @@ using namespace std;
class PlanBasicTest : public PlannerTestBase {};
TEST_F(PlanBasicTest, select) {
TEST_F(PlanBasicTest, selectClause) {
useDb("root", "test");
run("select * from t1");
run("select 1 from t1");
run("select * from st1");
run("select 1 from st1");
run("SELECT * FROM t1");
run("SELECT 1 FROM t1");
run("SELECT * FROM st1");
run("SELECT 1 FROM st1");
}
TEST_F(PlanBasicTest, where) {
TEST_F(PlanBasicTest, whereClause) {
useDb("root", "test");
run("select * from t1 where c1 > 10");
run("SELECT * FROM t1 WHERE c1 > 10");
run("SELECT * FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59'");
}
TEST_F(PlanBasicTest, join) {
TEST_F(PlanBasicTest, joinClause) {
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");
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");
}
TEST_F(PlanBasicTest, func) {
useDb("root", "test");
run("select diff(c1) from t1");
run("SELECT DIFF(c1) FROM t1");
}
......@@ -35,7 +35,10 @@ TEST_F(PlanIntervalTest, pseudoCol) {
TEST_F(PlanIntervalTest, fill) {
useDb("root", "test");
run("SELECT COUNT(*) FROM t1 INTERVAL(10s) FILL(LINEAR)");
run("SELECT COUNT(*) FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' "
"INTERVAL(10s) FILL(LINEAR)");
run("SELECT COUNT(*), sum(c1) FROM t1 INTERVAL(10s) FILL(VALUE, 10, 20)");
run("SELECT COUNT(*), SUM(c1) FROM t1 "
"WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' "
"INTERVAL(10s) FILL(VALUE, 10, 20)");
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册