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_HINT,
QUERY_NODE_VIEW,
QUERY_NODE_WINDOW_OFFSET,
// Statement nodes are used in parser and planner module.
QUERY_NODE_SET_OPERATOR = 100,

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) ::=

View File

@ -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);

View File

@ -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},

View File

@ -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);
}

View File

@ -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