diff --git a/docs/en/12-taos-sql/10-function.md b/docs/en/12-taos-sql/10-function.md index 14dedfb216..243ede5fcb 100644 --- a/docs/en/12-taos-sql/10-function.md +++ b/docs/en/12-taos-sql/10-function.md @@ -867,6 +867,7 @@ INTERP(expr) - The number of rows in the result set of `INTERP` is determined by the parameter `EVERY`. Starting from timestamp1, one interpolation is performed for every time interval specified `EVERY` parameter. - Interpolation is performed based on `FILL` parameter. - `INTERP` can only be used to interpolate in single timeline. So it must be used with `partition by tbname` when it's used on a STable. +- Pseudo column `_irowts` can be used along with `INTERP` to return the timestamps associated with interpolation points(support after version 3.0.1.4). ### LAST diff --git a/docs/zh/12-taos-sql/10-function.md b/docs/zh/12-taos-sql/10-function.md index 2a4d82045f..4c33b5232a 100644 --- a/docs/zh/12-taos-sql/10-function.md +++ b/docs/zh/12-taos-sql/10-function.md @@ -868,6 +868,7 @@ INTERP(expr) - INTERP 根据 EVERY 字段来确定输出时间范围内的结果条数,即从 timestamp1 开始每隔固定长度的时间(EVERY 值)进行插值。如果没有指定 EVERY,则默认窗口大小为无穷大,即从 timestamp1 开始只有一个窗口。 - INTERP 根据 FILL 字段来决定在每个符合输出条件的时刻如何进行插值。 - INTERP 只能在一个时间序列内进行插值,因此当作用于超级表时必须跟 partition by tbname 一起使用。 +- INTERP 可以与伪列 _irowts 一起使用,返回插值点所对应的时间戳(3.0.1.4版本以后支持)。 ### LAST diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index 12d35be0b7..b4e2b73889 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -2099,12 +2099,17 @@ static void genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp bool hasInterp = true; for (int32_t j = 0; j < pExprSup->numOfExprs; ++j) { SExprInfo* pExprInfo = &pExprSup->pExprInfo[j]; - int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; - int32_t dstSlot = pExprInfo->base.resSchema.slotId; - // SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); + int32_t dstSlot = pExprInfo->base.resSchema.slotId; SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot); + if (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type)) { + colDataAppend(pDst, rows, (char*)&pSliceInfo->current, false); + continue; + } + + int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; + // SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); switch (pSliceInfo->fillType) { case TSDB_FILL_NULL: { colDataAppendNULL(pDst, rows); @@ -2350,19 +2355,24 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) { if (ts == pSliceInfo->current) { for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) { SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[j]; - int32_t dstSlot = pExprInfo->base.resSchema.slotId; - int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; - SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); + int32_t dstSlot = pExprInfo->base.resSchema.slotId; SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot); - if (colDataIsNull_s(pSrc, i)) { - colDataAppendNULL(pDst, pResBlock->info.rows); - continue; - } + if (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type)) { + colDataAppend(pDst, pResBlock->info.rows, (char *)&pSliceInfo->current, false); + } else { + int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; + SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); - char* v = colDataGetData(pSrc, i); - colDataAppend(pDst, pResBlock->info.rows, v, false); + if (colDataIsNull_s(pSrc, i)) { + colDataAppendNULL(pDst, pResBlock->info.rows); + continue; + } + + char* v = colDataGetData(pSrc, i); + colDataAppend(pDst, pResBlock->info.rows, v, false); + } } pResBlock->info.rows += 1; @@ -2482,14 +2492,24 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) { if (ts == pSliceInfo->current && pSliceInfo->current <= pSliceInfo->win.ekey) { for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) { SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[j]; - int32_t dstSlot = pExprInfo->base.resSchema.slotId; - int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; - SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); + int32_t dstSlot = pExprInfo->base.resSchema.slotId; SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot); - char* v = colDataGetData(pSrc, i); - colDataAppend(pDst, pResBlock->info.rows, v, false); + if (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type)) { + colDataAppend(pDst, pResBlock->info.rows, (char *)&pSliceInfo->current, false); + } else { + int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; + SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, srcSlot); + + if (colDataIsNull_s(pSrc, i)) { + colDataAppendNULL(pDst, pResBlock->info.rows); + continue; + } + + char* v = colDataGetData(pSrc, i); + colDataAppend(pDst, pResBlock->info.rows, v, false); + } } pResBlock->info.rows += 1; diff --git a/tests/system-test/2-query/interp.py b/tests/system-test/2-query/interp.py index 7bf0191ec1..bee20710b5 100644 --- a/tests/system-test/2-query/interp.py +++ b/tests/system-test/2-query/interp.py @@ -356,8 +356,261 @@ class TDTestCase: tdSql.query(f"select interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:16', '2020-02-01 00:00:19') every(1s) fill(linear)") tdSql.checkRows(0) + tdLog.printNoPrefix("==========step8:test _irowts with interp") - tdLog.printNoPrefix("==========step8:test intra block interpolation") + # fill null + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(null)") + tdSql.checkRows(9) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:09.500') + tdSql.checkData(4, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.500') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(null)") + tdSql.checkRows(13) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:06.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(6, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + tdSql.checkData(9, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(10, 0, '2020-02-01 00:00:14.000') + tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(12, 0, '2020-02-01 00:00:16.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(null)") + tdSql.checkRows(6) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + + # fill value + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(value, 1)") + tdSql.checkRows(9) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:09.500') + tdSql.checkData(4, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.500') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(value, 1)") + tdSql.checkRows(13) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:06.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(6, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + tdSql.checkData(9, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(10, 0, '2020-02-01 00:00:14.000') + tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(12, 0, '2020-02-01 00:00:16.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(value, 1)") + tdSql.checkRows(6) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + + # fill prev + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(prev)") + tdSql.checkRows(9) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:09.500') + tdSql.checkData(4, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.500') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(prev)") + tdSql.checkRows(12) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:06.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:12.000') + tdSql.checkData(8, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(9, 0, '2020-02-01 00:00:14.000') + tdSql.checkData(10, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(11, 0, '2020-02-01 00:00:16.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(prev)") + tdSql.checkRows(6) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + + # fill next + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(next)") + tdSql.checkRows(9) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:09.500') + tdSql.checkData(4, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.500') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(next)") + tdSql.checkRows(12) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:06.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(6, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + tdSql.checkData(9, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(10, 0, '2020-02-01 00:00:14.000') + tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(next)") + tdSql.checkRows(6) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + + # fill linear + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(linear)") + tdSql.checkRows(9) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:09.500') + tdSql.checkData(4, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.500') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') + tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkRows(11) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:06.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:08.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:10.000') + tdSql.checkData(6, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 0, '2020-02-01 00:00:12.000') + tdSql.checkData(8, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(9, 0, '2020-02-01 00:00:14.000') + tdSql.checkData(10, 0, '2020-02-01 00:00:15.000') + + tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(linear)") + tdSql.checkRows(6) + tdSql.checkCols(2) + + tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') + tdSql.checkData(2, 0, '2020-02-01 00:00:09.000') + tdSql.checkData(3, 0, '2020-02-01 00:00:11.000') + tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') + tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + + # multiple _irowts + tdSql.query(f"select interp(c0),_irowts from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkRows(11) + tdSql.checkCols(2) + + tdSql.checkData(0, 1, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 1, '2020-02-01 00:00:06.000') + tdSql.checkData(2, 1, '2020-02-01 00:00:07.000') + tdSql.checkData(3, 1, '2020-02-01 00:00:08.000') + tdSql.checkData(4, 1, '2020-02-01 00:00:09.000') + tdSql.checkData(5, 1, '2020-02-01 00:00:10.000') + tdSql.checkData(6, 1, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 1, '2020-02-01 00:00:12.000') + tdSql.checkData(8, 1, '2020-02-01 00:00:13.000') + tdSql.checkData(9, 1, '2020-02-01 00:00:14.000') + tdSql.checkData(10, 1, '2020-02-01 00:00:15.000') + + tdSql.query(f"select _irowts, interp(c0), interp(c0), _irowts from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkRows(11) + tdSql.checkCols(4) + + cols = (0, 3) + for i in cols: + tdSql.checkData(0, i, '2020-02-01 00:00:05.000') + tdSql.checkData(1, i, '2020-02-01 00:00:06.000') + tdSql.checkData(2, i, '2020-02-01 00:00:07.000') + tdSql.checkData(3, i, '2020-02-01 00:00:08.000') + tdSql.checkData(4, i, '2020-02-01 00:00:09.000') + tdSql.checkData(5, i, '2020-02-01 00:00:10.000') + tdSql.checkData(6, i, '2020-02-01 00:00:11.000') + tdSql.checkData(7, i, '2020-02-01 00:00:12.000') + tdSql.checkData(8, i, '2020-02-01 00:00:13.000') + tdSql.checkData(9, i, '2020-02-01 00:00:14.000') + tdSql.checkData(10, i, '2020-02-01 00:00:15.000') + + + tdLog.printNoPrefix("==========step9:test intra block interpolation") tdSql.execute(f"drop database {dbname}"); tdSql.prepare() @@ -551,7 +804,7 @@ class TDTestCase: tdSql.checkData(0, 0, 15) tdSql.checkData(1, 0, 15) - tdLog.printNoPrefix("==========step9:test multi-interp cases") + tdLog.printNoPrefix("==========step10:test multi-interp cases") tdSql.query(f"select interp(c0),interp(c1),interp(c2),interp(c3) from {dbname}.{tbname} range('2020-02-09 00:00:05', '2020-02-13 00:00:05') every(1d) fill(null)") tdSql.checkRows(5) tdSql.checkCols(4) @@ -601,7 +854,7 @@ class TDTestCase: for i in range (tdSql.queryCols): tdSql.checkData(0, i, 13) - tdLog.printNoPrefix("==========step10:test error cases") + tdLog.printNoPrefix("==========step11:test error cases") tdSql.error(f"select interp(c0) from {dbname}.{tbname}") tdSql.error(f"select interp(c0) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05')")