From 343df4e2a078a63c20e2624ca32a745f56edf62d Mon Sep 17 00:00:00 2001 From: slguan Date: Thu, 29 Aug 2019 17:45:10 +0800 Subject: [PATCH] fix the issue #435 --- src/client/src/tscSQLParser.c | 68 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index e5692d154c..5c9ba52d5a 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -108,7 +108,7 @@ static int32_t validateColumnName(char* name); static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo); static bool hasTimestampForPointInterpQuery(SSqlCmd* pCmd); static void updateTagColumnIndex(SSqlCmd* pCmd); -static int32_t setLimitOffsetValueInfo(SSqlObj* pSql, SQuerySQL* pQuerySql); +static int32_t parseLimitClause(SSqlObj* pSql, SQuerySQL* pQuerySql); static void addRequiredTagColumn(SSqlCmd* pCmd, int32_t tagColIndex); static int32_t parseCreateDBOptions(SCreateDBInfo* pCreateDbSql, SSqlCmd* pCmd); @@ -876,7 +876,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) { pCmd->limit = pQuerySql->limit; /* temporarily save the original limitation value */ - if ((code = setLimitOffsetValueInfo(pSql, pQuerySql)) != TSDB_CODE_SUCCESS) { + if ((code = parseLimitClause(pSql, pQuerySql)) != TSDB_CODE_SUCCESS) { return code; } @@ -3930,20 +3930,29 @@ bool hasTimestampForPointInterpQuery(SSqlCmd* pCmd) { return (pCmd->stime == pCmd->etime) && (pCmd->stime != 0); } -int32_t setLimitOffsetValueInfo(SSqlObj* pSql, SQuerySQL* pQuerySql) { - SSqlCmd* pCmd = &pSql->cmd; - bool isMetric = UTIL_METER_IS_METRIC(pCmd); +int32_t parseLimitClause(SSqlObj* pSql, SQuerySQL* pQuerySql) { + SSqlCmd* pCmd = &pSql->cmd; - const char* msg0 = "soffset can not be less than 0"; - const char* msg1 = "offset can not be less than 0"; - const char* msg2 = "slimit/soffset only available for STable query"; - const char* msg3 = "function not supported on table"; + const char* msg0 = "soffset/offset can not be less than 0"; + const char* msg1 = "slimit/soffset only available for STable query"; + const char* msg2 = "function not supported on table"; + const char* msg3 = "slimit/soffset can not apply to projection query"; // handle the limit offset value, validate the limit pCmd->limit = pQuerySql->limit; pCmd->glimit = pQuerySql->glimit; - if (isMetric) { + if (pCmd->glimit.offset < 0 || pCmd->limit.offset < 0) { + setErrMsg(pCmd, msg0); + return TSDB_CODE_INVALID_SQL; + } + + if (pCmd->limit.limit == 0) { + tscTrace("%p limit 0, no output result", pSql); + pCmd->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; + } + + if (UTIL_METER_IS_METRIC(pCmd)) { bool queryOnTags = false; int32_t ret = tscQueryOnlyMetricTags(pCmd, &queryOnTags); if (ret != TSDB_CODE_SUCCESS) { @@ -3952,34 +3961,30 @@ int32_t setLimitOffsetValueInfo(SSqlObj* pSql, SQuerySQL* pQuerySql) { if (queryOnTags == true) { // local handle the metric tag query pCmd->command = TSDB_SQL_RETRIEVE_TAGS; + } else { + if (tscProjectionQueryOnMetric(pSql) && (pCmd->glimit.limit > 0 || pCmd->glimit.offset > 0)) { + setErrMsg(pCmd, msg3); + return TSDB_CODE_INVALID_SQL; + } } - if (pCmd->glimit.limit == 0 || pCmd->limit.limit == 0) { + if (pCmd->glimit.limit == 0) { tscTrace("%p limit 0, no output result", pSql); pCmd->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; return TSDB_CODE_SUCCESS; } - if (pCmd->glimit.offset < 0) { - setErrMsg(pCmd, msg0); - return TSDB_CODE_INVALID_SQL; - } - /* - * get the distribution of all meters among available vnodes that satisfy query condition from mnode , - * then launching multiple async-queries on referenced vnodes, which is the first-stage query operation] + * get the distribution of all tables among available virtual nodes that satisfy query condition and + * created according to this super table from management node. + * And then launching multiple async-queries on required virtual nodes, which is the first-stage query operation. */ int32_t code = tscGetMetricMeta(pSql, pCmd->name); if (code != TSDB_CODE_SUCCESS) { return code; } - /* - * Query results are empty. Therefore, the result is filled with 0 if count function is employed in selection - * clause. - * - * The fill of empty result is required only when interval clause is absent. - */ + //No tables included. No results generated. Query results are empty. SMetricMeta* pMetricMeta = pCmd->pMetricMeta; if (pCmd->pMeterMeta == NULL || pMetricMeta == NULL || pMetricMeta->numOfVnodes == 0 || pMetricMeta->numOfMeters == 0) { @@ -3991,27 +3996,18 @@ int32_t setLimitOffsetValueInfo(SSqlObj* pSql, SQuerySQL* pQuerySql) { pCmd->globalLimit = pCmd->limit.limit; } else { if (pCmd->glimit.limit != -1 || pCmd->glimit.offset != 0) { - setErrMsg(pCmd, msg2); + setErrMsg(pCmd, msg1); return TSDB_CODE_INVALID_SQL; } + // filter the query functions operating on "tbname" column that are not supported by normal columns. for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { SSqlExpr* pExpr = tscSqlExprGet(pCmd, i); if (pExpr->colInfo.colIdx == -1) { - setErrMsg(pCmd, msg3); + setErrMsg(pCmd, msg2); return TSDB_CODE_INVALID_SQL; } } - - if (pCmd->limit.limit == 0) { - tscTrace("%p limit 0, no output result", pSql); - pCmd->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; - } - - if (pCmd->limit.offset < 0) { - setErrMsg(pCmd, msg1); - return TSDB_CODE_INVALID_SQL; - } } return TSDB_CODE_SUCCESS;