feat: support more join type

This commit is contained in:
dapan1121 2023-11-27 20:01:00 +08:00
parent d3ac79aeb7
commit 19752b020f
15 changed files with 3351 additions and 2941 deletions

View File

@ -241,6 +241,7 @@ typedef enum ENodeType {
QUERY_NODE_EVENT_WINDOW, QUERY_NODE_EVENT_WINDOW,
QUERY_NODE_HINT, QUERY_NODE_HINT,
QUERY_NODE_VIEW, QUERY_NODE_VIEW,
QUERY_NODE_WINDOW_OFFSET,
// Statement nodes are used in parser and planner module. // Statement nodes are used in parser and planner module.
QUERY_NODE_SET_OPERATOR = 100, QUERY_NODE_SET_OPERATOR = 100,

View File

@ -284,84 +284,96 @@
#define TK_IN 265 #define TK_IN 265
#define TK_JOIN 266 #define TK_JOIN 266
#define TK_INNER 267 #define TK_INNER 267
#define TK_SELECT 268 #define TK_LEFT 268
#define TK_NK_HINT 269 #define TK_RIGHT 269
#define TK_DISTINCT 270 #define TK_FULL 270
#define TK_WHERE 271 #define TK_OUTER 271
#define TK_PARTITION 272 #define TK_SEMI 272
#define TK_BY 273 #define TK_ANTI 273
#define TK_SESSION 274 #define TK_ANY 274
#define TK_STATE_WINDOW 275 #define TK_ASOF 275
#define TK_EVENT_WINDOW 276 #define TK_WINDOW 276
#define TK_SLIDING 277 #define TK_WINDOW_OFFSET 277
#define TK_FILL 278 #define TK_JLIMIT 278
#define TK_VALUE 279 #define TK_SELECT 279
#define TK_VALUE_F 280 #define TK_NK_HINT 280
#define TK_NONE 281 #define TK_DISTINCT 281
#define TK_PREV 282 #define TK_WHERE 282
#define TK_NULL_F 283 #define TK_PARTITION 283
#define TK_LINEAR 284 #define TK_BY 284
#define TK_NEXT 285 #define TK_SESSION 285
#define TK_HAVING 286 #define TK_STATE_WINDOW 286
#define TK_RANGE 287 #define TK_EVENT_WINDOW 287
#define TK_EVERY 288 #define TK_SLIDING 288
#define TK_ORDER 289 #define TK_FILL 289
#define TK_SLIMIT 290 #define TK_VALUE 290
#define TK_SOFFSET 291 #define TK_VALUE_F 291
#define TK_LIMIT 292 #define TK_NONE 292
#define TK_OFFSET 293 #define TK_PREV 293
#define TK_ASC 294 #define TK_NULL_F 294
#define TK_NULLS 295 #define TK_LINEAR 295
#define TK_ABORT 296 #define TK_NEXT 296
#define TK_AFTER 297 #define TK_HAVING 297
#define TK_ATTACH 298 #define TK_RANGE 298
#define TK_BEFORE 299 #define TK_EVERY 299
#define TK_BEGIN 300 #define TK_ORDER 300
#define TK_BITAND 301 #define TK_SLIMIT 301
#define TK_BITNOT 302 #define TK_SOFFSET 302
#define TK_BITOR 303 #define TK_LIMIT 303
#define TK_BLOCKS 304 #define TK_OFFSET 304
#define TK_CHANGE 305 #define TK_ASC 305
#define TK_COMMA 306 #define TK_NULLS 306
#define TK_CONCAT 307 #define TK_ABORT 307
#define TK_CONFLICT 308 #define TK_AFTER 308
#define TK_COPY 309 #define TK_ATTACH 309
#define TK_DEFERRED 310 #define TK_BEFORE 310
#define TK_DELIMITERS 311 #define TK_BEGIN 311
#define TK_DETACH 312 #define TK_BITAND 312
#define TK_DIVIDE 313 #define TK_BITNOT 313
#define TK_DOT 314 #define TK_BITOR 314
#define TK_EACH 315 #define TK_BLOCKS 315
#define TK_FAIL 316 #define TK_CHANGE 316
#define TK_FILE 317 #define TK_COMMA 317
#define TK_FOR 318 #define TK_CONCAT 318
#define TK_GLOB 319 #define TK_CONFLICT 319
#define TK_ID 320 #define TK_COPY 320
#define TK_IMMEDIATE 321 #define TK_DEFERRED 321
#define TK_IMPORT 322 #define TK_DELIMITERS 322
#define TK_INITIALLY 323 #define TK_DETACH 323
#define TK_INSTEAD 324 #define TK_DIVIDE 324
#define TK_ISNULL 325 #define TK_DOT 325
#define TK_KEY 326 #define TK_EACH 326
#define TK_MODULES 327 #define TK_FAIL 327
#define TK_NK_BITNOT 328 #define TK_FILE 328
#define TK_NK_SEMI 329 #define TK_FOR 329
#define TK_NOTNULL 330 #define TK_GLOB 330
#define TK_OF 331 #define TK_ID 331
#define TK_PLUS 332 #define TK_IMMEDIATE 332
#define TK_PRIVILEGE 333 #define TK_IMPORT 333
#define TK_RAISE 334 #define TK_INITIALLY 334
#define TK_RESTRICT 335 #define TK_INSTEAD 335
#define TK_ROW 336 #define TK_ISNULL 336
#define TK_SEMI 337 #define TK_KEY 337
#define TK_STAR 338 #define TK_MODULES 338
#define TK_STATEMENT 339 #define TK_NK_BITNOT 339
#define TK_STRICT 340 #define TK_NK_SEMI 340
#define TK_STRING 341 #define TK_NOTNULL 341
#define TK_TIMES 342 #define TK_OF 342
#define TK_VALUES 343 #define TK_PLUS 343
#define TK_VARIABLE 344 #define TK_PRIVILEGE 344
#define TK_WAL 345 #define TK_RAISE 345
#define TK_RESTRICT 346
#define TK_ROW 347
#define TK_STAR 348
#define TK_STATEMENT 349
#define TK_STRICT 350
#define TK_STRING 351
#define TK_TIMES 352
#define TK_VALUES 353
#define TK_VARIABLE 354
#define TK_WAL 355

View File

@ -201,8 +201,19 @@ typedef enum EJoinType {
JOIN_TYPE_INNER = 1, JOIN_TYPE_INNER = 1,
JOIN_TYPE_LEFT, JOIN_TYPE_LEFT,
JOIN_TYPE_RIGHT, JOIN_TYPE_RIGHT,
JOIN_TYPE_FULL,
} EJoinType; } EJoinType;
typedef enum EJoinSubType {
JOIN_STYPE_NONE = 1,
JOIN_STYPE_OUTER,
JOIN_STYPE_SEMI,
JOIN_STYPE_ANTI,
JOIN_STYPE_ANY,
JOIN_STYPE_ASOF,
JOIN_STYPE_WIN,
} EJoinSubType;
typedef enum EJoinAlgorithm { typedef enum EJoinAlgorithm {
JOIN_ALGO_UNKNOWN = 0, JOIN_ALGO_UNKNOWN = 0,
JOIN_ALGO_MERGE, JOIN_ALGO_MERGE,
@ -214,13 +225,16 @@ typedef enum EDynQueryType {
} EDynQueryType; } EDynQueryType;
typedef struct SJoinTableNode { typedef struct SJoinTableNode {
STableNode table; // QUERY_NODE_JOIN_TABLE STableNode table; // QUERY_NODE_JOIN_TABLE
EJoinType joinType; EJoinType joinType;
bool hasSubQuery; EJoinSubType subType;
bool isLowLevelJoin; SNode* pWindowOffset;
SNode* pLeft; SNode* pJLimit;
SNode* pRight; bool hasSubQuery;
SNode* pOnCond; bool isLowLevelJoin;
SNode* pLeft;
SNode* pRight;
SNode* pOnCond;
} SJoinTableNode; } SJoinTableNode;
typedef enum EGroupingSetType { GP_TYPE_NORMAL = 1 } EGroupingSetType; typedef enum EGroupingSetType { GP_TYPE_NORMAL = 1 } EGroupingSetType;
@ -322,6 +336,13 @@ typedef struct SCaseWhenNode {
SNodeList* pWhenThenList; SNodeList* pWhenThenList;
} SCaseWhenNode; } SCaseWhenNode;
typedef struct SWindowOffsetNode {
ENodeType type; // QUERY_NODE_WINDOW_OFFSET
SNode* pStartOffset; // SValueNode
SNode* pEndOffset; // SValueNode
} SWindowOffsetNode;
typedef struct SSelectStmt { typedef struct SSelectStmt {
ENodeType type; // QUERY_NODE_SELECT_STMT ENodeType type; // QUERY_NODE_SELECT_STMT
bool isDistinct; bool isDistinct;
@ -560,6 +581,11 @@ const char* logicConditionTypeStr(ELogicConditionType type);
bool nodesIsStar(SNode* pNode); bool nodesIsStar(SNode* pNode);
bool nodesIsTableStar(SNode* pNode); bool nodesIsTableStar(SNode* pNode);
char* getJoinTypeString(EJoinType type);
char* getJoinSTypeString(EJoinSubType type);
char* getFullJoinTypeString(EJoinType type, EJoinSubType stype);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -259,6 +259,7 @@ static int32_t tempTableNodeCopy(const STempTableNode* pSrc, STempTableNode* pDs
static int32_t joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) { static int32_t joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) {
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy); COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
COPY_SCALAR_FIELD(joinType); COPY_SCALAR_FIELD(joinType);
COPY_SCALAR_FIELD(subType);
COPY_SCALAR_FIELD(hasSubQuery); COPY_SCALAR_FIELD(hasSubQuery);
COPY_SCALAR_FIELD(isLowLevelJoin); COPY_SCALAR_FIELD(isLowLevelJoin);
CLONE_NODE_FIELD(pLeft); CLONE_NODE_FIELD(pLeft);
@ -368,6 +369,14 @@ static int32_t hintNodeCopy(const SHintNode* pSrc, SHintNode* pDst) {
return copyHintValue(pSrc, pDst); return copyHintValue(pSrc, pDst);
} }
static int32_t windowOffsetCopy(const SWindowOffsetNode* pSrc, SWindowOffsetNode* pDst) {
COPY_SCALAR_FIELD(type);
CLONE_NODE_FIELD(pStartOffset);
CLONE_NODE_FIELD(pEndOffset);
return TSDB_CODE_SUCCESS;
}
static int32_t logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) { static int32_t logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
CLONE_NODE_LIST_FIELD(pTargets); CLONE_NODE_LIST_FIELD(pTargets);
CLONE_NODE_FIELD(pConditions); CLONE_NODE_FIELD(pConditions);
@ -851,6 +860,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
case QUERY_NODE_HINT: case QUERY_NODE_HINT:
code = hintNodeCopy((const SHintNode*)pNode, (SHintNode*)pDst); code = hintNodeCopy((const SHintNode*)pNode, (SHintNode*)pDst);
break; break;
case QUERY_NODE_WINDOW_OFFSET:
code = windowOffsetCopy((const SWindowOffsetNode*)pNode, (SWindowOffsetNode*)pDst);
break;
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
code = setOperatorCopy((const SSetOperator*)pNode, (SSetOperator*)pDst); code = setOperatorCopy((const SSetOperator*)pNode, (SSetOperator*)pDst);
break; break;

View File

@ -91,6 +91,8 @@ const char* nodesNodeName(ENodeType type) {
return "CaseWhen"; return "CaseWhen";
case QUERY_NODE_EVENT_WINDOW: case QUERY_NODE_EVENT_WINDOW:
return "EventWindow"; return "EventWindow";
case QUERY_NODE_WINDOW_OFFSET:
return "WindowOffset";
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
return "SetOperator"; return "SetOperator";
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -4125,6 +4127,7 @@ static int32_t jsonToTempTableNode(const SJson* pJson, void* pObj) {
} }
static const char* jkJoinTableJoinType = "JoinType"; static const char* jkJoinTableJoinType = "JoinType";
static const char* jkJoinTableSubType = "SubType";
static const char* jkJoinTableLeft = "Left"; static const char* jkJoinTableLeft = "Left";
static const char* jkJoinTableRight = "Right"; static const char* jkJoinTableRight = "Right";
static const char* jkJoinTableOnCond = "OnCond"; static const char* jkJoinTableOnCond = "OnCond";
@ -4136,6 +4139,9 @@ static int32_t joinTableNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinTableJoinType, pNode->joinType); code = tjsonAddIntegerToObject(pJson, jkJoinTableJoinType, pNode->joinType);
} }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinTableSubType, pNode->subType);
}
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkJoinTableLeft, nodeToJson, pNode->pLeft); code = tjsonAddObject(pJson, jkJoinTableLeft, nodeToJson, pNode->pLeft);
} }
@ -4156,6 +4162,9 @@ static int32_t jsonToJoinTableNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
tjsonGetNumberValue(pJson, jkJoinTableJoinType, pNode->joinType, code); tjsonGetNumberValue(pJson, jkJoinTableJoinType, pNode->joinType, code);
} }
if (TSDB_CODE_SUCCESS == code) {
tjsonGetNumberValue(pJson, jkJoinTableSubType, pNode->subType, code);
}
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkJoinTableLeft, &pNode->pLeft); code = jsonToNodeObject(pJson, jkJoinTableLeft, &pNode->pLeft);
} }
@ -4608,6 +4617,29 @@ static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) {
return code; return code;
} }
static const char* jkWindowOffsetStartOffset = "StartOffset";
static const char* jkWindowOffsetEndOffset = "EndOffset";
static int32_t windowOffsetNodeToJson(const void* pObj, SJson* pJson) {
const SWindowOffsetNode* pNode = (const SWindowOffsetNode*)pObj;
int32_t code = tjsonAddObject(pJson, jkWindowOffsetStartOffset, nodeToJson, pNode->pStartOffset);
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkWindowOffsetEndOffset, nodeToJson, pNode->pEndOffset);
}
return code;
}
static int32_t jsonToWindowOffsetNode(const SJson* pJson, void* pObj) {
SWindowOffsetNode* pNode = (SWindowOffsetNode*)pObj;
int32_t code = jsonToNodeObject(pJson, jkWindowOffsetStartOffset, &pNode->pStartOffset);
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkWindowOffsetEndOffset, &pNode->pEndOffset);
}
return code;
}
static const char* jkDatabaseOptionsBuffer = "Buffer"; static const char* jkDatabaseOptionsBuffer = "Buffer";
static const char* jkDatabaseOptionsCacheModel = "CacheModel"; static const char* jkDatabaseOptionsCacheModel = "CacheModel";
static const char* jkDatabaseOptionsCompressionLevel = "CompressionLevel"; static const char* jkDatabaseOptionsCompressionLevel = "CompressionLevel";
@ -6867,6 +6899,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return caseWhenNodeToJson(pObj, pJson); return caseWhenNodeToJson(pObj, pJson);
case QUERY_NODE_EVENT_WINDOW: case QUERY_NODE_EVENT_WINDOW:
return eventWindowNodeToJson(pObj, pJson); return eventWindowNodeToJson(pObj, pJson);
case QUERY_NODE_WINDOW_OFFSET:
return windowOffsetNodeToJson(pObj, pJson);
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
return setOperatorToJson(pObj, pJson); return setOperatorToJson(pObj, pJson);
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -7190,6 +7224,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToCaseWhenNode(pJson, pObj); return jsonToCaseWhenNode(pJson, pObj);
case QUERY_NODE_EVENT_WINDOW: case QUERY_NODE_EVENT_WINDOW:
return jsonToEventWindowNode(pJson, pObj); return jsonToEventWindowNode(pJson, pObj);
case QUERY_NODE_WINDOW_OFFSET:
return jsonToWindowOffsetNode(pJson, pObj);
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
return jsonToSetOperator(pJson, pObj); return jsonToSetOperator(pJson, pObj);
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:

