提交 5964e3b6 编写于 作者: H Haojun Liao

[td-225] fix bug in parser scripts

上级 0152521f
...@@ -21,7 +21,7 @@ extern "C" { ...@@ -21,7 +21,7 @@ extern "C" {
#endif #endif
#include "qextbuffer.h" #include "qextbuffer.h"
#include "qinterpolation.h" #include "qfill.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tlosertree.h" #include "tlosertree.h"
#include "tsclient.h" #include "tsclient.h"
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include "os.h" #include "os.h"
#include "qast.h" #include "qast.h"
#include "qextbuffer.h" #include "qextbuffer.h"
#include "qfill.h"
#include "qhistogram.h" #include "qhistogram.h"
#include "qinterpolation.h"
#include "qpercentile.h" #include "qpercentile.h"
#include "qsyntaxtreefunction.h" #include "qsyntaxtreefunction.h"
#include "qtsbuf.h" #include "qtsbuf.h"
...@@ -3418,6 +3418,7 @@ static void spread_function(SQLFunctionCtx *pCtx) { ...@@ -3418,6 +3418,7 @@ static void spread_function(SQLFunctionCtx *pCtx) {
int32_t numOfElems = pCtx->size; int32_t numOfElems = pCtx->size;
// todo : opt with pre-calculated result
// column missing cause the hasNull to be true // column missing cause the hasNull to be true
if (usePreVal(pCtx)) { if (usePreVal(pCtx)) {
numOfElems = pCtx->size - pCtx->preAggVals.statis.numOfNull; numOfElems = pCtx->size - pCtx->preAggVals.statis.numOfNull;
...@@ -3446,13 +3447,13 @@ static void spread_function(SQLFunctionCtx *pCtx) { ...@@ -3446,13 +3447,13 @@ static void spread_function(SQLFunctionCtx *pCtx) {
} }
} }
} else { } else {
if (pInfo->min > pCtx->param[1].dKey) { // if (pInfo->min > pCtx->param[1].dKey) {
pInfo->min = pCtx->param[1].dKey; // pInfo->min = pCtx->param[1].dKey;
} // }
//
if (pInfo->max < pCtx->param[2].dKey) { // if (pInfo->max < pCtx->param[2].dKey) {
pInfo->max = pCtx->param[2].dKey; // pInfo->max = pCtx->param[2].dKey;
} // }
} }
void *pData = GET_INPUT_CHAR(pCtx); void *pData = GET_INPUT_CHAR(pCtx);
......
...@@ -5562,7 +5562,15 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { ...@@ -5562,7 +5562,15 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
} }
ret = tVariantDump(&(pList->a[i].pVar), varDataVal(tagVal), pTagSchema[i].type); ret = tVariantDump(&(pList->a[i].pVar), varDataVal(tagVal), pTagSchema[i].type);
varDataSetLen(tagVal, pList->a[i].pVar.nLen); if (pList->a[i].pVar.nType == TSDB_DATA_TYPE_NULL) {
if (pTagSchema[i].type == TSDB_DATA_TYPE_BINARY) {
varDataSetLen(tagVal, sizeof(uint8_t));
} else {
varDataSetLen(tagVal, sizeof(uint32_t));
}
} else { // todo refactor
varDataSetLen(tagVal, pList->a[i].pVar.nLen);
}
} else { } else {
ret = tVariantDump(&(pList->a[i].pVar), tagVal, pTagSchema[i].type); ret = tVariantDump(&(pList->a[i].pVar), tagVal, pTagSchema[i].type);
} }
......
...@@ -367,7 +367,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd ...@@ -367,7 +367,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
int32_t startIndex = pQueryInfo->fieldsInfo.numOfOutput - pQueryInfo->groupbyExpr.numOfGroupCols; int32_t startIndex = pQueryInfo->fieldsInfo.numOfOutput - pQueryInfo->groupbyExpr.numOfGroupCols;
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) { if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 && pReducer->pFillInfo != NULL) {
pReducer->pFillInfo->pTags[0] = (char *)pReducer->pFillInfo->pTags + POINTER_BYTES * pQueryInfo->groupbyExpr.numOfGroupCols; pReducer->pFillInfo->pTags[0] = (char *)pReducer->pFillInfo->pTags + POINTER_BYTES * pQueryInfo->groupbyExpr.numOfGroupCols;
for (int32_t i = 1; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) { for (int32_t i = 1; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
SSchema *pSchema = getColumnModelSchema(pReducer->resColModel, startIndex + i - 1); SSchema *pSchema = getColumnModelSchema(pReducer->resColModel, startIndex + i - 1);
......
...@@ -1879,9 +1879,7 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) { ...@@ -1879,9 +1879,7 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) {
static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) { static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) {
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
if (pRes->tsrow[columnIndex] != NULL && isNull(pRes->tsrow[columnIndex], pField->type)) { if (pRes->tsrow[columnIndex] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) {
pRes->tsrow[columnIndex] = NULL;
} else if (pField->type == TSDB_DATA_TYPE_NCHAR) {
// convert unicode to native code in a temporary buffer extra one byte for terminated symbol // convert unicode to native code in a temporary buffer extra one byte for terminated symbol
if (pRes->buffer[columnIndex] == NULL) { if (pRes->buffer[columnIndex] == NULL) {
pRes->buffer[columnIndex] = malloc(pField->bytes + TSDB_NCHAR_SIZE); pRes->buffer[columnIndex] = malloc(pField->bytes + TSDB_NCHAR_SIZE);
...@@ -1893,7 +1891,7 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF ...@@ -1893,7 +1891,7 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF
if (taosUcs4ToMbs(pRes->tsrow[columnIndex], pField->bytes - VARSTR_HEADER_SIZE, pRes->buffer[columnIndex])) { if (taosUcs4ToMbs(pRes->tsrow[columnIndex], pField->bytes - VARSTR_HEADER_SIZE, pRes->buffer[columnIndex])) {
pRes->tsrow[columnIndex] = pRes->buffer[columnIndex]; pRes->tsrow[columnIndex] = pRes->buffer[columnIndex];
} else { } else {
tscError("%p charset:%s to %s. val:%ls convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, pRes->tsrow); tscError("%p charset:%s to %s. val:%ls convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, pRes->tsrow[columnIndex]);
pRes->tsrow[columnIndex] = NULL; pRes->tsrow[columnIndex] = NULL;
} }
} }
......
...@@ -2126,16 +2126,26 @@ void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pFieldInfo, int32_t column ...@@ -2126,16 +2126,26 @@ void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pFieldInfo, int32_t column
int32_t realLen = varDataLen(pData); int32_t realLen = varDataLen(pData);
assert(realLen <= bytes - VARSTR_HEADER_SIZE); assert(realLen <= bytes - VARSTR_HEADER_SIZE);
if (isNull(pData, type)) {
pRes->tsrow[columnIndex] = NULL;
} else {
pRes->tsrow[columnIndex] = pData + VARSTR_HEADER_SIZE;
}
if (realLen < pInfo->pSqlExpr->resBytes - VARSTR_HEADER_SIZE) { // todo refactor if (realLen < pInfo->pSqlExpr->resBytes - VARSTR_HEADER_SIZE) { // todo refactor
*(char*) (pData + realLen + VARSTR_HEADER_SIZE) = 0; *(char*) (pData + realLen + VARSTR_HEADER_SIZE) = 0;
} }
pRes->tsrow[columnIndex] = pData + VARSTR_HEADER_SIZE;
pRes->length[columnIndex] = realLen; pRes->length[columnIndex] = realLen;
} else { } else {
assert(bytes == tDataTypeDesc[type].nSize); assert(bytes == tDataTypeDesc[type].nSize);
pRes->tsrow[columnIndex] = pData; if (isNull(pData, type)) {
pRes->tsrow[columnIndex] = NULL;
} else {
pRes->tsrow[columnIndex] = pData;
}
pRes->length[columnIndex] = bytes; pRes->length[columnIndex] = bytes;
} }
} }
......
...@@ -402,7 +402,7 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) { ...@@ -402,7 +402,7 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) {
*(uint64_t *)(val + i * tDataTypeDesc[type].nSize) = TSDB_DATA_DOUBLE_NULL; *(uint64_t *)(val + i * tDataTypeDesc[type].nSize) = TSDB_DATA_DOUBLE_NULL;
} }
break; break;
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR: // todo : without length?
for (int32_t i = 0; i < numOfElems; ++i) { for (int32_t i = 0; i < numOfElems; ++i) {
*(uint32_t *)(val + i * bytes) = TSDB_DATA_NCHAR_NULL; *(uint32_t *)(val + i * bytes) = TSDB_DATA_NCHAR_NULL;
} }
......
...@@ -18,15 +18,15 @@ ...@@ -18,15 +18,15 @@
#include "os.h" #include "os.h"
#include "hash.h" #include "hash.h"
#include "tsdb.h" #include "qfill.h"
#include "qinterpolation.h"
#include "qresultBuf.h" #include "qresultBuf.h"
#include "qsqlparser.h" #include "qsqlparser.h"
#include "qtsbuf.h" #include "qtsbuf.h"
#include "taosdef.h" #include "taosdef.h"
#include "tarray.h"
#include "tref.h" #include "tref.h"
#include "tsdb.h"
#include "tsqlfunction.h" #include "tsqlfunction.h"
#include "tarray.h"
//typedef struct tFilePage { //typedef struct tFilePage {
// int64_t num; // int64_t num;
...@@ -154,7 +154,7 @@ typedef struct SQueryRuntimeEnv { ...@@ -154,7 +154,7 @@ typedef struct SQueryRuntimeEnv {
int16_t numOfRowsPerPage; int16_t numOfRowsPerPage;
int16_t offset[TSDB_MAX_COLUMNS]; int16_t offset[TSDB_MAX_COLUMNS];
uint16_t scanFlag; // denotes reversed scan of data or not uint16_t scanFlag; // denotes reversed scan of data or not
SFillInfo* pFillInfo; SFillInfo* pFillInfo;
SWindowResInfo windowResInfo; SWindowResInfo windowResInfo;
STSBuf* pTSBuf; STSBuf* pTSBuf;
STSCursor cur; STSCursor cur;
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef TDENGINE_TINTERPOLATION_H #ifndef TDENGINE_QFILL_H
#define TDENGINE_TINTERPOLATION_H #define TDENGINE_QFILL_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -58,7 +58,7 @@ typedef struct SPoint { ...@@ -58,7 +58,7 @@ typedef struct SPoint {
void * val; void * val;
} SPoint; } SPoint;
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t timeRange, char intervalTimeUnit, int16_t precision); int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, char timeUnit, int16_t precision);
SFillInfo* taosInitFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int32_t capacity, SFillInfo* taosInitFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int32_t capacity,
int32_t numOfCols, int64_t slidingTime, int32_t fillType, SFillColInfo* pFillCol); int32_t numOfCols, int64_t slidingTime, int32_t fillType, SFillColInfo* pFillCol);
...@@ -89,4 +89,4 @@ void taosGenerateDataBlock(SFillInfo* pFillInfo, tFilePage** output, int64_t* ou ...@@ -89,4 +89,4 @@ void taosGenerateDataBlock(SFillInfo* pFillInfo, tFilePage** output, int64_t* ou
} }
#endif #endif
#endif // TDENGINE_TINTERPOLATION_H #endif // TDENGINE_QFILL_H
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef TDENGINE_RPC_LOG_H #ifndef TDENGINE_QUERY_LOG_H
#define TDENGINE_RPC_LOG_H #define TDENGINE_QUERY_LOG_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -24,22 +24,23 @@ extern "C" { ...@@ -24,22 +24,23 @@ extern "C" {
extern int32_t qDebugFlag; extern int32_t qDebugFlag;
#define qTrace(...) \ #define qTrace(...) \
if (qDebugFlag & DEBUG_TRACE) { \ if (qDebugFlag & DEBUG_TRACE) { \
taosPrintLog("DND QRY ", qDebugFlag, __VA_ARGS__); \ taosPrintLog("QRY ", qDebugFlag, __VA_ARGS__); \
} }
#define qError(...) \ #define qError(...) \
if (qDebugFlag & DEBUG_ERROR) { \ if (qDebugFlag & DEBUG_ERROR) { \
taosPrintLog("ERROR QRY ", qDebugFlag, __VA_ARGS__); \ taosPrintLog("ERROR QRY ", qDebugFlag, __VA_ARGS__); \
} }
#define qWarn(...) \
if (qDebugFlag & DEBUG_WARN) { \ #define qWarn(...) \
taosPrintLog("WARN QRY ", qDebugFlag, __VA_ARGS__); \ if (qDebugFlag & DEBUG_WARN) { \
} taosPrintLog("WARN QRY ", qDebugFlag, __VA_ARGS__); \
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // TDENGINE_RPC_CACHE_H #endif // TDENGINE_QUERY_CACHE_H
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <qinterpolation.h> #include <qfill.h>
#include "os.h" #include "os.h"
#include "hash.h" #include "hash.h"
...@@ -1203,11 +1203,9 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS ...@@ -1203,11 +1203,9 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
while (1) { while (1) {
getNextTimeWindow(pQuery, &nextWin); getNextTimeWindow(pQuery, &nextWin);
assert(pWindowResInfo->startTime <= nextWin.skey); if (/*pWindowResInfo->startTime > nextWin.skey ||*/
if (pWindowResInfo->startTime > nextWin.skey ||
(nextWin.skey > pQuery->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || (nextWin.skey > pQuery->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(nextWin.skey > pQuery->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) { (nextWin.skey < pQuery->window.ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
break; break;
} }
...@@ -1337,7 +1335,6 @@ void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void *inputData, TSKEY ...@@ -1337,7 +1335,6 @@ void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void *inputData, TSKEY
// last_dist or first_dist function // last_dist or first_dist function
// store the first&last timestamp into the intermediate buffer [1], the true // store the first&last timestamp into the intermediate buffer [1], the true
// value may be null but timestamp will never be null // value may be null but timestamp will never be null
// pCtx->ptsList = tsCol;
} else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_TWA || } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_TWA ||
functionId == TSDB_FUNC_DIFF || (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) { functionId == TSDB_FUNC_DIFF || (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) {
/* /*
...@@ -2374,7 +2371,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -2374,7 +2371,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
SDataBlockInfo blockInfo = tsdbRetrieveDataBlockInfo(pQueryHandle); SDataBlockInfo blockInfo = tsdbRetrieveDataBlockInfo(pQueryHandle);
// todo extract methods // todo extract methods
if (isIntervalQuery(pQuery) && pRuntimeEnv->windowResInfo.prevSKey == 0) { if (isIntervalQuery(pQuery) && pRuntimeEnv->windowResInfo.prevSKey == TSKEY_INITIAL_VAL) {
TSKEY skey1, ekey1; TSKEY skey1, ekey1;
STimeWindow w = TSWINDOW_INITIALIZER; STimeWindow w = TSWINDOW_INITIALIZER;
SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo; SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
...@@ -3258,16 +3255,19 @@ bool needScanDataBlocksAgain(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -3258,16 +3255,19 @@ bool needScanDataBlocksAgain(SQueryRuntimeEnv *pRuntimeEnv) {
return toContinue; return toContinue;
} }
static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv) { static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
STableQueryInfo* pTableQueryInfo = pQuery->current; STableQueryInfo* pTableQueryInfo = pQuery->current;
assert((start <= pTableQueryInfo->lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
(start >= pTableQueryInfo->lastKey && !QUERY_IS_ASC_QUERY(pQuery)));
SQueryStatusInfo info = { SQueryStatusInfo info = {
.status = pQuery->status, .status = pQuery->status,
.windowIndex = pRuntimeEnv->windowResInfo.curIndex, .windowIndex = pRuntimeEnv->windowResInfo.curIndex,
.lastKey = pTableQueryInfo->lastKey, .lastKey = start,
.w = pQuery->window, .w = pQuery->window,
.curWindow = {.skey = pTableQueryInfo->lastKey, .ekey = pTableQueryInfo->win.ekey}, .curWindow = {.skey = start, .ekey = pTableQueryInfo->win.ekey},
}; };
return info; return info;
...@@ -3330,7 +3330,7 @@ static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus ...@@ -3330,7 +3330,7 @@ static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus
pTableQueryInfo->win = pStatus->w; pTableQueryInfo->win = pStatus->w;
} }
void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv); SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv);
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
STableQueryInfo *pTableQueryInfo = pQuery->current; STableQueryInfo *pTableQueryInfo = pQuery->current;
...@@ -3338,7 +3338,7 @@ void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -3338,7 +3338,7 @@ void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
setQueryStatus(pQuery, QUERY_NOT_COMPLETED); setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
// store the start query position // store the start query position
SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv); SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv, start);
SET_MASTER_SCAN_FLAG(pRuntimeEnv); SET_MASTER_SCAN_FLAG(pRuntimeEnv);
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
...@@ -3995,8 +3995,9 @@ void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -3995,8 +3995,9 @@ void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
} }
} }
static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) { static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
*start = pQuery->current->lastKey;
// if queried with value filter, do NOT forward query start position // if queried with value filter, do NOT forward query start position
if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || pRuntimeEnv->pFillInfo != NULL) { if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
...@@ -4019,13 +4020,14 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4019,13 +4020,14 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) {
while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) { while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
SDataBlockInfo blockInfo = tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle); SDataBlockInfo blockInfo = tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle);
if (QUERY_IS_ASC_QUERY(pQuery) && pWindowResInfo->prevSKey == 0) { if (QUERY_IS_ASC_QUERY(pQuery)) {
getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &skey1, &ekey1, if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
&w); getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &skey1,
pWindowResInfo->startTime = w.skey; &ekey1, &w);
pWindowResInfo->prevSKey = w.skey; pWindowResInfo->startTime = w.skey;
pWindowResInfo->prevSKey = w.skey;
}
} else { } else {
// the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &skey1, &ekey1, getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &skey1, &ekey1,
&w); &w);
...@@ -4049,7 +4051,8 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4049,7 +4051,8 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) {
if (pQuery->limit.offset == 0) { if (pQuery->limit.offset == 0) {
if ((tw.skey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || if ((tw.skey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(tw.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) { (tw.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
// load the data block // load the data block and check data remaining in current data block
// TODO optimize performance
SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
...@@ -4060,24 +4063,38 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4060,24 +4063,38 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) {
// set the abort info // set the abort info
pQuery->pos = startPos; pQuery->pos = startPos;
pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos];
// reset the query start timestamp
pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
pQuery->window.skey = pTableQueryInfo->win.skey;
*start = pTableQueryInfo->win.skey;
pWindowResInfo->prevSKey = tw.skey; pWindowResInfo->prevSKey = tw.skey;
int32_t index = pRuntimeEnv->windowResInfo.curIndex;
int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, NULL, binarySearchForKey, pDataBlock); int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, NULL, binarySearchForKey, pDataBlock);
pRuntimeEnv->windowResInfo.curIndex = index; // restore the window index
qTrace("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", rows:%d, res:%d", qTrace("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", rows:%d, res:%d",
GET_QINFO_ADDR(pRuntimeEnv), blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes); GET_QINFO_ADDR(pRuntimeEnv), blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes);
return true; return true;
} else { } else { // do nothing
// do nothing, *start = tw.skey;
pQuery->window.skey = tw.skey;
pWindowResInfo->prevSKey = tw.skey;
return true; return true;
} }
} }
// next time window starts from current data block /*
* If the next time window still starts from current data block,
* load the primary timestamp column first, and then find the start position for the next queried time window.
* Note that only the primary timestamp column is required.
* TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required
* time window resides in current data block.
*/
if ((tw.skey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || if ((tw.skey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(tw.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) { (tw.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
// load the data block, note that only the primary timestamp column is required
SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
...@@ -4092,7 +4109,7 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4092,7 +4109,7 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv) {
pWindowResInfo->prevSKey = tw.skey; pWindowResInfo->prevSKey = tw.skey;
win = tw; win = tw;
} else { } else {
break; // offset is not 0, and next time window locates in the next block. break; // offset is not 0, and next time window begins or ends in the next block.
} }
} }
} }
...@@ -4132,7 +4149,11 @@ static void setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) { ...@@ -4132,7 +4149,11 @@ static void setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
cond.twindow = pItem->info->win; cond.twindow = pItem->info->win;
} }
pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQInfo->tableIdGroupInfo); if (isFirstLastRowQuery(pQuery)) {
pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQInfo->tableIdGroupInfo);
} else {
pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQInfo->tableIdGroupInfo);
}
} }
...@@ -4405,41 +4426,6 @@ static bool multiTableMultioutputHelper(SQInfo *pQInfo, int32_t index) { ...@@ -4405,41 +4426,6 @@ static bool multiTableMultioutputHelper(SQInfo *pQInfo, int32_t index) {
return true; return true;
} }
static UNUSED_FUNC int64_t doCheckTables(SQInfo *pQInfo, SArray* pTableList) {
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
if (!multiTableMultioutputHelper(pQInfo, 0)) {
return 0;
}
SPointInterpoSupporter pointInterpSupporter = {0};
pointInterpSupporterInit(pQuery, &pointInterpSupporter);
/*
* here we set the value for before and after the specified time into the
* parameter for interpolation query
*/
pointInterpSupporterSetData(pQInfo, &pointInterpSupporter);
pointInterpSupporterDestroy(&pointInterpSupporter);
scanAllDataBlocks(pRuntimeEnv);
// first/last_row query, do not invoke the finalize for super table query
finalizeQueryResult(pRuntimeEnv);
int64_t numOfRes = getNumOfResult(pRuntimeEnv);
assert(numOfRes == 1 || numOfRes == 0);
// accumulate the point interpolation result
if (numOfRes > 0) {
pQuery->rec.rows += numOfRes;
forwardCtxOutputBuf(pRuntimeEnv, numOfRes);
}
return numOfRes;
}
/** /**
* super table query handler * super table query handler
* 1. super table projection query, group-by on normal columns query, ts-comp query * 1. super table projection query, group-by on normal columns query, ts-comp query
...@@ -4490,8 +4476,8 @@ static void sequentialTableProcess(SQInfo *pQInfo) { ...@@ -4490,8 +4476,8 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
setTagVal(pRuntimeEnv, (STableId*) taosArrayGet(tx, 0), pQInfo->tsdb); setTagVal(pRuntimeEnv, (STableId*) taosArrayGet(tx, 0), pQInfo->tsdb);
// here we simply set the first table as current table // here we simply set the first table as current table
pRuntimeEnv->pQuery->current = ((SGroupItem*) taosArrayGet(group, 0))->info; pQuery->current = ((SGroupItem*) taosArrayGet(group, 0))->info;
scanAllDataBlocks(pRuntimeEnv); scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
int64_t numOfRes = getNumOfResult(pRuntimeEnv); int64_t numOfRes = getNumOfResult(pRuntimeEnv);
if (numOfRes > 0) { if (numOfRes > 0) {
...@@ -4551,14 +4537,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) { ...@@ -4551,14 +4537,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
// TODO handle the limit offset problem // TODO handle the limit offset problem
if (pQuery->numOfFilterCols == 0 && pQuery->limit.offset > 0) { if (pQuery->numOfFilterCols == 0 && pQuery->limit.offset > 0) {
// skipBlocks(pRuntimeEnv); // skipBlocks(pRuntimeEnv);
if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
pQInfo->tableIndex++; pQInfo->tableIndex++;
continue; continue;
} }
} }
scanAllDataBlocks(pRuntimeEnv); scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
pQuery->rec.rows = getNumOfResult(pRuntimeEnv); pQuery->rec.rows = getNumOfResult(pRuntimeEnv);
skipResults(pRuntimeEnv); skipResults(pRuntimeEnv);
...@@ -4807,23 +4792,22 @@ static void tableFixedOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) ...@@ -4807,23 +4792,22 @@ static void tableFixedOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
if (!isTopBottomQuery(pQuery) && pQuery->limit.offset > 0) { // no need to execute, since the output will be ignore.
return;
}
pQuery->current = pTableInfo; // set current query table info pQuery->current = pTableInfo; // set current query table info
scanAllDataBlocks(pRuntimeEnv); scanAllDataBlocks(pRuntimeEnv, pTableInfo->lastKey);
finalizeQueryResult(pRuntimeEnv); finalizeQueryResult(pRuntimeEnv);
if (isQueryKilled(pQInfo)) { if (isQueryKilled(pQInfo)) {
return; return;
} }
// since the numOfOutputElems must be identical for all sql functions that are allowed to be executed simutanelously. // since the numOfRows must be identical for all sql functions that are allowed to be executed simutaneously.
pQuery->rec.rows = getNumOfResult(pRuntimeEnv); pQuery->rec.rows = getNumOfResult(pRuntimeEnv);
// must be top/bottom query if offset > 0
if (pQuery->limit.offset > 0) {
assert(isTopBottomQuery(pQuery));
}
skipResults(pRuntimeEnv); skipResults(pRuntimeEnv);
limitResults(pQInfo); limitResults(pQInfo);
} }
...@@ -4847,7 +4831,7 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) ...@@ -4847,7 +4831,7 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
} }
while (1) { while (1) {
scanAllDataBlocks(pRuntimeEnv); scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
finalizeQueryResult(pRuntimeEnv); finalizeQueryResult(pRuntimeEnv);
if (isQueryKilled(pQInfo)) { if (isQueryKilled(pQInfo)) {
...@@ -4890,11 +4874,11 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) ...@@ -4890,11 +4874,11 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
} }
} }
static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv) { static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
while (1) { while (1) {
scanAllDataBlocks(pRuntimeEnv); scanAllDataBlocks(pRuntimeEnv, start);
if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) { if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) {
return; return;
...@@ -4925,19 +4909,21 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv) { ...@@ -4925,19 +4909,21 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv) {
static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv); SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv);
int32_t numOfInterpo = 0;
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
pQuery->current = pTableInfo; pQuery->current = pTableInfo;
int32_t numOfInterpo = 0;
TSKEY newStartKey = TSKEY_INITIAL_VAL;
// skip blocks without load the actual data block from file if no filter condition present // skip blocks without load the actual data block from file if no filter condition present
skipTimeInterval(pRuntimeEnv); skipTimeInterval(pRuntimeEnv, &newStartKey);
if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) { if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) {
setQueryStatus(pQuery, QUERY_COMPLETED); setQueryStatus(pQuery, QUERY_COMPLETED);
return; return;
} }
while (1) { while (1) {
tableIntervalProcessImpl(pRuntimeEnv); tableIntervalProcessImpl(pRuntimeEnv, newStartKey);
if (isIntervalQuery(pQuery)) { if (isIntervalQuery(pQuery)) {
pQInfo->groupIndex = 0; // always start from 0 pQInfo->groupIndex = 0; // always start from 0
...@@ -6268,10 +6254,10 @@ static void buildTagQueryResult(SQInfo* pQInfo) { ...@@ -6268,10 +6254,10 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
memcpy(dst, data, bytes); memcpy(dst, data, bytes);
} }
} }
} }
} }
pQInfo->tableIndex = pQInfo->groupInfo.numOfTables;
qTrace("QInfo:%p create tag values results completed, rows:%d", pQInfo, num); qTrace("QInfo:%p create tag values results completed, rows:%d", pQInfo, num);
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "qextbuffer.h" #include "qextbuffer.h"
#include "ttime.h" #include "ttime.h"
#include "qinterpolation.h" #include "qfill.h"
#include "ttime.h" #include "ttime.h"
#include "qExecutor.h" #include "qExecutor.h"
...@@ -37,7 +37,8 @@ int32_t initWindowResInfo(SWindowResInfo *pWindowResInfo, SQueryRuntimeEnv *pRun ...@@ -37,7 +37,8 @@ int32_t initWindowResInfo(SWindowResInfo *pWindowResInfo, SQueryRuntimeEnv *pRun
pWindowResInfo->hashList = taosHashInit(threshold, fn, false); pWindowResInfo->hashList = taosHashInit(threshold, fn, false);
pWindowResInfo->curIndex = -1; pWindowResInfo->curIndex = -1;
pWindowResInfo->size = 0; pWindowResInfo->size = 0;
pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
// use the pointer arraylist // use the pointer arraylist
pWindowResInfo->pResult = calloc(threshold, sizeof(SWindowResult)); pWindowResInfo->pResult = calloc(threshold, sizeof(SWindowResult));
...@@ -96,8 +97,8 @@ void resetTimeWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowR ...@@ -96,8 +97,8 @@ void resetTimeWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowR
_hash_fn_t fn = taosGetDefaultHashFunction(pWindowResInfo->type); _hash_fn_t fn = taosGetDefaultHashFunction(pWindowResInfo->type);
pWindowResInfo->hashList = taosHashInit(pWindowResInfo->capacity, fn, false); pWindowResInfo->hashList = taosHashInit(pWindowResInfo->capacity, fn, false);
pWindowResInfo->startTime = 0; pWindowResInfo->startTime = TSKEY_INITIAL_VAL;
pWindowResInfo->prevSKey = 0; pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
} }
void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "qinterpolation.h" #include "qfill.h"
#include "os.h" #include "os.h"
#include "qextbuffer.h" #include "qextbuffer.h"
#include "taosdef.h" #include "taosdef.h"
...@@ -22,13 +22,13 @@ ...@@ -22,13 +22,13 @@
#define FILL_IS_ASC_FILL(_f) ((_f)->order == TSDB_ORDER_ASC) #define FILL_IS_ASC_FILL(_f) ((_f)->order == TSDB_ORDER_ASC)
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t timeRange, char intervalTimeUnit, int16_t precision) { int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, char timeUnit, int16_t precision) {
if (timeRange == 0) { if (slidingTime == 0) {
return startTime; return startTime;
} }
if (intervalTimeUnit == 'a' || intervalTimeUnit == 'm' || intervalTimeUnit == 's' || intervalTimeUnit == 'h') { if (timeUnit == 'a' || timeUnit == 'm' || timeUnit == 's' || timeUnit == 'h') {
return (startTime / timeRange) * timeRange; return (startTime / slidingTime) * slidingTime;
} else { } else {
/* /*
* here we revised the start time of day according to the local time zone, * here we revised the start time of day according to the local time zone,
...@@ -47,10 +47,10 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t timeRange, char ...@@ -47,10 +47,10 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t timeRange, char
int64_t t = (precision == TSDB_TIME_PRECISION_MILLI) ? MILLISECOND_PER_SECOND : MILLISECOND_PER_SECOND * 1000L; int64_t t = (precision == TSDB_TIME_PRECISION_MILLI) ? MILLISECOND_PER_SECOND : MILLISECOND_PER_SECOND * 1000L;
int64_t revStartime = (startTime / timeRange) * timeRange + timezone * t; int64_t revStartime = (startTime / slidingTime) * slidingTime + timezone * t;
int64_t revEndtime = revStartime + timeRange - 1; int64_t revEndtime = revStartime + slidingTime - 1;
if (revEndtime < startTime) { if (revEndtime < startTime) {
revStartime += timeRange; revStartime += slidingTime;
} }
return revStartime; return revStartime;
......
...@@ -318,12 +318,12 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) { ...@@ -318,12 +318,12 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) {
if (pCheckInfo->iter == NULL) { if (pCheckInfo->iter == NULL) {
return false; return false;
} }
}
if (!tSkipListIterNext(pCheckInfo->iter)) { // buffer is empty if (!tSkipListIterNext(pCheckInfo->iter)) { // buffer is empty
return false; return false;
}
} }
SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter); SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
if (node == NULL) { if (node == NULL) {
return false; return false;
...@@ -576,12 +576,12 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock ...@@ -576,12 +576,12 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock
} }
} }
cur->pos = 0;
if ((k1 != TSKEY_INITIAL_VAL && k1 < binfo.window.ekey) || (k2 != TSKEY_INITIAL_VAL && k2 < binfo.window.ekey)) { if ((k1 != TSKEY_INITIAL_VAL && k1 < binfo.window.ekey) || (k2 != TSKEY_INITIAL_VAL && k2 < binfo.window.ekey)) {
doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo); doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo);
mergeDataInDataBlock(pQueryHandle, pCheckInfo, pBlock, sa); mergeDataInDataBlock(pQueryHandle, pCheckInfo, pBlock, sa);
} else { } else {
pQueryHandle->realNumOfRows = binfo.rows; pQueryHandle->realNumOfRows = binfo.rows;
cur->pos = 0;
} }
} }
} else { //desc order } else { //desc order
...@@ -638,9 +638,11 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock ...@@ -638,9 +638,11 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock
} }
cur->pos = binfo.rows - 1; cur->pos = binfo.rows - 1;
if ((k1 != TSKEY_INITIAL_VAL && k1 < binfo.window.ekey) || (k2 != TSKEY_INITIAL_VAL && k2 < binfo.window.ekey)) { if ((k1 != TSKEY_INITIAL_VAL && k1 > binfo.window.ekey) || (k2 != TSKEY_INITIAL_VAL && k2 > binfo.window.ekey)) {
doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo); doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo);
mergeDataInDataBlock(pQueryHandle, pCheckInfo, pBlock, sa); mergeDataInDataBlock(pQueryHandle, pCheckInfo, pBlock, sa);
} else {
pQueryHandle->realNumOfRows = binfo.rows;
} }
} }
// pQueryHandle->realNumOfRows = pBlock->numOfPoints; // pQueryHandle->realNumOfRows = pBlock->numOfPoints;
...@@ -713,8 +715,7 @@ static int vnodeBinarySearchKey(char* pValue, int num, TSKEY key, int order) { ...@@ -713,8 +715,7 @@ static int vnodeBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
return midPos; return midPos;
} }
static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, SDataBlockInfo* pBlockInfo, int32_t capacity, static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) {
int32_t numOfRows, int32_t start, int32_t end) {
char* pData = NULL; char* pData = NULL;
int32_t step = ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)? 1 : -1; int32_t step = ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)? 1 : -1;
...@@ -844,7 +845,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo ...@@ -844,7 +845,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo
cur->win.ekey = tsArray[end]; cur->win.ekey = tsArray[end];
// todo opt in case of no data in buffer // todo opt in case of no data in buffer
numOfRows = copyDataFromFileBlock(pQueryHandle, &blockInfo, pQueryHandle->outputCapacity, numOfRows, start, end); numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end);
// if the buffer is not full in case of descending order query, move the data in the front of the buffer // if the buffer is not full in case of descending order query, move the data in the front of the buffer
if (!ASCENDING_ORDER_TRAVERSE(pQueryHandle->order) && numOfRows < pQueryHandle->outputCapacity) { if (!ASCENDING_ORDER_TRAVERSE(pQueryHandle->order) && numOfRows < pQueryHandle->outputCapacity) {
...@@ -857,6 +858,9 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo ...@@ -857,6 +858,9 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo
} }
} }
cur->blockCompleted = (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) ||
((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)));
pCheckInfo->lastKey = cur->lastKey; pCheckInfo->lastKey = cur->lastKey;
pQueryHandle->realNumOfRows = numOfRows; pQueryHandle->realNumOfRows = numOfRows;
cur->rows = numOfRows; cur->rows = numOfRows;
...@@ -927,8 +931,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo ...@@ -927,8 +931,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo
end = pos; end = pos;
} }
numOfRows = numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end);
copyDataFromFileBlock(pQueryHandle, &blockInfo, pQueryHandle->outputCapacity, numOfRows, start, end);
pos += (end - start + 1) * step; pos += (end - start + 1) * step;
} }
} while (numOfRows < pQueryHandle->outputCapacity); } while (numOfRows < pQueryHandle->outputCapacity);
...@@ -964,8 +967,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo ...@@ -964,8 +967,7 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo
end = pos; end = pos;
} }
numOfRows = numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end);
copyDataFromFileBlock(pQueryHandle, &blockInfo, pQueryHandle->outputCapacity, numOfRows, start, end);
pos += (end - start + 1) * step; pos += (end - start + 1) * step;
} else { } else {
...@@ -993,8 +995,8 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo ...@@ -993,8 +995,8 @@ static void mergeDataInDataBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo
} }
} }
cur->blockCompleted = ((pos >= endPos && ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) || cur->blockCompleted = (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) ||
(pos <= endPos && !ASCENDING_ORDER_TRAVERSE(pQueryHandle->order))); ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)));
if (!ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) { if (!ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) {
SWAP(cur->win.skey, cur->win.ekey, TSKEY); SWAP(cur->win.skey, cur->win.ekey, TSKEY);
...@@ -1342,35 +1344,9 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pqHandle) { ...@@ -1342,35 +1344,9 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pqHandle) {
pQueryHandle->checkFiles = false; pQueryHandle->checkFiles = false;
} }
// if (ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) { // TODO: opt by using lastKeyOnFile
return doHasDataInBuffer(pQueryHandle); // TODO: opt by consider the scan order
// } else { return doHasDataInBuffer(pQueryHandle);
// assert(0);
// return false;
// }
// if (ASCENDING_ORDER_TRAVERSE(pQueryHandle->order)) {
// if (pQueryHandle->checkFiles) {
// if (getDataBlocksInFiles(pQueryHandle)) {
// return true;
// }
//
// pQueryHandle->activeIndex = 0;
// pQueryHandle->checkFiles = false;
// }
//
// return doHasDataInBuffer(pQueryHandle);
// } else { // starts from the buffer in case of descending timestamp order check data blocks
// if (!pQueryHandle->checkFiles) {
// if (doHasDataInBuffer(pQueryHandle)) {
// return true;
// }
//
// pQueryHandle->checkFiles = true;
// }
//
// return getDataBlocksInFiles(pQueryHandle);
// }
} }
void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) { void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) {
...@@ -1420,6 +1396,8 @@ void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) { ...@@ -1420,6 +1396,8 @@ void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) {
taosArrayDestroy(pQueryHandle->pTableCheckInfo); taosArrayDestroy(pQueryHandle->pTableCheckInfo);
pQueryHandle->pTableCheckInfo = taosArrayInit(1, sizeof(STableCheckInfo)); pQueryHandle->pTableCheckInfo = taosArrayInit(1, sizeof(STableCheckInfo));
info.lastKey = key;
taosArrayPush(pQueryHandle->pTableCheckInfo, &info); taosArrayPush(pQueryHandle->pTableCheckInfo, &info);
// update the query time window according to the chosen last timestamp // update the query time window according to the chosen last timestamp
...@@ -1539,27 +1517,6 @@ SDataBlockInfo tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle) { ...@@ -1539,27 +1517,6 @@ SDataBlockInfo tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle) {
SDataBlockInfo binfo = getTrueDataBlockInfo(pCheckInfo, pBlockInfo->pBlock.compBlock); SDataBlockInfo binfo = getTrueDataBlockInfo(pCheckInfo, pBlockInfo->pBlock.compBlock);
return binfo; return binfo;
} }
// else {
/*
* no data in mem or imem, or data in mem/imem with greater timestamp, no need to load data in buffer
* return the file block info directly
*/
// if (!pHandle->cur.mixBlock || pHandle->cur.rows == pBlockInfo->pBlock.compBlock->numOfPoints) {
// pBlockInfo->pTableCheckInfo->lastKey = pBlockInfo->pBlock.compBlock->keyLast + step;
// assert(pHandle->outputCapacity >= pBlockInfo->pBlock.compBlock->numOfPoints);
//
// return binfo;
// } else {
// SDataBlockInfo blockInfo = {
// .uid = pTable->tableId.uid,
// .tid = pTable->tableId.tid,
// .rows = pHandle->cur.rows,
// .window = pHandle->cur.win,
// };
//
// return blockInfo;
// }
// }
} else { } else {
STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex); STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
pTable = pCheckInfo->pTableObj; pTable = pCheckInfo->pTableObj;
...@@ -1576,6 +1533,10 @@ SDataBlockInfo tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle) { ...@@ -1576,6 +1533,10 @@ SDataBlockInfo tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle) {
pCheckInfo->lastKey = win->ekey + step; pCheckInfo->lastKey = win->ekey + step;
} }
if (!ASCENDING_ORDER_TRAVERSE(pHandle->order)) {
SWAP(pHandle->cur.win.skey, pHandle->cur.win.ekey, TSKEY);
}
SDataBlockInfo blockInfo = { SDataBlockInfo blockInfo = {
.uid = pTable->tableId.uid, .uid = pTable->tableId.uid,
.tid = pTable->tableId.tid, .tid = pTable->tableId.tid,
...@@ -1618,14 +1579,24 @@ SArray* tsdbRetrieveDataBlock(TsdbQueryHandleT* pQueryHandle, SArray* pIdList) { ...@@ -1618,14 +1579,24 @@ SArray* tsdbRetrieveDataBlock(TsdbQueryHandleT* pQueryHandle, SArray* pIdList) {
if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fileId == pHandle->cur.fid && if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fileId == pHandle->cur.fid &&
pBlockLoadInfo->tid == pCheckInfo->pTableObj->tableId.tid) { pBlockLoadInfo->tid == pCheckInfo->pTableObj->tableId.tid) {
return pHandle->pColumns; return pHandle->pColumns;
} else { } else { // only load the file block
SCompBlock* pBlock = pBlockInfoEx->pBlock.compBlock; SCompBlock* pBlock = pBlockInfoEx->pBlock.compBlock;
doLoadFileDataBlock(pHandle, pBlock, pCheckInfo); doLoadFileDataBlock(pHandle, pBlock, pCheckInfo);
SArray* sa = getDefaultLoadColumns(pHandle, true); // todo refactor
mergeDataInDataBlock(pHandle, pCheckInfo, pBlock, sa); int32_t numOfRows = copyDataFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfPoints - 1);
taosArrayDestroy(sa);
// if the buffer is not full in case of descending order query, move the data in the front of the buffer
if (!ASCENDING_ORDER_TRAVERSE(pHandle->order) && numOfRows < pHandle->outputCapacity) {
int32_t emptySize = pHandle->outputCapacity - numOfRows;
int32_t reqNumOfCols = taosArrayGetSize(pHandle->pColumns);
for(int32_t i = 0; i < reqNumOfCols; ++i) {
SColumnInfoData* pColInfo = taosArrayGet(pHandle->pColumns, i);
memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes);
}
}
return pHandle->pColumns; return pHandle->pColumns;
} }
} }
......
...@@ -573,6 +573,7 @@ bool tSkipListIterNext(SSkipListIterator *iter) { ...@@ -573,6 +573,7 @@ bool tSkipListIterNext(SSkipListIterator *iter) {
pthread_rwlock_unlock(pSkipList->lock); pthread_rwlock_unlock(pSkipList->lock);
} }
iter->step += 1;
return (iter->order == TSDB_ORDER_ASC)? (iter->cur != pSkipList->pTail) : (iter->cur != pSkipList->pHead); return (iter->order == TSDB_ORDER_ASC)? (iter->cur != pSkipList->pTail) : (iter->cur != pSkipList->pHead);
} }
......
...@@ -111,18 +111,7 @@ endi ...@@ -111,18 +111,7 @@ endi
if $data09 != nchar0 then if $data09 != nchar0 then
return -1 return -1
endi endi
if $data11 != NULL then
return -1
endi
if $data12 != NULL then
return -1
endi
if $data13 != NULL then
return -1
endi
if $data14 != NULL then
return -1
endi
## TBASE-329 ## TBASE-329
sql select * from $tb where c1 < 9 order by ts desc limit 1 offset 1 sql select * from $tb where c1 < 9 order by ts desc limit 1 offset 1
...@@ -537,7 +526,8 @@ endi ...@@ -537,7 +526,8 @@ endi
if $data14 != 8.000000000 then if $data14 != 8.000000000 then
return -1 return -1
endi endi
if $data21 != NULL then if $data21 != null then
print expect null, actual: $data21
return -1 return -1
endi endi
...@@ -554,7 +544,7 @@ endi ...@@ -554,7 +544,7 @@ endi
if $data21 != 9 then if $data21 != 9 then
return -1 return -1
endi endi
if $data31 != NULL then if $data31 != null then
return -1 return -1
endi endi
...@@ -574,7 +564,7 @@ endi ...@@ -574,7 +564,7 @@ endi
if $data31 != 9 then if $data31 != 9 then
return -1 return -1
endi endi
if $data41 != NULL then if $data41 != null then
return -1 return -1
endi endi
sql select sum(c1), sum(c2), sum(c3), sum(c4), sum(c5), sum(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(30m) limit 5 offset 1 sql select sum(c1), sum(c2), sum(c3), sum(c4), sum(c5), sum(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(30m) limit 5 offset 1
...@@ -590,7 +580,7 @@ endi ...@@ -590,7 +580,7 @@ endi
if $data21 != 9 then if $data21 != 9 then
return -1 return -1
endi endi
if $data31 != NULL then if $data31 != null then
return -1 return -1
endi endi
...@@ -607,7 +597,7 @@ endi ...@@ -607,7 +597,7 @@ endi
if $data21 != 7.000000000 then if $data21 != 7.000000000 then
return -1 return -1
endi endi
if $data31 != NULL then if $data31 != null then
return -1 return -1
endi endi
sql select avg(c1), avg(c2), avg(c3), avg(c4), avg(c5), avg(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(30m) limit 3 offset 1 sql select avg(c1), avg(c2), avg(c3), avg(c4), avg(c5), avg(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(30m) limit 3 offset 1
...@@ -623,7 +613,7 @@ endi ...@@ -623,7 +613,7 @@ endi
if $data21 != 9.000000000 then if $data21 != 9.000000000 then
return -1 return -1
endi endi
if $data31 != NULL then if $data31 != null then
return -1 return -1
endi endi
......
...@@ -84,43 +84,43 @@ endi ...@@ -84,43 +84,43 @@ endi
#### case 1: tag NULL, or 'NULL' #### case 1: tag NULL, or 'NULL'
sql create table mt2 (ts timestamp, col1 int, col3 float, col5 binary(8), col6 bool, col9 nchar(8)) tags (tag1 binary(8), tag2 nchar(8), tag3 int, tag5 bool) sql create table mt2 (ts timestamp, col1 int, col3 float, col5 binary(8), col6 bool, col9 nchar(8)) tags (tag1 binary(8), tag2 nchar(8), tag3 int, tag5 bool)
sql create table st2 using mt2 tags (NULL, 'NULL', 102, 'true') sql create table st2 using mt2 tags (NULL, 'NULL', 102, 'true')
sql describe st2 sql select tag1, tag2, tag3, tag5 from st2
if $rows != 10 then if $rows != 1 then
return -1 return -1
endi endi
if $data63 != NULL then if $data00 != NULL then
print ==1== expect: NULL, actually: $data63 print ==1== expect: NULL, actually: $data00
return -1 return -1
endi endi
if $data73 != NULL then if $data01 != NULL then
print ==2== expect: NULL, actually: $data73 print ==2== expect: NULL, actually: $data01
return -1 return -1
endi endi
if $data83 != 102 then if $data02 != 102 then
print ==3== expect: NULL, actually: $data83 print ==3== expect: NULL, actually: $data02
return -1 return -1
endi endi
if $data93 != true then if $data03 != 1 then
print ==4== expect: NULL, actually: $data93 print ==4== expect: 1, actually: $data03
return -1 return -1
endi endi
sql create table st3 using mt2 tags (NULL, 'ABC', 103, 'FALSE') sql create table st3 using mt2 tags (NULL, 'ABC', 103, 'FALSE')
sql describe st3 sql select tag1, tag2, tag3, tag5 from st3
if $rows != 10 then if $rows != 1 then
return -1 return -1
endi endi
if $data63 != NULL then if $data00 != NULL then
print ==5== expect: NULL, actually: $data63 print ==5== expect: NULL, actually: $data00
return -1 return -1
endi endi
if $data73 != ABC then if $data01 != ABC then
return -1 return -1
endi endi
if $data83 != 103 then if $data02 != 103 then
return -1 return -1
endi endi
if $data93 != false then if $data03 != 0 then
return -1 return -1
endi endi
...@@ -128,39 +128,39 @@ endi ...@@ -128,39 +128,39 @@ endi
sql_error create table stx using mt2 tags ('NULL', '123aBc', 104, '123') sql_error create table stx using mt2 tags ('NULL', '123aBc', 104, '123')
sql_error create table sty using mt2 tags ('NULL', '123aBc', 104, 'xtz') sql_error create table sty using mt2 tags ('NULL', '123aBc', 104, 'xtz')
sql create table st4 using mt2 tags ('NULL', '123aBc', 104, 'NULL') sql create table st4 using mt2 tags ('NULL', '123aBc', 104, 'NULL')
sql describe st4 sql select tag1,tag2,tag3,tag5 from st4
if $rows != 10 then if $rows != 1 then
return -1 return -1
endi endi
if $data63 != NULL then if $data00 != NULL then
return -1 return -1
endi endi
if $data73 != 123aBc then if $data01 != 123aBc then
return -1 return -1
endi endi
if $data83 != 104 then if $data02 != 104 then
return -1 return -1
endi endi
if $data93 != NULL then if $data03 != NULL then
print ==6== expect: NULL, actually: $data93 print ==6== expect: NULL, actually: $data03
return -1 return -1
endi endi
sql create table st5 using mt2 tags ('NULL', '123aBc', 105, NULL) sql create table st5 using mt2 tags ('NULL', '123aBc', 105, NULL)
sql describe st5 sql select tag1,tag2,tag3,tag5 from st5
if $rows != 10 then if $rows != 1 then
return -1 return -1
endi endi
if $data63 != NULL then if $data00 != NULL then
return -1 return -1
endi endi
if $data73 != 123aBc then if $data01 != 123aBc then
return -1 return -1
endi endi
if $data83 != 105 then if $data02 != 105 then
return -1 return -1
endi endi
if $data93 != NULL then if $data03 != NULL then
return -1 return -1
endi endi
...@@ -177,28 +177,29 @@ sql_error insert into st34 using mt3 tags ('NULL', '123aBc', 105, NULL) values ...@@ -177,28 +177,29 @@ sql_error insert into st34 using mt3 tags ('NULL', '123aBc', 105, NULL) values
#### case 3: set tag value #### case 3: set tag value
sql create table mt4 (ts timestamp, c1 int) tags (tag_binary binary(16), tag_nchar nchar(16), tag_int int, tag_bool bool, tag_float float, tag_double double) sql create table mt4 (ts timestamp, c1 int) tags (tag_binary binary(16), tag_nchar nchar(16), tag_int int, tag_bool bool, tag_float float, tag_double double)
sql create table st41 using mt4 tags ("beijing", 'nchar_tag', 100, false, 9.12345, 7.123456789) sql create table st41 using mt4 tags ("beijing", 'nchar_tag', 100, false, 9.12345, 7.123456789)
sql describe st41 sql select tag_binary, tag_nchar, tag_int, tag_bool, tag_float, tag_double st41
if $rows != 8 then if $rows != 1 then
return -1 return -1
endi endi
if $data23 != beijing then if $data00 != beijing then
return -1 return -1
endi endi
if $data33 != nchar_tag then if $data01 != nchar_tag then
return -1 return -1
endi endi
if $data43 != 100 then if $data02 != 100 then
return -1 return -1
endi endi
if $data53 != false then if $data03 != false then
return -1 return -1
endi endi
if $data63 != 9.123450 then if $dat04 != 9.123450 then
return -1 return -1
endi endi
if $data73 != 7.123457 then if $data05 != 7.123457 then
return -1 return -1
endi endi
################# binary ################# binary
sql alter table st41 set tag tag_binary = "shanghai" sql alter table st41 set tag tag_binary = "shanghai"
sql describe st41 sql describe st41
......
...@@ -23,7 +23,7 @@ $stb = $stbPrefix . $i ...@@ -23,7 +23,7 @@ $stb = $stbPrefix . $i
sql drop database $db -x step1 sql drop database $db -x step1
step1: step1:
sql create database $db cache 2048 tables 200 sql create database $db cache 16 maxtables 200
print ====== create tables print ====== create tables
sql use $db sql use $db
sql create table $stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 smallint, c6 tinyint, c7 bool, c8 binary(10), c9 nchar(10)) tags(t1 int) sql create table $stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 smallint, c6 tinyint, c7 bool, c8 binary(10), c9 nchar(10)) tags(t1 int)
......
...@@ -15,7 +15,7 @@ $db = $dbPrefix ...@@ -15,7 +15,7 @@ $db = $dbPrefix
$stb = $stbPrefix $stb = $stbPrefix
sql drop database if exists $db sql drop database if exists $db
sql create database $db rows 200 maxTables 4 sql create database $db maxrows 200 maxTables 4
print ====== create tables print ====== create tables
sql use $db sql use $db
sql create table $stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 bool, c6 binary(10), c7 nchar(10)) tags(t1 int) sql create table $stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 bool, c6 binary(10), c7 nchar(10)) tags(t1 int)
......
...@@ -130,6 +130,7 @@ if $data03 != 1 then ...@@ -130,6 +130,7 @@ if $data03 != 1 then
return -1 return -1
endi endi
if $data04 != 0.000000000 then if $data04 != 0.000000000 then
print expect: 0.00000000 , actual: $data04
return -1 return -1
endi endi
if $data05 != 1 then if $data05 != 1 then
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册