Merge pull request #17152 from taosdata/feat/3.0_parser_planner
feat: sql command 'show table tags from table_name'
This commit is contained in:
commit
74c5bf9bd0
|
@ -227,110 +227,111 @@
|
|||
#define TK_WEND 209
|
||||
#define TK_WDURATION 210
|
||||
#define TK_IROWTS 211
|
||||
#define TK_CAST 212
|
||||
#define TK_NOW 213
|
||||
#define TK_TODAY 214
|
||||
#define TK_TIMEZONE 215
|
||||
#define TK_CLIENT_VERSION 216
|
||||
#define TK_SERVER_VERSION 217
|
||||
#define TK_SERVER_STATUS 218
|
||||
#define TK_CURRENT_USER 219
|
||||
#define TK_COUNT 220
|
||||
#define TK_LAST_ROW 221
|
||||
#define TK_CASE 222
|
||||
#define TK_END 223
|
||||
#define TK_WHEN 224
|
||||
#define TK_THEN 225
|
||||
#define TK_ELSE 226
|
||||
#define TK_BETWEEN 227
|
||||
#define TK_IS 228
|
||||
#define TK_NK_LT 229
|
||||
#define TK_NK_GT 230
|
||||
#define TK_NK_LE 231
|
||||
#define TK_NK_GE 232
|
||||
#define TK_NK_NE 233
|
||||
#define TK_MATCH 234
|
||||
#define TK_NMATCH 235
|
||||
#define TK_CONTAINS 236
|
||||
#define TK_IN 237
|
||||
#define TK_JOIN 238
|
||||
#define TK_INNER 239
|
||||
#define TK_SELECT 240
|
||||
#define TK_DISTINCT 241
|
||||
#define TK_WHERE 242
|
||||
#define TK_PARTITION 243
|
||||
#define TK_BY 244
|
||||
#define TK_SESSION 245
|
||||
#define TK_STATE_WINDOW 246
|
||||
#define TK_SLIDING 247
|
||||
#define TK_FILL 248
|
||||
#define TK_VALUE 249
|
||||
#define TK_NONE 250
|
||||
#define TK_PREV 251
|
||||
#define TK_LINEAR 252
|
||||
#define TK_NEXT 253
|
||||
#define TK_HAVING 254
|
||||
#define TK_RANGE 255
|
||||
#define TK_EVERY 256
|
||||
#define TK_ORDER 257
|
||||
#define TK_SLIMIT 258
|
||||
#define TK_SOFFSET 259
|
||||
#define TK_LIMIT 260
|
||||
#define TK_OFFSET 261
|
||||
#define TK_ASC 262
|
||||
#define TK_NULLS 263
|
||||
#define TK_ABORT 264
|
||||
#define TK_AFTER 265
|
||||
#define TK_ATTACH 266
|
||||
#define TK_BEFORE 267
|
||||
#define TK_BEGIN 268
|
||||
#define TK_BITAND 269
|
||||
#define TK_BITNOT 270
|
||||
#define TK_BITOR 271
|
||||
#define TK_BLOCKS 272
|
||||
#define TK_CHANGE 273
|
||||
#define TK_COMMA 274
|
||||
#define TK_COMPACT 275
|
||||
#define TK_CONCAT 276
|
||||
#define TK_CONFLICT 277
|
||||
#define TK_COPY 278
|
||||
#define TK_DEFERRED 279
|
||||
#define TK_DELIMITERS 280
|
||||
#define TK_DETACH 281
|
||||
#define TK_DIVIDE 282
|
||||
#define TK_DOT 283
|
||||
#define TK_EACH 284
|
||||
#define TK_FAIL 285
|
||||
#define TK_FILE 286
|
||||
#define TK_FOR 287
|
||||
#define TK_GLOB 288
|
||||
#define TK_ID 289
|
||||
#define TK_IMMEDIATE 290
|
||||
#define TK_IMPORT 291
|
||||
#define TK_INITIALLY 292
|
||||
#define TK_INSTEAD 293
|
||||
#define TK_ISNULL 294
|
||||
#define TK_KEY 295
|
||||
#define TK_NK_BITNOT 296
|
||||
#define TK_NK_SEMI 297
|
||||
#define TK_NOTNULL 298
|
||||
#define TK_OF 299
|
||||
#define TK_PLUS 300
|
||||
#define TK_PRIVILEGE 301
|
||||
#define TK_RAISE 302
|
||||
#define TK_REPLACE 303
|
||||
#define TK_RESTRICT 304
|
||||
#define TK_ROW 305
|
||||
#define TK_SEMI 306
|
||||
#define TK_STAR 307
|
||||
#define TK_STATEMENT 308
|
||||
#define TK_STRING 309
|
||||
#define TK_TIMES 310
|
||||
#define TK_UPDATE 311
|
||||
#define TK_VALUES 312
|
||||
#define TK_VARIABLE 313
|
||||
#define TK_VIEW 314
|
||||
#define TK_WAL 315
|
||||
#define TK_QTAGS 212
|
||||
#define TK_CAST 213
|
||||
#define TK_NOW 214
|
||||
#define TK_TODAY 215
|
||||
#define TK_TIMEZONE 216
|
||||
#define TK_CLIENT_VERSION 217
|
||||
#define TK_SERVER_VERSION 218
|
||||
#define TK_SERVER_STATUS 219
|
||||
#define TK_CURRENT_USER 220
|
||||
#define TK_COUNT 221
|
||||
#define TK_LAST_ROW 222
|
||||
#define TK_CASE 223
|
||||
#define TK_END 224
|
||||
#define TK_WHEN 225
|
||||
#define TK_THEN 226
|
||||
#define TK_ELSE 227
|
||||
#define TK_BETWEEN 228
|
||||
#define TK_IS 229
|
||||
#define TK_NK_LT 230
|
||||
#define TK_NK_GT 231
|
||||
#define TK_NK_LE 232
|
||||
#define TK_NK_GE 233
|
||||
#define TK_NK_NE 234
|
||||
#define TK_MATCH 235
|
||||
#define TK_NMATCH 236
|
||||
#define TK_CONTAINS 237
|
||||
#define TK_IN 238
|
||||
#define TK_JOIN 239
|
||||
#define TK_INNER 240
|
||||
#define TK_SELECT 241
|
||||
#define TK_DISTINCT 242
|
||||
#define TK_WHERE 243
|
||||
#define TK_PARTITION 244
|
||||
#define TK_BY 245
|
||||
#define TK_SESSION 246
|
||||
#define TK_STATE_WINDOW 247
|
||||
#define TK_SLIDING 248
|
||||
#define TK_FILL 249
|
||||
#define TK_VALUE 250
|
||||
#define TK_NONE 251
|
||||
#define TK_PREV 252
|
||||
#define TK_LINEAR 253
|
||||
#define TK_NEXT 254
|
||||
#define TK_HAVING 255
|
||||
#define TK_RANGE 256
|
||||
#define TK_EVERY 257
|
||||
#define TK_ORDER 258
|
||||
#define TK_SLIMIT 259
|
||||
#define TK_SOFFSET 260
|
||||
#define TK_LIMIT 261
|
||||
#define TK_OFFSET 262
|
||||
#define TK_ASC 263
|
||||
#define TK_NULLS 264
|
||||
#define TK_ABORT 265
|
||||
#define TK_AFTER 266
|
||||
#define TK_ATTACH 267
|
||||
#define TK_BEFORE 268
|
||||
#define TK_BEGIN 269
|
||||
#define TK_BITAND 270
|
||||
#define TK_BITNOT 271
|
||||
#define TK_BITOR 272
|
||||
#define TK_BLOCKS 273
|
||||
#define TK_CHANGE 274
|
||||
#define TK_COMMA 275
|
||||
#define TK_COMPACT 276
|
||||
#define TK_CONCAT 277
|
||||
#define TK_CONFLICT 278
|
||||
#define TK_COPY 279
|
||||
#define TK_DEFERRED 280
|
||||
#define TK_DELIMITERS 281
|
||||
#define TK_DETACH 282
|
||||
#define TK_DIVIDE 283
|
||||
#define TK_DOT 284
|
||||
#define TK_EACH 285
|
||||
#define TK_FAIL 286
|
||||
#define TK_FILE 287
|
||||
#define TK_FOR 288
|
||||
#define TK_GLOB 289
|
||||
#define TK_ID 290
|
||||
#define TK_IMMEDIATE 291
|
||||
#define TK_IMPORT 292
|
||||
#define TK_INITIALLY 293
|
||||
#define TK_INSTEAD 294
|
||||
#define TK_ISNULL 295
|
||||
#define TK_KEY 296
|
||||
#define TK_NK_BITNOT 297
|
||||
#define TK_NK_SEMI 298
|
||||
#define TK_NOTNULL 299
|
||||
#define TK_OF 300
|
||||
#define TK_PLUS 301
|
||||
#define TK_PRIVILEGE 302
|
||||
#define TK_RAISE 303
|
||||
#define TK_REPLACE 304
|
||||
#define TK_RESTRICT 305
|
||||
#define TK_ROW 306
|
||||
#define TK_SEMI 307
|
||||
#define TK_STAR 308
|
||||
#define TK_STATEMENT 309
|
||||
#define TK_STRING 310
|
||||
#define TK_TIMES 311
|
||||
#define TK_UPDATE 312
|
||||
#define TK_VALUES 313
|
||||
#define TK_VARIABLE 314
|
||||
#define TK_VIEW 315
|
||||
#define TK_WAL 316
|
||||
|
||||
#define TK_NK_SPACE 300
|
||||
#define TK_NK_COMMENT 301
|
||||
|
|
|
@ -120,6 +120,7 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_WEND,
|
||||
FUNCTION_TYPE_WDURATION,
|
||||
FUNCTION_TYPE_IROWTS,
|
||||
FUNCTION_TYPE_TAGS,
|
||||
|
||||
// internal function
|
||||
FUNCTION_TYPE_SELECT_VALUE = 3750,
|
||||
|
|
|
@ -27,9 +27,10 @@ extern "C" {
|
|||
|
||||
#define LIST_LENGTH(l) (NULL != (l) ? (l)->length : 0)
|
||||
|
||||
#define FOREACH(node, list) \
|
||||
for (SListCell *cell = (NULL != (list) ? (list)->pHead : NULL), *pNext; \
|
||||
(NULL != cell ? (node = cell->pNode, pNext = cell->pNext, true) : (node = NULL, pNext = NULL, false)); cell = pNext)
|
||||
#define FOREACH(node, list) \
|
||||
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL), *pNext; \
|
||||
(NULL != cell ? (node = cell->pNode, pNext = cell->pNext, true) : (node = NULL, pNext = NULL, false)); \
|
||||
cell = pNext)
|
||||
|
||||
#define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode)
|
||||
|
||||
|
@ -192,6 +193,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT,
|
||||
QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT,
|
||||
QUERY_NODE_SHOW_SCORES_STMT,
|
||||
QUERY_NODE_SHOW_TABLE_TAGS_STMT,
|
||||
QUERY_NODE_KILL_CONNECTION_STMT,
|
||||
QUERY_NODE_KILL_QUERY_STMT,
|
||||
QUERY_NODE_KILL_TRANSACTION_STMT,
|
||||
|
|
|
@ -565,6 +565,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_PAR_GET_META_ERROR TAOS_DEF_ERROR_CODE(0, 0x2662)
|
||||
#define TSDB_CODE_PAR_NOT_UNIQUE_TABLE_ALIAS TAOS_DEF_ERROR_CODE(0, 0x2663)
|
||||
#define TSDB_CODE_PAR_NOT_SUPPORT_JOIN TAOS_DEF_ERROR_CODE(0, 0x2664)
|
||||
#define TSDB_CODE_PAR_INVALID_TAGS_PC TAOS_DEF_ERROR_CODE(0, 0x2665)
|
||||
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF)
|
||||
|
||||
//planner
|
||||
|
|
|
@ -2020,6 +2020,11 @@ static int32_t translateUserFunc(SFunctionNode* pFunc, char* pErrBuf, int32_t le
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateTagsPseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
// The _tags pseudo-column will be expanded to the actual tags on the client side
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||
{
|
||||
|
@ -3156,6 +3161,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "_tags",
|
||||
.type = FUNCTION_TYPE_TAGS,
|
||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_MULTI_RES_FUNC,
|
||||
.translateFunc = translateTagsPseudoColumn,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -419,6 +419,7 @@ SNode* nodesMakeNode(ENodeType type) {
|
|||
case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
|
||||
case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
|
||||
case QUERY_NODE_SHOW_TAGS_STMT:
|
||||
case QUERY_NODE_SHOW_TABLE_TAGS_STMT:
|
||||
return makeNode(type, sizeof(SShowStmt));
|
||||
case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
|
||||
return makeNode(type, sizeof(SShowDnodeVariablesStmt));
|
||||
|
@ -921,7 +922,8 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT:
|
||||
case QUERY_NODE_SHOW_TRANSACTIONS_STMT:
|
||||
case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT:
|
||||
case QUERY_NODE_SHOW_TAGS_STMT: {
|
||||
case QUERY_NODE_SHOW_TAGS_STMT:
|
||||
case QUERY_NODE_SHOW_TABLE_TAGS_STMT: {
|
||||
SShowStmt* pStmt = (SShowStmt*)pNode;
|
||||
nodesDestroyNode(pStmt->pDbName);
|
||||
nodesDestroyNode(pStmt->pTbName);
|
||||
|
|
|
@ -420,6 +420,7 @@ cmd ::= SHOW TABLE DISTRIBUTED full_table_name(A).
|
|||
cmd ::= SHOW CONSUMERS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONSUMERS_STMT); }
|
||||
cmd ::= SHOW SUBSCRIPTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT); }
|
||||
cmd ::= SHOW TAGS FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TAGS_STMT, B, A, OP_TYPE_EQUAL); }
|
||||
cmd ::= SHOW TABLE TAGS FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLE_TAGS_STMT, B, A, OP_TYPE_EQUAL); }
|
||||
cmd ::= SHOW VNODES NK_INTEGER(A). { pCxt->pRootNode = createShowVnodesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &A), NULL); }
|
||||
cmd ::= SHOW VNODES NK_STRING(A). { pCxt->pRootNode = createShowVnodesStmt(pCxt, NULL, createValueNode(pCxt, TSDB_DATA_TYPE_VARCHAR, &A)); }
|
||||
|
||||
|
@ -708,6 +709,7 @@ pseudo_column(A) ::= WSTART(B).
|
|||
pseudo_column(A) ::= WEND(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= WDURATION(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= IROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= QTAGS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
|
||||
function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
||||
function_expression(A) ::= star_func(B) NK_LP star_func_para_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
||||
|
|
|
@ -1310,7 +1310,7 @@ SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|||
static bool needDbShowStmt(ENodeType type) {
|
||||
return QUERY_NODE_SHOW_TABLES_STMT == type || QUERY_NODE_SHOW_STABLES_STMT == type ||
|
||||
QUERY_NODE_SHOW_VGROUPS_STMT == type || QUERY_NODE_SHOW_INDEXES_STMT == type ||
|
||||
QUERY_NODE_SHOW_TAGS_STMT == type;
|
||||
QUERY_NODE_SHOW_TAGS_STMT == type || QUERY_NODE_SHOW_TABLE_TAGS_STMT == type;
|
||||
}
|
||||
|
||||
SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type) {
|
||||
|
|
|
@ -414,6 +414,11 @@ static int32_t collectMetaKeyFromShowTags(SCollectMetaKeyCxt* pCxt, SShowStmt* p
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t collectMetaKeyFromShowStableTags(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
|
||||
return collectMetaKeyFromRealTableImpl(pCxt, ((SValueNode*)pStmt->pDbName)->literal,
|
||||
((SValueNode*)pStmt->pTbName)->literal, AUTH_TYPE_READ);
|
||||
}
|
||||
|
||||
static int32_t collectMetaKeyFromShowUsers(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
|
||||
return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USERS,
|
||||
pCxt->pMetaCache);
|
||||
|
@ -595,6 +600,8 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
|
|||
return collectMetaKeyFromShowTables(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_TAGS_STMT:
|
||||
return collectMetaKeyFromShowTags(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_TABLE_TAGS_STMT:
|
||||
return collectMetaKeyFromShowStableTags(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_USERS_STMT:
|
||||
return collectMetaKeyFromShowUsers(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_LICENCES_STMT:
|
||||
|
|
|
@ -257,6 +257,7 @@ static SKeyword keywordTable[] = {
|
|||
{"_QEND", TK_QEND},
|
||||
{"_QSTART", TK_QSTART},
|
||||
{"_ROWTS", TK_ROWTS},
|
||||
{"_TAGS", TK_QTAGS},
|
||||
{"_WDURATION", TK_WDURATION},
|
||||
{"_WEND", TK_WEND},
|
||||
{"_WSTART", TK_WSTART},
|
||||
|
|
|
@ -1215,6 +1215,9 @@ static bool isMultiResFunc(SNode* pNode) {
|
|||
if (QUERY_NODE_FUNCTION != nodeType(pNode) || !fmIsMultiResFunc(((SFunctionNode*)pNode)->funcId)) {
|
||||
return false;
|
||||
}
|
||||
if (FUNCTION_TYPE_TAGS == ((SFunctionNode*)pNode)->funcType) {
|
||||
return true;
|
||||
}
|
||||
SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
|
||||
if (LIST_LENGTH(pParameterList) > 1) {
|
||||
return true;
|
||||
|
@ -1556,7 +1559,7 @@ static int32_t translateMultiResFunc(STranslateContext* pCxt, SFunctionNode* pFu
|
|||
"%s(*) is only supported in SELECTed list", pFunc->functionName);
|
||||
}
|
||||
}
|
||||
if (tsKeepColumnName) {
|
||||
if (tsKeepColumnName && 1 == LIST_LENGTH(pFunc->pParameterList)) {
|
||||
strcpy(pFunc->node.userAlias, ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->userAlias);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -1842,17 +1845,46 @@ static EDealRes translateWhenThen(STranslateContext* pCxt, SWhenThenNode* pWhenT
|
|||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static bool isCondition(const SNode* pNode) {
|
||||
if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
|
||||
return nodesIsComparisonOp((const SOperatorNode*)pNode);
|
||||
}
|
||||
return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
|
||||
}
|
||||
|
||||
static int32_t rewriteIsTrue(SNode* pSrc, SNode** pIsTrue) {
|
||||
SOperatorNode* pOp = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR);
|
||||
if (NULL == pOp) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
pOp->opType = OP_TYPE_IS_TRUE;
|
||||
pOp->pLeft = pSrc;
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
||||
*pIsTrue = (SNode*)pOp;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EDealRes translateCaseWhen(STranslateContext* pCxt, SCaseWhenNode* pCaseWhen) {
|
||||
bool first = true;
|
||||
SNode* pNode = NULL;
|
||||
FOREACH(pNode, pCaseWhen->pWhenThenList) {
|
||||
SWhenThenNode* pWhenThen = (SWhenThenNode*)pNode;
|
||||
if (NULL == pCaseWhen->pCase && !isCondition(pWhenThen->pWhen)) {
|
||||
SNode* pIsTrue = NULL;
|
||||
pCxt->errCode = rewriteIsTrue(pWhenThen->pWhen, &pIsTrue);
|
||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
pWhenThen->pWhen = pIsTrue;
|
||||
}
|
||||
if (first) {
|
||||
pCaseWhen->node.resType = ((SExprNode*)pNode)->resType;
|
||||
} else if (!dataTypeEqual(&pCaseWhen->node.resType, &((SExprNode*)pNode)->resType)) {
|
||||
SWhenThenNode* pWhenThen = (SWhenThenNode*)pNode;
|
||||
SNode* pCastFunc = NULL;
|
||||
if (TSDB_CODE_SUCCESS != createCastFunc(pCxt, pWhenThen->pThen, pCaseWhen->node.resType, &pCastFunc)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, "CASE WHEN data type mismatch");
|
||||
SNode* pCastFunc = NULL;
|
||||
pCxt->errCode = createCastFunc(pCxt, pWhenThen->pThen, pCaseWhen->node.resType, &pCastFunc);
|
||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
pWhenThen->pThen = pCastFunc;
|
||||
pWhenThen->node.resType = pCaseWhen->node.resType;
|
||||
|
@ -1860,8 +1892,9 @@ static EDealRes translateCaseWhen(STranslateContext* pCxt, SCaseWhenNode* pCaseW
|
|||
}
|
||||
if (NULL != pCaseWhen->pElse && !dataTypeEqual(&pCaseWhen->node.resType, &((SExprNode*)pCaseWhen->pElse)->resType)) {
|
||||
SNode* pCastFunc = NULL;
|
||||
if (TSDB_CODE_SUCCESS != createCastFunc(pCxt, pCaseWhen->pElse, pCaseWhen->node.resType, &pCastFunc)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, "CASE WHEN data type mismatch");
|
||||
pCxt->errCode = createCastFunc(pCxt, pCaseWhen->pElse, pCaseWhen->node.resType, &pCastFunc);
|
||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
pCaseWhen->pElse = pCastFunc;
|
||||
((SExprNode*)pCaseWhen->pElse)->resType = pCaseWhen->node.resType;
|
||||
|
@ -2585,6 +2618,34 @@ static int32_t createMultiResFuncsFromStar(STranslateContext* pCxt, SFunctionNod
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createTags(STranslateContext* pCxt, SNodeList** pOutput) {
|
||||
if (QUERY_NODE_REAL_TABLE != nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_PC,
|
||||
"The _TAGS pseudo column can only be used for subtable and supertable queries");
|
||||
}
|
||||
|
||||
SRealTableNode* pTable = (SRealTableNode*)(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable);
|
||||
const STableMeta* pMeta = pTable->pMeta;
|
||||
if (TSDB_SUPER_TABLE != pMeta->tableType && TSDB_CHILD_TABLE != pMeta->tableType) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_PC,
|
||||
"The _TAGS pseudo column can only be used for subtable and supertable queries");
|
||||
}
|
||||
|
||||
SSchema* pTagsSchema = getTableTagSchema(pMeta);
|
||||
for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) {
|
||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
if (NULL == pCol) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
|
||||
}
|
||||
setColumnInfoBySchema(pTable, pTagsSchema + i, 1, pCol);
|
||||
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(pOutput, (SNode*)pCol)) {
|
||||
NODES_DESTORY_LIST(*pOutput);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
SNode* pNode = NULL;
|
||||
WHERE_EACH(pNode, pSelect->pProjectionList) {
|
||||
|
@ -2598,10 +2659,14 @@ static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
continue;
|
||||
}
|
||||
} else if (isMultiResFunc(pNode)) {
|
||||
SNodeList* pFuncs = NULL;
|
||||
code = createMultiResFuncsFromStar(pCxt, (SFunctionNode*)pNode, &pFuncs);
|
||||
SNodeList* pNodeList = NULL;
|
||||
if (FUNCTION_TYPE_TAGS == ((SFunctionNode*)pNode)->funcType) {
|
||||
code = createTags(pCxt, &pNodeList);
|
||||
} else {
|
||||
code = createMultiResFuncsFromStar(pCxt, (SFunctionNode*)pNode, &pNodeList);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
INSERT_LIST(pSelect->pProjectionList, pFuncs);
|
||||
INSERT_LIST(pSelect->pProjectionList, pNodeList);
|
||||
ERASE_NODE(pSelect->pProjectionList);
|
||||
continue;
|
||||
}
|
||||
|
@ -4579,6 +4644,8 @@ static SNode* createTbnameFunction() {
|
|||
return NULL;
|
||||
}
|
||||
strcpy(pFunc->functionName, "tbname");
|
||||
strcpy(pFunc->node.aliasName, "tbname");
|
||||
strcpy(pFunc->node.userAlias, "tbname");
|
||||
return (SNode*)pFunc;
|
||||
}
|
||||
|
||||
|
@ -6007,7 +6074,7 @@ static SNode* createProjectCol(const char* pProjCol) {
|
|||
|
||||
static SNodeList* createProjectCols(int32_t ncols, const char* const pCols[]) {
|
||||
SNodeList* pProjections = NULL;
|
||||
if (ncols <= 0) {
|
||||
if (0 == ncols) {
|
||||
nodesListMakeStrictAppend(&pProjections, createStarCol());
|
||||
return pProjections;
|
||||
}
|
||||
|
@ -6039,10 +6106,12 @@ static int32_t createSimpleSelectStmt(const char* pDb, const char* pTable, int32
|
|||
strcpy(pRealTable->table.tableAlias, pTable);
|
||||
pSelect->pFromTable = (SNode*)pRealTable;
|
||||
|
||||
pSelect->pProjectionList = createProjectCols(numOfProjs, pProjCol);
|
||||
if (NULL == pSelect->pProjectionList) {
|
||||
nodesDestroyNode((SNode*)pSelect);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
if (numOfProjs >= 0) {
|
||||
pSelect->pProjectionList = createProjectCols(numOfProjs, pProjCol);
|
||||
if (NULL == pSelect->pProjectionList) {
|
||||
nodesDestroyNode((SNode*)pSelect);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
*pStmt = pSelect;
|
||||
|
@ -6145,6 +6214,40 @@ static int32_t rewriteShow(STranslateContext* pCxt, SQuery* pQuery) {
|
|||
pQuery->showRewrite = true;
|
||||
nodesDestroyNode(pQuery->pRoot);
|
||||
pQuery->pRoot = (SNode*)pStmt;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pStmt);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static SNode* createTagsFunction() {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
return NULL;
|
||||
}
|
||||
strcpy(pFunc->functionName, "_tags");
|
||||
return (SNode*)pFunc;
|
||||
}
|
||||
|
||||
static int32_t rewriteShowStableTags(STranslateContext* pCxt, SQuery* pQuery) {
|
||||
const char* cols[] = {"tbname", "_tags"};
|
||||
SShowStmt* pShow = (SShowStmt*)pQuery->pRoot;
|
||||
SSelectStmt* pSelect = NULL;
|
||||
int32_t code = createSimpleSelectStmt(((SValueNode*)pShow->pDbName)->literal, ((SValueNode*)pShow->pTbName)->literal,
|
||||
-1, NULL, &pSelect);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodesListMakeStrictAppend(&pSelect->pProjectionList, createTbnameFunction());
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodesListMakeStrictAppend(&pSelect->pProjectionList, createTagsFunction());
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pSelect->isDistinct = true;
|
||||
pQuery->showRewrite = true;
|
||||
nodesDestroyNode(pQuery->pRoot);
|
||||
pQuery->pRoot = (SNode*)pSelect;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pSelect);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -7282,6 +7385,9 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
|
|||
case QUERY_NODE_SHOW_TAGS_STMT:
|
||||
code = rewriteShow(pCxt, pQuery);
|
||||
break;
|
||||
case QUERY_NODE_SHOW_TABLE_TAGS_STMT:
|
||||
code = rewriteShowStableTags(pCxt, pQuery);
|
||||
break;
|
||||
case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT:
|
||||
code = rewriteShowDnodeVariables(pCxt, pQuery);
|
||||
break;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -180,6 +180,8 @@ TEST_F(PlanBasicTest, pseudoColumn) {
|
|||
|
||||
run("SELECT _QSTART, _QEND, _QDURATION, _WSTART, _WEND, _WDURATION, COUNT(*) FROM t1 "
|
||||
"WHERE ts BETWEEN '2017-7-14 18:00:00' AND '2017-7-14 19:00:00' INTERVAL(10S)");
|
||||
|
||||
run("SELECT _TAGS, * FROM st1s1");
|
||||
}
|
||||
|
||||
TEST_F(PlanBasicTest, indefiniteRowsFunc) {
|
||||
|
|
|
@ -86,6 +86,8 @@ TEST_F(PlanOtherTest, show) {
|
|||
run("SHOW DNODE 1 VARIABLES");
|
||||
|
||||
run("SHOW TAGS FROM st1s1");
|
||||
|
||||
run("SHOW TABLE TAGS FROM st1");
|
||||
}
|
||||
|
||||
TEST_F(PlanOtherTest, delete) {
|
||||
|
|
Loading…
Reference in New Issue