提交 bfd23c61 编写于 作者: H Haojun Liao

[td-10564] 1. refactor and fix bug in order by validation. 2. Support the...

[td-10564] 1. refactor and fix bug in order by validation. 2. Support the compatible model of ver. 2.0
上级 fadd69c6
......@@ -55,11 +55,18 @@ typedef struct SDataBlockInfo {
int64_t uid;
} SDataBlockInfo;
typedef struct SConstantItem {
SColumnInfo info;
int32_t startIndex; // run-length-encoding to save the space for multiple rows
int32_t endIndex;
SVariant value;
} SConstantItem;
typedef struct SSDataBlock {
SColumnDataAgg *pBlockAgg;
SArray *pDataBlock; // SArray<SColumnInfoData>
SArray *pTagsList; // SArray<SVariant> for tag value
SDataBlockInfo info;
SArray *pDataBlock; // SArray<SColumnInfoData>
SArray *pConstantList; // SArray<SConstantItem>, it is a constant/tags value of the corresponding result value.
SDataBlockInfo info;
} SSDataBlock;
typedef struct SColumnInfoData {
......@@ -83,7 +90,7 @@ typedef struct SLimit {
typedef struct SOrder {
uint32_t order;
int32_t orderColId;
SColumn col;
} SOrder;
typedef struct SGroupbyExpr {
......
......@@ -277,7 +277,7 @@ typedef struct SSchema {
uint8_t type;
char name[TSDB_COL_NAME_LEN];
int16_t colId;
int16_t bytes;
int32_t bytes;
} SSchema;
//#endif
......
......@@ -58,6 +58,7 @@ extern int32_t tsCompressColData;
extern int32_t tsMaxNumOfDistinctResults;
extern char tsTempDir[];
extern int64_t tsMaxVnodeQueuedBytes;
extern int tsCompatibleModel; // 2.0 compatible model
//query buffer management
extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing
......
......@@ -229,7 +229,7 @@ typedef struct SScalarFunctionInfo {
typedef struct SMultiFunctionsDesc {
bool stableQuery;
bool groupbyColumn;
bool simpleAgg;
bool agg;
bool arithmeticOnAgg;
bool projectionQuery;
bool hasFilter;
......@@ -261,6 +261,7 @@ int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction);
bool qIsValidUdf(SArray* pUdfInfo, const char* name, int32_t len, int32_t* functionId);
bool qIsAggregateFunction(const char* functionName);
bool qIsSelectivityFunction(const char* functionName);
tExprNode* exprTreeFromBinary(const void* data, size_t size);
......
......@@ -86,7 +86,7 @@ typedef struct SQueryStmtInfo {
SLimit slimit;
STagCond tagCond;
SArray * colCond;
SOrder order;
SArray * order;
int16_t numOfTables;
int16_t curTableIdx;
STableMetaInfo **pTableMetaInfo;
......
......@@ -79,6 +79,11 @@ int32_t tsCompressMsgSize = -1;
*/
int32_t tsCompressColData = -1;
/*
* denote if 3.0 query pattern compatible for 2.0
*/
int32_t tsCompatibleModel = 1;
// client
int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN;
int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_DEFAULT_LEN;
......
......@@ -4589,7 +4589,7 @@ SAggFunctionInfo aggFunc[35] = {{
},
{
// 16
"ts",
"dummy",
FUNCTION_TYPE_AGG,
FUNCTION_TS,
FUNCTION_TS,
......
......@@ -54,6 +54,18 @@ bool qIsAggregateFunction(const char* functionName) {
return !scalarfunc;
}
bool qIsSelectivityFunction(const char* functionName) {
assert(functionName != NULL);
pthread_once(&functionHashTableInit, doInitFunctionHashTable);
size_t len = strlen(functionName);
SAggFunctionInfo** pInfo = taosHashGet(functionHashTable, functionName, len);
if (pInfo != NULL) {
return ((*pInfo)->status | FUNCSTATE_SELECTIVITY) != 0;
}
return false;
}
SAggFunctionInfo* qGetFunctionInfo(const char* name, int32_t len) {
pthread_once(&functionHashTableInit, doInitFunctionHashTable);
......@@ -79,16 +91,17 @@ void qRemoveUdfInfo(uint64_t id, SUdfInfo* pUdfInfo) {
bool isTagsQuery(SArray* pFunctionIdList) {
int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList);
for (int32_t i = 0; i < num; ++i) {
int16_t f = *(int16_t*) taosArrayGet(pFunctionIdList, i);
char* f = *(char**) taosArrayGet(pFunctionIdList, i);
// todo handle count(tbname) query
if (strcmp(f, "project") != 0 && strcmp(f, "count") != 0) {
return false;
}
// "select count(tbname)" query
// if (functId == FUNCTION_COUNT && pExpr->base.colpDesc->colId == TSDB_TBNAME_COLUMN_INDEX) {
// continue;
// }
if (f != FUNCTION_TAGPRJ && f != FUNCTION_TID_TAG) {
return false;
}
}
return true;
......@@ -113,23 +126,13 @@ bool isTagsQuery(SArray* pFunctionIdList) {
bool isProjectionQuery(SArray* pFunctionIdList) {
int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList);
for (int32_t i = 0; i < num; ++i) {
int32_t f = *(int16_t*) taosArrayGet(pFunctionIdList, i);
if (f == FUNCTION_TS_DUMMY) {
continue;
}
if (f != FUNCTION_PRJ &&
f != FUNCTION_TAGPRJ &&
f != FUNCTION_TAG &&
f != FUNCTION_TS &&
f != FUNCTION_ARITHM &&
f != FUNCTION_DIFF &&
f != FUNCTION_DERIVATIVE) {
return false;
char* f = *(char**) taosArrayGet(pFunctionIdList, i);
if (strcmp(f, "project") == 0) {
return true;
}
}
return true;
return false;
}
bool isDiffDerivativeQuery(SArray* pFunctionIdList) {
......@@ -190,11 +193,11 @@ bool isTopBotQuery(SArray* pFunctionIdList) {
int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList);
for (int32_t i = 0; i < num; ++i) {
char* f = *(char**) taosArrayGet(pFunctionIdList, i);
if (f == FUNCTION_TS) {
if (strcmp(f, "project") == 0) {
continue;
}
if (f == FUNCTION_TOP || f == FUNCTION_BOTTOM) {
if (strcmp(f, "top") == 0 || strcmp(f, "bottom") == 0) {
return true;
}
}
......@@ -273,49 +276,26 @@ bool needReverseScan(SArray* pFunctionIdList) {
return false;
}
bool isSimpleAggregateRv(SArray* pFunctionIdList) {
// if (pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0) {
// return false;
// }
//
// if (tscIsDiffDerivQuery(pQueryInfo)) {
// return false;
// }
//
// size_t numOfExprs = getNumOfExprs(pQueryInfo);
// for (int32_t i = 0; i < numOfExprs; ++i) {
// SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
// if (pExpr == NULL) {
// continue;
// }
//
// int32_t functionId = pExpr->base.functionId;
// if (functionId < 0) {
// SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * functionId - 1);
// if (pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE) {
// return true;
// }
//
// continue;
// }
//
// if (functionId == FUNCTION_TS || functionId == FUNCTION_TS_DUMMY) {
// continue;
// }
//
// if ((!IS_MULTIOUTPUT(aAggs[functionId].status)) ||
// (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_TS_COMP)) {
// return true;
// }
// }
bool isAgg(SArray* pFunctionIdList) {
size_t size = taosArrayGetSize(pFunctionIdList);
for (int32_t i = 0; i < size; ++i) {
char* f = *(char**) taosArrayGet(pFunctionIdList, i);
if (strcmp(f, "project") == 0) {
return false;
}
if (qIsAggregateFunction(f)) {
return true;
}
}
return false;
}
bool isBlockDistQuery(SArray* pFunctionIdList) {
int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList);
int32_t f = *(int16_t*) taosArrayGet(pFunctionIdList, 0);
return (num == 1 && f == FUNCTION_BLKINFO);
char* f = *(char**) taosArrayGet(pFunctionIdList, 0);
return (num == 1 && strcmp(f, "block_dist") == 0);
}
bool isTwoStageSTableQuery(SArray* pFunctionIdList, int32_t tableIndex) {
......@@ -426,8 +406,9 @@ void extractFunctionDesc(SArray* pFunctionIdList, SMultiFunctionsDesc* pDesc) {
return;
}
pDesc->projectionQuery = isProjectionQuery(pFunctionIdList);
pDesc->onlyTagQuery = isTagsQuery(pFunctionIdList);
// pDesc->projectionQuery = isProjectionQuery(pFunctionIdList);
// pDesc->onlyTagQuery = isTagsQuery(pFunctionIdList);
pDesc->interpQuery = isInterpQuery(pFunctionIdList);
pDesc->topbotQuery = isTopBotQuery(pFunctionIdList);
pDesc->agg = isAgg(pFunctionIdList);
}
......@@ -13,7 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <astGenerator.h>
#include <function.h>
#include "astGenerator.h"
#include "function.h"
......@@ -703,6 +702,8 @@ static int32_t parseSlidingClause(SQueryStmtInfo* pQueryInfo, SToken* pSliding,
return TSDB_CODE_SUCCESS;
}
static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex);
// validate the interval info
int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) {
const char* msg1 = "sliding cannot be used without interval";
......@@ -720,11 +721,6 @@ int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMs
}
}
// orderby column not set yet, set it to be the primary timestamp column
if (pQueryInfo->order.orderColId == INT32_MIN) {
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_ID;
}
// interval is not null
SToken *t = &pSqlNode->interval.interval;
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval,
......@@ -753,6 +749,13 @@ int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMs
return TSDB_CODE_TSC_INVALID_OPERATION;
}
if (tsCompatibleModel) {
SExprInfo* pFirstExpr = getExprInfo(pQueryInfo, 0);
if (pFirstExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE || strcasecmp(pFirstExpr->pExpr->_function.functionName, "dummy") != 0) {
setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, 0, 0);
}
}
// It is a time window query
pQueryInfo->info.timewindow = true;
return TSDB_CODE_SUCCESS;
......@@ -922,8 +925,6 @@ int32_t validateLimitNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBu
}
}
static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex);
int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) {
const char* msg1 = "invalid column name in orderby clause";
const char* msg2 = "too many order by columns";
......@@ -934,6 +935,8 @@ int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsg
return TSDB_CODE_SUCCESS;
}
pQueryInfo->order = taosArrayInit(4, sizeof(SOrder));
STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0);
SArray* pSortOrder = pSqlNode->pSortOrder;
......@@ -944,39 +947,42 @@ int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsg
* for super table query, the order option must be less than 3.
*/
size_t size = taosArrayGetSize(pSortOrder);
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) {
if ((UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) && (pQueryInfo->info.projectionQuery)) {
if (size > 1) {
return buildInvalidOperationMsg(pMsgBuf, msg3);
}
} else {
if (size > 2) {
return buildInvalidOperationMsg(pMsgBuf, msg2);
}
}
// handle the first part of order by
SVariant* pVar = taosArrayGet(pSortOrder, 0);
SSchema s = {0};
if (pVar->nType == TSDB_DATA_TYPE_BINARY) {
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
SToken columnName = {pVar->nLen, pVar->nType, pVar->pz};
if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
return buildInvalidOperationMsg(pMsgBuf, msg1);
}
for(int32_t i = 0; i < taosArrayGetSize(pSortOrder); ++i) {
SVariant* pVar = taosArrayGet(pSortOrder, i);
if (pVar->nType == TSDB_DATA_TYPE_BINARY) {
SColumn c = {0};
// find the orde column among the result field.
for (int32_t j = 0; j < getNumOfFields(&pQueryInfo->fieldsInfo); ++j) {
SInternalField* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.internalField, j);
SSchema* pSchema = &pInfo->pExpr->base.resSchema;
if (strcasecmp(pVar->pz, pSchema->name) == 0) {
setColumn(&c, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, &pSchema);
return TSDB_CODE_SUCCESS;
}
}
s = *(SSchema*) getOneColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
} else { // order by [1|2|3]
if (pVar->i > getNumOfFields(&pQueryInfo->fieldsInfo)) {
return buildInvalidOperationMsg(pMsgBuf, msg4);
}
return buildInvalidOperationMsg(pMsgBuf, "invalid order by column");
} else { // order by [1|2|3]
if (pVar->i > getNumOfFields(&pQueryInfo->fieldsInfo)) {
return buildInvalidOperationMsg(pMsgBuf, msg4);
}
SExprInfo* pExprInfo = getExprInfo(pQueryInfo, pVar->i);
s = pExprInfo->base.resSchema;
}
int32_t index = pVar->i - 1;
SExprInfo* pExprInfo = getExprInfo(pQueryInfo, index);
SListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = s.colId;
SOrder c = {0};
setColumn(&c.col, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, &pExprInfo->base.resSchema);
taosArrayPush(pQueryInfo->order, &c);
}
}
return TSDB_CODE_SUCCESS;
}
......@@ -1378,6 +1384,8 @@ int32_t validateFillNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf
return TSDB_CODE_SUCCESS;
}
static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo);
int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
assert(pSqlNode != NULL && (pSqlNode->from == NULL || taosArrayGetSize(pSqlNode->from->list) > 0));
......@@ -1529,11 +1537,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// set order by info
if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// set interval value
if (validateIntervalNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
......@@ -1558,6 +1561,11 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return TSDB_CODE_SUCCESS;
}
// set order by info
if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
if ((code = validateLimitNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
......@@ -1567,7 +1575,9 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
for(int32_t i = 0; i < getExprFunctionLevel(pQueryInfo); ++i) {
exprInfoPushDown(pQueryInfo);
for(int32_t i = 0; i < 1; ++i) {
SArray* functionList = extractFunctionList(pQueryInfo->exprList[i]);
extractFunctionDesc(functionList, &pQueryInfo->info);
......@@ -1579,6 +1589,87 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return TSDB_CODE_SUCCESS; // Does not build query message here
}
static bool isTagOrPrimaryTs(SExprInfo* pExprInfo) {
if (pExprInfo->pExpr->nodeType != TEXPR_COL_NODE) {
return false;
}
assert(pExprInfo->base.pColumns->info.colId == pExprInfo->pExpr->pSchema->colId);
return (TSDB_COL_IS_TAG(pExprInfo->base.pColumns->flag) || pExprInfo->pExpr->pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
}
// todo extract the table column in expression
static bool isGroupbyCol(SExprInfo* pExprInfo, SGroupbyExpr* pGroupbyExpr) {
assert(pExprInfo != NULL && pGroupbyExpr != NULL);
int32_t nodeType = pExprInfo->pExpr->nodeType;
assert(nodeType == TEXPR_COL_NODE || nodeType == TEXPR_BINARYEXPR_NODE);
for(int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) {
SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i);
if (pCol->info.colId == pExprInfo->pExpr->pSchema->colId) {
return true;
}
}
return false;
}
static bool isAllAggExpr(SArray* pList) {
assert(pList != NULL);
for (int32_t k = 0; k < taosArrayGetSize(pList); ++k) {
SExprInfo* p = taosArrayGetP(pList, k);
if (p->pExpr->nodeType != TEXPR_FUNCTION_NODE || !qIsAggregateFunction(p->pExpr->_function.functionName)) {
return false;
}
}
return true;
}
static SExprInfo* doCreateColumnNodeFromAggFunc(SSchema* pSchema);
static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo) {
assert(pQueryInfo != NULL);
size_t level = getExprFunctionLevel(pQueryInfo);
for(int32_t i = 0; i < level - 1; ++i) {
SArray* p = pQueryInfo->exprList[i];
SArray* pNext = pQueryInfo->exprList[i + 1];
if (!isAllAggExpr(pNext)) {
continue;
}
for (int32_t j = 0; j < taosArrayGetSize(p); ++j) {
SExprInfo* pExpr = taosArrayGetP(p, j);
if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE && qIsAggregateFunction(pExpr->pExpr->_function.functionName)) {
bool canPushDown = true;
for (int32_t k = 0; k < taosArrayGetSize(pNext); ++k) {
SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k);
if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) {
// pExpr is dependent on the output of the under layer, so it can not be push downwards
canPushDown = false;
break;
}
}
if (canPushDown) {
taosArrayInsert(pNext, j, &pExpr);
taosArrayRemove(p, j);
// todo add the project function in level of "i"
SExprInfo* pNew = doCreateColumnNodeFromAggFunc(&pExpr->base.resSchema);
taosArrayInsert(p, j, &pNew);
}
}
}
}
}
int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
assert(pQueryInfo != NULL && pMsgBuf != NULL);
......@@ -1597,9 +1688,18 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
// 1. invalid sql:
// select top(col, k) from table_name [interval(1d)|session(ts, 1d)|statewindow(col)] order by k asc
// order by normal column is not supported
int32_t colId = pQueryInfo->order.orderColId;
if (pQueryInfo->info.timewindow && colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
return buildInvalidOperationMsg(pMsgBuf, msg2);
if (pQueryInfo->order != NULL) {
size_t numOfOrder = taosArrayGetSize(pQueryInfo->order);
if (numOfOrder > 1) {
return buildInvalidOperationMsg(pMsgBuf, msg2);
}
if (numOfOrder > 0) {
SColumn* pOrderCol = taosArrayGet(pQueryInfo->order, 0);
if (pQueryInfo->info.timewindow && pOrderCol->info.colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
return buildInvalidOperationMsg(pMsgBuf, msg2);
}
}
}
// select top(col, k) from table_name interval(10s) fill(prev)
......@@ -1609,14 +1709,25 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
}
// select top(col, k), count(*) from table_name
int32_t num = 0;
SExprInfo* pMain = NULL;
size_t size = getNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < size; ++i) {
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
const char* functionName = pExpr->pExpr->_function.functionName;
if (strcmp(functionName, "top") != 0 && strcmp(functionName, "bottom") != 0) {
if (pExpr->pExpr->nodeType == TEXPR_COL_NODE) {
if (!isTagOrPrimaryTs(pExpr) && !isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) {
return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause");
}
} else if (pExpr->pExpr->nodeType == TEXPR_BINARYEXPR_NODE) {
continue;
// todo extract all column node in tree, and check for each node
continue;
}
// dummy column is also the placeholder for primary timestamp column in the result.
const char* functionName = pExpr->pExpr->_function.functionName;
if (strcmp(functionName, "top") != 0 && strcmp(functionName, "bottom") != 0 && strcmp(functionName, "dummy") != 0) {
if (qIsAggregateFunction(functionName)) {
return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause");
}
......@@ -1709,6 +1820,35 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) {
pQueryInfo->info.groupbyColumn) {
return buildInvalidOperationMsg(pMsgBuf, msg9);
}
/*
* 9. invalid sql:
* select count(*), col_name from table_name
*/
if (pQueryInfo->info.agg) {
bool isSelectivity = false;
if (pQueryInfo->info.projectionQuery) {
size_t size = getNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < size; ++i) {
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE) {
if (!isSelectivity) {
isSelectivity = qIsSelectivityFunction(pExpr->pExpr->_function.functionName);
}
continue;
}
if (isSelectivity && isTagOrPrimaryTs(pExpr)) {
continue;
}
if (!isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) {
return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select");
}
}
}
}
}
int32_t addResColumnInfo(SQueryStmtInfo* pQueryInfo, int32_t outputIndex, SSchema* pSchema, SExprInfo* pSqlExpr) {
......@@ -1856,7 +1996,7 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab
SSourceParam param = {0};
addIntoSourceParam(&param, NULL, &col);
SExprInfo* pExpr = createExprInfo(pTableMetaInfo, "ts_dummy", &param, &s, TSDB_KEYSIZE);
SExprInfo* pExpr = createExprInfo(pTableMetaInfo, "dummy", &param, &s, TSDB_KEYSIZE);
strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token));
SArray* pExprList = getCurrentExprList(pQueryInfo);
......@@ -2695,6 +2835,7 @@ int32_t doAddOneProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, S
addResColumnInfo(pQueryInfo, exists, &pExpr->base.resSchema, pExpr);
}
pQueryInfo->info.projectionQuery = true;
return TSDB_CODE_SUCCESS;
}
......@@ -2926,9 +3067,9 @@ static tExprNode* doCreateColumnNode(SQueryStmtInfo* pQueryInfo, SColumnIndex* p
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
tExprNode* pExpr = calloc(1, sizeof(tExprNode));
pExpr->nodeType = TEXPR_COL_NODE;
pExpr->pSchema = calloc(1, sizeof(SSchema));
pExpr->nodeType = TEXPR_COL_NODE;
pExpr->pSchema = calloc(1, sizeof(SSchema));
SSchema* pSchema = NULL;
if (pIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
......@@ -2955,6 +3096,23 @@ static tExprNode* doCreateColumnNode(SQueryStmtInfo* pQueryInfo, SColumnIndex* p
return pExpr;
}
static SExprInfo* doCreateColumnNodeFromAggFunc(SSchema* pSchema) {
tExprNode* pExprNode = calloc(1, sizeof(tExprNode));
pExprNode->nodeType = TEXPR_COL_NODE;
pExprNode->pSchema = calloc(1, sizeof(SSchema));
*(SSchema*)(pExprNode->pSchema) = *pSchema;
SExprInfo* pExpr = calloc(1, sizeof(SExprInfo));
if (pExpr == NULL) {
return NULL;
}
pExpr->pExpr = pExprNode;
memcpy(&pExpr->base.resSchema, pSchema, sizeof(SSchema));
return pExpr;
}
static int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SMsgBuf* pMsgBuf);
static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_t* num, tExprNode*** p, SArray* pCols,
......@@ -3366,7 +3524,6 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
} else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) {
// use the dynamic array list to decide if the function is valid or not
// select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2
// todo refacto to remove this function
if ((code = addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf)) != TSDB_CODE_SUCCESS) {
return code;
}
......
......@@ -325,12 +325,15 @@ SArray* extractFunctionList(SArray* pExprInfoList) {
size_t len = taosArrayGetSize(pExprInfoList);
SArray* p = taosArrayInit(len, POINTER_BYTES);
for(int32_t i = 0; i < len; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i);
if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) {
taosArrayPush(p, &pExprInfo->pExpr->_function.functionName);
char* name = strdup(pExprInfo->pExpr->_function.functionName);
taosArrayPush(p, &name);
} else {
taosArrayPush(p, "project");
char* name = strdup("project");
taosArrayPush(p, &name);
}
}
......
......@@ -16,6 +16,7 @@
#include <function.h>
#include <gtest/gtest.h>
#include <iostream>
#include "tglobal.h"
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
......@@ -422,8 +423,8 @@ TEST(testCase, function_Test10) {
sqlCheck("select block_dist() + 20 from `t.1abc`", true);
sqlCheck("select count(b), c from `t.1abc`", false);
sqlCheck("select top(a, 20), count(b) from `t.1abc`", false);
// sqlCheck("select top(a, 20), b from `t.1abc`", false);
// sqlCheck("select top(a, 20), a+20 from `t.1abc`", true);
sqlCheck("select top(a, 20), b from `t.1abc`", false);
sqlCheck("select top(a, 20), a+20 from `t.1abc`", true);
// sqlCheck("select top(a, 20), bottom(a, 10) from `t.1abc`", false);
// sqlCheck("select last_row(*), count(b) from `t.1abc`", false);
// sqlCheck("select last_row(a, b) + 20 from `t.1abc`", false);
......@@ -457,9 +458,14 @@ TEST(testCase, function_Test6) {
ASSERT_EQ(ret, 0);
SArray* pExprList = pQueryInfo->exprList[0];
ASSERT_EQ(taosArrayGetSize(pExprList), 5);
if (tsCompatibleModel) {
ASSERT_EQ(taosArrayGetSize(pExprList), 6);
} else {
ASSERT_EQ(taosArrayGetSize(pExprList), 5);
}
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0);
int32_t index = tsCompatibleModel? 1:0;
SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, index);
ASSERT_EQ(p1->base.pColumns->uid, 110);
ASSERT_EQ(p1->base.numOfParams, 0);
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
......@@ -477,9 +483,12 @@ TEST(testCase, function_Test6) {
ASSERT_STREQ(pParam->pSchema->name, "t.1abc.a+b");
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5);
SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, 1);
int32_t numOfResCol = tsCompatibleModel? 6:5;
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfResCol);
index = tsCompatibleModel? 2:1;
SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, index);
ASSERT_EQ(p2->base.pColumns->uid, 110);
ASSERT_EQ(p2->base.numOfParams, 0);
ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
......@@ -527,9 +536,10 @@ TEST(testCase, function_Test6) {
ASSERT_EQ(ret, 0);
SArray* pExprList = pQueryInfo->exprList[0];
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
ASSERT_EQ(taosArrayGetSize(pExprList), 3);
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
int32_t index = tsCompatibleModel? 1:0;
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, index);
ASSERT_EQ(p1->base.pColumns->uid, 110);
ASSERT_EQ(p1->base.numOfParams, 0);
ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
......@@ -553,7 +563,9 @@ TEST(testCase, function_Test6) {
ASSERT_EQ(pParam->pSchema->colId, p2->base.resSchema.colId);
ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
int32_t numOfCols = tsCompatibleModel? 3:2;
ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfCols);
destroyQueryInfo(pQueryInfo);
qParserClearupMetaRequestInfo(&req);
......
......@@ -15,6 +15,7 @@
#include <function.h>
#include <gtest/gtest.h>
#include <tglobal.h>
#include <iostream>
#pragma GCC diagnostic ignored "-Wwrite-strings"
......@@ -63,7 +64,6 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) {
setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1);
setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2);
setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3);
}
void generateLogicplan(const char* sql) {
......@@ -132,7 +132,9 @@ TEST(testCase, planner_test) {
ASSERT_EQ(ret, 0);
SArray* pExprList = pQueryInfo->exprList[0];
ASSERT_EQ(taosArrayGetSize(pExprList), 2);
int32_t num = tsCompatibleModel? 2:1;
ASSERT_EQ(taosArrayGetSize(pExprList), num);
SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1);
ASSERT_EQ(p1->base.pColumns->uid, 110);
......@@ -172,6 +174,7 @@ TEST(testCase, displayPlan) {
generateLogicplan("select count(A+B) from `t.1abc` group by a");
generateLogicplan("select count(length(a)+b) from `t.1abc` group by a");
generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s)");
generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s) order by 1 desc ");
generateLogicplan("select count(*),sum(a),avg(b),min(a+b)+99 from `t.1abc`");
generateLogicplan("select count(*), min(a) + 99 from `t.1abc`");
generateLogicplan("select count(length(count(*) + 22)) from `t.1abc`");
......@@ -180,7 +183,7 @@ TEST(testCase, displayPlan) {
generateLogicplan("select count(*), first(a), last(b) from `t.1abc` session(ts, 20s)");
// order by + group by column + limit offset + fill
generateLogicplan("select top(a, 20) k from `t.1abc` order by k asc limit 3 offset 1");
// join
......
......@@ -46,14 +46,12 @@ typedef struct SJoinCond {
static SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo);
static void doDestroyQueryNode(SQueryPlanNode* pQueryNode);
static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo);
int32_t qOptimizeQueryPlan(struct SQueryPlanNode* pQueryNode) {
return 0;
}
int32_t qCreateQueryPlan(const struct SQueryStmtInfo* pQueryInfo, struct SQueryPlanNode** pQueryNode) {
exprInfoPushDown((struct SQueryStmtInfo*) pQueryInfo);
SArray* upstream = createQueryPlanImpl((struct SQueryStmtInfo*) pQueryInfo);
assert(taosArrayGetSize(upstream) == 1);
......@@ -164,6 +162,12 @@ static SQueryPlanNode* createQueryNode(int32_t type, const char* name, SQueryPla
memcpy(pNode->pExtInfo, pExtInfo, sizeof(SLimit));
break;
}
case QNODE_SORT: {
pNode->pExtInfo = taosArrayDup(pExtInfo);
break;
}
default:
break;
}
......@@ -267,6 +271,11 @@ static SQueryPlanNode* doCreateQueryPlanForSingleTableImpl(SQueryStmtInfo* pQuer
pNode = createQueryNode(QNODE_FILL, "Fill", &pNode, 1, NULL, 0, pInfo);
}
if (pQueryInfo->order != NULL) {
SArray* pList = pQueryInfo->exprList[0];
pNode = createQueryNode(QNODE_SORT, "Sort", &pNode, 1, pList->pData, taosArrayGetSize(pList), pQueryInfo->order);
}
if (pQueryInfo->limit.limit != -1 || pQueryInfo->limit.offset != 0) {
pNode = createQueryNode(QNODE_LIMIT, "Limit", &pNode, 1, NULL, 0, &pQueryInfo->limit);
}
......@@ -306,44 +315,6 @@ static bool isAllAggExpr(SArray* pList) {
return true;
}
static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo) {
assert(pQueryInfo != NULL);
size_t level = getExprFunctionLevel(pQueryInfo);
for(int32_t i = 0; i < level - 1; ++i) {
SArray* p = pQueryInfo->exprList[i];
SArray* pNext = pQueryInfo->exprList[i + 1];
if (!isAllAggExpr(pNext)) {
continue;
}
for (int32_t j = 0; j < taosArrayGetSize(p); ++j) {
SExprInfo* pExpr = taosArrayGetP(p, j);
if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE && qIsAggregateFunction(pExpr->pExpr->_function.functionName)) {
bool canPushDown = true;
for (int32_t k = 0; k < taosArrayGetSize(pNext); ++k) {
SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k);
if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) {
// pExpr is dependent on the output of the under layer, so it can not be push downwards
canPushDown = false;
break;
}
}
if (canPushDown) {
taosArrayInsert(pNext, j, &pExpr);
taosArrayRemove(p, j);
// todo add the project function in level of "i"
}
}
}
}
}
SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) {
SArray* upstream = NULL;
......@@ -440,13 +411,13 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
switch(pQueryNode->info.type) {
case QNODE_TABLESCAN: {
SQueryTableInfo* pInfo = (SQueryTableInfo*) pQueryNode->pExtInfo;
len1 = sprintf(buf + len, "%s #%" PRIu64 ") time_range: %" PRId64 " - %" PRId64,
pInfo->tableName, pInfo->uid, pInfo->window.skey, pInfo->window.ekey);
SQueryTableInfo* pInfo = (SQueryTableInfo*)pQueryNode->pExtInfo;
len1 = sprintf(buf + len, "%s #%" PRIu64 ") time_range: %" PRId64 " - %" PRId64, pInfo->tableName, pInfo->uid,
pInfo->window.skey, pInfo->window.ekey);
assert(len1 > 0);
len += len1;
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SColumn* pCol = taosArrayGetP(pQueryNode->pExpr, i);
len1 = sprintf(buf + len, " [%s #%d] ", pCol->name, pCol->info.colId);
......@@ -467,7 +438,7 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
len += len1;
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* p = &pExprInfo->base;
......@@ -485,18 +456,18 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
len1 = sprintf(buf + len, ")");
len += len1;
//todo print filter info
// todo print filter info
len1 = sprintf(buf + len, " filters:(nil)\n");
len += len1;
break;
}
case QNODE_AGGREGATE: {
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
len += sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len, ", ");
len += len1;
......@@ -509,43 +480,43 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
}
case QNODE_TIMEWINDOW: {
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
len += sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
len1 = sprintf(buf + len,") ");
len1 = sprintf(buf + len, ") ");
len += len1;
SInterval* pInterval = pQueryNode->pExtInfo;
// todo dynamic return the time precision
len1 = sprintf(buf + len, "interval:%" PRId64 "(%s), sliding:%" PRId64 "(%s), offset:%" PRId64 "(%s)\n",
pInterval->interval, TSDB_TIME_PRECISION_MILLI_STR, pInterval->sliding, TSDB_TIME_PRECISION_MILLI_STR,
pInterval->offset, TSDB_TIME_PRECISION_MILLI_STR);
pInterval->interval, TSDB_TIME_PRECISION_MILLI_STR, pInterval->sliding,
TSDB_TIME_PRECISION_MILLI_STR, pInterval->offset, TSDB_TIME_PRECISION_MILLI_STR);
len += len1;
break;
}
case QNODE_STATEWINDOW: {
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
len1 = sprintf(buf + len,") ");
len1 = sprintf(buf + len, ") ");
len += len1;
SColumn* pCol = pQueryNode->pExtInfo;
......@@ -555,44 +526,44 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
}
case QNODE_SESSIONWINDOW: {
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
SSqlExpr* pExpr = &pExprInfo->base;
len += sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
len1 = sprintf(buf + len,") ");
len1 = sprintf(buf + len, ") ");
len += len1;
struct SSessionWindow* ps = pQueryNode->pExtInfo;
len1 = sprintf(buf + len, "col:[%s #%d], gap:%"PRId64" (ms) \n", ps->col.name, ps->col.info.colId, ps->gap);
len1 = sprintf(buf + len, "col:[%s #%d], gap:%" PRId64 " (ms) \n", ps->col.name, ps->col.info.colId, ps->gap);
len += len1;
break;
}
case QNODE_GROUPBY: { // todo hide the invisible column
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
case QNODE_GROUPBY: {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSqlExpr* pExpr = &pExprInfo->base;
len1 = sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
len1 = sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId);
len += len1;
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
SGroupbyExpr* pGroupbyExpr = pQueryNode->pExtInfo;
len1 = sprintf(buf + len,") groupby_col: ");
len1 = sprintf(buf + len, ") groupby_col: ");
len += len1;
for(int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) {
for (int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) {
SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i);
len1 = sprintf(buf + len, "[%s #%d] ", pCol->name, pCol->info.colId);
len += len1;
......@@ -604,58 +575,75 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
case QNODE_FILL: {
SFillEssInfo* pEssInfo = pQueryNode->pExtInfo;
len1 = sprintf(buf + len,"%d", pEssInfo->fillType);
len1 = sprintf(buf + len, "%d", pEssInfo->fillType);
len += len1;
if (pEssInfo->fillType == TSDB_FILL_SET_VALUE) {
len1 = sprintf(buf + len,", val:");
len1 = sprintf(buf + len, ", val:");
len += len1;
// todo get the correct fill data type
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
len1 = sprintf(buf + len,"%"PRId64, pEssInfo->val[i]);
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
len1 = sprintf(buf + len, "%" PRId64, pEssInfo->val[i]);
len += len1;
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
}
len1 = sprintf(buf + len,")\n");
len1 = sprintf(buf + len, ")\n");
len += len1;
break;
}
case QNODE_LIMIT: {
SLimit* pVal = pQueryNode->pExtInfo;
len1 = sprintf(buf + len,"limit: %"PRId64", offset: %"PRId64")\n", pVal->limit, pVal->offset);
len1 = sprintf(buf + len, "limit: %" PRId64 ", offset: %" PRId64 ")\n", pVal->limit, pVal->offset);
len += len1;
break;
}
case QNODE_DISTINCT:
case QNODE_TAGSCAN: {
len1 = sprintf(buf + len,"cols: ");
len1 = sprintf(buf + len, "cols: ");
len += len1;
for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i);
SSchema* resSchema = &pExprInfo->base.resSchema;
SSchema* resSchema = &pExprInfo->base.resSchema;
len1 = sprintf(buf + len,"[%s #%d]", resSchema->name, resSchema->colId);
len1 = sprintf(buf + len, "[%s #%d]", resSchema->name, resSchema->colId);
len += len1;
if (i < pQueryNode->numOfExpr - 1) {
len1 = sprintf(buf + len,", ");
len1 = sprintf(buf + len, ", ");
len += len1;
}
}
len1 = sprintf(buf + len,")\n");
len1 = sprintf(buf + len, ")\n");
len += len1;
break;
}
case QNODE_SORT: {
len1 = sprintf(buf + len, "cols:");
len += len1;
SArray* pSort = pQueryNode->pExtInfo;
for (int32_t i = 0; i < taosArrayGetSize(pSort); ++i) {
SOrder* p = taosArrayGet(pSort, i);
len1 = sprintf(buf + len, " [%s #%d %s]", p->col.name, p->col.info.colId, p->order == TSDB_ORDER_ASC? "ASC":"DESC");
len += len1;
}
len1 = sprintf(buf + len, ")\n");
len += len1;
break;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册