diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index d2c52e972af5aa65bc97497f93936187fc97164f..d0141835a38df44515e4a36627e42fa11718d97b 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -229,8 +229,9 @@ typedef struct STableDataBlocks { typedef struct SQueryInfo { int16_t command; // the command may be different for each subclause, so keep it seperately. - uint32_t type; // query/insert type + char intervalTimeUnit; char slidingTimeUnit; + uint32_t type; // query/insert type STimeWindow window; // query time window int64_t intervalTime; // aggregation time interval int64_t slidingTime; // sliding window in mseconds diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 5ce4c7125f3111cead393057e55e977e5cb6ede1..1fb8594588e05f533a3fb8b5458e3d5179e18560 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -586,22 +586,21 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ } // interval is not null - SStrToken* t = &pQuerySql->interval; - if (getTimestampInUsFromStr(t->z, t->n, &pQueryInfo->intervalTime) != TSDB_CODE_SUCCESS) { + SSQLToken* t = &pQuerySql->interval; + if (parseDuration(t->z, t->n, &pQueryInfo->intervalTime, &pQueryInfo->intervalTimeUnit) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } - // if the unit of time window value is millisecond, change the value from microsecond - if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) { - pQueryInfo->intervalTime = pQueryInfo->intervalTime / 1000; - } - - /* parser has filter the illegal type, no need to check here */ - pQueryInfo->slidingTimeUnit = pQuerySql->interval.z[pQuerySql->interval.n - 1]; + if (pQueryInfo->intervalTimeUnit != 'n' && pQueryInfo->intervalTimeUnit != 'y') { + // if the unit of time window value is millisecond, change the value from microsecond + if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) { + pQueryInfo->intervalTime = pQueryInfo->intervalTime / 1000; + } - // interval cannot be less than 10 milliseconds - if (pQueryInfo->intervalTime < tsMinIntervalTime) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); + // interval cannot be less than 10 milliseconds + if (pQueryInfo->intervalTime < tsMinIntervalTime) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); + } } // for top/bottom + interval query, we do not add additional timestamp column in the front @@ -666,28 +665,35 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu const char* msg0 = "sliding value too small"; const char* msg1 = "sliding value no larger than the interval value"; const char* msg2 = "sliding value can not less than 1% of interval value"; + const char* msg3 = "does not support sliding when interval is natual month/year"; const static int32_t INTERVAL_SLIDING_FACTOR = 100; STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); - SStrToken* pSliding = &pQuerySql->sliding; - if (pSliding->n != 0) { - getTimestampInUsFromStr(pSliding->z, pSliding->n, &pQueryInfo->slidingTime); - if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) { - pQueryInfo->slidingTime /= 1000; - } + SSQLToken* pSliding = &pQuerySql->sliding; + if (pSliding->n == 0) { + pQueryInfo->slidingTimeUnit = pQueryInfo->intervalTimeUnit; + pQueryInfo->slidingTime = pQueryInfo->intervalTime; + return TSDB_CODE_SUCCESS; + } - if (pQueryInfo->slidingTime < tsMinSlidingTime) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0); - } + if (pQueryInfo->intervalTimeUnit == 'n' || pQueryInfo->intervalTimeUnit == 'y') { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); + } - if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) { - return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); - } - } else { - pQueryInfo->slidingTime = pQueryInfo->intervalTime; + getTimestampInUsFromStr(pSliding->z, pSliding->n, &pQueryInfo->slidingTime); + if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) { + pQueryInfo->slidingTime /= 1000; + } + + if (pQueryInfo->slidingTime < tsMinSlidingTime) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0); + } + + if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } if ((pQueryInfo->intervalTime != 0) && (pQueryInfo->intervalTime/pQueryInfo->slidingTime > INTERVAL_SLIDING_FACTOR)) { diff --git a/src/os/inc/osTime.h b/src/os/inc/osTime.h index cd2553f75336bc00225b4292638b3eb96f082ae9..97432ca24112805b1352b47e1ba2e34503477fb3 100644 --- a/src/os/inc/osTime.h +++ b/src/os/inc/osTime.h @@ -64,6 +64,7 @@ static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) { } int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts); +int32_t parseDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit); int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth); void deltaToUtcInitOnce(); diff --git a/src/os/src/detail/osTime.c b/src/os/src/detail/osTime.c index 57634e468a87c9e482794fe1937a108d646cfaa1..9d8328a71b19c5a37eaa29fba8f2844c95dd77ca 100644 --- a/src/os/src/detail/osTime.c +++ b/src/os/src/detail/osTime.c @@ -319,6 +319,8 @@ int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec) { *time = factor * seconds + fraction; return 0; } + + static int32_t getTimestampInUsFromStrImpl(int64_t val, char unit, int64_t* result) { *result = val; @@ -384,6 +386,23 @@ int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts) { return getTimestampInUsFromStrImpl(timestamp, token[tokenlen - 1], ts); } +int32_t parseDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit) { + errno = 0; + + /* get the basic numeric value */ + *duration = strtoll(token, NULL, 10); + if (errno != 0) { + return -1; + } + + *unit = token[tokenLen - 1]; + if (*unit == 'n' || *unit == 'y') { + return 0; + } + + return getTimestampInUsFromStrImpl(*duration, *unit, duration); +} + // internal function, when program is paused in debugger, // one can call this function from debugger to print a // timestamp as human readable string, for example (gdb):