View File

@ -366,6 +366,14 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
} }
break; break;
} }
case QUERY_NODE_WINDOW_OFFSET: {
SWindowOffsetNode* pWin = (SWindowOffsetNode*)pNode;
res = rewriteExpr(&pWin->pStartOffset, order, rewriter, pContext);
if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
res = rewriteExpr(&pWin->pEndOffset, order, rewriter, pContext);
}
break;
}
default: default:
break; break;
} }

View File

@ -44,6 +44,27 @@ typedef struct SNodeAllocator {
static threadlocal SNodeAllocator* g_pNodeAllocator; static threadlocal SNodeAllocator* g_pNodeAllocator;
static int32_t g_allocatorReqRefPool = -1; static int32_t g_allocatorReqRefPool = -1;
char* getJoinTypeString(EJoinType type) {
static char* joinType[] = {"", "INNER", "LEFT", "RIGHT", "FULL"};
return joinType[type];
}
char* getJoinSTypeString(EJoinSubType type) {
static char* joinSType[] = {"", "", "OUTER", "SEMI", "ANTI", "ANY", "ASOF", "WINDOW"};
return joinSType[type];
}
char* getFullJoinTypeString(EJoinType type, EJoinSubType stype) {
static char* joinFullType[][8] = {
{},
{"INNER", "INNER", "INNER", "INNER", "INNER", "INNER ANY", "INNER", "INNER"},
{"LEFT", "LEFT", "LEFT OUTER", "LEFT SEMI", "LEFT ANTI", "LEFT ANY", "LEFT ASOF", "LEFT WINDOW"},
{"RIGHT", "RIGHT", "RIGHT OUTER", "RIGHT SEMI", "RIGHT ANTI", "RIGHT ANY", "RIGHT ASOF", "RIGHT WINDOW"},
{"FULL", "FULL", "FULL OUTER", "FULL", "FULL", "FULL ANY", "FULL", "FULL"}
};
return joinFullType[type][stype];
}
static SNodeMemChunk* callocNodeChunk(SNodeAllocator* pAllocator) { static SNodeMemChunk* callocNodeChunk(SNodeAllocator* pAllocator) {
SNodeMemChunk* pNewChunk = taosMemoryCalloc(1, sizeof(SNodeMemChunk) + pAllocator->chunkSize); SNodeMemChunk* pNewChunk = taosMemoryCalloc(1, sizeof(SNodeMemChunk) + pAllocator->chunkSize);
if (NULL == pNewChunk) { if (NULL == pNewChunk) {
@ -306,6 +327,8 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SHintNode)); return makeNode(type, sizeof(SHintNode));
case QUERY_NODE_VIEW: case QUERY_NODE_VIEW:
return makeNode(type, sizeof(SViewNode)); return makeNode(type, sizeof(SViewNode));
case QUERY_NODE_WINDOW_OFFSET:
return makeNode(type, sizeof(SWindowOffsetNode));
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
return makeNode(type, sizeof(SSetOperator)); return makeNode(type, sizeof(SSetOperator));
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -848,6 +871,12 @@ void nodesDestroyNode(SNode* pNode) {
taosArrayDestroyEx(pView->pSmaIndexes, destroySmaIndex); taosArrayDestroyEx(pView->pSmaIndexes, destroySmaIndex);
break; break;
} }
case QUERY_NODE_WINDOW_OFFSET: {
SWindowOffsetNode* pWin = (SWindowOffsetNode*)pNode;
nodesDestroyNode(pWin->pStartOffset);
nodesDestroyNode(pWin->pEndOffset);
break;
}
case QUERY_NODE_SET_OPERATOR: { case QUERY_NODE_SET_OPERATOR: {
SSetOperator* pStmt = (SSetOperator*)pNode; SSetOperator* pStmt = (SSetOperator*)pNode;
nodesDestroyList(pStmt->pProjectionList); nodesDestroyList(pStmt->pProjectionList);

View File

@ -124,7 +124,7 @@ SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2); SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2);
SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias); SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias);
SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias); SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias);
SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, SNode* pLeft, SNode* pRight, SNode* pJoinCond); SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight, SNode* pJoinCond);
SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName); SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName);
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset); SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset);
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder); SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder);
@ -133,6 +133,7 @@ SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr);
SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond); SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond);
SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding,
SNode* pFill); SNode* pFill);
SNode* createWindowOffsetNode(SAstCreateContext* pCxt, SNode* pStartOffset, SNode* pEndOffset);
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues); SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues);
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode); SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode);
SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd); SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd);
@ -151,6 +152,8 @@ SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit);
SNode* addRangeClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pRange); SNode* addRangeClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pRange);
SNode* addEveryClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pEvery); SNode* addEveryClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pEvery);
SNode* addFillClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pFill); SNode* addFillClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pFill);
SNode* addJLimitClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pJLimit);
SNode* addWindowOffsetClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pWinOffset);
SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable, SNodeList* pHint); SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable, SNodeList* pHint);
SNode* setSelectStmtTagMode(SAstCreateContext* pCxt, SNode* pStmt, bool bSelectTags); SNode* setSelectStmtTagMode(SAstCreateContext* pCxt, SNode* pStmt, bool bSelectTags);
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight); SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight);

