未验证 提交 37f124ac 编写于 作者: D dapan1121 提交者: GitHub

Merge pull request #8800 from taosdata/fix/TD-11074-master

Fix/td 11074 fix err logic order by tbname & optimize order by logic
......@@ -3130,13 +3130,15 @@ int32_t doGetColumnIndexByName(SStrToken* pToken, SQueryInfo* pQueryInfo, SColum
const char* msg0 = "ambiguous column name";
const char* msg1 = "invalid column name";
if (pToken->n == 0) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
if (isTablenameToken(pToken)) {
pIndex->columnIndex = TSDB_TBNAME_COLUMN_INDEX;
} else if (strlen(DEFAULT_PRIMARY_TIMESTAMP_COL_NAME) == pToken->n &&
strncasecmp(pToken->z, DEFAULT_PRIMARY_TIMESTAMP_COL_NAME, pToken->n) == 0) {
pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest
} else if (pToken->n == 0) {
pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest
} else {
// not specify the table name, try to locate the table tsc_index by column name
if (pIndex->tableIndex == COLUMN_INDEX_INITIAL_VAL) {
......@@ -5562,20 +5564,25 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
}
int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) {
const char* msg0 = "only support order by primary timestamp";
const char* msg1 = "invalid column name";
const char* msg2 = "order by primary timestamp, first tag or groupby column in groupby clause allowed";
const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed";
const char* msg4 = "orderby column must projected in subquery";
const char* msg0 = "only one column allowed in orderby";
const char* msg1 = "invalid column name in orderby clause";
const char* msg2 = "too many order by columns";
const char* msg3 = "only primary timestamp/tbname/first tag in groupby clause allowed";
const char* msg4 = "only tag in groupby clause allowed in order clause";
const char* msg5 = "only primary timestamp/column in top/bottom function allowed as order column";
const char* msg6 = "only primary timestamp allowed as the second order column";
const char* msg7 = "only primary timestamp/column in groupby clause allowed as order column";
const char* msg8 = "only column in groupby clause allowed as order column";
const char* msg9 = "orderby column must projected in subquery";
const char* msg10 = "not support distinct mixed with order by";
const char* msg11 = "not support order with udf";
const char* msg12 = "order by tags not supported with diff/derivative/csum/mavg";
setDefaultOrderInfo(pQueryInfo);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (pQueryInfo->distinct || pSqlNode->pSortOrder == NULL) {
if (pSqlNode->pSortOrder == NULL) {
return TSDB_CODE_SUCCESS;
}
char* pMsgBuf = tscGetErrorMsgPayload(pCmd);
SArray* pSortOrder = pSqlNode->pSortOrder;
......@@ -5583,34 +5590,43 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
* for table query, there is only one or none order option is allowed, which is the
* ts or values(top/bottom) order is supported.
*
* for super table query, the order option must be less than 3.
* for super table query, the order option must be less than 3 and the second must be ts.
*
* order by has 5 situations
* 1. from stable group by tag1 order by tag1 [ts]
* 2. from stable group by tbname order by tbname [ts]
* 3. from stable/table group by column1 order by column1
* 4. from stable/table order by ts
* 5. select stable/table top(column2,1) ... order by column2
*/
size_t size = taosArrayGetSize(pSortOrder);
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) {
if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
if (size > 1) {
return invalidOperationMsg(pMsgBuf, msg0);
}
} else {
if (size > 2) {
return invalidOperationMsg(pMsgBuf, msg3);
return invalidOperationMsg(pMsgBuf, msg2);
}
}
if (size > 0 && pQueryInfo->distinct) {
return invalidOperationMsg(pMsgBuf, msg10);
}
// handle the first part of order by
tVariant* pVar = taosArrayGet(pSortOrder, 0);
// e.g., order by 1 asc, return directly with out further check.
if (pVar->nType >= TSDB_DATA_TYPE_TINYINT && pVar->nType <= TSDB_DATA_TYPE_BIGINT) {
return TSDB_CODE_SUCCESS;
if (pVar->nType != TSDB_DATA_TYPE_BINARY){
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
SStrToken columnName = {pVar->nLen, pVar->nType, pVar->pz};
SColumnIndex tsc_index = COLUMN_INDEX_INITIALIZER;
SColumnIndex indexColumn = COLUMN_INDEX_INITIALIZER;
bool udf = false;
if (pQueryInfo->pUdfInfo && taosArrayGetSize(pQueryInfo->pUdfInfo) > 0) {
int32_t usize = (int32_t)taosArrayGetSize(pQueryInfo->pUdfInfo);
for (int32_t i = 0; i < usize; ++i) {
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, i);
if (pUdfInfo->funcType == TSDB_UDF_TYPE_SCALAR) {
......@@ -5621,7 +5637,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
}
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query
if (getColumnIndexByName(&columnName, pQueryInfo, &tsc_index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
if (getColumnIndexByName(&columnName, pQueryInfo, &indexColumn, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(pMsgBuf, msg1);
}
......@@ -5629,43 +5645,49 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
bool orderByTS = false;
bool orderByGroupbyCol = false;
if (tsc_index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
int32_t relTagIndex = tsc_index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
if (indexColumn.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // order by tag1
int32_t relTagIndex = indexColumn.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
// it is a tag column
if (pQueryInfo->groupbyExpr.columnInfo == NULL) {
return invalidOperationMsg(pMsgBuf, msg2);
return invalidOperationMsg(pMsgBuf, msg4);
}
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0);
if (relTagIndex == pColIndex->colIndex) {
orderByTags = true;
}
} else if (tsc_index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
orderByTags = true;
}
if (PRIMARYKEY_TIMESTAMP_COL_INDEX == tsc_index.columnIndex) {
} else if (indexColumn.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { // order by tbname
// it is a tag column
if (pQueryInfo->groupbyExpr.columnInfo == NULL) {
return invalidOperationMsg(pMsgBuf, msg4);
}
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0);
if (TSDB_TBNAME_COLUMN_INDEX == pColIndex->colIndex) {
orderByTags = true;
}
}else if (indexColumn.columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { // order by ts
orderByTS = true;
}
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
if (PRIMARYKEY_TIMESTAMP_COL_INDEX != tsc_index.columnIndex && pColIndex->colIndex == tsc_index.columnIndex) {
orderByGroupbyCol = true;
}else{ // order by normal column
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
if (pColIndex->colIndex == indexColumn.columnIndex) {
orderByGroupbyCol = true;
}
}
}
if (!(orderByTags || orderByTS || orderByGroupbyCol) && !isTopBottomQuery(pQueryInfo)) {
return invalidOperationMsg(pMsgBuf, msg3);
} else { // order by top/bottom result value column is not supported in case of interval query.
assert(!(orderByTags && orderByTS && orderByGroupbyCol));
}
size_t s = taosArrayGetSize(pSortOrder);
if (s == 1) {
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = tsc_index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
if (tscIsDiffDerivQuery(pQueryInfo)) {
return invalidOperationMsg(pMsgBuf, msg12);
}
pQueryInfo->groupbyExpr.orderIndex = indexColumn.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
......@@ -5673,25 +5695,27 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
pQueryInfo->order.orderColId = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->order.orderColId = pSchema[indexColumn.columnIndex].colId;
if (udf) {
return invalidOperationMsg(pMsgBuf, msg11);
}
} else if (isTopBottomQuery(pQueryInfo)) {
int32_t topBotIndex = tscGetTopBotQueryExprIndex(pQueryInfo);
assert(topBotIndex >= 1);
/* order of top/bottom query in interval is not valid */
SExprInfo* pExpr = tscExprGet(pQueryInfo, topBotIndex-1);
int32_t pos = tscGetTopBotQueryExprIndex(pQueryInfo);
assert(pos > 0);
SExprInfo* pExpr = tscExprGet(pQueryInfo, pos - 1);
assert(pExpr->base.functionId == TSDB_FUNC_TS);
pExpr = tscExprGet(pQueryInfo, topBotIndex);
if (pExpr->base.colInfo.colIndex != tsc_index.columnIndex && tsc_index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg2);
pExpr = tscExprGet(pQueryInfo, pos);
if (pExpr->base.colInfo.colIndex != indexColumn.columnIndex && indexColumn.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg5);
}
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->order.orderColId = pSchema[indexColumn.columnIndex].colId;
return TSDB_CODE_SUCCESS;
} else {
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
......@@ -5705,7 +5729,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
// orderby ts query on super table
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
bool found = false;
bool found = false;
for (int32_t i = 0; i < tscNumOfExprs(pQueryInfo); ++i) {
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
if (pExpr->base.functionId == TSDB_FUNC_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
......@@ -5714,7 +5738,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
}
}
if (!found && pQueryInfo->pDownstream) {
return invalidOperationMsg(pMsgBuf, msg4);
return invalidOperationMsg(pMsgBuf, msg9);
}
addPrimaryTsColIntoResult(pQueryInfo, pCmd);
}
......@@ -5722,11 +5746,11 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
} else {
tVariantListItem *pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = tsc_index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
pQueryInfo->groupbyExpr.orderIndex = indexColumn.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
pQueryInfo->groupbyExpr.orderType = pItem->sortOrder;
} else if (orderByGroupbyCol){
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = tsc_index.columnIndex;
pQueryInfo->order.orderColId = indexColumn.columnIndex;
if (udf) {
return invalidOperationMsg(pMsgBuf, msg11);
}
......@@ -5741,12 +5765,12 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
pItem = taosArrayGet(pSqlNode->pSortOrder, 1);
tVariant* pVar2 = &pItem->pVar;
SStrToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz};
if (getColumnIndexByName(&cname, pQueryInfo, &tsc_index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
if (getColumnIndexByName(&cname, pQueryInfo, &indexColumn, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(pMsgBuf, msg1);
}
if (tsc_index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg2);
if (indexColumn.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg6);
} else {
tVariantListItem* p1 = taosArrayGet(pSortOrder, 1);
pQueryInfo->order.order = p1->sortOrder;
......@@ -5755,20 +5779,24 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
}
} else if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo)) { // check order by clause for normal table & temp table
if (getColumnIndexByName(&columnName, pQueryInfo, &tsc_index, pMsgBuf) != TSDB_CODE_SUCCESS) {
if (getColumnIndexByName(&columnName, pQueryInfo, &indexColumn, pMsgBuf) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(pMsgBuf, msg1);
}
if (tsc_index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) {
if (indexColumn.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) {
bool validOrder = false;
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
validOrder = (pColIndex->colIndex == tsc_index.columnIndex);
validOrder = (pColIndex->colIndex == indexColumn.columnIndex);
}
if (!validOrder) {
return invalidOperationMsg(pMsgBuf, msg2);
return invalidOperationMsg(pMsgBuf, msg7);
}
if (udf) {
return invalidOperationMsg(pMsgBuf, msg11);
}
if (udf) {
......@@ -5776,39 +5804,35 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
}
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderIndex = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->groupbyExpr.orderIndex = pSchema[indexColumn.columnIndex].colId;
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
}
if (isTopBottomQuery(pQueryInfo)) {
bool validOrder = false;
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
validOrder = (pColIndex->colIndex == tsc_index.columnIndex);
} else {
int32_t topBotIndex = tscGetTopBotQueryExprIndex(pQueryInfo);
assert(topBotIndex >= 1);
/* order of top/bottom query in interval is not valid */
SExprInfo* pExpr = tscExprGet(pQueryInfo, topBotIndex-1);
assert(pExpr->base.functionId == TSDB_FUNC_TS);
pExpr = tscExprGet(pQueryInfo, topBotIndex);
if (pExpr->base.colInfo.colIndex != tsc_index.columnIndex && tsc_index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg2);
if (pColIndex->colIndex != indexColumn.columnIndex) {
return invalidOperationMsg(pMsgBuf, msg8);
}
} else {
int32_t pos = tscGetTopBotQueryExprIndex(pQueryInfo);
assert(pos > 0);
SExprInfo* pExpr = tscExprGet(pQueryInfo, pos - 1);
assert(pExpr->base.functionId == TSDB_FUNC_TS);
validOrder = true;
}
pExpr = tscExprGet(pQueryInfo, pos);
if (!validOrder) {
return invalidOperationMsg(pMsgBuf, msg2);
if (pExpr->base.colInfo.colIndex != indexColumn.columnIndex && indexColumn.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidOperationMsg(pMsgBuf, msg5);
}
}
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->order.orderColId = pSchema[indexColumn.columnIndex].colId;
return TSDB_CODE_SUCCESS;
}
......@@ -5818,13 +5842,13 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->order.orderColId = pSchema[indexColumn.columnIndex].colId;
} else {
// handle the temp table order by clause. You can order by any single column in case of the temp table, created by
// inner subquery.
assert(UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo) && taosArrayGetSize(pSqlNode->pSortOrder) == 1);
if (getColumnIndexByName(&columnName, pQueryInfo, &tsc_index, pMsgBuf) != TSDB_CODE_SUCCESS) {
if (getColumnIndexByName(&columnName, pQueryInfo, &indexColumn, pMsgBuf) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(pMsgBuf, msg1);
}
......@@ -5834,7 +5858,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[tsc_index.columnIndex].colId;
pQueryInfo->order.orderColId = pSchema[indexColumn.columnIndex].colId;
}
return TSDB_CODE_SUCCESS;
......
......@@ -122,6 +122,44 @@ class TDTestCase:
(i, i))
self.checkColumnSorted(1, "desc")
# order by rules: https://jira.taosdata.com:18090/pages/viewpage.action?pageId=123455481
tdSql.error("select tbcol1 from st order by 123")
tdSql.error("select tbcol1 from st order by tbname")
tdSql.error("select tbcol1 from st order by tagcol1")
tdSql.error("select tbcol1 from st order by ''")
tdSql.error("select top(tbcol1, 12) from st1 order by tbcol1,ts")
tdSql.error("select top(tbcol1, 12) from st order by tbcol1,ts,tbcol2")
tdSql.error("select top(tbcol1, 12) from st order by ts, tbcol1")
tdSql.error("select top(tbcol1, 2) from st1 group by tbcol1 order by tbcol2")
tdSql.query("select top(tbcol1, 2) from st1 group by tbcol2 order by tbcol2")
tdSql.query("select top(tbcol1, 12) from st order by tbcol1, ts")
tdSql.query("select avg(tbcol1) from st group by tbname order by tbname")
tdSql.checkData(1, 0, 5.5)
tdSql.checkData(5, 1, "st6")
tdSql.query("select top(tbcol1, 2) from st group by tbname order by tbname")
tdSql.checkData(1, 1, 10)
tdSql.checkData(2, 2, "st2")
tdSql.query("select top(tbcol1, 12) from st order by tbcol1")
tdSql.checkData(1, 1, 9)
tdSql.error("select top(tbcol1, 12) from st1 order by tbcol1,ts")
tdSql.error("select top(tbcol1, 12),tbname from st order by tbcol1,tbname")
tdSql.query("select top(tbcol1, 12) from st group by tbname order by tbname desc")
tdSql.checkData(1, 2, "st10")
tdSql.checkData(10, 2, "st9")
tdSql.query("select top(tbcol1, 2) from st group by tbname order by tbname desc,ts")
tdSql.checkData(1, 2, "st10")
tdSql.checkData(10, 2, "st5")
tdSql.checkData(0, 0, "2018-09-17 09:00:00.109")
tdSql.checkData(1, 0, "2018-09-17 09:00:00.110")
tdSql.checkData(2, 0, "2018-09-17 09:00:00.099")
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册