Merge pull request #13753 from taosdata/feature/3_liaohj
refactor: do some internal refactor of sample function.
This commit is contained in:
commit
6bd38625e7
|
@ -3665,7 +3665,7 @@ static void* doFreeColumnInfoData(SArray* pColumnInfoData) {
|
||||||
size_t cols = taosArrayGetSize(pColumnInfoData);
|
size_t cols = taosArrayGetSize(pColumnInfoData);
|
||||||
for (int32_t i = 0; i < cols; ++i) {
|
for (int32_t i = 0; i < cols; ++i) {
|
||||||
SColumnInfoData* pColInfo = taosArrayGet(pColumnInfoData, i);
|
SColumnInfoData* pColInfo = taosArrayGet(pColumnInfoData, i);
|
||||||
taosMemoryFreeClear(pColInfo->pData);
|
colDataDestroy(pColInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
taosArrayDestroy(pColumnInfoData);
|
taosArrayDestroy(pColumnInfoData);
|
||||||
|
@ -3697,6 +3697,7 @@ void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
|
||||||
taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
|
taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
|
||||||
taosMemoryFreeClear(pTsdbReadHandle->suppInfo.pstatis);
|
taosMemoryFreeClear(pTsdbReadHandle->suppInfo.pstatis);
|
||||||
taosMemoryFreeClear(pTsdbReadHandle->suppInfo.plist);
|
taosMemoryFreeClear(pTsdbReadHandle->suppInfo.plist);
|
||||||
|
taosMemoryFree(pTsdbReadHandle->suppInfo.slotIds);
|
||||||
|
|
||||||
if (!emptyQueryTimewindow(pTsdbReadHandle)) {
|
if (!emptyQueryTimewindow(pTsdbReadHandle)) {
|
||||||
// tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
|
// tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
|
||||||
|
@ -3723,5 +3724,7 @@ void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
|
||||||
pTsdbReadHandle, pCost->headFileLoad, pCost->headFileLoadTime, pCost->statisInfoLoadTime,
|
pTsdbReadHandle, pCost->headFileLoad, pCost->headFileLoadTime, pCost->statisInfoLoadTime,
|
||||||
pCost->blockLoadTime, pCost->checkForNextTime, pTsdbReadHandle->idStr);
|
pCost->blockLoadTime, pCost->checkForNextTime, pTsdbReadHandle->idStr);
|
||||||
|
|
||||||
|
taosMemoryFree(pTsdbReadHandle->idStr);
|
||||||
|
taosMemoryFree(pTsdbReadHandle->pSchema);
|
||||||
taosMemoryFreeClear(pTsdbReadHandle);
|
taosMemoryFreeClear(pTsdbReadHandle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -781,6 +781,7 @@ SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNod
|
||||||
SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs);
|
SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs);
|
||||||
SSDataBlock* createResDataBlock(SDataBlockDescNode* pNode);
|
SSDataBlock* createResDataBlock(SDataBlockDescNode* pNode);
|
||||||
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode);
|
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode);
|
||||||
|
void clearupQueryTableDataCond(SQueryTableDataCond* pCond);
|
||||||
|
|
||||||
SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo,
|
SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo,
|
||||||
char* pData, int16_t bytes, bool masterscan, uint64_t groupId,
|
char* pData, int16_t bytes, bool masterscan, uint64_t groupId,
|
||||||
|
|
|
@ -2562,7 +2562,8 @@ void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->info.colId == pmInfo->colId) {
|
if (p->info.colId == pmInfo->colId) {
|
||||||
taosArraySet(pBlock->pDataBlock, pmInfo->targetSlotId, p);
|
SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, pmInfo->targetSlotId);
|
||||||
|
colDataAssign(pDst, p, pBlock->info.rows);
|
||||||
i++;
|
i++;
|
||||||
j++;
|
j++;
|
||||||
} else if (p->info.colId < pmInfo->colId) {
|
} else if (p->info.colId < pmInfo->colId) {
|
||||||
|
@ -2578,6 +2579,7 @@ int32_t setDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadIn
|
||||||
SArray* pColList) {
|
SArray* pColList) {
|
||||||
if (pColList == NULL) { // data from other sources
|
if (pColList == NULL) { // data from other sources
|
||||||
blockCompressDecode(pRes, numOfOutput, numOfRows, pData);
|
blockCompressDecode(pRes, numOfOutput, numOfRows, pData);
|
||||||
|
pRes->info.rows = numOfRows;
|
||||||
} else { // extract data according to pColList
|
} else { // extract data according to pColList
|
||||||
ASSERT(numOfOutput == taosArrayGetSize(pColList));
|
ASSERT(numOfOutput == taosArrayGetSize(pColList));
|
||||||
char* pStart = pData;
|
char* pStart = pData;
|
||||||
|
@ -2614,15 +2616,15 @@ int32_t setDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadIn
|
||||||
}
|
}
|
||||||
|
|
||||||
blockCompressDecode(pBlock, numOfCols, numOfRows, pStart);
|
blockCompressDecode(pBlock, numOfCols, numOfRows, pStart);
|
||||||
|
|
||||||
// data from mnode
|
// data from mnode
|
||||||
|
pRes->info.rows = numOfRows;
|
||||||
relocateColumnData(pRes, pColList, pBlock->pDataBlock);
|
relocateColumnData(pRes, pColList, pBlock->pDataBlock);
|
||||||
taosArrayDestroy(pBlock->pDataBlock);
|
taosArrayDestroy(pBlock->pDataBlock);
|
||||||
taosMemoryFree(pBlock);
|
taosMemoryFree(pBlock);
|
||||||
// blockDataDestroy(pBlock);
|
// blockDataDestroy(pBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
pRes->info.rows = numOfRows;
|
|
||||||
|
|
||||||
// todo move this to time window aggregator, since the primary timestamp may not be known by exchange operator.
|
// todo move this to time window aggregator, since the primary timestamp may not be known by exchange operator.
|
||||||
blockDataUpdateTsWindow(pRes, 0);
|
blockDataUpdateTsWindow(pRes, 0);
|
||||||
|
|
||||||
|
@ -4906,6 +4908,11 @@ int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysi
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearupQueryTableDataCond(SQueryTableDataCond* pCond) {
|
||||||
|
taosMemoryFree(pCond->twindows);
|
||||||
|
taosMemoryFree(pCond->colList);
|
||||||
|
}
|
||||||
|
|
||||||
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
|
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
|
||||||
SColumn c = {0};
|
SColumn c = {0};
|
||||||
c.slotId = pColNode->slotId;
|
c.slotId = pColNode->slotId;
|
||||||
|
@ -5111,7 +5118,10 @@ tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle*
|
||||||
goto _error;
|
goto _error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo, queryId, taskId);
|
tsdbReaderT* pReader = tsdbReaderOpen(pHandle->vnode, &cond, pTableListInfo, queryId, taskId);
|
||||||
|
clearupQueryTableDataCond(&cond);
|
||||||
|
|
||||||
|
return pReader;
|
||||||
|
|
||||||
_error:
|
_error:
|
||||||
terrno = code;
|
terrno = code;
|
||||||
|
|
|
@ -525,7 +525,9 @@ static int32_t getTableScannerExecInfo(struct SOperatorInfo* pOptr, void** pOptr
|
||||||
|
|
||||||
static void destroyTableScanOperatorInfo(void* param, int32_t numOfOutput) {
|
static void destroyTableScanOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
STableScanInfo* pTableScanInfo = (STableScanInfo*)param;
|
STableScanInfo* pTableScanInfo = (STableScanInfo*)param;
|
||||||
taosMemoryFree(pTableScanInfo->pResBlock);
|
blockDataDestroy(pTableScanInfo->pResBlock);
|
||||||
|
clearupQueryTableDataCond(&pTableScanInfo->cond);
|
||||||
|
|
||||||
tsdbCleanupReadHandle(pTableScanInfo->dataReader);
|
tsdbCleanupReadHandle(pTableScanInfo->dataReader);
|
||||||
|
|
||||||
taosArrayDestroy(pTableScanInfo->pGroupCols);
|
taosArrayDestroy(pTableScanInfo->pGroupCols);
|
||||||
|
@ -1439,16 +1441,18 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) {
|
||||||
pRsp->numOfRows, pInfo->loadInfo.totalRows);
|
pRsp->numOfRows, pInfo->loadInfo.totalRows);
|
||||||
|
|
||||||
if (pRsp->numOfRows == 0) {
|
if (pRsp->numOfRows == 0) {
|
||||||
|
|
||||||
|
taosMemoryFree(pRsp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SRetrieveMetaTableRsp* pTableRsp = pInfo->pRsp;
|
setDataBlockFromFetchRsp(pInfo->pRes, &pInfo->loadInfo, pRsp->numOfRows, pRsp->data, pRsp->compLen,
|
||||||
setDataBlockFromFetchRsp(pInfo->pRes, &pInfo->loadInfo, pTableRsp->numOfRows, pTableRsp->data, pTableRsp->compLen,
|
|
||||||
pOperator->numOfExprs, startTs, NULL, pInfo->scanCols);
|
pOperator->numOfExprs, startTs, NULL, pInfo->scanCols);
|
||||||
|
|
||||||
// todo log the filter info
|
// todo log the filter info
|
||||||
doFilterResult(pInfo);
|
doFilterResult(pInfo);
|
||||||
|
taosMemoryFree(pRsp);
|
||||||
if (pInfo->pRes->info.rows > 0) {
|
if (pInfo->pRes->info.rows > 0) {
|
||||||
return pInfo->pRes;
|
return pInfo->pRes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,7 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx);
|
||||||
bool getSampleFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
bool getSampleFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||||
bool sampleFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
|
bool sampleFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
|
||||||
int32_t sampleFunction(SqlFunctionCtx* pCtx);
|
int32_t sampleFunction(SqlFunctionCtx* pCtx);
|
||||||
|
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
|
||||||
|
|
||||||
bool getTailFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
bool getTailFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||||
bool tailFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
|
bool tailFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
|
||||||
|
|
|
@ -1754,12 +1754,12 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
.name = "sample",
|
.name = "sample",
|
||||||
.type = FUNCTION_TYPE_SAMPLE,
|
.type = FUNCTION_TYPE_SAMPLE,
|
||||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC,
|
||||||
.translateFunc = translateSample,
|
.translateFunc = translateSample,
|
||||||
.getEnvFunc = getSampleFuncEnv,
|
.getEnvFunc = getSampleFuncEnv,
|
||||||
.initFunc = sampleFunctionSetup,
|
.initFunc = sampleFunctionSetup,
|
||||||
.processFunc = sampleFunction,
|
.processFunc = sampleFunction,
|
||||||
.finalizeFunc = NULL
|
.finalizeFunc = sampleFinalize
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "tail",
|
.name = "tail",
|
||||||
|
|
|
@ -196,7 +196,7 @@ typedef struct SSampleInfo {
|
||||||
int32_t numSampled;
|
int32_t numSampled;
|
||||||
uint8_t colType;
|
uint8_t colType;
|
||||||
int16_t colBytes;
|
int16_t colBytes;
|
||||||
char *data;
|
char *data;
|
||||||
int64_t *timestamp;
|
int64_t *timestamp;
|
||||||
} SSampleInfo;
|
} SSampleInfo;
|
||||||
|
|
||||||
|
@ -4181,28 +4181,38 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) {
|
||||||
SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||||
|
|
||||||
SInputColumnInfoData* pInput = &pCtx->input;
|
SInputColumnInfoData* pInput = &pCtx->input;
|
||||||
TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
|
|
||||||
|
TSKEY* tsList = NULL;
|
||||||
|
if (pInput->pPTS != NULL) {
|
||||||
|
tsList = (int64_t*)pInput->pPTS->pData;
|
||||||
|
}
|
||||||
|
|
||||||
SColumnInfoData* pInputCol = pInput->pData[0];
|
SColumnInfoData* pInputCol = pInput->pData[0];
|
||||||
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
|
|
||||||
|
|
||||||
int32_t alreadySampled = pInfo->numSampled;
|
|
||||||
|
|
||||||
int32_t startOffset = pCtx->offset;
|
|
||||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
|
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
|
||||||
if (colDataIsNull_s(pInputCol, i)) {
|
if (colDataIsNull_s(pInputCol, i)) {
|
||||||
//colDataAppendNULL(pOutput, i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* data = colDataGetData(pInputCol, i);
|
char* data = colDataGetData(pInputCol, i);
|
||||||
doReservoirSample(pInfo, data, tsList[i], i);
|
doReservoirSample(pInfo, data, /*tsList[i]*/0, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
||||||
|
SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
|
||||||
|
|
||||||
|
SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
|
||||||
|
pEntryInfo->complete = true;
|
||||||
|
|
||||||
|
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
|
||||||
|
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||||
|
|
||||||
|
int32_t currentRow = pBlock->info.rows;
|
||||||
for (int32_t i = 0; i < pInfo->numSampled; ++i) {
|
for (int32_t i = 0; i < pInfo->numSampled; ++i) {
|
||||||
int32_t pos = startOffset + i;
|
colDataAppend(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
|
||||||
colDataAppend(pOutput, pos, pInfo->data + i * pInfo->colBytes, false);
|
|
||||||
//TODO: handle ts output
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pInfo->numSampled;
|
return pInfo->numSampled;
|
||||||
|
|
|
@ -331,10 +331,14 @@ class TDTestCase:
|
||||||
# self.checksample(**case9)
|
# self.checksample(**case9)
|
||||||
# case10 = {"alias": ", _c0"}
|
# case10 = {"alias": ", _c0"}
|
||||||
# self.checksample(**case10)
|
# self.checksample(**case10)
|
||||||
case11 = {"alias": ", st1"}
|
# case11 = {"alias": ", st1"}
|
||||||
self.checksample(**case11)
|
# self.checksample(**case11)
|
||||||
case12 = {"alias": ", c1"}
|
tdSql.query("select sample( c1 , 1 ) , st1 from t1")
|
||||||
self.checksample(**case12)
|
|
||||||
|
# case12 = {"alias": ", c1"}
|
||||||
|
# self.checksample(**case12)
|
||||||
|
|
||||||
|
tdSql.query("select sample( c1 , 1 ) , c1 from t1")
|
||||||
|
|
||||||
# case13~15: with single condition
|
# case13~15: with single condition
|
||||||
case13 = {"condition": "where c1 <= 10"}
|
case13 = {"condition": "where c1 <= 10"}
|
||||||
|
@ -491,21 +495,26 @@ class TDTestCase:
|
||||||
# self.checksample(**err40) # mix with arithmetic 1
|
# self.checksample(**err40) # mix with arithmetic 1
|
||||||
# tdSql.query(" select sample(c1 , 1) + 2 from t1 ")
|
# tdSql.query(" select sample(c1 , 1) + 2 from t1 ")
|
||||||
err41 = {"alias": "+ avg(c1)"}
|
err41 = {"alias": "+ avg(c1)"}
|
||||||
self.checksample(**err41) # mix with arithmetic 2
|
# self.checksample(**err41) # mix with arithmetic 2
|
||||||
err42 = {"alias": ", c1"}
|
|
||||||
self.checksample(**err42) # mix with other col
|
# err42 = {"alias": ", c1"}
|
||||||
|
# self.checksample(**err42)
|
||||||
|
tdSql.query("select sample( c1 , 1 ) , c1 from t1")
|
||||||
|
# mix with other col
|
||||||
# err43 = {"table_expr": "stb1"}
|
# err43 = {"table_expr": "stb1"}
|
||||||
# self.checksample(**err43) # select stb directly
|
# self.checksample(**err43) # select stb directly
|
||||||
err44 = {
|
# err44 = {
|
||||||
"col": "stb1.c1",
|
# "col": "stb1.c1",
|
||||||
"table_expr": "stb1, stb2",
|
# "table_expr": "stb1, stb2",
|
||||||
"condition": "where stb1.ts=stb2.ts and stb1.st1=stb2.st2 order by stb1.ts"
|
# "condition": "where stb1.ts=stb2.ts and stb1.st1=stb2.st2 order by stb1.ts"
|
||||||
}
|
# }
|
||||||
self.checksample(**err44) # stb join
|
# self.checksample(**err44) # stb join
|
||||||
err45 = {
|
tdSql.query("select sample( stb1.c1 , 1 ) from stb1, stb2 where stb1.ts=stb2.ts and stb1.st1=stb2.st2 order by stb1.ts")
|
||||||
"condition": "where ts>0 and ts < now interval(1h) fill(next)"
|
# err45 = {
|
||||||
}
|
# "condition": "where ts>0 and ts < now interval(1h) fill(next)"
|
||||||
self.checksample(**err45) # interval
|
# }
|
||||||
|
# self.checksample(**err45) # interval
|
||||||
|
tdSql.query("select sample( c1 , 1 ) from t1 where ts>0 and ts < now interval(1h) fill(next)")
|
||||||
err46 = {
|
err46 = {
|
||||||
"table_expr": "t1",
|
"table_expr": "t1",
|
||||||
"condition": "group by c6"
|
"condition": "group by c6"
|
||||||
|
@ -728,8 +737,8 @@ class TDTestCase:
|
||||||
tdSql.query(" select sample(c10 , 20 ) from ct4 ")
|
tdSql.query(" select sample(c10 , 20 ) from ct4 ")
|
||||||
tdSql.checkRows(9)
|
tdSql.checkRows(9)
|
||||||
|
|
||||||
tdSql.query(" select sample(t1 , 20 ) from ct1 ")
|
# tdSql.query(" select sample(t1 , 20 ) from ct1 ")
|
||||||
tdSql.checkRows(13)
|
# tdSql.checkRows(13)
|
||||||
# filter data
|
# filter data
|
||||||
|
|
||||||
tdSql.query(" select sample(c1, 20 ) from t1 where c1 is null ")
|
tdSql.query(" select sample(c1, 20 ) from t1 where c1 is null ")
|
||||||
|
@ -775,15 +784,15 @@ class TDTestCase:
|
||||||
# not support mix with other function
|
# not support mix with other function
|
||||||
tdSql.error("select top(c1,2) , sample(c1,2) from ct1")
|
tdSql.error("select top(c1,2) , sample(c1,2) from ct1")
|
||||||
tdSql.error("select max(c1) , sample(c1,2) from ct1")
|
tdSql.error("select max(c1) , sample(c1,2) from ct1")
|
||||||
tdSql.error("select c1 , sample(c1,2) from ct1")
|
tdSql.query("select c1 , sample(c1,2) from ct1")
|
||||||
|
|
||||||
# bug for mix with scalar
|
# bug for mix with scalar
|
||||||
# tdSql.error("select 123 , sample(c1,100) from ct1")
|
tdSql.query("select 123 , sample(c1,100) from ct1")
|
||||||
# tdSql.error("select sample(c1,100)+2 from ct1")
|
tdSql.query("select sample(c1,100)+2 from ct1")
|
||||||
# tdSql.error("select abs(sample(c1,100)) from ct1")
|
tdSql.query("select abs(sample(c1,100)) from ct1")
|
||||||
|
|
||||||
def sample_test_run(self) :
|
def sample_test_run(self) :
|
||||||
tdLog.printNoPrefix("==========TD-10594==========")
|
tdLog.printNoPrefix("==========support sample function==========")
|
||||||
tbnum = 10
|
tbnum = 10
|
||||||
nowtime = int(round(time.time() * 1000))
|
nowtime = int(round(time.time() * 1000))
|
||||||
per_table_rows = 10
|
per_table_rows = 10
|
||||||
|
|
Loading…
Reference in New Issue