feat: support more join type
This commit is contained in:
parent
d3ac79aeb7
commit
19752b020f
|
@ -241,6 +241,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_EVENT_WINDOW,
|
||||
QUERY_NODE_HINT,
|
||||
QUERY_NODE_VIEW,
|
||||
QUERY_NODE_WINDOW_OFFSET,
|
||||
|
||||
// Statement nodes are used in parser and planner module.
|
||||
QUERY_NODE_SET_OPERATOR = 100,
|
||||
|
|
|
@ -284,84 +284,96 @@
|
|||
#define TK_IN 265
|
||||
#define TK_JOIN 266
|
||||
#define TK_INNER 267
|
||||
#define TK_SELECT 268
|
||||
#define TK_NK_HINT 269
|
||||
#define TK_DISTINCT 270
|
||||
#define TK_WHERE 271
|
||||
#define TK_PARTITION 272
|
||||
#define TK_BY 273
|
||||
#define TK_SESSION 274
|
||||
#define TK_STATE_WINDOW 275
|
||||
#define TK_EVENT_WINDOW 276
|
||||
#define TK_SLIDING 277
|
||||
#define TK_FILL 278
|
||||
#define TK_VALUE 279
|
||||
#define TK_VALUE_F 280
|
||||
#define TK_NONE 281
|
||||
#define TK_PREV 282
|
||||
#define TK_NULL_F 283
|
||||
#define TK_LINEAR 284
|
||||
#define TK_NEXT 285
|
||||
#define TK_HAVING 286
|
||||
#define TK_RANGE 287
|
||||
#define TK_EVERY 288
|
||||
#define TK_ORDER 289
|
||||
#define TK_SLIMIT 290
|
||||
#define TK_SOFFSET 291
|
||||
#define TK_LIMIT 292
|
||||
#define TK_OFFSET 293
|
||||
#define TK_ASC 294
|
||||
#define TK_NULLS 295
|
||||
#define TK_ABORT 296
|
||||
#define TK_AFTER 297
|
||||
#define TK_ATTACH 298
|
||||
#define TK_BEFORE 299
|
||||
#define TK_BEGIN 300
|
||||
#define TK_BITAND 301
|
||||
#define TK_BITNOT 302
|
||||
#define TK_BITOR 303
|
||||
#define TK_BLOCKS 304
|
||||
#define TK_CHANGE 305
|
||||
#define TK_COMMA 306
|
||||
#define TK_CONCAT 307
|
||||
#define TK_CONFLICT 308
|
||||
#define TK_COPY 309
|
||||
#define TK_DEFERRED 310
|
||||
#define TK_DELIMITERS 311
|
||||
#define TK_DETACH 312
|
||||
#define TK_DIVIDE 313
|
||||
#define TK_DOT 314
|
||||
#define TK_EACH 315
|
||||
#define TK_FAIL 316
|
||||
#define TK_FILE 317
|
||||
#define TK_FOR 318
|
||||
#define TK_GLOB 319
|
||||
#define TK_ID 320
|
||||
#define TK_IMMEDIATE 321
|
||||
#define TK_IMPORT 322
|
||||
#define TK_INITIALLY 323
|
||||
#define TK_INSTEAD 324
|
||||
#define TK_ISNULL 325
|
||||
#define TK_KEY 326
|
||||
#define TK_MODULES 327
|
||||
#define TK_NK_BITNOT 328
|
||||
#define TK_NK_SEMI 329
|
||||
#define TK_NOTNULL 330
|
||||
#define TK_OF 331
|
||||
#define TK_PLUS 332
|
||||
#define TK_PRIVILEGE 333
|
||||
#define TK_RAISE 334
|
||||
#define TK_RESTRICT 335
|
||||
#define TK_ROW 336
|
||||
#define TK_SEMI 337
|
||||
#define TK_STAR 338
|
||||
#define TK_STATEMENT 339
|
||||
#define TK_STRICT 340
|
||||
#define TK_STRING 341
|
||||
#define TK_TIMES 342
|
||||
#define TK_VALUES 343
|
||||
#define TK_VARIABLE 344
|
||||
#define TK_WAL 345
|
||||
#define TK_LEFT 268
|
||||
#define TK_RIGHT 269
|
||||
#define TK_FULL 270
|
||||
#define TK_OUTER 271
|
||||
#define TK_SEMI 272
|
||||
#define TK_ANTI 273
|
||||
#define TK_ANY 274
|
||||
#define TK_ASOF 275
|
||||
#define TK_WINDOW 276
|
||||
#define TK_WINDOW_OFFSET 277
|
||||
#define TK_JLIMIT 278
|
||||
#define TK_SELECT 279
|
||||
#define TK_NK_HINT 280
|
||||
#define TK_DISTINCT 281
|
||||
#define TK_WHERE 282
|
||||
#define TK_PARTITION 283
|
||||
#define TK_BY 284
|
||||
#define TK_SESSION 285
|
||||
#define TK_STATE_WINDOW 286
|
||||
#define TK_EVENT_WINDOW 287
|
||||
#define TK_SLIDING 288
|
||||
#define TK_FILL 289
|
||||
#define TK_VALUE 290
|
||||
#define TK_VALUE_F 291
|
||||
#define TK_NONE 292
|
||||
#define TK_PREV 293
|
||||
#define TK_NULL_F 294
|
||||
#define TK_LINEAR 295
|
||||
#define TK_NEXT 296
|
||||
#define TK_HAVING 297
|
||||
#define TK_RANGE 298
|
||||
#define TK_EVERY 299
|
||||
#define TK_ORDER 300
|
||||
#define TK_SLIMIT 301
|
||||
#define TK_SOFFSET 302
|
||||
#define TK_LIMIT 303
|
||||
#define TK_OFFSET 304
|
||||
#define TK_ASC 305
|
||||
#define TK_NULLS 306
|
||||
#define TK_ABORT 307
|
||||
#define TK_AFTER 308
|
||||
#define TK_ATTACH 309
|
||||
#define TK_BEFORE 310
|
||||
#define TK_BEGIN 311
|
||||
#define TK_BITAND 312
|
||||
#define TK_BITNOT 313
|
||||
#define TK_BITOR 314
|
||||
#define TK_BLOCKS 315
|
||||
#define TK_CHANGE 316
|
||||
#define TK_COMMA 317
|
||||
#define TK_CONCAT 318
|
||||
#define TK_CONFLICT 319
|
||||
#define TK_COPY 320
|
||||
#define TK_DEFERRED 321
|
||||
#define TK_DELIMITERS 322
|
||||
#define TK_DETACH 323
|
||||
#define TK_DIVIDE 324
|
||||
#define TK_DOT 325
|
||||
#define TK_EACH 326
|
||||
#define TK_FAIL 327
|
||||
#define TK_FILE 328
|
||||
#define TK_FOR 329
|
||||
#define TK_GLOB 330
|
||||
#define TK_ID 331
|
||||
#define TK_IMMEDIATE 332
|
||||
#define TK_IMPORT 333
|
||||
#define TK_INITIALLY 334
|
||||
#define TK_INSTEAD 335
|
||||
#define TK_ISNULL 336
|
||||
#define TK_KEY 337
|
||||
#define TK_MODULES 338
|
||||
#define TK_NK_BITNOT 339
|
||||
#define TK_NK_SEMI 340
|
||||
#define TK_NOTNULL 341
|
||||
#define TK_OF 342
|
||||
#define TK_PLUS 343
|
||||
#define TK_PRIVILEGE 344
|
||||
#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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -201,8 +201,19 @@ typedef enum EJoinType {
|
|||
JOIN_TYPE_INNER = 1,
|
||||
JOIN_TYPE_LEFT,
|
||||
JOIN_TYPE_RIGHT,
|
||||
JOIN_TYPE_FULL,
|
||||
} 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 {
|
||||
JOIN_ALGO_UNKNOWN = 0,
|
||||
JOIN_ALGO_MERGE,
|
||||
|
@ -214,13 +225,16 @@ typedef enum EDynQueryType {
|
|||
} EDynQueryType;
|
||||
|
||||
typedef struct SJoinTableNode {
|
||||
STableNode table; // QUERY_NODE_JOIN_TABLE
|
||||
EJoinType joinType;
|
||||
bool hasSubQuery;
|
||||
bool isLowLevelJoin;
|
||||
SNode* pLeft;
|
||||
SNode* pRight;
|
||||
SNode* pOnCond;
|
||||
STableNode table; // QUERY_NODE_JOIN_TABLE
|
||||
EJoinType joinType;
|
||||
EJoinSubType subType;
|
||||
SNode* pWindowOffset;
|
||||
SNode* pJLimit;
|
||||
bool hasSubQuery;
|
||||
bool isLowLevelJoin;
|
||||
SNode* pLeft;
|
||||
SNode* pRight;
|
||||
SNode* pOnCond;
|
||||
} SJoinTableNode;
|
||||
|
||||
typedef enum EGroupingSetType { GP_TYPE_NORMAL = 1 } EGroupingSetType;
|
||||
|
@ -322,6 +336,13 @@ typedef struct SCaseWhenNode {
|
|||
SNodeList* pWhenThenList;
|
||||
} SCaseWhenNode;
|
||||
|
||||
typedef struct SWindowOffsetNode {
|
||||
ENodeType type; // QUERY_NODE_WINDOW_OFFSET
|
||||
SNode* pStartOffset; // SValueNode
|
||||
SNode* pEndOffset; // SValueNode
|
||||
} SWindowOffsetNode;
|
||||
|
||||
|
||||
typedef struct SSelectStmt {
|
||||
ENodeType type; // QUERY_NODE_SELECT_STMT
|
||||
bool isDistinct;
|
||||
|
@ -560,6 +581,11 @@ const char* logicConditionTypeStr(ELogicConditionType type);
|
|||
bool nodesIsStar(SNode* pNode);
|
||||
bool nodesIsTableStar(SNode* pNode);
|
||||
|
||||
char* getJoinTypeString(EJoinType type);
|
||||
char* getJoinSTypeString(EJoinSubType type);
|
||||
char* getFullJoinTypeString(EJoinType type, EJoinSubType stype);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -259,6 +259,7 @@ static int32_t tempTableNodeCopy(const STempTableNode* pSrc, STempTableNode* pDs
|
|||
static int32_t joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
|
||||
COPY_SCALAR_FIELD(joinType);
|
||||
COPY_SCALAR_FIELD(subType);
|
||||
COPY_SCALAR_FIELD(hasSubQuery);
|
||||
COPY_SCALAR_FIELD(isLowLevelJoin);
|
||||
CLONE_NODE_FIELD(pLeft);
|
||||
|
@ -368,6 +369,14 @@ static int32_t hintNodeCopy(const SHintNode* pSrc, SHintNode* 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) {
|
||||
CLONE_NODE_LIST_FIELD(pTargets);
|
||||
CLONE_NODE_FIELD(pConditions);
|
||||
|
@ -851,6 +860,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
|||
case QUERY_NODE_HINT:
|
||||
code = hintNodeCopy((const SHintNode*)pNode, (SHintNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_WINDOW_OFFSET:
|
||||
code = windowOffsetCopy((const SWindowOffsetNode*)pNode, (SWindowOffsetNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
code = setOperatorCopy((const SSetOperator*)pNode, (SSetOperator*)pDst);
|
||||
break;
|
||||
|
|
|
@ -91,6 +91,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "CaseWhen";
|
||||
case QUERY_NODE_EVENT_WINDOW:
|
||||
return "EventWindow";
|
||||
case QUERY_NODE_WINDOW_OFFSET:
|
||||
return "WindowOffset";
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return "SetOperator";
|
||||
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* jkJoinTableSubType = "SubType";
|
||||
static const char* jkJoinTableLeft = "Left";
|
||||
static const char* jkJoinTableRight = "Right";
|
||||
static const char* jkJoinTableOnCond = "OnCond";
|
||||
|
@ -4136,6 +4139,9 @@ static int32_t joinTableNodeToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddIntegerToObject(pJson, jkJoinTableJoinType, pNode->joinType);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddIntegerToObject(pJson, jkJoinTableSubType, pNode->subType);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
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) {
|
||||
tjsonGetNumberValue(pJson, jkJoinTableJoinType, pNode->joinType, code);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
tjsonGetNumberValue(pJson, jkJoinTableSubType, pNode->subType, code);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkJoinTableLeft, &pNode->pLeft);
|
||||
}
|
||||
|
@ -4608,6 +4617,29 @@ static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) {
|
|||
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* jkDatabaseOptionsCacheModel = "CacheModel";
|
||||
static const char* jkDatabaseOptionsCompressionLevel = "CompressionLevel";
|
||||
|
@ -6867,6 +6899,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return caseWhenNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_EVENT_WINDOW:
|
||||
return eventWindowNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_WINDOW_OFFSET:
|
||||
return windowOffsetNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return setOperatorToJson(pObj, pJson);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -7190,6 +7224,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToCaseWhenNode(pJson, pObj);
|
||||
case QUERY_NODE_EVENT_WINDOW:
|
||||
return jsonToEventWindowNode(pJson, pObj);
|
||||
case QUERY_NODE_WINDOW_OFFSET:
|
||||
return jsonToWindowOffsetNode(pJson, pObj);
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return jsonToSetOperator(pJson, pObj);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
|
|
@ -366,6 +366,14 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
|
|||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,27 @@ typedef struct SNodeAllocator {
|
|||
static threadlocal SNodeAllocator* g_pNodeAllocator;
|
||||
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) {
|
||||
SNodeMemChunk* pNewChunk = taosMemoryCalloc(1, sizeof(SNodeMemChunk) + pAllocator->chunkSize);
|
||||
if (NULL == pNewChunk) {
|
||||
|
@ -306,6 +327,8 @@ SNode* nodesMakeNode(ENodeType type) {
|
|||
return makeNode(type, sizeof(SHintNode));
|
||||
case QUERY_NODE_VIEW:
|
||||
return makeNode(type, sizeof(SViewNode));
|
||||
case QUERY_NODE_WINDOW_OFFSET:
|
||||
return makeNode(type, sizeof(SWindowOffsetNode));
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return makeNode(type, sizeof(SSetOperator));
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -848,6 +871,12 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
taosArrayDestroyEx(pView->pSmaIndexes, destroySmaIndex);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_WINDOW_OFFSET: {
|
||||
SWindowOffsetNode* pWin = (SWindowOffsetNode*)pNode;
|
||||
nodesDestroyNode(pWin->pStartOffset);
|
||||
nodesDestroyNode(pWin->pEndOffset);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_SET_OPERATOR: {
|
||||
SSetOperator* pStmt = (SSetOperator*)pNode;
|
||||
nodesDestroyList(pStmt->pProjectionList);
|
||||
|
|
|
@ -124,7 +124,7 @@ SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
|
|||
SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2);
|
||||
SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, 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* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset);
|
||||
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* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding,
|
||||
SNode* pFill);
|
||||
SNode* createWindowOffsetNode(SAstCreateContext* pCxt, SNode* pStartOffset, SNode* pEndOffset);
|
||||
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues);
|
||||
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode);
|
||||
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* addEveryClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pEvery);
|
||||
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* setSelectStmtTagMode(SAstCreateContext* pCxt, SNode* pStmt, bool bSelectTags);
|
||||
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight);
|
||||
|
|
|
@ -77,6 +77,7 @@ typedef struct SParseMetaCache {
|
|||
int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...);
|
||||
int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...);
|
||||
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);
|
||||
|
||||
SSchema* getTableColumnSchema(const STableMeta* pTableMeta);
|
||||
|
|
|
@ -1047,7 +1047,7 @@ from_clause_opt(A) ::= .
|
|||
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_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(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(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 }
|
||||
%destructor join_type { }
|
||||
join_type(A) ::= . { 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(A) ::=
|
||||
|
|
|
@ -771,11 +771,12 @@ SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const STok
|
|||
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);
|
||||
SJoinTableNode* joinTable = (SJoinTableNode*)nodesMakeNode(QUERY_NODE_JOIN_TABLE);
|
||||
CHECK_OUT_OF_MEM(joinTable);
|
||||
joinTable->joinType = type;
|
||||
joinTable->subType = stype;
|
||||
joinTable->pLeft = pLeft;
|
||||
joinTable->pRight = pRight;
|
||||
joinTable->pOnCond = pJoinCond;
|
||||
|
@ -876,6 +877,15 @@ SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode
|
|||
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) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SFillNode* fill = (SFillNode*)nodesMakeNode(QUERY_NODE_FILL);
|
||||
|
@ -1047,6 +1057,31 @@ SNode* addFillClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pFill) {
|
|||
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,
|
||||
SNodeList* pHint) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
|
|
|
@ -37,9 +37,12 @@ static SKeyword keywordTable[] = {
|
|||
{"ALTER", TK_ALTER},
|
||||
{"ANALYZE", TK_ANALYZE},
|
||||
{"AND", TK_AND},
|
||||
{"ANTI", TK_ANTI},
|
||||
{"ANY", TK_ANY},
|
||||
{"APPS", TK_APPS},
|
||||
{"AS", TK_AS},
|
||||
{"ASC", TK_ASC},
|
||||
{"ASOF", TK_ASOF},
|
||||
{"AT_ONCE", TK_AT_ONCE},
|
||||
{"BALANCE", TK_BALANCE},
|
||||
{"BATCH_SCAN", TK_BATCH_SCAN},
|
||||
|
@ -103,6 +106,7 @@ static SKeyword keywordTable[] = {
|
|||
{"FLUSH", TK_FLUSH},
|
||||
{"FROM", TK_FROM},
|
||||
{"FORCE", TK_FORCE},
|
||||
{"FULL", TK_FULL},
|
||||
{"FUNCTION", TK_FUNCTION},
|
||||
{"FUNCTIONS", TK_FUNCTIONS},
|
||||
{"GEOMETRY", TK_GEOMETRY},
|
||||
|
@ -124,6 +128,7 @@ static SKeyword keywordTable[] = {
|
|||
{"INTERVAL", TK_INTERVAL},
|
||||
{"INTO", TK_INTO},
|
||||
{"IS", TK_IS},
|
||||
{"JLIMIT", TK_JLIMIT},
|
||||
{"JOIN", TK_JOIN},
|
||||
{"JSON", TK_JSON},
|
||||
{"KEEP", TK_KEEP},
|
||||
|
@ -132,6 +137,7 @@ static SKeyword keywordTable[] = {
|
|||
{"LAST", TK_LAST},
|
||||
{"LAST_ROW", TK_LAST_ROW},
|
||||
{"LEADER", TK_LEADER},
|
||||
{"LEFT", TK_LEFT},
|
||||
{"LICENCES", TK_LICENCES},
|
||||
{"LIKE", TK_LIKE},
|
||||
{"LIMIT", TK_LIMIT},
|
||||
|
@ -165,6 +171,7 @@ static SKeyword keywordTable[] = {
|
|||
{"ON", TK_ON},
|
||||
{"OR", TK_OR},
|
||||
{"ORDER", TK_ORDER},
|
||||
{"OUTER", TK_OUTER},
|
||||
{"OUTPUTTYPE", TK_OUTPUTTYPE},
|
||||
{"PAGES", TK_PAGES},
|
||||
{"PAGESIZE", TK_PAGESIZE},
|
||||
|
@ -193,10 +200,12 @@ static SKeyword keywordTable[] = {
|
|||
{"RESTORE", TK_RESTORE},
|
||||
{"RETENTIONS", TK_RETENTIONS},
|
||||
{"REVOKE", TK_REVOKE},
|
||||
{"RIGHT", TK_RIGHT},
|
||||
{"ROLLUP", TK_ROLLUP},
|
||||
{"SCHEMALESS", TK_SCHEMALESS},
|
||||
{"SCORES", TK_SCORES},
|
||||
{"SELECT", TK_SELECT},
|
||||
{"SEMI", TK_SEMI},
|
||||
{"SERVER_STATUS", TK_SERVER_STATUS},
|
||||
{"SERVER_VERSION", TK_SERVER_VERSION},
|
||||
{"SESSION", TK_SESSION},
|
||||
|
@ -279,7 +288,9 @@ static SKeyword keywordTable[] = {
|
|||
{"WATERMARK", TK_WATERMARK},
|
||||
{"WHEN", TK_WHEN},
|
||||
{"WHERE", TK_WHERE},
|
||||
{"WINDOW", TK_WINDOW},
|
||||
{"WINDOW_CLOSE", TK_WINDOW_CLOSE},
|
||||
{"WINDOW_OFFSET", TK_WINDOW_OFFSET},
|
||||
{"WITH", TK_WITH},
|
||||
{"WRITE", TK_WRITE},
|
||||
{"_C0", TK_ROWTS},
|
||||
|
|
|
@ -2913,6 +2913,41 @@ static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTabl
|
|||
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 code = TSDB_CODE_SUCCESS;
|
||||
switch (nodeType(*pTable)) {
|
||||
|
@ -2973,7 +3008,10 @@ int32_t translateTable(STranslateContext* pCxt, SNode** pTable) {
|
|||
}
|
||||
case QUERY_NODE_JOIN_TABLE: {
|
||||
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) {
|
||||
code = translateTable(pCxt, &pJoinTable->pRight);
|
||||
}
|
||||
|
|
|
@ -216,6 +216,15 @@ int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
|
|||
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) {
|
||||
if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
const char* msgFormat1 = "syntax error near \'%s\'";
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue