Merge pull request #6365 from taosdata/feature/td-3126
[TD-3126]<feature>support nanoseconds time precision
This commit is contained in:
commit
8347db05b1
|
@ -107,14 +107,10 @@ int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int1
|
|||
return tscInvalidOperationMsg(error, "value expected in timestamp", sToken.z);
|
||||
}
|
||||
|
||||
if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval) != TSDB_CODE_SUCCESS) {
|
||||
if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, timePrec) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (timePrec == TSDB_TIME_PRECISION_MILLI) {
|
||||
interval /= 1000;
|
||||
}
|
||||
|
||||
if (sToken.type == TK_PLUS) {
|
||||
useconds += interval;
|
||||
} else {
|
||||
|
|
|
@ -925,18 +925,15 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
|
|||
|
||||
// interval is not null
|
||||
SStrToken *t = &pSqlNode->interval.interval;
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, &pQueryInfo->interval.intervalUnit) != TSDB_CODE_SUCCESS) {
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval,
|
||||
&pQueryInfo->interval.intervalUnit, tinfo.precision) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
// if the unit of time window value is millisecond, change the value from microsecond
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->interval.interval = pQueryInfo->interval.interval / 1000;
|
||||
}
|
||||
|
||||
// interval cannot be less than 10 milliseconds
|
||||
if (pQueryInfo->interval.interval < tsMinIntervalTime) {
|
||||
if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MILLI) < tsMinIntervalTime) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
}
|
||||
|
@ -1012,6 +1009,8 @@ int32_t validateSessionNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode * pS
|
|||
const char* msg3 = "invalid column name";
|
||||
const char* msg4 = "invalid time window";
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
// no session window
|
||||
if (!TPARSER_HAS_TOKEN(pSqlNode->sessionVal.gap)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -1021,7 +1020,7 @@ int32_t validateSessionNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode * pS
|
|||
SStrToken* gap = &pSqlNode->sessionVal.gap;
|
||||
|
||||
char timeUnit = 0;
|
||||
if (parseNatualDuration(gap->z, gap->n, &pQueryInfo->sessionWindow.gap, &timeUnit) != TSDB_CODE_SUCCESS) {
|
||||
if (parseNatualDuration(gap->z, gap->n, &pQueryInfo->sessionWindow.gap, &timeUnit, tinfo.precision) != TSDB_CODE_SUCCESS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
}
|
||||
|
||||
|
@ -1029,13 +1028,6 @@ int32_t validateSessionNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode * pS
|
|||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
// if the unit of time window value is millisecond, change the value from microsecond
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->sessionWindow.gap = pQueryInfo->sessionWindow.gap / 1000;
|
||||
}
|
||||
|
||||
if (pQueryInfo->sessionWindow.gap != 0 && pQueryInfo->interval.interval != 0) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
@ -1072,7 +1064,8 @@ int32_t parseIntervalOffset(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* of
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.offset, &pQueryInfo->interval.offsetUnit) != TSDB_CODE_SUCCESS) {
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.offset,
|
||||
&pQueryInfo->interval.offsetUnit, tinfo.precision) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -1081,10 +1074,6 @@ int32_t parseIntervalOffset(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* of
|
|||
}
|
||||
|
||||
if (pQueryInfo->interval.offsetUnit != 'n' && pQueryInfo->interval.offsetUnit != 'y') {
|
||||
// if the unit of time window value is millisecond, change the value from microsecond
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->interval.offset = pQueryInfo->interval.offset / 1000;
|
||||
}
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
if (pQueryInfo->interval.offset >= pQueryInfo->interval.interval) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
|
@ -1129,12 +1118,10 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* pSl
|
|||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
parseAbsoluteDuration(pSliding->z, pSliding->n, &pQueryInfo->interval.sliding);
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->interval.sliding /= 1000;
|
||||
}
|
||||
parseAbsoluteDuration(pSliding->z, pSliding->n, &pQueryInfo->interval.sliding, tinfo.precision);
|
||||
|
||||
if (pQueryInfo->interval.sliding < tsMinSlidingTime) {
|
||||
if (pQueryInfo->interval.sliding <
|
||||
convertTimePrecision(tsMinSlidingTime, TSDB_TIME_PRECISION_MILLI, tinfo.precision)) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0);
|
||||
}
|
||||
|
||||
|
@ -3317,8 +3304,9 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
return retVal;
|
||||
}
|
||||
} else if ((colType == TSDB_DATA_TYPE_TIMESTAMP) && (TSDB_DATA_TYPE_BIGINT == pRight->value.nType)) {
|
||||
if ((timePrecision == TSDB_TIME_PRECISION_MILLI) && (pRight->flags & (1 << EXPR_FLAG_US_TIMESTAMP))) {
|
||||
pRight->value.i64 /= 1000;
|
||||
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
|
||||
pRight->value.i64 =
|
||||
convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4861,7 +4849,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
|
|||
|
||||
char* seg = strnchr(pRight->value.pz, '-', pRight->value.nLen, false);
|
||||
if (seg != NULL) {
|
||||
if (taosParseTime(pRight->value.pz, &val, pRight->value.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) {
|
||||
if (taosParseTime(pRight->value.pz, &val, pRight->value.nLen, timePrecision, tsDaylight) == TSDB_CODE_SUCCESS) {
|
||||
parsed = true;
|
||||
} else {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
|
@ -4874,18 +4862,6 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
} else if (pRight->tokenId == TK_INTEGER && timePrecision == TSDB_TIME_PRECISION_MILLI) {
|
||||
/*
|
||||
* if the pRight->tokenId == TK_INTEGER/TK_FLOAT, the value is adaptive, we
|
||||
* need the time precision in metermeta to transfer the value in MICROSECOND
|
||||
*
|
||||
* Additional check to avoid data overflow
|
||||
*/
|
||||
if (pRight->value.i64 <= INT64_MAX / 1000) {
|
||||
pRight->value.i64 *= 1000;
|
||||
}
|
||||
} else if (pRight->tokenId == TK_FLOAT && timePrecision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pRight->value.dKey *= 1000;
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
|
@ -4893,33 +4869,19 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
|
|||
* failed to parse timestamp in regular formation, try next
|
||||
* it may be a epoch time in string format
|
||||
*/
|
||||
tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true);
|
||||
|
||||
/*
|
||||
* transfer it into MICROSECOND format if it is a string, since for
|
||||
* TK_INTEGER/TK_FLOAT the value has been transferred
|
||||
*
|
||||
* additional check to avoid data overflow
|
||||
*/
|
||||
if (pRight->tokenId == TK_STRING && timePrecision == TSDB_TIME_PRECISION_MILLI) {
|
||||
if (val <= INT64_MAX / 1000) {
|
||||
val *= 1000;
|
||||
}
|
||||
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
|
||||
pRight->value.i64 = convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t delta = 1;
|
||||
/* for millisecond, delta is 1ms=1000us */
|
||||
if (timePrecision == TSDB_TIME_PRECISION_MILLI) {
|
||||
delta *= 1000;
|
||||
|
||||
tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true);
|
||||
}
|
||||
|
||||
if (optr == TK_LE) {
|
||||
win->ekey = val;
|
||||
} else if (optr == TK_LT) {
|
||||
win->ekey = val - delta;
|
||||
win->ekey = val - 1;
|
||||
} else if (optr == TK_GT) {
|
||||
win->skey = val + delta;
|
||||
win->skey = val + 1;
|
||||
} else if (optr == TK_GE) {
|
||||
win->skey = val;
|
||||
} else if (optr == TK_EQ) {
|
||||
|
@ -5642,8 +5604,10 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
int32_t validateSqlFunctionInStreamSql(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
|
||||
const char* msg0 = "sample interval can not be less than 10ms.";
|
||||
const char* msg1 = "functions not allowed in select clause";
|
||||
|
||||
if (pQueryInfo->interval.interval != 0 && pQueryInfo->interval.interval < 10 &&
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
if (pQueryInfo->interval.interval != 0 &&
|
||||
convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MILLI)< 10 &&
|
||||
pQueryInfo->interval.intervalUnit != 'n' &&
|
||||
pQueryInfo->interval.intervalUnit != 'y') {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0);
|
||||
|
@ -6036,11 +6000,15 @@ static int32_t setTimePrecision(SSqlCmd* pCmd, SCreateDbMsg* pMsg, SCreateDbInfo
|
|||
} else if (strncmp(pToken->z, TSDB_TIME_PRECISION_MICRO_STR, pToken->n) == 0 &&
|
||||
strlen(TSDB_TIME_PRECISION_MICRO_STR) == pToken->n) {
|
||||
pMsg->precision = TSDB_TIME_PRECISION_MICRO;
|
||||
} else if (strncmp(pToken->z, TSDB_TIME_PRECISION_NANO_STR, pToken->n) == 0 &&
|
||||
strlen(TSDB_TIME_PRECISION_NANO_STR) == pToken->n) {
|
||||
pMsg->precision = TSDB_TIME_PRECISION_NANO;
|
||||
} else {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -6682,9 +6650,10 @@ int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCreateDbMsg* pCreate) {
|
|||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
|
||||
if (pCreate->precision != TSDB_TIME_PRECISION_MILLI && pCreate->precision != TSDB_TIME_PRECISION_MICRO) {
|
||||
snprintf(msg, tListLen(msg), "invalid db option timePrecision: %d valid value: [%d, %d]", pCreate->precision,
|
||||
TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO);
|
||||
if (pCreate->precision != TSDB_TIME_PRECISION_MILLI && pCreate->precision != TSDB_TIME_PRECISION_MICRO &&
|
||||
pCreate->precision != TSDB_TIME_PRECISION_NANO) {
|
||||
snprintf(msg, tListLen(msg), "invalid db option timePrecision: %d valid value: [%d, %d, %d]", pCreate->precision,
|
||||
TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO, TSDB_TIME_PRECISION_NANO);
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
|
||||
|
@ -7819,12 +7788,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
||||
if (pTableMeta->tableInfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->window.skey = pQueryInfo->window.skey / 1000;
|
||||
pQueryInfo->window.ekey = pQueryInfo->window.ekey / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
// validate the interval info
|
||||
|
@ -7878,18 +7841,12 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
}
|
||||
|
||||
// set where info
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
if (pSqlNode->pWhere != NULL) {
|
||||
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
pSqlNode->pWhere = NULL;
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->window.skey = pQueryInfo->window.skey / 1000;
|
||||
pQueryInfo->window.ekey = pQueryInfo->window.ekey / 1000;
|
||||
}
|
||||
} else {
|
||||
if (taosArrayGetSize(pSqlNode->from->list) > 1) { // Cross join not allowed yet
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "cross join not supported yet");
|
||||
|
|
|
@ -53,9 +53,7 @@ static int64_t tscGetRetryDelayTime(SSqlStream* pStream, int64_t slidingTime, in
|
|||
|
||||
if (pStream->interval.intervalUnit != 'n' && pStream->interval.intervalUnit != 'y') {
|
||||
// change to ms
|
||||
if (prec == TSDB_TIME_PRECISION_MICRO) {
|
||||
slidingTime = slidingTime / 1000;
|
||||
}
|
||||
slidingTime = convertTimePrecision(slidingTime, pStream->precision, TSDB_TIME_PRECISION_MILLI);
|
||||
|
||||
if (slidingTime < retryDelta) {
|
||||
return slidingTime;
|
||||
|
@ -162,11 +160,7 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
|
|||
pQueryInfo->window.skey = pStream->stime;
|
||||
int64_t etime = taosGetTimestamp(pStream->precision);
|
||||
// delay to wait all data in last time window
|
||||
if (pStream->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
etime -= tsMaxStreamComputDelay * 1000l;
|
||||
} else {
|
||||
etime -= tsMaxStreamComputDelay;
|
||||
}
|
||||
etime -= convertTimePrecision(tsMaxStreamComputDelay, TSDB_TIME_PRECISION_MILLI, pStream->precision);
|
||||
if (etime > pStream->etime) {
|
||||
etime = pStream->etime;
|
||||
} else if (pStream->interval.intervalUnit != 'y' && pStream->interval.intervalUnit != 'n') {
|
||||
|
@ -183,8 +177,8 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
|
|||
int64_t timer = pStream->interval.sliding;
|
||||
if (pStream->interval.intervalUnit == 'y' || pStream->interval.intervalUnit == 'n') {
|
||||
timer = 86400 * 1000l;
|
||||
} else if (pStream->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
timer /= 1000l;
|
||||
} else {
|
||||
timer = convertTimePrecision(timer, pStream->precision, TSDB_TIME_PRECISION_MILLI);
|
||||
}
|
||||
tscSetRetryTimer(pStream, pSql, timer);
|
||||
return;
|
||||
|
@ -378,9 +372,8 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer)
|
|||
}
|
||||
|
||||
static int64_t getLaunchTimeDelay(const SSqlStream* pStream) {
|
||||
int64_t maxDelay =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMaxStreamComputDelay * 1000L : tsMaxStreamComputDelay;
|
||||
|
||||
int64_t maxDelay = convertTimePrecision(tsMaxStreamComputDelay, TSDB_TIME_PRECISION_MILLI, pStream->precision);
|
||||
|
||||
int64_t delayDelta = maxDelay;
|
||||
if (pStream->interval.intervalUnit != 'n' && pStream->interval.intervalUnit != 'y') {
|
||||
delayDelta = (int64_t)(pStream->interval.sliding * tsStreamComputDelayRatio);
|
||||
|
@ -447,16 +440,14 @@ static void tscSetNextLaunchTimer(SSqlStream *pStream, SSqlObj *pSql) {
|
|||
|
||||
timer += getLaunchTimeDelay(pStream);
|
||||
|
||||
if (pStream->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
timer = timer / 1000L;
|
||||
}
|
||||
timer = convertTimePrecision(timer, pStream->precision, TSDB_TIME_PRECISION_MILLI);
|
||||
|
||||
tscSetRetryTimer(pStream, pSql, timer);
|
||||
}
|
||||
|
||||
static int32_t tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
|
||||
int64_t minIntervalTime =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinIntervalTime * 1000L : tsMinIntervalTime;
|
||||
convertTimePrecision(tsMinIntervalTime, TSDB_TIME_PRECISION_MILLI, pStream->precision);
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfo(&pSql->cmd);
|
||||
|
||||
|
@ -480,7 +471,7 @@ static int32_t tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
|
|||
}
|
||||
|
||||
int64_t minSlidingTime =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinSlidingTime * 1000L : tsMinSlidingTime;
|
||||
convertTimePrecision(tsMinSlidingTime, TSDB_TIME_PRECISION_MILLI, pStream->precision);
|
||||
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && pQueryInfo->interval.sliding < minSlidingTime) {
|
||||
tscWarn("0x%"PRIx64" stream:%p, original sliding value:%" PRId64 " too small, reset to:%" PRId64, pSql->self, pStream,
|
||||
|
@ -548,13 +539,12 @@ static int64_t tscGetLaunchTimestamp(const SSqlStream *pStream) {
|
|||
timer = pStream->stime - now;
|
||||
}
|
||||
|
||||
int64_t startDelay =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsStreamCompStartDelay * 1000L : tsStreamCompStartDelay;
|
||||
|
||||
int64_t startDelay = convertTimePrecision(tsStreamCompStartDelay, TSDB_TIME_PRECISION_MILLI, pStream->precision);
|
||||
|
||||
timer += getLaunchTimeDelay(pStream);
|
||||
timer += startDelay;
|
||||
|
||||
return (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? timer / 1000L : timer;
|
||||
return convertTimePrecision(timer, pStream->precision, TSDB_TIME_PRECISION_MILLI);
|
||||
}
|
||||
|
||||
static void tscCreateStream(void *param, TAOS_RES *res, int code) {
|
||||
|
|
|
@ -398,7 +398,10 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
|||
|
||||
time_t tt;
|
||||
int32_t ms = 0;
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
tt = (time_t)(val / 1000000000);
|
||||
ms = val % 1000000000;
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
tt = (time_t)(val / 1000000);
|
||||
ms = val % 1000000;
|
||||
} else {
|
||||
|
@ -419,7 +422,9 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
|||
#endif
|
||||
if (tt <= 0 && ms < 0) {
|
||||
tt--;
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
ms += 1000000000;
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
ms += 1000000;
|
||||
} else {
|
||||
ms += 1000;
|
||||
|
@ -427,9 +432,11 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
|||
}
|
||||
|
||||
struct tm* ptm = localtime(&tt);
|
||||
size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
sprintf(buf + pos, ".%09d", ms);
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
sprintf(buf + pos, ".%06d", ms);
|
||||
} else {
|
||||
sprintf(buf + pos, ".%03d", ms);
|
||||
|
@ -778,6 +785,8 @@ static int calcColWidth(TAOS_FIELD* field, int precision) {
|
|||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (args.is_raw_time) {
|
||||
return MAX(14, width);
|
||||
} if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
return MAX(29, width);
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
return MAX(26, width); // '2020-01-01 00:00:00.000000'
|
||||
} else {
|
||||
|
|
|
@ -1852,7 +1852,9 @@ static void printfQueryMeta() {
|
|||
|
||||
static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
||||
time_t tt;
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
tt = (time_t)(val / 1000000000);
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
tt = (time_t)(val / 1000000);
|
||||
} else {
|
||||
tt = (time_t)(val / 1000);
|
||||
|
@ -1873,7 +1875,9 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
|
|||
struct tm* ptm = localtime(&tt);
|
||||
size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
sprintf(buf + pos, ".%09d", (int)(val % 1000000000));
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
sprintf(buf + pos, ".%06d", (int)(val % 1000000));
|
||||
} else {
|
||||
sprintf(buf + pos, ".%03d", (int)(val % 1000));
|
||||
|
@ -6253,9 +6257,11 @@ static void startMultiThreadInsertData(int threads, char* db_name,
|
|||
if (0 != precision[0]) {
|
||||
if (0 == strncasecmp(precision, "ms", 2)) {
|
||||
timePrec = TSDB_TIME_PRECISION_MILLI;
|
||||
} else if (0 == strncasecmp(precision, "us", 2)) {
|
||||
} else if (0 == strncasecmp(precision, "us", 2)) {
|
||||
timePrec = TSDB_TIME_PRECISION_MICRO;
|
||||
} else {
|
||||
} else if (0 == strncasecmp(precision, "ns", 2)) {
|
||||
timePrec = TSDB_TIME_PRECISION_NANO;
|
||||
} else {
|
||||
errorPrint("Not support precision: %s\n", precision);
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -820,8 +820,13 @@ static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void
|
|||
#endif
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
char *prec = (pDb->cfg.precision == TSDB_TIME_PRECISION_MILLI) ? TSDB_TIME_PRECISION_MILLI_STR
|
||||
: TSDB_TIME_PRECISION_MICRO_STR;
|
||||
char *prec = NULL;
|
||||
switch (pDb->cfg.precision) {
|
||||
case TSDB_TIME_PRECISION_MILLI: prec = TSDB_TIME_PRECISION_MILLI_STR; break;
|
||||
case TSDB_TIME_PRECISION_MICRO: prec = TSDB_TIME_PRECISION_MICRO_STR; break;
|
||||
case TSDB_TIME_PRECISION_NANO: prec = TSDB_TIME_PRECISION_NANO_STR; break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
STR_WITH_SIZE_TO_VARSTR(pWrite, prec, 2);
|
||||
cols++;
|
||||
|
||||
|
|
|
@ -55,6 +55,13 @@ static FORCE_INLINE int64_t taosGetTimestampUs() {
|
|||
return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec;
|
||||
}
|
||||
|
||||
//@return timestamp in nanosecond
|
||||
static FORCE_INLINE int64_t taosGetTimestampNs() {
|
||||
struct timespec systemTime = {0};
|
||||
clock_gettime(CLOCK_REALTIME, &systemTime);
|
||||
return (int64_t)systemTime.tv_sec * 1000000000L + (int64_t)systemTime.tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return timestamp decided by global conf variable, tsTimePrecision
|
||||
* if precision == TSDB_TIME_PRECISION_MICRO, it returns timestamp in microsecond.
|
||||
|
@ -63,7 +70,9 @@ static FORCE_INLINE int64_t taosGetTimestampUs() {
|
|||
static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) {
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
return taosGetTimestampUs();
|
||||
} else {
|
||||
} else if (precision == TSDB_TIME_PRECISION_NANO) {
|
||||
return taosGetTimestampNs();
|
||||
}else {
|
||||
return taosGetTimestampMs();
|
||||
}
|
||||
}
|
||||
|
@ -88,12 +97,13 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision);
|
|||
int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precision);
|
||||
int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char unit, int32_t precision);
|
||||
|
||||
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* ts);
|
||||
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit);
|
||||
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* ts, int32_t timePrecision);
|
||||
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision);
|
||||
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth);
|
||||
void deltaToUtcInitOnce();
|
||||
|
||||
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,13 @@
|
|||
*/
|
||||
|
||||
#define _BSD_SOURCE
|
||||
|
||||
#ifdef DARWIN
|
||||
#define _XOPEN_SOURCE
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include "os.h"
|
||||
|
@ -119,8 +125,9 @@ int64_t parseFraction(char* str, char** end, int32_t timePrec) {
|
|||
|
||||
const int32_t MILLI_SEC_FRACTION_LEN = 3;
|
||||
const int32_t MICRO_SEC_FRACTION_LEN = 6;
|
||||
const int32_t NANO_SEC_FRACTION_LEN = 9;
|
||||
|
||||
int32_t factor[6] = {1, 10, 100, 1000, 10000, 100000};
|
||||
int32_t factor[9] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
|
||||
int32_t times = 1;
|
||||
|
||||
while (str[i] >= '0' && str[i] <= '9') {
|
||||
|
@ -140,12 +147,17 @@ int64_t parseFraction(char* str, char** end, int32_t timePrec) {
|
|||
}
|
||||
|
||||
times = MILLI_SEC_FRACTION_LEN - i;
|
||||
} else {
|
||||
assert(timePrec == TSDB_TIME_PRECISION_MICRO);
|
||||
} else if (timePrec == TSDB_TIME_PRECISION_MICRO) {
|
||||
if (i >= MICRO_SEC_FRACTION_LEN) {
|
||||
i = MICRO_SEC_FRACTION_LEN;
|
||||
}
|
||||
times = MICRO_SEC_FRACTION_LEN - i;
|
||||
} else {
|
||||
assert(timePrec == TSDB_TIME_PRECISION_NANO);
|
||||
if (i >= NANO_SEC_FRACTION_LEN) {
|
||||
i = NANO_SEC_FRACTION_LEN;
|
||||
}
|
||||
times = NANO_SEC_FRACTION_LEN - i;
|
||||
}
|
||||
|
||||
fraction = strnatoi(str, i) * factor[times];
|
||||
|
@ -202,7 +214,9 @@ int32_t parseTimezone(char* str, int64_t* tzOffset) {
|
|||
* 2013-04-12T15:52:01.123+0800
|
||||
*/
|
||||
int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec) {
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : 1000000;
|
||||
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
|
||||
(timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
|
||||
int64_t tzOffset = 0;
|
||||
|
||||
struct tm tm = {0};
|
||||
|
@ -287,7 +301,8 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) {
|
|||
}
|
||||
}
|
||||
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : 1000000;
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
|
||||
(timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
|
||||
*time = factor * seconds + fraction;
|
||||
|
||||
return 0;
|
||||
|
@ -315,37 +330,50 @@ int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec) {
|
|||
}
|
||||
}
|
||||
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : 1000000;
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 :
|
||||
(timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000);
|
||||
*time = factor * seconds + fraction;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int32_t getDurationInUs(int64_t val, char unit, int64_t* result) {
|
||||
*result = val;
|
||||
|
||||
int64_t factor = 1000L;
|
||||
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision) {
|
||||
assert(fromPrecision == TSDB_TIME_PRECISION_MILLI ||
|
||||
fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||
fromPrecision == TSDB_TIME_PRECISION_NANO);
|
||||
assert(toPrecision == TSDB_TIME_PRECISION_MILLI ||
|
||||
toPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||
toPrecision == TSDB_TIME_PRECISION_NANO);
|
||||
static double factors[3][3] = { {1., 1000., 1000000.},
|
||||
{1.0 / 1000, 1., 1000.},
|
||||
{1.0 / 1000000, 1.0 / 1000, 1.} };
|
||||
return (int64_t)((double)time * factors[fromPrecision][toPrecision]);
|
||||
}
|
||||
static int32_t getDuration(int64_t val, char unit, int64_t* result, int32_t timePrecision) {
|
||||
|
||||
switch (unit) {
|
||||
case 's':
|
||||
(*result) *= MILLISECOND_PER_SECOND*factor;
|
||||
(*result) = convertTimePrecision(val * MILLISECOND_PER_SECOND, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'm':
|
||||
(*result) *= MILLISECOND_PER_MINUTE*factor;
|
||||
(*result) = convertTimePrecision(val * MILLISECOND_PER_MINUTE, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'h':
|
||||
(*result) *= MILLISECOND_PER_HOUR*factor;
|
||||
(*result) = convertTimePrecision(val * MILLISECOND_PER_HOUR, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'd':
|
||||
(*result) *= MILLISECOND_PER_DAY*factor;
|
||||
(*result) = convertTimePrecision(val * MILLISECOND_PER_DAY, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'w':
|
||||
(*result) *= MILLISECOND_PER_WEEK*factor;
|
||||
(*result) = convertTimePrecision(val * MILLISECOND_PER_WEEK, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'a':
|
||||
(*result) *= factor;
|
||||
(*result) = convertTimePrecision(val, TSDB_TIME_PRECISION_MILLI, timePrecision);
|
||||
break;
|
||||
case 'u':
|
||||
(*result) = convertTimePrecision(val, TSDB_TIME_PRECISION_MICRO, timePrecision);
|
||||
break;
|
||||
case 'b':
|
||||
(*result) = convertTimePrecision(val, TSDB_TIME_PRECISION_NANO, timePrecision);
|
||||
break;
|
||||
default: {
|
||||
return -1;
|
||||
|
@ -357,6 +385,8 @@ static int32_t getDurationInUs(int64_t val, char unit, int64_t* result) {
|
|||
}
|
||||
|
||||
/*
|
||||
* b - nanoseconds;
|
||||
* u - microseconds;
|
||||
* a - Millionseconds
|
||||
* s - Seconds
|
||||
* m - Minutes
|
||||
|
@ -366,7 +396,7 @@ static int32_t getDurationInUs(int64_t val, char unit, int64_t* result) {
|
|||
* n - Months (30 days)
|
||||
* y - Years (365 days)
|
||||
*/
|
||||
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* duration) {
|
||||
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* duration, int32_t timePrecision) {
|
||||
errno = 0;
|
||||
char* endPtr = NULL;
|
||||
|
||||
|
@ -382,10 +412,10 @@ int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* duration)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return getDurationInUs(timestamp, unit, duration);
|
||||
return getDuration(timestamp, unit, duration, timePrecision);
|
||||
}
|
||||
|
||||
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit) {
|
||||
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision) {
|
||||
errno = 0;
|
||||
|
||||
/* get the basic numeric value */
|
||||
|
@ -399,7 +429,7 @@ int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* durati
|
|||
return 0;
|
||||
}
|
||||
|
||||
return getDurationInUs(*duration, *unit, duration);
|
||||
return getDuration(*duration, *unit, duration, timePrecision);
|
||||
}
|
||||
|
||||
int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) {
|
||||
|
|
|
@ -64,8 +64,8 @@ void httpJsonOriginString(JsonBuf* buf, char* sVal, int32_t len);
|
|||
void httpJsonStringForTransMean(JsonBuf* buf, char* SVal, int32_t maxLen);
|
||||
void httpJsonInt64(JsonBuf* buf, int64_t num);
|
||||
void httpJsonUInt64(JsonBuf* buf, uint64_t num);
|
||||
void httpJsonTimestamp(JsonBuf* buf, int64_t t, bool us);
|
||||
void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, bool us);
|
||||
void httpJsonTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision);
|
||||
void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision);
|
||||
void httpJsonInt(JsonBuf* buf, int32_t num);
|
||||
void httpJsonUInt(JsonBuf* buf, uint32_t num);
|
||||
void httpJsonFloat(JsonBuf* buf, float num);
|
||||
|
|
|
@ -262,42 +262,92 @@ void httpJsonUInt64(JsonBuf* buf, uint64_t num) {
|
|||
buf->lst += snprintf(buf->lst, MAX_NUM_STR_SZ, "%" PRIu64, num);
|
||||
}
|
||||
|
||||
void httpJsonTimestamp(JsonBuf* buf, int64_t t, bool us) {
|
||||
void httpJsonTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) {
|
||||
char ts[35] = {0};
|
||||
struct tm* ptm;
|
||||
int32_t precision = 1000;
|
||||
if (us) {
|
||||
precision = 1000000;
|
||||
|
||||
int32_t fractionLen;
|
||||
char* format = NULL;
|
||||
time_t quot = 0;
|
||||
long mod = 0;
|
||||
|
||||
switch (timePrecision) {
|
||||
case TSDB_TIME_PRECISION_MILLI: {
|
||||
quot = t / 1000;
|
||||
fractionLen = 5;
|
||||
format = ".%03" PRId64;
|
||||
mod = t % 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_TIME_PRECISION_MICRO: {
|
||||
quot = t / 1000000;
|
||||
fractionLen = 8;
|
||||
format = ".%06" PRId64;
|
||||
mod = t % 1000000;
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_TIME_PRECISION_NANO: {
|
||||
quot = t / 1000000000;
|
||||
fractionLen = 11;
|
||||
format = ".%09" PRId64;
|
||||
mod = t % 1000000000;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
time_t tt = t / precision;
|
||||
ptm = localtime(&tt);
|
||||
ptm = localtime(");
|
||||
int32_t length = (int32_t)strftime(ts, 35, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
if (us) {
|
||||
length += snprintf(ts + length, 8, ".%06" PRId64, t % precision);
|
||||
} else {
|
||||
length += snprintf(ts + length, 5, ".%03" PRId64, t % precision);
|
||||
}
|
||||
length += snprintf(ts + length, fractionLen, format, mod);
|
||||
|
||||
httpJsonString(buf, ts, length);
|
||||
}
|
||||
|
||||
void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, bool us) {
|
||||
void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) {
|
||||
char ts[40] = {0};
|
||||
struct tm* ptm;
|
||||
int32_t precision = 1000;
|
||||
if (us) {
|
||||
precision = 1000000;
|
||||
|
||||
int32_t fractionLen;
|
||||
char* format = NULL;
|
||||
time_t quot = 0;
|
||||
long mod = 0;
|
||||
|
||||
switch (timePrecision) {
|
||||
case TSDB_TIME_PRECISION_MILLI: {
|
||||
quot = t / 1000;
|
||||
fractionLen = 5;
|
||||
format = ".%03" PRId64;
|
||||
mod = t % 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_TIME_PRECISION_MICRO: {
|
||||
quot = t / 1000000;
|
||||
fractionLen = 8;
|
||||
format = ".%06" PRId64;
|
||||
mod = t % 1000000;
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_TIME_PRECISION_NANO: {
|
||||
quot = t / 1000000000;
|
||||
fractionLen = 11;
|
||||
format = ".%09" PRId64;
|
||||
mod = t % 1000000000;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
time_t tt = t / precision;
|
||||
ptm = localtime(&tt);
|
||||
ptm = localtime(");
|
||||
int32_t length = (int32_t)strftime(ts, 40, "%Y-%m-%dT%H:%M:%S", ptm);
|
||||
if (us) {
|
||||
length += snprintf(ts + length, 8, ".%06" PRId64, t % precision);
|
||||
} else {
|
||||
length += snprintf(ts + length, 5, ".%03" PRId64, t % precision);
|
||||
}
|
||||
length += snprintf(ts + length, fractionLen, format, mod);
|
||||
length += (int32_t)strftime(ts + length, 40 - length, "%z", ptm);
|
||||
|
||||
httpJsonString(buf, ts, length);
|
||||
|
|
|
@ -186,13 +186,11 @@ bool restBuildSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result,
|
|||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (timestampFormat == REST_TIMESTAMP_FMT_LOCAL_STRING) {
|
||||
httpJsonTimestamp(jsonBuf, *((int64_t *)row[i]),
|
||||
taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO);
|
||||
httpJsonTimestamp(jsonBuf, *((int64_t *)row[i]), taos_result_precision(result));
|
||||
} else if (timestampFormat == REST_TIMESTAMP_FMT_TIMESTAMP) {
|
||||
httpJsonInt64(jsonBuf, *((int64_t *)row[i]));
|
||||
} else {
|
||||
httpJsonUtcTimestamp(jsonBuf, *((int64_t *)row[i]),
|
||||
taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO);
|
||||
httpJsonUtcTimestamp(jsonBuf, *((int64_t *)row[i]), taos_result_precision(result));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -46,7 +46,7 @@ enum SQL_NODE_FROM_TYPE {
|
|||
|
||||
enum SQL_EXPR_FLAG {
|
||||
EXPR_FLAG_TS_ERROR = 1,
|
||||
EXPR_FLAG_US_TIMESTAMP = 2,
|
||||
EXPR_FLAG_NS_TIMESTAMP = 2,
|
||||
EXPR_FLAG_TIMESTAMP_VAR = 3,
|
||||
};
|
||||
|
||||
|
|
|
@ -131,10 +131,10 @@ static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
|
|||
return;
|
||||
}
|
||||
|
||||
int64_t key = tw->skey / 1000, interval = pQueryAttr->interval.interval;
|
||||
if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
key /= 1000;
|
||||
}
|
||||
int64_t key = tw->skey, interval = pQueryAttr->interval.interval;
|
||||
//convert key to second
|
||||
key = convertTimePrecision(key, pQueryAttr->precision, TSDB_TIME_PRECISION_MILLI) / 1000;
|
||||
|
||||
if (pQueryAttr->interval.intervalUnit == 'y') {
|
||||
interval *= 12;
|
||||
}
|
||||
|
@ -146,17 +146,13 @@ static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
|
|||
int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
|
||||
tm.tm_year = mon / 12;
|
||||
tm.tm_mon = mon % 12;
|
||||
tw->skey = mktime(&tm) * 1000L;
|
||||
tw->skey = convertTimePrecision(mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
|
||||
mon = (int)(mon + interval);
|
||||
tm.tm_year = mon / 12;
|
||||
tm.tm_mon = mon % 12;
|
||||
tw->ekey = mktime(&tm) * 1000L;
|
||||
tw->ekey = convertTimePrecision(mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
|
||||
if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
tw->skey *= 1000L;
|
||||
tw->ekey *= 1000L;
|
||||
}
|
||||
tw->ekey -= 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,19 +139,20 @@ tSqlExpr *tSqlExprCreateIdValue(SStrToken *pToken, int32_t optrType) {
|
|||
pSqlExpr->tokenId = optrType;
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
} else if (optrType == TK_NOW) {
|
||||
// use microsecond by default
|
||||
pSqlExpr->value.i64 = taosGetTimestamp(TSDB_TIME_PRECISION_MICRO);
|
||||
// use nanosecond by default TODO set value after getting database precision
|
||||
pSqlExpr->value.i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
|
||||
pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pSqlExpr->tokenId = TK_TIMESTAMP; // TK_TIMESTAMP used to denote the time value is in microsecond
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
pSqlExpr->flags |= 1 << EXPR_FLAG_US_TIMESTAMP;
|
||||
pSqlExpr->flags |= 1 << EXPR_FLAG_NS_TIMESTAMP;
|
||||
} else if (optrType == TK_VARIABLE) {
|
||||
int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->value.i64);
|
||||
// use nanosecond by default TODO set value after getting database precision
|
||||
int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->value.i64, TSDB_TIME_PRECISION_NANO);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
pSqlExpr->flags |= 1 << EXPR_FLAG_US_TIMESTAMP;
|
||||
pSqlExpr->flags |= 1 << EXPR_FLAG_NS_TIMESTAMP;
|
||||
pSqlExpr->flags |= 1 << EXPR_FLAG_TIMESTAMP_VAR;
|
||||
pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pSqlExpr->tokenId = TK_TIMESTAMP;
|
||||
|
|
|
@ -494,9 +494,9 @@ uint32_t tGetToken(char* z, uint32_t* tokenId) {
|
|||
}
|
||||
|
||||
/* here is the 1u/1a/2s/3m/9y */
|
||||
if ((z[i] == 'u' || z[i] == 'a' || z[i] == 's' || z[i] == 'm' || z[i] == 'h' || z[i] == 'd' || z[i] == 'n' ||
|
||||
if ((z[i] == 'b' || z[i] == 'u' || z[i] == 'a' || z[i] == 's' || z[i] == 'm' || z[i] == 'h' || z[i] == 'd' || z[i] == 'n' ||
|
||||
z[i] == 'y' || z[i] == 'w' ||
|
||||
z[i] == 'U' || z[i] == 'A' || z[i] == 'S' || z[i] == 'M' || z[i] == 'H' || z[i] == 'D' || z[i] == 'N' ||
|
||||
z[i] == 'B' || z[i] == 'U' || z[i] == 'A' || z[i] == 'S' || z[i] == 'M' || z[i] == 'H' || z[i] == 'D' || z[i] == 'N' ||
|
||||
z[i] == 'Y' || z[i] == 'W') &&
|
||||
(isIdChar[(uint8_t)z[i + 1]] == 0)) {
|
||||
*tokenId = TK_VARIABLE;
|
||||
|
|
|
@ -135,6 +135,7 @@ run general/parser/tags_dynamically_specifiy.sim
|
|||
run general/parser/set_tag_vals.sim
|
||||
#unsupport run general/parser/repeatAlter.sim
|
||||
#unsupport run general/parser/slimit_alter_tags.sim
|
||||
run general/parser/precision_ns.sim
|
||||
run general/stable/disk.sim
|
||||
run general/stable/dnode3.sim
|
||||
run general/stable/metrics.sim
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
system sh/stop_dnodes.sh
|
||||
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/cfg.sh -n dnode1 -c walLevel -v 1
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
sleep 1000
|
||||
sql connect
|
||||
|
||||
$dbPrefix = m_di_db_ns
|
||||
$tbPrefix = m_di_tb
|
||||
$mtPrefix = m_di_mt
|
||||
$ntPrefix = m_di_nt
|
||||
$tbNum = 2
|
||||
$rowNum = 200
|
||||
$futureTs = 300000000000
|
||||
|
||||
print =============== step1: create database and tables and insert data
|
||||
$i = 0
|
||||
$db = $dbPrefix . $i
|
||||
$mt = $mtPrefix . $i
|
||||
$nt = $ntPrefix . $i
|
||||
|
||||
sql drop database $db -x step1
|
||||
step1:
|
||||
sql create database $db precision 'ns'
|
||||
sql use $db
|
||||
sql create table $mt (ts timestamp, tbcol int) TAGS(tgcol int)
|
||||
|
||||
$i = 0
|
||||
while $i < $tbNum
|
||||
$tb = $tbPrefix . $i
|
||||
sql create table $tb using $mt tags( $i )
|
||||
|
||||
$x = 0
|
||||
while $x < $rowNum
|
||||
$cc = $futureTs + $x * 100 + 43
|
||||
$ns = $cc . b
|
||||
sql insert into $tb values (now + $ns , $x )
|
||||
$x = $x + 1
|
||||
endw
|
||||
|
||||
$i = $i + 1
|
||||
endw
|
||||
|
||||
sql create table $nt (ts timestamp, tbcol int)
|
||||
$x = 0
|
||||
while $x < $rowNum
|
||||
$cc = $futureTs + $x * 100 + 43
|
||||
$ns = $cc . b
|
||||
sql insert into $nt values (now + $ns , $x )
|
||||
$x = $x + 1
|
||||
endw
|
||||
|
||||
sleep 100
|
||||
|
||||
print =============== step2: select count(*) from tables
|
||||
$i = 0
|
||||
$tb = $tbPrefix . $i
|
||||
|
||||
sql select count(*) from $tb
|
||||
|
||||
if $data00 != $rowNum then
|
||||
print expect $rowNum, actual:$data00
|
||||
return -1
|
||||
endi
|
||||
|
||||
$i = 0
|
||||
$mt = $mtPrefix . $i
|
||||
sql select count(*) from $mt
|
||||
|
||||
$mtRowNum = $tbNum * $rowNum
|
||||
if $data00 != $mtRowNum then
|
||||
print expect $mtRowNum, actual:$data00
|
||||
return -1
|
||||
endi
|
||||
|
||||
$i = 0
|
||||
$nt = $ntPrefix . $i
|
||||
|
||||
sql select count(*) from $nt
|
||||
|
||||
if $data00 != $rowNum then
|
||||
print expect $rowNum, actual:$data00
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step3: check nano second timestamp
|
||||
$i = 0
|
||||
$mt = $mtPrefix . $i
|
||||
$tb = $tbPrefix . $i
|
||||
sql insert into $tb values (now-43b , $x )
|
||||
sql select count(*) from $tb where ts<now
|
||||
if $data00 != 1 then
|
||||
print expected 1, actual: $data00
|
||||
endi
|
||||
|
||||
|
||||
print =============== step4: check interval/sliding nano second
|
||||
$i = 0
|
||||
$mt = $mtPrefix . $i
|
||||
sql_error select count(*) from $mt interval(1000b) sliding(100b)
|
||||
sql_error select count(*) from $mt interval(10000000b) sliding(99999b)
|
||||
|
||||
sql select count(*) from $mt interval(100000000b) sliding(100000000b)
|
||||
|
||||
print =============== clear
|
||||
sql drop database $db
|
||||
sql show databases
|
||||
if $rows != 0 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
|
@ -62,4 +62,5 @@ run general/parser/binary_escapeCharacter.sim
|
|||
run general/parser/between_and.sim
|
||||
run general/parser/last_cache.sim
|
||||
run general/parser/nestquery.sim
|
||||
run general/parser/precision_ns.sim
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ run general/parser/bug.sim
|
|||
run general/parser/tags_dynamically_specifiy.sim
|
||||
run general/parser/set_tag_vals.sim
|
||||
run general/parser/repeatAlter.sim
|
||||
run general/parser/precision_ns.sim
|
||||
##unsupport run general/parser/slimit_alter_tags.sim
|
||||
run general/stable/disk.sim
|
||||
run general/stable/dnode3.sim
|
||||
|
|
|
@ -813,8 +813,15 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
|
|||
value[length[i]] = 0;
|
||||
// snprintf(value, fields[i].bytes, "%s", (char *)row[i]);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
tt = *(int64_t *)row[i] / 1000;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
int32_t precision = taos_result_precision(pSql);
|
||||
if (precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
tt = (*(int64_t *)row[i]) / 1000;
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
tt = (*(int64_t *)row[i]) / 1000000;
|
||||
} else {
|
||||
tt = (*(int64_t *)row[i]) / 1000000000;
|
||||
}
|
||||
/* comment out as it make testcases like select_with_tags.sim fail.
|
||||
but in windows, this may cause the call to localtime crash if tt < 0,
|
||||
need to find a better solution.
|
||||
|
@ -829,9 +836,16 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
|
|||
|
||||
tp = localtime(&tt);
|
||||
strftime(timeStr, 64, "%y-%m-%d %H:%M:%S", tp);
|
||||
sprintf(value, "%s.%03d", timeStr, (int32_t)(*((int64_t *)row[i]) % 1000));
|
||||
if (precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
sprintf(value, "%s.%03d", timeStr, (int32_t)(*((int64_t *)row[i]) % 1000));
|
||||
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
sprintf(value, "%s.%06d", timeStr, (int32_t)(*((int64_t *)row[i]) % 1000000));
|
||||
} else {
|
||||
sprintf(value, "%s.%09d", timeStr, (int32_t)(*((int64_t *)row[i]) % 1000000000));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} // end of switch
|
||||
|
|
Loading…
Reference in New Issue