diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 9b18453d7b134c998c3aec6c19f6379b366f895d..258b8056dcc1bf344e22a30a1236ee710d1d770c 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -3256,13 +3256,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 index by column name if (pIndex->tableIndex == COLUMN_INDEX_INITIAL_VAL) { @@ -5873,10 +5875,17 @@ 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); } @@ -5886,15 +5895,14 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq } } if (size > 0 && pQueryInfo->distinct) { - return invalidOperationMsg(pMsgBuf, msg10); + 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}; @@ -5903,7 +5911,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq 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) { @@ -5922,9 +5930,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq bool orderByTS = false; bool orderByGroupbyCol = false; - if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { + if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // order by tag1 int32_t relTagIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta); - + // it is a tag column if (pQueryInfo->groupbyExpr.columnInfo == NULL) { return invalidOperationMsg(pMsgBuf, msg4); @@ -5933,26 +5941,29 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq if (relTagIndex == pColIndex->colIndex) { orderByTags = true; } - } else if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - orderByTags = true; - } - - if (PRIMARYKEY_TIMESTAMP_COL_INDEX == index.columnIndex) { + } else if (index.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 (index.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 != index.columnIndex && pColIndex->colIndex == 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 == index.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); @@ -6087,7 +6098,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) { SColIndex* pColIndex = taosArrayGet(columnInfo, 0); - if (pColIndex->colIndex == index.columnIndex) { + if (pColIndex->colIndex != index.columnIndex) { return invalidOperationMsg(pMsgBuf, msg8); } } else { diff --git a/tests/pytest/query/querySort.py b/tests/pytest/query/querySort.py index 17022bdc41057bcb67e1530a2cb6d399bada20ff..31d53ea0041b0656c52ebf0afe3954290f8763d4 100644 --- a/tests/pytest/query/querySort.py +++ b/tests/pytest/query/querySort.py @@ -97,7 +97,7 @@ class TDTestCase: self.checkColumnSorted(0, "desc") print("======= step 2: verify order for special column =========") - + tdSql.query("select tbcol1 from st order by ts desc") tdSql.query("select tbcol6 from st order by ts desc") @@ -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__)