View File

@ -77,6 +77,7 @@ typedef struct SParseMetaCache {
int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...); int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...);
int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...); int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...);
int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg); int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg);
int32_t buildInvalidOperationMsgExt(SMsgBuf* pBuf, const char* pFormat, ...);
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr);
SSchema* getTableColumnSchema(const STableMeta* pTableMeta); SSchema* getTableColumnSchema(const STableMeta* pTableMeta);

View File

@ -1047,7 +1047,7 @@ from_clause_opt(A) ::= .
from_clause_opt(A) ::= FROM table_reference_list(B). { A = B; } from_clause_opt(A) ::= FROM table_reference_list(B). { A = B; }
table_reference_list(A) ::= table_reference(B). { A = B; } table_reference_list(A) ::= table_reference(B). { A = B; }
table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, B, C, NULL); } table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, JOIN_STYPE_NONE, B, C, NULL); }
/************************************************ table_reference *****************************************************/ /************************************************ table_reference *****************************************************/
table_reference(A) ::= table_primary(B). { A = B; } table_reference(A) ::= table_primary(B). { A = B; }
@ -1069,12 +1069,40 @@ parenthesized_joined_table(A) ::= NK_LP parenthesized_joined_table(B) NK_RP.
/************************************************ joined_table ********************************************************/ /************************************************ joined_table ********************************************************/
joined_table(A) ::= joined_table(A) ::=
table_reference(B) join_type(C) JOIN table_reference(D) ON search_condition(E). { A = createJoinTableNode(pCxt, C, B, D, E); } table_reference(B) join_type(C) join_subtype(D) JOIN table_reference(E) ON search_condition(F)
window_offset_clause_opt(G) jlimit_clause_opt(H). {
A = createJoinTableNode(pCxt, C, D, B, E, F);
A = addWindowOffsetClause(pCxt, A, G);
A = addJLimitClause(pCxt, A, H);
}
%type join_type { EJoinType } %type join_type { EJoinType }
%destructor join_type { } %destructor join_type { }
join_type(A) ::= . { A = JOIN_TYPE_INNER; } join_type(A) ::= . { A = JOIN_TYPE_INNER; }
join_type(A) ::= INNER. { A = JOIN_TYPE_INNER; } join_type(A) ::= INNER. { A = JOIN_TYPE_INNER; }
join_type(A) ::= LEFT. { A = JOIN_TYPE_LEFT; }
join_type(A) ::= RIGHT. { A = JOIN_TYPE_RIGHT; }
join_type(A) ::= FULL. { A = JOIN_TYPE_FULL; }
%type join_subtype { EJoinSubType }
%destructor join_subtype { }
join_subtype(A) ::= . { A = JOIN_STYPE_NONE; }
join_subtype(A) ::= OUTER. { A = JOIN_STYPE_OUTER; }
join_subtype(A) ::= SEMI. { A = JOIN_STYPE_SEMI; }
join_subtype(A) ::= ANTI. { A = JOIN_STYPE_ANTI; }
join_subtype(A) ::= ANY. { A = JOIN_STYPE_ANY; }
join_subtype(A) ::= ASOF. { A = JOIN_STYPE_ASOF; }
join_subtype(A) ::= WINDOW. { A = JOIN_STYPE_WIN; }
window_offset_clause_opt(A) ::= . { A = NULL; }
window_offset_clause_opt(A) ::= WINDOW_OFFSET NK_LP window_offset_literal(B)
NK_COMMA window_offset_literal(C) NK_RP. { A = createWindowOffsetNode(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); }
window_offset_literal(A) ::= NK_VARIABLE(B). { A = createRawExprNode(pCxt, &B, createDurationValueNode(pCxt, &B)); }
window_offset_literal(A) ::= NK_INTEGER(B). { A = createRawExprNode(pCxt, &B, createDurationValueNode(pCxt, &B)); }
jlimit_clause_opt(A) ::= . { A = NULL; }
jlimit_clause_opt(A) ::= JLIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); }
/************************************************ query_specification *************************************************/ /************************************************ query_specification *************************************************/
query_specification(A) ::= query_specification(A) ::=

