fix: cols funcs, sub query
This commit is contained in:
parent
7e553f7bc9
commit
fbe345a82e
|
@ -699,6 +699,8 @@ char* getJoinSTypeString(EJoinSubType type);
|
|||
char* getFullJoinTypeString(EJoinType type, EJoinSubType stype);
|
||||
int32_t mergeJoinConds(SNode** ppDst, SNode** ppSrc);
|
||||
|
||||
int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,7 +41,7 @@ int32_t sendSyncReq(const SEpSet *pEpSet, SRpcMsg *pMsg) {
|
|||
}
|
||||
|
||||
char *i642str(int64_t val) {
|
||||
static char str[24] = {0};
|
||||
static threadlocal char str[24] = {0};
|
||||
(void)snprintf(str, sizeof(str), "%" PRId64, val);
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -1702,7 +1702,7 @@ static int32_t translateOutVarchar(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateColsFunction(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
static int32_t invalidColsFunction(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
|
||||
|
@ -5654,7 +5654,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
},
|
||||
{
|
||||
.name = "cols",
|
||||
.translateFunc = translateColsFunction,
|
||||
.translateFunc = invalidColsFunction,
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
|
|
@ -3237,3 +3237,7 @@ int32_t nodesListDeduplicate(SNodeList** ppList) {
|
|||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num) {
|
||||
return tsnprintf(pNode->aliasName, TSDB_COL_NAME_LEN, "expr_%d", num);
|
||||
}
|
||||
|
|
|
@ -1574,24 +1574,30 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef,
|
|||
STempTableNode* pTempTable = (STempTableNode*)pTable;
|
||||
SNodeList* pProjectList = getProjectList(pTempTable->pSubquery);
|
||||
SNode* pNode;
|
||||
SExprNode* pFoundExpr = NULL;
|
||||
FOREACH(pNode, pProjectList) {
|
||||
SExprNode* pExpr = (SExprNode*)pNode;
|
||||
if (0 == strcmp(pCol->colName, pExpr->aliasName)) {
|
||||
if (0 == strcmp(pCol->colName, pExpr->aliasName) || 0 == strcmp(pCol->colName, pExpr->userAlias)) {
|
||||
if (*pFound) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
|
||||
}
|
||||
code = setColumnInfoByExpr(pTempTable, pExpr, pColRef);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
break;
|
||||
}
|
||||
pFoundExpr = pExpr;
|
||||
*pFound = true;
|
||||
} else if (isPrimaryKeyImpl(pNode) && isInternalPrimaryKey(pCol)) {
|
||||
code = setColumnInfoByExpr(pTempTable, pExpr, pColRef);
|
||||
if (TSDB_CODE_SUCCESS != code) break;
|
||||
if (*pFound) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
|
||||
}
|
||||
pFoundExpr = pExpr;
|
||||
pCol->isPrimTs = true;
|
||||
*pFound = true;
|
||||
}
|
||||
}
|
||||
if (pFoundExpr) {
|
||||
code = setColumnInfoByExpr(pTempTable, pFoundExpr, pColRef);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -5561,7 +5567,7 @@ static int32_t rewriteProjectAlias(SNodeList* pProjectionList) {
|
|||
if ('\0' == pExpr->userAlias[0]) {
|
||||
tstrncpy(pExpr->userAlias, pExpr->aliasName, TSDB_COL_NAME_LEN);
|
||||
}
|
||||
snprintf(pExpr->aliasName, TSDB_COL_NAME_LEN,"#expr_%d", no++);
|
||||
rewriteExprAliasName(pExpr, no++);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -7622,6 +7628,16 @@ static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList
|
|||
}
|
||||
|
||||
static int32_t translateColsFunction(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable)) {
|
||||
SNode* pSubquery = ((STempTableNode*)pSelect->pFromTable)->pSubquery;
|
||||
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
|
||||
SSelectStmt* pSubSelect = (SSelectStmt*)pSubquery;
|
||||
int32_t code = translateColsFunction(pCxt, pSubSelect);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
SNodeList* selectFuncList = NULL;
|
||||
int32_t code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &selectFuncList);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
|
@ -7647,9 +7663,9 @@ _end:
|
|||
static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
pCxt->pCurrStmt = (SNode*)pSelect;
|
||||
pCxt->dual = false;
|
||||
int32_t code = translateFrom(pCxt, &pSelect->pFromTable);
|
||||
int32_t code = translateColsFunction(pCxt, pSelect);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateColsFunction(pCxt, pSelect);
|
||||
code = translateFrom(pCxt, &pSelect->pFromTable);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pSelect->precision = ((STableNode*)pSelect->pFromTable)->precision;
|
||||
|
|
|
@ -152,7 +152,7 @@ static EDealRes doNameExpr(SNode* pNode, void* pContext) {
|
|||
case QUERY_NODE_LOGIC_CONDITION:
|
||||
case QUERY_NODE_FUNCTION: {
|
||||
if ('\0' == ((SExprNode*)pNode)->aliasName[0]) {
|
||||
snprintf(((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN, "#expr_%p", pNode);
|
||||
rewriteExprAliasName((SExprNode*)pNode, (int64_t)pNode);
|
||||
}
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
|
|
|
@ -3035,7 +3035,7 @@ static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNo
|
|||
}
|
||||
SExprNode exprNode;
|
||||
exprNode.resType = ((SExprNode*)pWsNode)->resType;
|
||||
snprintf(exprNode.aliasName, TSDB_COL_NAME_LEN, "#expr_%d", index + 1);
|
||||
rewriteExprAliasName(&exprNode, index + 1);
|
||||
SColumnNode* pkNode = NULL;
|
||||
code = smaIndexOptCreateSmaCol((SNode*)&exprNode, tableId, PRIMARYKEY_TIMESTAMP_COL_ID, &pkNode);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nodes.h"
|
||||
#include "planInt.h"
|
||||
|
||||
#include "catalog.h"
|
||||
|
@ -30,98 +31,106 @@ typedef struct SSlotIndex {
|
|||
SArray* pSlotIdsInfo; // duplicate name slot
|
||||
} SSlotIndex;
|
||||
|
||||
static int64_t getExprBindIndexStr(SNode* pNode, char* bindInfo) {
|
||||
if (nodeType(pNode) == QUERY_NODE_COLUMN) {
|
||||
SColumnNode* pCol = (SColumnNode*)pNode;
|
||||
if (pCol->dataBlockId == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (nodesIsExprNode(pNode)) {
|
||||
SExprNode* pExpr = (SExprNode*)pNode;
|
||||
if (pExpr->bindTupleFuncIdx > 0 && pExpr->bindTupleFuncIdx <= 9) {
|
||||
bindInfo[0] = '0' + pExpr->bindTupleFuncIdx;
|
||||
return 1;
|
||||
} else if (pExpr->bindTupleFuncIdx != 0) {
|
||||
return tsnprintf(bindInfo, sizeof(bindInfo), "%d", pExpr->bindTupleFuncIdx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
SLOT_KEY_TYPE_ALL = 1,
|
||||
SLOT_KEY_TYPE_COLNAME = 2,
|
||||
};
|
||||
|
||||
static int32_t getSlotKeyHelper(SNode* pNode, const char* pPreName, const char* name, char** ppKey, int32_t callocLen,
|
||||
int32_t* pLen, uint16_t extraBufLen, int8_t slotKeyType) {
|
||||
int32_t code = 0;
|
||||
char bindInfo[16] = {0};
|
||||
//int exBindInfoLen = getExprBindIndexStr(pNode, bindInfo);
|
||||
*ppKey = taosMemoryCalloc(1, callocLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
if (slotKeyType == SLOT_KEY_TYPE_ALL) {
|
||||
TAOS_STRNCAT(*ppKey, pPreName, TSDB_TABLE_NAME_LEN);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, name, TSDB_COL_NAME_LEN);
|
||||
// if (exBindInfoLen > 0) {
|
||||
// TAOS_STRNCAT(*ppKey, bindInfo, exBindInfoLen);
|
||||
// }
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
} else {
|
||||
TAOS_STRNCAT(*ppKey, name, TSDB_COL_NAME_LEN);
|
||||
*pLen = strlen(*ppKey);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t getSlotKey(SNode* pNode, const char* pStmtName, char** ppKey, int32_t* pLen, uint16_t extraBufLen) {
|
||||
int32_t code = 0;
|
||||
int32_t callocLen = 0;
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||
SColumnNode* pCol = (SColumnNode*)pNode;
|
||||
if (NULL != pStmtName) {
|
||||
if ('\0' != pStmtName[0]) {
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pStmtName, TSDB_TABLE_NAME_LEN);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, pCol->node.aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
return code;
|
||||
callocLen = TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, pCol->node.aliasName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_ALL);
|
||||
} else {
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pCol->node.aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = strlen(*ppKey);
|
||||
return code;
|
||||
callocLen = TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, pCol->node.aliasName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_COLNAME);
|
||||
}
|
||||
}
|
||||
if ('\0' == pCol->tableAlias[0]) {
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pCol->colName, TSDB_COL_NAME_LEN);
|
||||
*pLen = strlen(*ppKey);
|
||||
return code;
|
||||
callocLen = TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, pCol->colName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_COLNAME);
|
||||
}
|
||||
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pCol->tableAlias, TSDB_TABLE_NAME_LEN);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, pCol->colName, TSDB_COL_NAME_LEN);
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
return code;
|
||||
callocLen = TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pCol->tableAlias, pCol->colName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_ALL);
|
||||
} else if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)pNode;
|
||||
if (FUNCTION_TYPE_TBNAME == pFunc->funcType) {
|
||||
SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||
if (pVal) {
|
||||
if (NULL != pStmtName && '\0' != pStmtName[0]) {
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pStmtName, TSDB_TABLE_NAME_LEN);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, ((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
return code;
|
||||
callocLen = TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, ((SExprNode*)pNode)->aliasName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_ALL);
|
||||
}
|
||||
int32_t literalLen = strlen(pVal->literal);
|
||||
*ppKey = taosMemoryCalloc(1, literalLen + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pVal->literal, literalLen);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, ((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
return code;
|
||||
callocLen = literalLen + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pVal->literal, ((SExprNode*)pNode)->aliasName, ppKey, callocLen, pLen,
|
||||
extraBufLen, SLOT_KEY_TYPE_ALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != pStmtName && '\0' != pStmtName[0]) {
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, pStmtName, TSDB_TABLE_NAME_LEN);
|
||||
TAOS_STRNCAT(*ppKey, ".", 2);
|
||||
TAOS_STRNCAT(*ppKey, ((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = taosHashBinary(*ppKey, strlen(*ppKey));
|
||||
return code;
|
||||
callocLen = TSDB_TABLE_NAME_LEN + 1 + TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, ((SExprNode*)pNode)->aliasName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_ALL);
|
||||
}
|
||||
|
||||
*ppKey = taosMemoryCalloc(1, TSDB_COL_NAME_LEN + 1 + extraBufLen);
|
||||
if (!*ppKey) {
|
||||
return terrno;
|
||||
}
|
||||
TAOS_STRNCAT(*ppKey, ((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN);
|
||||
*pLen = strlen(*ppKey);
|
||||
callocLen = TSDB_COL_NAME_LEN + 1 + extraBufLen;
|
||||
return getSlotKeyHelper(pNode, pStmtName, ((SExprNode*)pNode)->aliasName, ppKey, callocLen, pLen, extraBufLen,
|
||||
SLOT_KEY_TYPE_COLNAME);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
|||
}
|
||||
}
|
||||
}
|
||||
pCol->node.bindTupleFuncIdx = pExpr->bindTupleFuncIdx;
|
||||
pCol->node.tupleFuncIdx = pExpr->tupleFuncIdx;
|
||||
return (TSDB_CODE_SUCCESS == nodesListStrictAppend(pCxt->pList, (SNode*)pCol) ? DEAL_RES_IGNORE_CHILD
|
||||
: DEAL_RES_ERROR);
|
||||
}
|
||||
|
|
|
@ -506,9 +506,35 @@ class TDTestCase:
|
|||
tdSql.checkData(1, 5, 1734574929003)
|
||||
tdSql.checkData(1, 6, 3)
|
||||
|
||||
# todo 2, sub query has cols func
|
||||
# select * from (select cols(last_row(c0), ts as t1, c1 as c11), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4);
|
||||
# todo 3, cols on system table
|
||||
# sub query has cols func
|
||||
tdSql.query(f'select c11 from (select cols(last_row(c0), ts as t1, c1 as c11), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4)')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(1)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.query(f'select c11, c21 from (select cols(last_row(c0), ts as t1, c1 as c11), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4)')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.checkData(0, 1, 1)
|
||||
tdSql.query(f'select c1, c21 from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4)')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.checkData(0, 1, 1)
|
||||
tdSql.error(f'select c1 from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1), first(c0) from test.meters where c0 < 4)')
|
||||
|
||||
# cols on system table
|
||||
tdSql.query(f'select cols(max(vgroup_id), uid) from information_schema.ins_tables')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(1)
|
||||
tdSql.query(f'select cols(max(vgroup_id), uid, `ttl`, create_time) from information_schema.ins_tables')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(3)
|
||||
tdSql.query(f'select cols(max(vgroup_id), uid as uidname) from information_schema.ins_tables')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(1)
|
||||
tdSql.error(f'select cols(last(vgroup_id), uid, `ttl`, create_time) from information_schema.ins_tables')
|
||||
tdSql.error(f'select cols(first(vgroup_id), uid, `ttl`, create_time) from information_schema.ins_tables')
|
||||
|
||||
def funcSupperTableTest(self):
|
||||
tdSql.execute('create database if not exists db;')
|
||||
|
@ -534,7 +560,7 @@ class TDTestCase:
|
|||
tdSql.checkData(0, 6, 'c2')
|
||||
tdSql.checkData(0, 7, True)
|
||||
|
||||
#tdSql.execute(f'drop table if exists db.st')
|
||||
tdSql.execute(f'drop table if exists db.st')
|
||||
|
||||
|
||||
def funcNestTest(self):
|
||||
|
|
Loading…
Reference in New Issue