View File

@ -771,11 +771,12 @@ SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const STok
return (SNode*)tempTable; return (SNode*)tempTable;
} }
SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, SNode* pLeft, SNode* pRight, SNode* pJoinCond) { SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight, SNode* pJoinCond) {
CHECK_PARSER_STATUS(pCxt); CHECK_PARSER_STATUS(pCxt);
SJoinTableNode* joinTable = (SJoinTableNode*)nodesMakeNode(QUERY_NODE_JOIN_TABLE); SJoinTableNode* joinTable = (SJoinTableNode*)nodesMakeNode(QUERY_NODE_JOIN_TABLE);
CHECK_OUT_OF_MEM(joinTable); CHECK_OUT_OF_MEM(joinTable);
joinTable->joinType = type; joinTable->joinType = type;
joinTable->subType = stype;
joinTable->pLeft = pLeft; joinTable->pLeft = pLeft;
joinTable->pRight = pRight; joinTable->pRight = pRight;
joinTable->pOnCond = pJoinCond; joinTable->pOnCond = pJoinCond;
@ -876,6 +877,15 @@ SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode
return (SNode*)interval; return (SNode*)interval;
} }
SNode* createWindowOffsetNode(SAstCreateContext* pCxt, SNode* pStartOffset, SNode* pEndOffset) {
CHECK_PARSER_STATUS(pCxt);
SWindowOffsetNode* winOffset = (SWindowOffsetNode*)nodesMakeNode(QUERY_NODE_WINDOW_OFFSET);
CHECK_OUT_OF_MEM(winOffset);
winOffset->pStartOffset = pStartOffset;
winOffset->pEndOffset = pEndOffset;
return (SNode*)winOffset;
}
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) { SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) {
CHECK_PARSER_STATUS(pCxt); CHECK_PARSER_STATUS(pCxt);
SFillNode* fill = (SFillNode*)nodesMakeNode(QUERY_NODE_FILL); SFillNode* fill = (SFillNode*)nodesMakeNode(QUERY_NODE_FILL);
@ -1047,6 +1057,31 @@ SNode* addFillClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pFill) {
return pStmt; return pStmt;
} }
SNode* addJLimitClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pJLimit) {
CHECK_PARSER_STATUS(pCxt);
if (NULL == pJLimit) {
return pJoin;
}
SJoinTableNode* pJoinNode = (SJoinTableNode*)pJoin;
pJoinNode->pJLimit = pJLimit;
return pJoin;
}
SNode* addWindowOffsetClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pWinOffset) {
CHECK_PARSER_STATUS(pCxt);
if (NULL == pWinOffset) {
return pJoin;
}
SJoinTableNode* pJoinNode = (SJoinTableNode*)pJoin;
pJoinNode->pWindowOffset = pWinOffset;
return pJoin;
}
SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable, SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable,
SNodeList* pHint) { SNodeList* pHint) {
CHECK_PARSER_STATUS(pCxt); CHECK_PARSER_STATUS(pCxt);

View File

@ -37,9 +37,12 @@ static SKeyword keywordTable[] = {
{"ALTER", TK_ALTER}, {"ALTER", TK_ALTER},
{"ANALYZE", TK_ANALYZE}, {"ANALYZE", TK_ANALYZE},
{"AND", TK_AND}, {"AND", TK_AND},
{"ANTI", TK_ANTI},
{"ANY", TK_ANY},
{"APPS", TK_APPS}, {"APPS", TK_APPS},
{"AS", TK_AS}, {"AS", TK_AS},
{"ASC", TK_ASC}, {"ASC", TK_ASC},
{"ASOF", TK_ASOF},
{"AT_ONCE", TK_AT_ONCE}, {"AT_ONCE", TK_AT_ONCE},
{"BALANCE", TK_BALANCE}, {"BALANCE", TK_BALANCE},
{"BATCH_SCAN", TK_BATCH_SCAN}, {"BATCH_SCAN", TK_BATCH_SCAN},
@ -103,6 +106,7 @@ static SKeyword keywordTable[] = {
{"FLUSH", TK_FLUSH}, {"FLUSH", TK_FLUSH},
{"FROM", TK_FROM}, {"FROM", TK_FROM},
{"FORCE", TK_FORCE}, {"FORCE", TK_FORCE},
{"FULL", TK_FULL},
{"FUNCTION", TK_FUNCTION}, {"FUNCTION", TK_FUNCTION},
{"FUNCTIONS", TK_FUNCTIONS}, {"FUNCTIONS", TK_FUNCTIONS},
{"GEOMETRY", TK_GEOMETRY}, {"GEOMETRY", TK_GEOMETRY},
@ -124,6 +128,7 @@ static SKeyword keywordTable[] = {
{"INTERVAL", TK_INTERVAL}, {"INTERVAL", TK_INTERVAL},
{"INTO", TK_INTO}, {"INTO", TK_INTO},
{"IS", TK_IS}, {"IS", TK_IS},
{"JLIMIT", TK_JLIMIT},
{"JOIN", TK_JOIN}, {"JOIN", TK_JOIN},
{"JSON", TK_JSON}, {"JSON", TK_JSON},
{"KEEP", TK_KEEP}, {"KEEP", TK_KEEP},
@ -132,6 +137,7 @@ static SKeyword keywordTable[] = {
{"LAST", TK_LAST}, {"LAST", TK_LAST},
{"LAST_ROW", TK_LAST_ROW}, {"LAST_ROW", TK_LAST_ROW},
{"LEADER", TK_LEADER}, {"LEADER", TK_LEADER},
{"LEFT", TK_LEFT},
{"LICENCES", TK_LICENCES}, {"LICENCES", TK_LICENCES},
{"LIKE", TK_LIKE}, {"LIKE", TK_LIKE},
{"LIMIT", TK_LIMIT}, {"LIMIT", TK_LIMIT},
@ -165,6 +171,7 @@ static SKeyword keywordTable[] = {
{"ON", TK_ON}, {"ON", TK_ON},
{"OR", TK_OR}, {"OR", TK_OR},
{"ORDER", TK_ORDER}, {"ORDER", TK_ORDER},
{"OUTER", TK_OUTER},
{"OUTPUTTYPE", TK_OUTPUTTYPE}, {"OUTPUTTYPE", TK_OUTPUTTYPE},
{"PAGES", TK_PAGES}, {"PAGES", TK_PAGES},
{"PAGESIZE", TK_PAGESIZE}, {"PAGESIZE", TK_PAGESIZE},
@ -193,10 +200,12 @@ static SKeyword keywordTable[] = {
{"RESTORE", TK_RESTORE}, {"RESTORE", TK_RESTORE},
{"RETENTIONS", TK_RETENTIONS}, {"RETENTIONS", TK_RETENTIONS},
{"REVOKE", TK_REVOKE}, {"REVOKE", TK_REVOKE},
{"RIGHT", TK_RIGHT},
{"ROLLUP", TK_ROLLUP}, {"ROLLUP", TK_ROLLUP},
{"SCHEMALESS", TK_SCHEMALESS}, {"SCHEMALESS", TK_SCHEMALESS},
{"SCORES", TK_SCORES}, {"SCORES", TK_SCORES},
{"SELECT", TK_SELECT}, {"SELECT", TK_SELECT},
{"SEMI", TK_SEMI},
{"SERVER_STATUS", TK_SERVER_STATUS}, {"SERVER_STATUS", TK_SERVER_STATUS},
{"SERVER_VERSION", TK_SERVER_VERSION}, {"SERVER_VERSION", TK_SERVER_VERSION},
{"SESSION", TK_SESSION}, {"SESSION", TK_SESSION},
@ -279,7 +288,9 @@ static SKeyword keywordTable[] = {
{"WATERMARK", TK_WATERMARK}, {"WATERMARK", TK_WATERMARK},
{"WHEN", TK_WHEN}, {"WHEN", TK_WHEN},
{"WHERE", TK_WHERE}, {"WHERE", TK_WHERE},
{"WINDOW", TK_WINDOW},
{"WINDOW_CLOSE", TK_WINDOW_CLOSE}, {"WINDOW_CLOSE", TK_WINDOW_CLOSE},
{"WINDOW_OFFSET", TK_WINDOW_OFFSET},
{"WITH", TK_WITH}, {"WITH", TK_WITH},
{"WRITE", TK_WRITE}, {"WRITE", TK_WRITE},
{"_C0", TK_ROWTS}, {"_C0", TK_ROWTS},

View File

@ -2913,6 +2913,41 @@ static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTabl
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t translateJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) {
EJoinType type = pJoinTable->joinType;
EJoinSubType* pSType = &pJoinTable->subType;
switch (type) {
case JOIN_TYPE_INNER:
if (*pSType == JOIN_STYPE_OUTER || *pSType == JOIN_STYPE_SEMI || *pSType == JOIN_STYPE_ANTI || *pSType == JOIN_STYPE_ASOF || *pSType == JOIN_STYPE_WIN) {
return buildInvalidOperationMsg(&pCxt->msgBuf, "not supported join type");
}
break;
case JOIN_TYPE_FULL:
if (*pSType == JOIN_STYPE_SEMI || *pSType == JOIN_STYPE_ANTI || *pSType == JOIN_STYPE_ASOF || *pSType == JOIN_STYPE_WIN) {
return buildInvalidOperationMsg(&pCxt->msgBuf, "not supported join type");
}
//fall down
default:
if (*pSType == JOIN_STYPE_NONE) {
*pSType = JOIN_STYPE_OUTER;
}
break;
}
if (NULL != pJoinTable->pWindowOffset && *pSType != JOIN_STYPE_WIN) {
return buildInvalidOperationMsg(&pCxt->msgBuf, "WINDOW_OFFSET only supported for WINDOW join");
}
if (NULL == pJoinTable->pWindowOffset && *pSType == JOIN_STYPE_WIN) {
return buildInvalidOperationMsg(&pCxt->msgBuf, "WINDOW_OFFSET required for WINDOW join");
}
if (NULL != pJoinTable->pJLimit && *pSType != JOIN_STYPE_ASOF && *pSType != JOIN_STYPE_WIN) {
return buildInvalidOperationMsgExt(&pCxt->msgBuf, "JLIMIT not supported for %s join", getFullJoinTypeString(type, *pSType));
}
return TSDB_CODE_SUCCESS;
}
int32_t translateTable(STranslateContext* pCxt, SNode** pTable) { int32_t translateTable(STranslateContext* pCxt, SNode** pTable) {
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(*pTable)) { switch (nodeType(*pTable)) {
@ -2973,7 +3008,10 @@ int32_t translateTable(STranslateContext* pCxt, SNode** pTable) {
} }
case QUERY_NODE_JOIN_TABLE: { case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* pJoinTable = (SJoinTableNode*)*pTable; SJoinTableNode* pJoinTable = (SJoinTableNode*)*pTable;
code = translateTable(pCxt, &pJoinTable->pLeft); code = translateJoinTable(pCxt, pJoinTable);
if (TSDB_CODE_SUCCESS == code) {
code = translateTable(pCxt, &pJoinTable->pLeft);
}
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = translateTable(pCxt, &pJoinTable->pRight); code = translateTable(pCxt, &pJoinTable->pRight);
} }

View File

@ -216,6 +216,15 @@ int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
} }
int32_t buildInvalidOperationMsgExt(SMsgBuf* pBuf, const char* pFormat, ...) {
va_list vArgList;
va_start(vArgList, pFormat);
vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
va_end(vArgList);
return TSDB_CODE_TSC_INVALID_OPERATION;
}
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) { int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) {
if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
const char* msgFormat1 = "syntax error near \'%s\'"; const char* msgFormat1 = "syntax error near \'%s\'";

File diff suppressed because it is too large Load Diff