testing
This commit is contained in:
parent
c9be37bdc6
commit
38ed0317e7
|
@ -1041,6 +1041,7 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) {
|
||||||
if (code != TSDB_CODE_SUCCESS && NEED_CLIENT_HANDLE_ERROR(code) && pRequest->sqlstr != NULL) {
|
if (code != TSDB_CODE_SUCCESS && NEED_CLIENT_HANDLE_ERROR(code) && pRequest->sqlstr != NULL) {
|
||||||
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%s, tryCount:%d, reqId:0x%" PRIx64, pRequest->self,
|
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%s, tryCount:%d, reqId:0x%" PRIx64, pRequest->self,
|
||||||
tstrerror(code), pRequest->retry, pRequest->requestId);
|
tstrerror(code), pRequest->retry, pRequest->requestId);
|
||||||
|
removeMeta(pTscObj, pRequest->targetTableList, IS_VIEW_REQUEST(pRequest->type));
|
||||||
restartAsyncQuery(pRequest, code);
|
restartAsyncQuery(pRequest, code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -605,10 +605,12 @@ int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob* pJob, con
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < pJob->tbTsmaNum; ++i) {
|
for (int32_t i = 0; i < pJob->tbTsmaNum; ++i) {
|
||||||
// TODO test for it
|
STablesReq* pTbReq = taosArrayGet(pReq->pTableTSMAs, i);
|
||||||
SName* name = taosArrayGet(pReq->pTableTSMAs, i);
|
for (int32_t j = 0; j < pTbReq->pTables->size; ++j) {
|
||||||
|
SName* name = taosArrayGet(pTbReq->pTables, j);
|
||||||
ctgDropTSMAForTbEnqueue(pCtg, name, true);
|
ctgDropTSMAForTbEnqueue(pCtg, name, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// REFRESH VIEW META
|
// REFRESH VIEW META
|
||||||
return ctgHandleForceUpdateView(pCtg, pReq);
|
return ctgHandleForceUpdateView(pCtg, pReq);
|
||||||
|
|
|
@ -3676,6 +3676,7 @@ static int32_t setTableTsmas(STranslateContext* pCxt, SName* pName, SRealTableNo
|
||||||
int32_t len = snprintf(tsmaTargetTbName.tname, TSDB_TABLE_NAME_LEN, "%s.%s", pTsma->dbFName, pTsma->name);
|
int32_t len = snprintf(tsmaTargetTbName.tname, TSDB_TABLE_NAME_LEN, "%s.%s", pTsma->dbFName, pTsma->name);
|
||||||
len = taosCreateMD5Hash(tsmaTargetTbName.tname, len);
|
len = taosCreateMD5Hash(tsmaTargetTbName.tname, len);
|
||||||
sprintf(tsmaTargetTbName.tname + len, "_%s", pRealTable->table.tableName);
|
sprintf(tsmaTargetTbName.tname + len, "_%s", pRealTable->table.tableName);
|
||||||
|
collectUseTable(&tsmaTargetTbName, pCxt->pTargetTables);
|
||||||
SVgroupInfo vgInfo = {0};
|
SVgroupInfo vgInfo = {0};
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
code = catalogGetCachedTableHashVgroup(pCxt->pParseCxt->pCatalog, &tsmaTargetTbName, &vgInfo, &exists);
|
code = catalogGetCachedTableHashVgroup(pCxt->pParseCxt->pCatalog, &tsmaTargetTbName, &vgInfo, &exists);
|
||||||
|
|
|
@ -19,13 +19,14 @@ class TSMA:
|
||||||
self.cols = []
|
self.cols = []
|
||||||
self.interval: str = ''
|
self.interval: str = ''
|
||||||
|
|
||||||
|
|
||||||
class UsedTsma:
|
class UsedTsma:
|
||||||
TS_MIN = '-9223372036854775808'
|
TS_MIN = '-9223372036854775808'
|
||||||
TS_MAX = '9223372036854775806'
|
TS_MAX = '9223372036854775806'
|
||||||
TSMA_RES_STB_POSTFIX = '_tsma_res_stb_'
|
TSMA_RES_STB_POSTFIX = '_tsma_res_stb_'
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.name = '' ## tsma name or table name
|
self.name = '' # tsma name or table name
|
||||||
self.time_range_start: float = float(UsedTsma.TS_MIN)
|
self.time_range_start: float = float(UsedTsma.TS_MIN)
|
||||||
self.time_range_end: float = float(UsedTsma.TS_MAX)
|
self.time_range_end: float = float(UsedTsma.TS_MAX)
|
||||||
self.is_tsma_ = False
|
self.is_tsma_ = False
|
||||||
|
@ -51,10 +52,11 @@ class UsedTsma:
|
||||||
def setIsTsma(self):
|
def setIsTsma(self):
|
||||||
self.is_tsma_ = self.name.endswith(self.TSMA_RES_STB_POSTFIX)
|
self.is_tsma_ = self.name.endswith(self.TSMA_RES_STB_POSTFIX)
|
||||||
if not self.is_tsma_:
|
if not self.is_tsma_:
|
||||||
pos = self.name.find('_') ## for tsma output child table
|
pos = self.name.find('_') # for tsma output child table
|
||||||
if pos == 32:
|
if pos == 32:
|
||||||
self.is_tsma_ = True
|
self.is_tsma_ = True
|
||||||
|
|
||||||
|
|
||||||
class TSMAQueryContext:
|
class TSMAQueryContext:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.sql = ''
|
self.sql = ''
|
||||||
|
@ -87,6 +89,7 @@ class TSMAQueryContext:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class TSMAQCBuilder:
|
class TSMAQCBuilder:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.qc_: TSMAQueryContext = TSMAQueryContext()
|
self.qc_: TSMAQueryContext = TSMAQueryContext()
|
||||||
|
@ -101,7 +104,8 @@ class TSMAQCBuilder:
|
||||||
def to_timestamp(self, ts: str) -> float:
|
def to_timestamp(self, ts: str) -> float:
|
||||||
if ts == UsedTsma.TS_MAX or ts == UsedTsma.TS_MIN:
|
if ts == UsedTsma.TS_MAX or ts == UsedTsma.TS_MIN:
|
||||||
return float(ts)
|
return float(ts)
|
||||||
tdSql.query("select to_timestamp('%s', 'yyyy-mm-dd hh24-mi-ss.ms')" % (ts))
|
tdSql.query(
|
||||||
|
"select to_timestamp('%s', 'yyyy-mm-dd hh24-mi-ss.ms')" % (ts))
|
||||||
res = tdSql.queryResult[0][0]
|
res = tdSql.queryResult[0][0]
|
||||||
return res.timestamp() * 1000
|
return res.timestamp() * 1000
|
||||||
|
|
||||||
|
@ -134,6 +138,7 @@ class TSMAQCBuilder:
|
||||||
self.qc_.used_tsmas.append(used_tsma)
|
self.qc_.used_tsmas.append(used_tsma)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class TSMATester:
|
class TSMATester:
|
||||||
def __init__(self, tdSql: TDSql) -> None:
|
def __init__(self, tdSql: TDSql) -> None:
|
||||||
self.tsmas = []
|
self.tsmas = []
|
||||||
|
@ -188,14 +193,17 @@ class TSMATester:
|
||||||
def check_explain(self, sql: str, expect: TSMAQueryContext) -> TSMAQueryContext:
|
def check_explain(self, sql: str, expect: TSMAQueryContext) -> TSMAQueryContext:
|
||||||
query_ctx = self.get_tsma_query_ctx(sql)
|
query_ctx = self.get_tsma_query_ctx(sql)
|
||||||
if not query_ctx == expect:
|
if not query_ctx == expect:
|
||||||
tdLog.exit('check explain failed for sql: %s \nexpect: %s \nactual: %s' % (sql, str(expect), str(query_ctx)))
|
tdLog.exit('check explain failed for sql: %s \nexpect: %s \nactual: %s' % (
|
||||||
|
sql, str(expect), str(query_ctx)))
|
||||||
elif expect.has_tsma():
|
elif expect.has_tsma():
|
||||||
tdLog.debug('check explain succeed for sql: %s \ntsma: %s' % (sql, str(expect.used_tsmas)))
|
tdLog.debug('check explain succeed for sql: %s \ntsma: %s' %
|
||||||
|
(sql, str(expect.used_tsmas)))
|
||||||
has_tsma = False
|
has_tsma = False
|
||||||
for tsma in query_ctx.used_tsmas:
|
for tsma in query_ctx.used_tsmas:
|
||||||
has_tsma = has_tsma or tsma.is_tsma_
|
has_tsma = has_tsma or tsma.is_tsma_
|
||||||
if not has_tsma and len(query_ctx.used_tsmas) > 1:
|
if not has_tsma and len(query_ctx.used_tsmas) > 1:
|
||||||
tdLog.exit(f'explain err for sql: {sql}, has multi non tsmas, {query_ctx.used_tsmas}')
|
tdLog.exit(
|
||||||
|
f'explain err for sql: {sql}, has multi non tsmas, {query_ctx.used_tsmas}')
|
||||||
return query_ctx
|
return query_ctx
|
||||||
|
|
||||||
def check_result(self, sql: str, skip_order: bool = False):
|
def check_result(self, sql: str, skip_order: bool = False):
|
||||||
|
@ -207,20 +215,28 @@ class TSMATester:
|
||||||
|
|
||||||
if no_tsma_res is None or tsma_res is None:
|
if no_tsma_res is None or tsma_res is None:
|
||||||
if no_tsma_res != tsma_res:
|
if no_tsma_res != tsma_res:
|
||||||
tdLog.exit("comparing tsma res for: %s got different rows of result: without tsma: %s, with tsma: %s" % (sql, str(no_tsma_res), str(tsma_res)))
|
tdLog.exit("comparing tsma res for: %s got different rows of result: without tsma: %s, with tsma: %s" % (
|
||||||
|
sql, str(no_tsma_res), str(tsma_res)))
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(no_tsma_res) != len(tsma_res):
|
if len(no_tsma_res) != len(tsma_res):
|
||||||
tdLog.exit("comparing tsma res for: %s got different rows of result: \nwithout tsma: %s\nwith tsma: %s" % (sql, str(no_tsma_res), str(tsma_res)))
|
tdLog.exit("comparing tsma res for: %s got different rows of result: \nwithout tsma: %s\nwith tsma: %s" % (
|
||||||
|
sql, str(no_tsma_res), str(tsma_res)))
|
||||||
if skip_order:
|
if skip_order:
|
||||||
no_tsma_res.sort()
|
try:
|
||||||
tsma_res.sort()
|
no_tsma_res.sort(key=lambda x: [v is None for v in x] + list(x))
|
||||||
|
tsma_res.sort(key=lambda x: [v is None for v in x] + list(x))
|
||||||
|
except Exception as e:
|
||||||
|
tdLog.exit("comparing tsma res for: %s got different data: \nno tsma res: %s \n tsma res: %s err: %s" % (
|
||||||
|
sql, str(no_tsma_res), str(tsma_res), str(e)))
|
||||||
|
|
||||||
for row_no_tsma, row_tsma in zip(no_tsma_res, tsma_res):
|
for row_no_tsma, row_tsma in zip(no_tsma_res, tsma_res):
|
||||||
if row_no_tsma != row_tsma:
|
if row_no_tsma != row_tsma:
|
||||||
tdLog.exit("comparing tsma res for: %s got different row data: no tsma row: %s, tsma row: %s \nno tsma res: %s \n tsma res: %s" % (sql, str(row_no_tsma), str(row_tsma), str(no_tsma_res), str(tsma_res)))
|
tdLog.exit("comparing tsma res for: %s got different row data: no tsma row: %s, tsma row: %s \nno tsma res: %s \n tsma res: %s" % (
|
||||||
tdLog.info('result check succeed for sql: %s. \n tsma-res: %s. \nno_tsma-res: %s' % (sql, str(tsma_res), str(no_tsma_res)))
|
sql, str(row_no_tsma), str(row_tsma), str(no_tsma_res), str(tsma_res)))
|
||||||
|
tdLog.info('result check succeed for sql: %s. \n tsma-res: %s. \nno_tsma-res: %s' %
|
||||||
|
(sql, str(tsma_res), str(no_tsma_res)))
|
||||||
|
|
||||||
def check_sql(self, sql: str, expect: TSMAQueryContext):
|
def check_sql(self, sql: str, expect: TSMAQueryContext):
|
||||||
tdLog.debug(f"start to check sql: {sql}")
|
tdLog.debug(f"start to check sql: {sql}")
|
||||||
|
@ -233,6 +249,7 @@ class TSMATester:
|
||||||
for sql, query_ctx in zip(sqls, expects):
|
for sql, query_ctx in zip(sqls, expects):
|
||||||
self.check_sql(sql, query_ctx)
|
self.check_sql(sql, query_ctx)
|
||||||
|
|
||||||
|
|
||||||
class TSMATesterSQLGeneratorOptions:
|
class TSMATesterSQLGeneratorOptions:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.ts_min: int = 1537146000000 - 1000 * 60 * 60
|
self.ts_min: int = 1537146000000 - 1000 * 60 * 60
|
||||||
|
@ -240,21 +257,25 @@ class TSMATesterSQLGeneratorOptions:
|
||||||
self.times: int = 100
|
self.times: int = 100
|
||||||
self.pk_col: str = 'ts'
|
self.pk_col: str = 'ts'
|
||||||
self.column_prefix: str = 'c'
|
self.column_prefix: str = 'c'
|
||||||
self.column_num: int = 9 ### c1 - c10
|
self.column_num: int = 9 # c1 - c10
|
||||||
self.tags_prefix: str = 't'
|
self.tags_prefix: str = 't'
|
||||||
self.tag_num: int = 6 ### t1 - t6
|
self.tag_num: int = 6 # t1 - t6
|
||||||
self.char_tag_idx: List = [2,3]
|
self.str_tag_idx: List = [2, 3]
|
||||||
self.child_table_name_prefix: str = 't'
|
self.child_table_name_prefix: str = 't'
|
||||||
self.child_table_num: int = 10 #### t0 - t9
|
self.child_table_num: int = 10 # t0 - t9
|
||||||
self.interval: bool = False
|
self.interval: bool = False
|
||||||
self.partition_by: bool = False ## 70% generating a partition by, 30% no partition by, same as group by
|
# 70% generating a partition by, 30% no partition by, same as group by
|
||||||
|
self.partition_by: bool = False
|
||||||
self.group_by: bool = False
|
self.group_by: bool = False
|
||||||
self.where_ts_range: bool = False ## generating no ts range condition is also possible
|
# generating no ts range condition is also possible
|
||||||
|
self.where_ts_range: bool = False
|
||||||
self.where_tbname_func: bool = False
|
self.where_tbname_func: bool = False
|
||||||
self.where_tag_func: bool = False
|
self.where_tag_func: bool = False
|
||||||
self.where_col_func: bool = False
|
self.where_col_func: bool = False
|
||||||
self.slimit_max = 10
|
self.slimit_max = 10
|
||||||
self.limit_max = 10
|
self.limit_max = 10
|
||||||
|
self.norm_tb = False
|
||||||
|
|
||||||
|
|
||||||
class TSMATesterSQLGeneratorRes:
|
class TSMATesterSQLGeneratorRes:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -269,13 +290,15 @@ class TSMATesterSQLGeneratorRes:
|
||||||
def can_ignore_res_order(self):
|
def can_ignore_res_order(self):
|
||||||
return not (self.has_limit and self.has_slimit)
|
return not (self.has_limit and self.has_slimit)
|
||||||
|
|
||||||
|
|
||||||
class TSMATestSQLGenerator:
|
class TSMATestSQLGenerator:
|
||||||
def __init__(self, opts: TSMATesterSQLGeneratorOptions = TSMATesterSQLGeneratorOptions()):
|
def __init__(self, opts: TSMATesterSQLGeneratorOptions = TSMATesterSQLGeneratorOptions()):
|
||||||
self.db_name_: str = ''
|
self.db_name_: str = ''
|
||||||
self.tb_name_: str = ''
|
self.tb_name_: str = ''
|
||||||
self.ts_scan_range_: List[float] = [float(UsedTsma.TS_MIN), float(UsedTsma.TS_MAX)]
|
self.ts_scan_range_: List[float] = [
|
||||||
|
float(UsedTsma.TS_MIN), float(UsedTsma.TS_MAX)]
|
||||||
self.agg_funcs_: List[str] = []
|
self.agg_funcs_: List[str] = []
|
||||||
self.tsmas_: List[TSMA] = [] ## currently created tsmas
|
self.tsmas_: List[TSMA] = [] # currently created tsmas
|
||||||
self.opts_: TSMATesterSQLGeneratorOptions = opts
|
self.opts_: TSMATesterSQLGeneratorOptions = opts
|
||||||
self.res_: TSMATesterSQLGeneratorRes = TSMATesterSQLGeneratorRes()
|
self.res_: TSMATesterSQLGeneratorRes = TSMATesterSQLGeneratorRes()
|
||||||
|
|
||||||
|
@ -309,9 +332,6 @@ class TSMATestSQLGenerator:
|
||||||
tdLog.debug(f'generating str func: {ret}')
|
tdLog.debug(f'generating str func: {ret}')
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_integer_func(self, column_name: str, depth: int = 0) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_random_type(self, funcs):
|
def get_random_type(self, funcs):
|
||||||
rand: int = randrange(1, len(funcs))
|
rand: int = randrange(1, len(funcs))
|
||||||
return funcs[rand-1]()
|
return funcs[rand-1]()
|
||||||
|
@ -345,16 +365,70 @@ class TSMATestSQLGenerator:
|
||||||
interval = self.generate_interval(interval_list)
|
interval = self.generate_interval(interval_list)
|
||||||
(partition_by, partition_by_list) = self.generate_partition_by()
|
(partition_by, partition_by_list) = self.generate_partition_by()
|
||||||
limit = self.generate_limit()
|
limit = self.generate_limit()
|
||||||
auto_select_list = self.generate_select_list(select_list, partition_by_list)
|
auto_select_list = self.generate_select_list(
|
||||||
|
select_list, partition_by_list)
|
||||||
order_by = self.generate_order_by(order_by_list, partition_by_list)
|
order_by = self.generate_order_by(order_by_list, partition_by_list)
|
||||||
sql = f"SELECT {auto_select_list} FROM {tb} {where} {partition_by} {partition_by_list} {interval} {order_by} {limit}"
|
sql = f"SELECT {auto_select_list} FROM {tb} {where} {partition_by} {partition_by_list} {interval} {order_by} {limit}"
|
||||||
|
tdLog.debug(sql)
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
def can_ignore_res_order(self):
|
def can_ignore_res_order(self):
|
||||||
return self.res_.can_ignore_res_order()
|
return self.res_.can_ignore_res_order()
|
||||||
|
|
||||||
def generate_where(self) -> str:
|
def generate_where(self) -> str:
|
||||||
return self.generate_ts_where_range()
|
v = random.random()
|
||||||
|
where = ''
|
||||||
|
if not self.opts_.norm_tb:
|
||||||
|
if v < 0.2:
|
||||||
|
where = f'{self.generate_tbname_where()}'
|
||||||
|
elif v < 0.5:
|
||||||
|
where = f'{self.generate_tag_where()}'
|
||||||
|
elif v < 0.7:
|
||||||
|
op = random.choice(['AND', 'OR'])
|
||||||
|
where = f'{self.generate_tbname_where()} {op} {self.generate_tag_where()}'
|
||||||
|
ts_where = self.generate_ts_where_range()
|
||||||
|
if len(ts_where) > 0 or len(where) > 0:
|
||||||
|
op = ''
|
||||||
|
if len(where) > 0 and len(ts_where) > 0:
|
||||||
|
op = random.choice(['AND', 'AND', 'AND', 'AND', 'OR'])
|
||||||
|
return f'WHERE {ts_where} {op} {where}'
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def generate_str_equal_operator(self, column_name: str, opts: List) -> str:
|
||||||
|
opt = random.choice(opts)
|
||||||
|
return f'{column_name} = "{opt}"'
|
||||||
|
|
||||||
|
## TODO support it
|
||||||
|
def generate_str_in_operator(self, column_name: str, opts: List) -> str:
|
||||||
|
opt = random.choice(opts)
|
||||||
|
IN = f'"{",".join(opts)}"'
|
||||||
|
return f'{column_name} in ({IN})'
|
||||||
|
|
||||||
|
def generate_str_like_operator(self, column_name: str, opts: List) -> str:
|
||||||
|
opt = random.choice(opts)
|
||||||
|
return f'{column_name} like "{opt}"'
|
||||||
|
|
||||||
|
def generate_tbname_where(self) -> str:
|
||||||
|
tbs = []
|
||||||
|
for idx in range(1, self.opts_.tag_num + 1):
|
||||||
|
tbs.append(f'{self.opts_.child_table_name_prefix}{idx}')
|
||||||
|
|
||||||
|
if random.random() < 0.5:
|
||||||
|
return self.generate_str_equal_operator('tbname', tbs)
|
||||||
|
else:
|
||||||
|
return self.generate_str_like_operator('tbname', ['t%', '%2'])
|
||||||
|
|
||||||
|
def generate_tag_where(self) -> str:
|
||||||
|
idx = random.randrange(1, self.opts_.tag_num + 1)
|
||||||
|
if random.random() < 0.5 and idx in self.opts_.str_tag_idx:
|
||||||
|
if random.random() < 0.5:
|
||||||
|
return self.generate_str_equal_operator(f'{self.opts_.tags_prefix}{idx}', [f'tb{random.randint(1,100)}'])
|
||||||
|
else:
|
||||||
|
return self.generate_str_like_operator(f'{self.opts_.tags_prefix}{idx}', ['%1', 'tb%', 'tb1%', '%1%'])
|
||||||
|
else:
|
||||||
|
operator = random.choice(['>', '>=', '<', '<=', '=', '!='])
|
||||||
|
val = random.randint(1, 100)
|
||||||
|
return f'{self.opts_.tags_prefix}{idx} {operator} {val}'
|
||||||
|
|
||||||
def generate_timestamp(self, min: float = -1, max: float = 0) -> int:
|
def generate_timestamp(self, min: float = -1, max: float = 0) -> int:
|
||||||
milliseconds_aligned: float = random.randint(int(min), int(max))
|
milliseconds_aligned: float = random.randint(int(min), int(max))
|
||||||
|
@ -364,7 +438,8 @@ class TSMATestSQLGenerator:
|
||||||
minutes_aligned = int(milliseconds_aligned / 1000 / 60) * 1000 * 60
|
minutes_aligned = int(milliseconds_aligned / 1000 / 60) * 1000 * 60
|
||||||
if minutes_aligned < min:
|
if minutes_aligned < min:
|
||||||
minutes_aligned = int(min)
|
minutes_aligned = int(min)
|
||||||
hour_aligned = int(milliseconds_aligned / 1000 / 60 / 60) * 1000 * 60 * 60
|
hour_aligned = int(milliseconds_aligned / 1000 /
|
||||||
|
60 / 60) * 1000 * 60 * 60
|
||||||
if hour_aligned < min:
|
if hour_aligned < min:
|
||||||
hour_aligned = int(min)
|
hour_aligned = int(min)
|
||||||
|
|
||||||
|
@ -380,7 +455,8 @@ class TSMATestSQLGenerator:
|
||||||
a = ''
|
a = ''
|
||||||
left_value = None
|
left_value = None
|
||||||
if left_operator:
|
if left_operator:
|
||||||
left_value = self.generate_timestamp(self.opts_.ts_min, self.opts_.ts_max)
|
left_value = self.generate_timestamp(
|
||||||
|
self.opts_.ts_min, self.opts_.ts_max)
|
||||||
a += f'{self.opts_.pk_col} {left_operator} {left_value}'
|
a += f'{self.opts_.pk_col} {left_operator} {left_value}'
|
||||||
if right_operator:
|
if right_operator:
|
||||||
if left_value:
|
if left_value:
|
||||||
|
@ -394,7 +470,6 @@ class TSMATestSQLGenerator:
|
||||||
# tdLog.debug(f'{self.opts_.pk_col} range with: {a}')
|
# tdLog.debug(f'{self.opts_.pk_col} range with: {a}')
|
||||||
if len(a) > 0:
|
if len(a) > 0:
|
||||||
self.res_.has_where_ts_range = True
|
self.res_.has_where_ts_range = True
|
||||||
return f'WHERE {a}'
|
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def generate_limit(self) -> str:
|
def generate_limit(self) -> str:
|
||||||
|
@ -409,23 +484,23 @@ class TSMATestSQLGenerator:
|
||||||
ret = ret + f' LIMIT {random.randint(0, self.opts_.limit_max)}'
|
ret = ret + f' LIMIT {random.randint(0, self.opts_.limit_max)}'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
## add sliding offset
|
# add sliding offset
|
||||||
def generate_interval(self, intervals: List[str]) -> str:
|
def generate_interval(self, intervals: List[str]) -> str:
|
||||||
if not self.opts_.interval:
|
if not self.opts_.interval:
|
||||||
return ''
|
return ''
|
||||||
if random.random() < 0.4: ## no interval
|
if random.random() < 0.4: # no interval
|
||||||
return ''
|
return ''
|
||||||
value = random.choice(intervals)
|
value = random.choice(intervals)
|
||||||
self.res_.has_interval = True
|
self.res_.has_interval = True
|
||||||
return f'INTERVAL({value})'
|
return f'INTERVAL({value})'
|
||||||
|
|
||||||
def generate_tag_list(self):
|
def generate_tag_list(self):
|
||||||
used_tag_num = random.randrange(1, self.opts_.tag_num)
|
used_tag_num = random.randrange(1, self.opts_.tag_num + 1)
|
||||||
ret = ''
|
ret = ''
|
||||||
for _ in range(used_tag_num):
|
for _ in range(used_tag_num):
|
||||||
tag_idx = random.randint(1, self.opts_.tag_num)
|
tag_idx = random.randint(1, self.opts_.tag_num)
|
||||||
tag_name = self.opts_.tags_prefix + f'{tag_idx}'
|
tag_name = self.opts_.tags_prefix + f'{tag_idx}'
|
||||||
if random.random() < 0.5 and tag_idx in self.opts_.char_tag_idx:
|
if random.random() < 0.5 and tag_idx in self.opts_.str_tag_idx:
|
||||||
tag_func = self.generate_str_func(tag_name, 2)
|
tag_func = self.generate_str_func(tag_name, 2)
|
||||||
else:
|
else:
|
||||||
tag_func = tag_name
|
tag_func = tag_name
|
||||||
|
@ -444,12 +519,10 @@ class TSMATestSQLGenerator:
|
||||||
ret = ret + self.opts_.tags_prefix + f'{tag_idx},'
|
ret = ret + self.opts_.tags_prefix + f'{tag_idx},'
|
||||||
return ret[:-1]
|
return ret[:-1]
|
||||||
|
|
||||||
|
|
||||||
## TODO add tbname, tag functions
|
|
||||||
def generate_partition_by(self):
|
def generate_partition_by(self):
|
||||||
if not self.opts_.partition_by and not self.opts_.group_by:
|
if not self.opts_.partition_by and not self.opts_.group_by:
|
||||||
return ('', '')
|
return ('', '')
|
||||||
## no partition or group
|
# no partition or group
|
||||||
if random.random() < 0.3:
|
if random.random() < 0.3:
|
||||||
return ('', '')
|
return ('', '')
|
||||||
ret = ''
|
ret = ''
|
||||||
|
@ -462,9 +535,9 @@ class TSMATestSQLGenerator:
|
||||||
elif rand < 0.8:
|
elif rand < 0.8:
|
||||||
ret = self.generate_tag_list()
|
ret = self.generate_tag_list()
|
||||||
else:
|
else:
|
||||||
## tbname and tag
|
# tbname and tag
|
||||||
ret = self.generate_tbname_tag_list()
|
ret = self.generate_tbname_tag_list()
|
||||||
tdLog.debug(f'partition by: {ret}')
|
# tdLog.debug(f'partition by: {ret}')
|
||||||
if self.res_.has_interval or random.random() < 0.5:
|
if self.res_.has_interval or random.random() < 0.5:
|
||||||
self.res_.partition_by = True
|
self.res_.partition_by = True
|
||||||
return (str('PARTITION BY'), f'{ret}')
|
return (str('PARTITION BY'), f'{ret}')
|
||||||
|
@ -484,14 +557,16 @@ class TSMATestSQLGenerator:
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
## generate func in tsmas(select list)
|
# generate func in tsmas(select list)
|
||||||
def _generate_agg_func_for_select(self) -> str:
|
def _generate_agg_func_for_select(self) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
## order by, limit, having, subquery...
|
# order by, limit, having, subquery...
|
||||||
|
|
||||||
|
|
||||||
class TDTestCase:
|
class TDTestCase:
|
||||||
updatecfgDict = {'debugFlag': 143, 'asynclog': 0}
|
updatecfgDict = {'debugFlag': 143, 'asynclog': 0}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.vgroups = 4
|
self.vgroups = 4
|
||||||
self.ctbNum = 10
|
self.ctbNum = 10
|
||||||
|
@ -509,14 +584,18 @@ class TDTestCase:
|
||||||
if dropFlag == 1:
|
if dropFlag == 1:
|
||||||
tsql.execute("drop database if exists %s" % (dbName))
|
tsql.execute("drop database if exists %s" % (dbName))
|
||||||
|
|
||||||
tsql.execute("create database if not exists %s vgroups %d replica %d duration %s"%(dbName, vgroups, replica, duration))
|
tsql.execute("create database if not exists %s vgroups %d replica %d duration %s" % (
|
||||||
|
dbName, vgroups, replica, duration))
|
||||||
tdLog.debug("complete to create database %s" % (dbName))
|
tdLog.debug("complete to create database %s" % (dbName))
|
||||||
return
|
return
|
||||||
|
|
||||||
def create_stable(self, tsql, paraDict):
|
def create_stable(self, tsql, paraDict):
|
||||||
colString = tdCom.gen_column_type_str(colname_prefix=paraDict["colPrefix"], column_elm_list=paraDict["colSchema"])
|
colString = tdCom.gen_column_type_str(
|
||||||
tagString = tdCom.gen_tag_type_str(tagname_prefix=paraDict["tagPrefix"], tag_elm_list=paraDict["tagSchema"])
|
colname_prefix=paraDict["colPrefix"], column_elm_list=paraDict["colSchema"])
|
||||||
sqlString = f"create table if not exists %s.%s (%s) tags (%s)"%(paraDict["dbName"], paraDict["stbName"], colString, tagString)
|
tagString = tdCom.gen_tag_type_str(
|
||||||
|
tagname_prefix=paraDict["tagPrefix"], tag_elm_list=paraDict["tagSchema"])
|
||||||
|
sqlString = f"create table if not exists %s.%s (%s) tags (%s)" % (
|
||||||
|
paraDict["dbName"], paraDict["stbName"], colString, tagString)
|
||||||
tdLog.debug("%s" % (sqlString))
|
tdLog.debug("%s" % (sqlString))
|
||||||
tsql.execute(sqlString)
|
tsql.execute(sqlString)
|
||||||
return
|
return
|
||||||
|
@ -524,18 +603,22 @@ class TDTestCase:
|
||||||
def create_ctable(self, tsql=None, dbName='dbx', stbName='stb', ctbPrefix='ctb', ctbNum=1, ctbStartIdx=0):
|
def create_ctable(self, tsql=None, dbName='dbx', stbName='stb', ctbPrefix='ctb', ctbNum=1, ctbStartIdx=0):
|
||||||
for i in range(ctbNum):
|
for i in range(ctbNum):
|
||||||
sqlString = "create table %s.%s%d using %s.%s tags(%d, 'tb%d', 'tb%d', %d, %d, %d)" % \
|
sqlString = "create table %s.%s%d using %s.%s tags(%d, 'tb%d', 'tb%d', %d, %d, %d)" % \
|
||||||
(dbName,ctbPrefix,i+ctbStartIdx,dbName,stbName,(i+ctbStartIdx) % 5,i+ctbStartIdx,i+ctbStartIdx,i+ctbStartIdx,i+ctbStartIdx,i+ctbStartIdx)
|
(dbName, ctbPrefix, i+ctbStartIdx, dbName, stbName, (i+ctbStartIdx) % 5, i+ctbStartIdx +
|
||||||
|
random.randint(1, 100), i+ctbStartIdx + random.randint(1, 100), i+ctbStartIdx + random.randint(1, 100), i+ctbStartIdx + random.randint(1, 100), i+ctbStartIdx + random.randint(1, 100))
|
||||||
tsql.execute(sqlString)
|
tsql.execute(sqlString)
|
||||||
|
|
||||||
tdLog.debug("complete to create %d child tables by %s.%s" %(ctbNum, dbName, stbName))
|
tdLog.debug("complete to create %d child tables by %s.%s" %
|
||||||
|
(ctbNum, dbName, stbName))
|
||||||
return
|
return
|
||||||
|
|
||||||
def init_normal_tb(self, tsql, db_name: str, tb_name: str, rows: int, start_ts: int, ts_step: int):
|
def init_normal_tb(self, tsql, db_name: str, tb_name: str, rows: int, start_ts: int, ts_step: int):
|
||||||
sql = 'CREATE TABLE %s.%s (ts timestamp, c1 INT, c2 INT, c3 VARCHAR(255), c4 INT)' % (db_name, tb_name)
|
sql = 'CREATE TABLE %s.%s (ts timestamp, c1 INT, c2 INT, c3 INT, c4 VARCHAR(255))' % (
|
||||||
|
db_name, tb_name)
|
||||||
tsql.execute(sql)
|
tsql.execute(sql)
|
||||||
sql = 'INSERT INTO %s.%s values' % (db_name, tb_name)
|
sql = 'INSERT INTO %s.%s values' % (db_name, tb_name)
|
||||||
for j in range(rows):
|
for j in range(rows):
|
||||||
sql += '(%d, %d,%d,"varchar_%d",%d),' % (start_ts + j * ts_step + randrange(500), j % 10 + randrange(100), j % 10 + randrange(200), j % 10, j % 10)
|
sql += '(%d, %d,%d,%d,"varchar_%d"),' % (start_ts + j * ts_step + randrange(500), j % 10 + randrange(200), j % 10, j % 10,
|
||||||
|
j % 10 + randrange(100))
|
||||||
tsql.execute(sql)
|
tsql.execute(sql)
|
||||||
|
|
||||||
def insert_data(self, tsql, dbName, ctbPrefix, ctbNum, rowsPerTbl, batchNum, startTs, tsStep):
|
def insert_data(self, tsql, dbName, ctbPrefix, ctbNum, rowsPerTbl, batchNum, startTs, tsStep):
|
||||||
|
@ -549,9 +632,11 @@ class TDTestCase:
|
||||||
sql += " %s%d values " % (ctbPrefix, i)
|
sql += " %s%d values " % (ctbPrefix, i)
|
||||||
for j in range(rowsPerTbl):
|
for j in range(rowsPerTbl):
|
||||||
if (i < ctbNum/2):
|
if (i < ctbNum/2):
|
||||||
sql += "(%d, %d, %d, %d,%d,%d,%d,true,'binary%d', 'nchar%d') "%(startTs + j*tsStep + randrange(500), j%10 + randrange(100), j%10 + randrange(200), j%10, j%10, j%10, j%10, j%10, j%10)
|
sql += "(%d, %d, %d, %d,%d,%d,%d,true,'binary%d', 'nchar%d') " % (startTs + j*tsStep + randrange(
|
||||||
|
500), j % 10 + randrange(100), j % 10 + randrange(200), j % 10, j % 10, j % 10, j % 10, j % 10, j % 10)
|
||||||
else:
|
else:
|
||||||
sql += "(%d, %d, NULL, %d,NULL,%d,%d,true,'binary%d', 'nchar%d') "%(startTs + j*tsStep + randrange(500), j%10, j%10, j%10, j%10, j%10, j%10)
|
sql += "(%d, %d, NULL, %d,NULL,%d,%d,true,'binary%d', 'nchar%d') " % (
|
||||||
|
startTs + j*tsStep + randrange(500), j % 10, j % 10, j % 10, j % 10, j % 10, j % 10)
|
||||||
rowsBatched += 1
|
rowsBatched += 1
|
||||||
if ((rowsBatched == batchNum) or (j == rowsPerTbl - 1)):
|
if ((rowsBatched == batchNum) or (j == rowsPerTbl - 1)):
|
||||||
tsql.execute(sql)
|
tsql.execute(sql)
|
||||||
|
@ -566,7 +651,8 @@ class TDTestCase:
|
||||||
return
|
return
|
||||||
|
|
||||||
def init_data(self, ctb_num: int = 10, rows_per_ctb: int = 10000, start_ts: int = 1537146000000, ts_step: int = 500):
|
def init_data(self, ctb_num: int = 10, rows_per_ctb: int = 10000, start_ts: int = 1537146000000, ts_step: int = 500):
|
||||||
tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ")
|
tdLog.printNoPrefix(
|
||||||
|
"======== prepare test env include database, stable, ctables, and insert data: ")
|
||||||
paraDict = {'dbName': 'test',
|
paraDict = {'dbName': 'test',
|
||||||
'dropFlag': 1,
|
'dropFlag': 1,
|
||||||
'vgroups': 2,
|
'vgroups': 2,
|
||||||
|
@ -588,25 +674,29 @@ class TDTestCase:
|
||||||
paraDict['rowsPerTbl'] = self.rowsPerTbl
|
paraDict['rowsPerTbl'] = self.rowsPerTbl
|
||||||
|
|
||||||
tdLog.info("create database")
|
tdLog.info("create database")
|
||||||
self.create_database(tsql=tdSql, dbName=paraDict["dbName"], dropFlag=paraDict["dropFlag"], vgroups=paraDict["vgroups"], replica=self.replicaVar, duration=self.duraion)
|
self.create_database(tsql=tdSql, dbName=paraDict["dbName"], dropFlag=paraDict["dropFlag"],
|
||||||
|
vgroups=paraDict["vgroups"], replica=self.replicaVar, duration=self.duraion)
|
||||||
|
|
||||||
tdLog.info("create stb")
|
tdLog.info("create stb")
|
||||||
self.create_stable(tsql=tdSql, paraDict=paraDict)
|
self.create_stable(tsql=tdSql, paraDict=paraDict)
|
||||||
|
|
||||||
tdLog.info("create child tables")
|
tdLog.info("create child tables")
|
||||||
self.create_ctable(tsql=tdSql, dbName=paraDict["dbName"], \
|
self.create_ctable(tsql=tdSql, dbName=paraDict["dbName"],
|
||||||
stbName=paraDict["stbName"],ctbPrefix=paraDict["ctbPrefix"],\
|
stbName=paraDict["stbName"], ctbPrefix=paraDict["ctbPrefix"],
|
||||||
ctbNum=paraDict["ctbNum"], ctbStartIdx=paraDict["ctbStartIdx"])
|
ctbNum=paraDict["ctbNum"], ctbStartIdx=paraDict["ctbStartIdx"])
|
||||||
self.insert_data(tsql=tdSql, dbName=paraDict["dbName"],\
|
self.insert_data(tsql=tdSql, dbName=paraDict["dbName"],
|
||||||
ctbPrefix=paraDict["ctbPrefix"],ctbNum=paraDict["ctbNum"],\
|
ctbPrefix=paraDict["ctbPrefix"], ctbNum=paraDict["ctbNum"],
|
||||||
rowsPerTbl=paraDict["rowsPerTbl"],batchNum=paraDict["batchNum"],\
|
rowsPerTbl=paraDict["rowsPerTbl"], batchNum=paraDict["batchNum"],
|
||||||
startTs=paraDict["startTs"], tsStep=paraDict["tsStep"])
|
startTs=paraDict["startTs"], tsStep=paraDict["tsStep"])
|
||||||
self.init_normal_tb(tdSql, paraDict['dbName'], 'norm_tb', paraDict['rowsPerTbl'], paraDict['startTs'], paraDict['tsStep'])
|
self.init_normal_tb(tdSql, paraDict['dbName'], 'norm_tb',
|
||||||
|
paraDict['rowsPerTbl'], paraDict['startTs'], paraDict['tsStep'])
|
||||||
|
|
||||||
def wait_for_tsma_calculation(self, func_list: list, db: str, tb: str, interval: str, tsma_name: str):
|
def wait_for_tsma_calculation(self, func_list: list, db: str, tb: str, interval: str, tsma_name: str):
|
||||||
while True:
|
while True:
|
||||||
sql = 'select %s from %s.%s interval(%s)' % (', '.join(func_list), db, tb, interval)
|
sql = 'select %s from %s.%s interval(%s)' % (
|
||||||
tdLog.debug(f'waiting for tsma {db}.{tsma_name} to be useful with sql {sql}')
|
', '.join(func_list), db, tb, interval)
|
||||||
|
tdLog.debug(
|
||||||
|
f'waiting for tsma {db}.{tsma_name} to be useful with sql {sql}')
|
||||||
ctx: TSMAQueryContext = self.tsma_tester.get_tsma_query_ctx(sql)
|
ctx: TSMAQueryContext = self.tsma_tester.get_tsma_query_ctx(sql)
|
||||||
if ctx.has_tsma():
|
if ctx.has_tsma():
|
||||||
if ctx.used_tsmas[0].name == tsma_name + UsedTsma.TSMA_RES_STB_POSTFIX:
|
if ctx.used_tsmas[0].name == tsma_name + UsedTsma.TSMA_RES_STB_POSTFIX:
|
||||||
|
@ -618,18 +708,20 @@ class TDTestCase:
|
||||||
else:
|
else:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
def create_tsma(self, tsma_name: str, db: str, tb: str, func_list: list, interval: str):
|
def create_tsma(self, tsma_name: str, db: str, tb: str, func_list: list, interval: str):
|
||||||
tdSql.execute('use %s' % db)
|
tdSql.execute('use %s' % db)
|
||||||
sql = "CREATE TSMA %s ON %s.%s FUNCTION(%s) INTERVAL(%s)" % (tsma_name, db, tb, ','.join(func_list), interval)
|
sql = "CREATE TSMA %s ON %s.%s FUNCTION(%s) INTERVAL(%s)" % (
|
||||||
|
tsma_name, db, tb, ','.join(func_list), interval)
|
||||||
tdSql.execute(sql, queryTimes=1)
|
tdSql.execute(sql, queryTimes=1)
|
||||||
self.wait_for_tsma_calculation(func_list, db, tb, interval, tsma_name)
|
self.wait_for_tsma_calculation(func_list, db, tb, interval, tsma_name)
|
||||||
|
|
||||||
def create_recursive_tsma(self, base_tsma_name: str, new_tsma_name: str, db: str, interval: str, tb_name: str, func_list: List[str] = ['avg(c1)']):
|
def create_recursive_tsma(self, base_tsma_name: str, new_tsma_name: str, db: str, interval: str, tb_name: str, func_list: List[str] = ['avg(c1)']):
|
||||||
tdSql.execute('use %s' % db, queryTimes=1)
|
tdSql.execute('use %s' % db, queryTimes=1)
|
||||||
sql = 'CREATE RECURSIVE TSMA %s ON %s.%s INTERVAL(%s)' % (new_tsma_name, db, base_tsma_name, interval)
|
sql = 'CREATE RECURSIVE TSMA %s ON %s.%s INTERVAL(%s)' % (
|
||||||
|
new_tsma_name, db, base_tsma_name, interval)
|
||||||
tdSql.execute(sql, queryTimes=1)
|
tdSql.execute(sql, queryTimes=1)
|
||||||
self.wait_for_tsma_calculation(func_list, db, tb_name, interval, new_tsma_name)
|
self.wait_for_tsma_calculation(
|
||||||
|
func_list, db, tb_name, interval, new_tsma_name)
|
||||||
|
|
||||||
def drop_tsma(self, tsma_name: str, db: str):
|
def drop_tsma(self, tsma_name: str, db: str):
|
||||||
sql = 'DROP TSMA %s.%s' % (db, tsma_name)
|
sql = 'DROP TSMA %s.%s' % (db, tsma_name)
|
||||||
|
@ -639,174 +731,212 @@ class TDTestCase:
|
||||||
plan_found = False
|
plan_found = False
|
||||||
for row in explain_output:
|
for row in explain_output:
|
||||||
if str(row).find(plan_str_expect) >= 0:
|
if str(row).find(plan_str_expect) >= 0:
|
||||||
tdLog.debug("plan: [%s] found in: [%s]" % (plan_str_expect, str(row)))
|
tdLog.debug("plan: [%s] found in: [%s]" %
|
||||||
|
(plan_str_expect, str(row)))
|
||||||
plan_found = True
|
plan_found = True
|
||||||
break
|
break
|
||||||
if not plan_found:
|
if not plan_found:
|
||||||
tdLog.exit("plan: %s not found in res: [%s]" % (plan_str_expect, str(explain_output)))
|
tdLog.exit("plan: %s not found in res: [%s]" % (
|
||||||
|
plan_str_expect, str(explain_output)))
|
||||||
|
|
||||||
def check(self, func):
|
def check(self, ctxs: List):
|
||||||
for ctx in func():
|
for ctx in ctxs:
|
||||||
self.tsma_tester.check_sql(ctx.sql, ctx)
|
self.tsma_tester.check_sql(ctx.sql, ctx)
|
||||||
|
|
||||||
def test_query_with_tsma(self):
|
def test_query_with_tsma(self):
|
||||||
self.create_tsma('tsma1', 'test', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
self.create_tsma('tsma1', 'test', 'meters', [
|
||||||
self.create_tsma('tsma2', 'test', 'meters', ['avg(c1)', 'avg(c2)'], '30m')
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
self.create_tsma('tsma5', 'test', 'norm_tb', ['avg(c1)', 'avg(c2)'], '10m')
|
self.create_tsma('tsma2', 'test', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '30m')
|
||||||
|
self.create_tsma('tsma5', 'test', 'norm_tb', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '10m')
|
||||||
|
|
||||||
self.test_query_with_tsma_interval()
|
#self.test_query_with_tsma_interval()
|
||||||
self.test_query_with_tsma_agg()
|
#self.test_query_with_tsma_agg()
|
||||||
self.test_recursive_tsma()
|
self.test_recursive_tsma()
|
||||||
## self.test_query_with_drop_tsma()
|
# self.test_query_with_drop_tsma()
|
||||||
## self.test_query_with_add_tag()
|
# self.test_query_with_add_tag()
|
||||||
## self.test_union()
|
# self.test_union()
|
||||||
self.test_query_sub_table()
|
self.test_query_sub_table()
|
||||||
|
|
||||||
def test_query_sub_table(self):
|
def test_query_sub_table(self):
|
||||||
sql = 'select avg(c1) from t1'
|
sql = 'select avg(c1) from t1'
|
||||||
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma('e8945e7385834f8c22705546d4016539_t1', UsedTsma.TS_MIN, UsedTsma.TS_MAX, child_tb=True).get_qc()
|
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma(
|
||||||
|
'e8945e7385834f8c22705546d4016539_t1', UsedTsma.TS_MIN, UsedTsma.TS_MAX, child_tb=True).get_qc()
|
||||||
self.tsma_tester.check_sql(sql, ctx)
|
self.tsma_tester.check_sql(sql, ctx)
|
||||||
sql = 'select avg(c1) from t3'
|
sql = 'select avg(c1) from t3'
|
||||||
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma('e8945e7385834f8c22705546d4016539_t3', child_tb=True).get_qc()
|
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma(
|
||||||
|
'e8945e7385834f8c22705546d4016539_t3', child_tb=True).get_qc()
|
||||||
self.tsma_tester.check_sql(sql, ctx)
|
self.tsma_tester.check_sql(sql, ctx)
|
||||||
|
|
||||||
def test_recursive_tsma(self):
|
def test_recursive_tsma(self):
|
||||||
tdSql.execute('drop tsma tsma2')
|
tdSql.execute('drop tsma tsma2')
|
||||||
func_list: List[str] = ['avg(c2)', 'avg(c3)']
|
func_list: List[str] = ['avg(c2)', 'avg(c3)']
|
||||||
self.create_tsma('tsma3', 'test', 'meters', func_list, '5m')
|
self.create_tsma('tsma3', 'test', 'meters', func_list, '5m')
|
||||||
self.create_recursive_tsma('tsma3', 'tsma4', 'test', '20m', 'meters', func_list)
|
self.create_recursive_tsma(
|
||||||
## now we have 5m, 10m, 30m, 1h 4 tsmas
|
'tsma3', 'tsma4', 'test', '20m', 'meters', func_list)
|
||||||
|
# now we have 5m, 10m, 30m, 1h 4 tsmas
|
||||||
sql = 'select avg(c2), "recursive tsma4" from meters'
|
sql = 'select avg(c2), "recursive tsma4" from meters'
|
||||||
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma4', UsedTsma.TS_MIN,UsedTsma.TS_MAX).get_qc()
|
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma(
|
||||||
|
'tsma4', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc()
|
||||||
self.tsma_tester.check_sql(sql, ctx)
|
self.tsma_tester.check_sql(sql, ctx)
|
||||||
self.create_recursive_tsma('tsma4', 'tsma6', 'test', '1h', 'meters', func_list)
|
time.sleep(9999999)
|
||||||
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma6', UsedTsma.TS_MIN,UsedTsma.TS_MAX).get_qc()
|
self.check(self.test_query_tsma_all(['avg(c2)', 'avg(c3)']))
|
||||||
|
self.create_recursive_tsma(
|
||||||
|
'tsma4', 'tsma6', 'test', '1h', 'meters', func_list)
|
||||||
|
ctx = TSMAQCBuilder().with_sql(sql).should_query_with_tsma(
|
||||||
|
'tsma6', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc()
|
||||||
self.tsma_tester.check_sql(sql, ctx)
|
self.tsma_tester.check_sql(sql, ctx)
|
||||||
|
|
||||||
|
self.check(self.test_query_tsma_all(['avg(c2)', 'avg(c3)']))
|
||||||
|
|
||||||
tdSql.error('drop tsma tsma3', -2147482491)
|
tdSql.error('drop tsma tsma3', -2147482491)
|
||||||
tdSql.error('drop tsma tsma4', -2147482491)
|
tdSql.error('drop tsma tsma4', -2147482491)
|
||||||
tdSql.execute('drop tsma tsma6')
|
tdSql.execute('drop tsma tsma6')
|
||||||
tdSql.execute('drop tsma tsma4')
|
tdSql.execute('drop tsma tsma4')
|
||||||
tdSql.execute('drop tsma tsma3')
|
tdSql.execute('drop tsma tsma3')
|
||||||
self.create_tsma('tsma2', 'test', 'meters', ['avg(c1)', 'avg(c2)'], '30m')
|
self.create_tsma('tsma2', 'test', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '30m')
|
||||||
|
|
||||||
def test_query_with_tsma_interval(self):
|
def test_query_with_tsma_interval(self):
|
||||||
self.check(self.test_query_with_tsma_interval_possibly_partition)
|
self.check(self.test_query_with_tsma_interval_possibly_partition())
|
||||||
self.check(self.test_query_with_tsma_interval_partition_by_col)
|
self.check(self.test_query_with_tsma_interval_partition_by_col())
|
||||||
|
|
||||||
|
def test_query_tsma_all(self, func_list: List = ['avg(c1)', 'avg(c2)']) -> List:
|
||||||
|
ctxs = []
|
||||||
|
interval_list = ['1s', '5s', '60s', '1m', '10m', '20m',
|
||||||
|
'30m', '59s', '1h', '120s', '1200', '2h', '90m', '1d']
|
||||||
|
opts: TSMATesterSQLGeneratorOptions = TSMATesterSQLGeneratorOptions()
|
||||||
|
opts.interval = True
|
||||||
|
opts.where_ts_range = True
|
||||||
|
for _ in range(1, 1000):
|
||||||
|
opts.partition_by = True
|
||||||
|
opts.group_by = True
|
||||||
|
opts.norm_tb = False
|
||||||
|
sql_generator = TSMATestSQLGenerator(opts)
|
||||||
|
sql = sql_generator.generate_one(
|
||||||
|
','.join(func_list), ['meters', 'meters', 't1', 't9'], '', interval_list)
|
||||||
|
ctxs.append(TSMAQCBuilder().with_sql(sql).ignore_query_table(
|
||||||
|
).ignore_res_order(sql_generator.can_ignore_res_order()).get_qc())
|
||||||
|
|
||||||
|
if random.random() > 0.7:
|
||||||
|
continue
|
||||||
|
opts.partition_by = False
|
||||||
|
opts.group_by = False
|
||||||
|
opts.norm_tb = True
|
||||||
|
sql_generator = TSMATestSQLGenerator(opts)
|
||||||
|
sql = sql_generator.generate_one(
|
||||||
|
','.join(func_list), ['norm_tb', 't5'], '', interval_list)
|
||||||
|
ctxs.append(TSMAQCBuilder().with_sql(sql).ignore_query_table(
|
||||||
|
).ignore_res_order(sql_generator.can_ignore_res_order()).get_qc())
|
||||||
|
return ctxs
|
||||||
|
|
||||||
def test_query_with_tsma_interval_possibly_partition(self) -> List[TSMAQueryContext]:
|
def test_query_with_tsma_interval_possibly_partition(self) -> List[TSMAQueryContext]:
|
||||||
ctxs: List[TSMAQueryContext] = []
|
ctxs: List[TSMAQueryContext] = []
|
||||||
sql = 'select avg(c1), avg(c2) from meters interval(5m)'
|
sql = 'select avg(c1), avg(c2) from meters interval(5m)'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma1', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
.should_query_with_tsma('tsma1', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters interval(10m)'
|
sql = 'select avg(c1), avg(c2) from meters interval(10m)'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma1', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
.should_query_with_tsma('tsma1', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
||||||
sql = 'select avg(c1), avg(c2) from meters interval(30m)'
|
sql = 'select avg(c1), avg(c2) from meters interval(30m)'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma2', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
.should_query_with_tsma('tsma2', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
||||||
sql = 'select avg(c1), avg(c2) from meters interval(60m)'
|
sql = 'select avg(c1), avg(c2) from meters interval(60m)'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma2', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
.should_query_with_tsma('tsma2', UsedTsma.TS_MIN, UsedTsma.TS_MAX).get_qc())
|
||||||
|
|
||||||
sql = "select avg(c1), avg(c2) from meters where ts >= '2018-09-17 09:00:00.009' and ts < '2018-09-17 10:23:19.665' interval(30m)"
|
sql = "select avg(c1), avg(c2) from meters where ts >= '2018-09-17 09:00:00.009' and ts < '2018-09-17 10:23:19.665' interval(30m)"
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.009','2018-09-17 09:29:59.999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.009', '2018-09-17 09:29:59.999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.664').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.664').get_qc())
|
||||||
|
|
||||||
sql = "SELECT avg(c1), avg(c2),_wstart, _wend,t3,t4,t5,t2 FROM meters WHERE ts >= '2018-09-17 8:00:00' AND ts < '2018-09-17 09:03:18.334' PARTITION BY t3,t4,t5,t2 INTERVAL(1d);"
|
sql = "SELECT avg(c1), avg(c2),_wstart, _wend,t3,t4,t5,t2 FROM meters WHERE ts >= '2018-09-17 8:00:00' AND ts < '2018-09-17 09:03:18.334' PARTITION BY t3,t4,t5,t2 INTERVAL(1d);"
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 8:00:00', '2018-09-17 09:03:18.333').get_qc())
|
.should_query_with_table('meters', '2018-09-17 8:00:00', '2018-09-17 09:03:18.333').get_qc())
|
||||||
|
ctxs.extend(self.test_query_tsma_all())
|
||||||
|
|
||||||
interval_list = ['1s', '5s', '60s', '1m', '10m', '20m', '30m', '59s', '1h', '120s', '1200', '2h', '90m', '1d']
|
|
||||||
opts: TSMATesterSQLGeneratorOptions = TSMATesterSQLGeneratorOptions()
|
|
||||||
opts.interval = True
|
|
||||||
opts.where_ts_range = True
|
|
||||||
for _ in range(1, 100):
|
|
||||||
opts.partition_by = True
|
|
||||||
sql_generator = TSMATestSQLGenerator(opts)
|
|
||||||
sql = sql_generator.generate_one('avg(c1), avg(c2)', ['meters', 't1', 't9'], '', interval_list)
|
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).ignore_query_table().ignore_res_order(sql_generator.can_ignore_res_order()).get_qc())
|
|
||||||
|
|
||||||
opts.partition_by = False
|
|
||||||
sql_generator = TSMATestSQLGenerator(opts)
|
|
||||||
sql = sql_generator.generate_one('avg(c1), avg(c2)', ['norm_tb', 't5'], '', interval_list)
|
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).ignore_query_table().ignore_res_order(sql_generator.can_ignore_res_order()).get_qc())
|
|
||||||
return ctxs
|
return ctxs
|
||||||
|
|
||||||
def test_query_with_tsma_interval_partition_by_col(self):
|
def test_query_with_tsma_interval_partition_by_col(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def test_query_with_tsma_agg(self):
|
def test_query_with_tsma_agg(self):
|
||||||
self.check(self.test_query_with_tsma_agg_no_group_by)
|
self.check(self.test_query_with_tsma_agg_no_group_by())
|
||||||
self.check(self.test_query_with_tsma_agg_group_by_tbname)
|
self.check(self.test_query_with_tsma_agg_group_by_tbname())
|
||||||
self.check(self.test_query_with_tsma_with_having)
|
self.check(self.test_query_with_tsma_with_having())
|
||||||
|
|
||||||
def test_query_with_tsma_agg_no_group_by(self):
|
def test_query_with_tsma_agg_no_group_by(self):
|
||||||
ctxs: List[TSMAQueryContext] = []
|
ctxs: List[TSMAQueryContext] = []
|
||||||
sql = 'select avg(c1), avg(c2) from meters'
|
sql = 'select avg(c1), avg(c2) from meters'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where ts between "2018-09-17 09:00:00.000" and "2018-09-17 10:00:00.000"'
|
sql = 'select avg(c1), avg(c2) from meters where ts between "2018-09-17 09:00:00.000" and "2018-09-17 10:00:00.000"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:00:00','2018-09-17 09:59:59:999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:00:00', '2018-09-17 09:59:59:999')
|
||||||
.should_query_with_table("meters", '2018-09-17 10:00:00', '2018-09-17 10:00:00').get_qc())
|
.should_query_with_table("meters", '2018-09-17 10:00:00', '2018-09-17 10:00:00').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
sql = 'select avg(c1), avg(c2) from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.200','2018-09-17 09:29:59:999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.200', '2018-09-17 09:29:59:999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2), avg(c2) from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
sql = 'select avg(c1) + avg(c2), avg(c2) from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.200','2018-09-17 09:29:59:999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.200', '2018-09-17 09:29:59:999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2), avg(c2) + 1 from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
sql = 'select avg(c1) + avg(c2), avg(c2) + 1 from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.200','2018-09-17 09:29:59:999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.200', '2018-09-17 09:29:59:999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
||||||
|
|
||||||
sql = "select avg(c1) + 1, avg(c2) from meters where ts >= '2018-09-17 9:30:00.118' and ts < '2018-09-17 10:50:00'"
|
sql = "select avg(c1) + 1, avg(c2) from meters where ts >= '2018-09-17 9:30:00.118' and ts < '2018-09-17 10:50:00'"
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 9:30:00.118', '2018-09-17 9:59:59.999') \
|
.should_query_with_table('meters', '2018-09-17 9:30:00.118', '2018-09-17 9:59:59.999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 10:00:00', '2018-09-17 10:29:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 10:00:00', '2018-09-17 10:29:59.999')
|
||||||
.should_query_with_tsma('tsma1', '2018-09-17 10:30:00.000', '2018-09-17 10:49:59.999').get_qc())
|
.should_query_with_tsma('tsma1', '2018-09-17 10:30:00.000', '2018-09-17 10:49:59.999').get_qc())
|
||||||
|
|
||||||
sql = "select avg(c1), avg(c2) from meters where ts >= '2018-09-17 9:00:00' and ts < '2018-09-17 9:45:00' limit 2"
|
sql = "select avg(c1), avg(c2) from meters where ts >= '2018-09-17 9:00:00' and ts < '2018-09-17 9:45:00' limit 2"
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql) \
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 9:00:00', '2018-09-17 9:29:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 9:00:00', '2018-09-17 9:29:59.999')
|
||||||
.should_query_with_tsma('tsma1', '2018-09-17 9:30:00', '2018-09-17 9:44:59.999').get_qc())
|
.should_query_with_tsma('tsma1', '2018-09-17 9:30:00', '2018-09-17 9:44:59.999').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2) from meters where tbname like "%t1%"'
|
sql = 'select avg(c1) + avg(c2) from meters where tbname like "%t1%"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where c1 is not NULL'
|
sql = 'select avg(c1), avg(c2) from meters where c1 is not NULL'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_table('meters').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_table('meters').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2), spread(c4) from meters'
|
sql = 'select avg(c1), avg(c2), spread(c4) from meters'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_table('meters').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_table('meters').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where tbname = \'t1\''
|
sql = 'select avg(c1), avg(c2) from meters where tbname = \'t1\''
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where tbname = \'t1\' or tbname = \'t2\''
|
sql = 'select avg(c1), avg(c2) from meters where tbname = \'t1\' or tbname = \'t2\''
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = '''select avg(c1), avg(c2) from meters where tbname = 't1' and c1 is not NULL'''
|
sql = '''select avg(c1), avg(c2) from meters where tbname = 't1' and c1 is not NULL'''
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_table('meters').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_table('meters').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1+c2) from meters'
|
sql = 'select avg(c1+c2) from meters'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_table('meters').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_table('meters').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), avg(c2) from meters where ts >= "2018-09-17 9:25:00" and ts < "2018-09-17 10:00:00" limit 6'
|
sql = 'select avg(c1), avg(c2) from meters where ts >= "2018-09-17 9:25:00" and ts < "2018-09-17 10:00:00" limit 6'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma1', '2018-09-17 9:25:00', '2018-09-17 9:29:59.999') \
|
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma1', '2018-09-17 9:25:00', '2018-09-17 9:29:59.999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 9:30:00', '2018-09-17 9:59:59.999').get_qc())
|
.should_query_with_tsma('tsma2', '2018-09-17 9:30:00', '2018-09-17 9:59:59.999').get_qc())
|
||||||
|
|
||||||
return ctxs
|
return ctxs
|
||||||
|
@ -814,38 +944,46 @@ class TDTestCase:
|
||||||
def test_query_with_tsma_agg_group_by_tbname(self):
|
def test_query_with_tsma_agg_group_by_tbname(self):
|
||||||
ctxs: List[TSMAQueryContext] = []
|
ctxs: List[TSMAQueryContext] = []
|
||||||
sql = 'select avg(c1) as a, avg(c2) as b, tbname from meters group by tbname order by tbname, a, b'
|
sql = 'select avg(c1) as a, avg(c2) as b, tbname from meters group by tbname order by tbname, a, b'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) as a, avg(c2) + 1 as b, tbname from meters where c1 > 10 group by tbname order by tbname, a, b'
|
sql = 'select avg(c1) as a, avg(c2) + 1 as b, tbname from meters where c1 > 10 group by tbname order by tbname, a, b'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_table('meters').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_table('meters').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2) as a, avg(c2) + 1 as b, tbname from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800" group by tbname order by tbname, a, b'
|
sql = 'select avg(c1) + avg(c2) as a, avg(c2) + 1 as b, tbname from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800" group by tbname order by tbname, a, b'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql)\
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.200','2018-09-17 09:29:59:999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.200', '2018-09-17 09:29:59:999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2) + 3 as a, substr(tbname, 1) as c from meters group by substr(tbname, 1) order by c, a'
|
sql = 'select avg(c1) + avg(c2) + 3 as a, substr(tbname, 1) as c from meters group by substr(tbname, 1) order by c, a'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + avg(c2) as a, avg(c2) + 1 as b, substr(tbname, 1, 1) as c from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800" group by substr(tbname, 1, 1) order by c, a, b'
|
sql = 'select avg(c1) + avg(c2) as a, avg(c2) + 1 as b, substr(tbname, 1, 1) as c from meters where ts between "2018-09-17 09:00:00.200" and "2018-09-17 10:23:19.800" group by substr(tbname, 1, 1) order by c, a, b'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql)\
|
ctxs.append(TSMAQCBuilder().with_sql(sql)
|
||||||
.should_query_with_table('meters', '2018-09-17 09:00:00.200','2018-09-17 09:29:59:999') \
|
.should_query_with_table('meters', '2018-09-17 09:00:00.200', '2018-09-17 09:29:59:999')
|
||||||
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00','2018-09-17 09:59:59.999') \
|
.should_query_with_tsma('tsma2', '2018-09-17 09:30:00', '2018-09-17 09:59:59.999')
|
||||||
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
.should_query_with_table('meters', '2018-09-17 10:00:00.000', '2018-09-17 10:23:19.800').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 order by tbname'
|
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 order by tbname'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1"'
|
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1"'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1" order by tbname'
|
sql = 'select avg(c1), tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1" order by tbname'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
sql = 'select avg(c1) + 1, tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1" order by tbname'
|
sql = 'select avg(c1) + 1, tbname from meters group by tbname having avg(c1) > 0 and tbname = "t1" order by tbname'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
sql = 'select avg(c1) + 1, tbname from meters group by tbname having avg(c1) > 0 and tbname like "t%" order by tbname'
|
sql = 'select avg(c1) + 1, tbname from meters group by tbname having avg(c1) > 0 and tbname like "t%" order by tbname'
|
||||||
ctxs.append(TSMAQCBuilder().with_sql(sql).should_query_with_tsma('tsma2').get_qc())
|
ctxs.append(TSMAQCBuilder().with_sql(
|
||||||
|
sql).should_query_with_tsma('tsma2').get_qc())
|
||||||
|
|
||||||
return ctxs
|
return ctxs
|
||||||
|
|
||||||
|
@ -871,17 +1009,19 @@ class TDTestCase:
|
||||||
self.test_create_tsma_on_norm_table()
|
self.test_create_tsma_on_norm_table()
|
||||||
self.test_create_tsma_on_child_table()
|
self.test_create_tsma_on_child_table()
|
||||||
self.test_create_recursive_tsma()
|
self.test_create_recursive_tsma()
|
||||||
## self.test_drop_stable() ## drop stable and recreate a stable
|
# self.test_drop_stable() ## drop stable and recreate a stable
|
||||||
## self.test_drop_ctable()
|
# self.test_drop_ctable()
|
||||||
self.test_drop_db()
|
self.test_drop_db()
|
||||||
|
|
||||||
def test_drop_tsma(self):
|
def test_drop_tsma(self):
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
self.create_tsma('tsma1', 'test', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
self.create_tsma('tsma1', 'test', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
self.create_recursive_tsma('tsma1', 'tsma2', 'test', '15m', 'meters')
|
self.create_recursive_tsma('tsma1', 'tsma2', 'test', '15m', 'meters')
|
||||||
|
|
||||||
tdSql.error('drop tsma tsma1', -2147482491) ## drop recursive tsma first
|
# drop recursive tsma first
|
||||||
|
tdSql.error('drop tsma tsma1', -2147482491)
|
||||||
tdSql.execute('drop tsma tsma2', queryTimes=1)
|
tdSql.execute('drop tsma tsma2', queryTimes=1)
|
||||||
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
||||||
tdSql.execute('drop database test', queryTimes=1)
|
tdSql.execute('drop database test', queryTimes=1)
|
||||||
|
@ -893,9 +1033,11 @@ class TDTestCase:
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
||||||
tdSql.execute('use nsdb', queryTimes=1)
|
tdSql.execute('use nsdb', queryTimes=1)
|
||||||
tdSql.execute('create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
tdSql.execute(
|
||||||
## TODO insert data
|
'create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
||||||
self.create_tsma('tsma1', 'nsdb', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
# TODO insert data
|
||||||
|
self.create_tsma('tsma1', 'nsdb', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
self.create_recursive_tsma('tsma1', 'tsma2', 'nsdb', '10m', 'meters')
|
self.create_recursive_tsma('tsma1', 'tsma2', 'nsdb', '10m', 'meters')
|
||||||
tdSql.query('select avg(c1) from meters', queryTimes=1)
|
tdSql.query('select avg(c1) from meters', queryTimes=1)
|
||||||
tdSql.execute('drop database nsdb', queryTimes=1)
|
tdSql.execute('drop database nsdb', queryTimes=1)
|
||||||
|
@ -905,42 +1047,57 @@ class TDTestCase:
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
||||||
tdSql.execute('use nsdb', queryTimes=1)
|
tdSql.execute('use nsdb', queryTimes=1)
|
||||||
tdSql.execute('create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
tdSql.execute(
|
||||||
self.create_tsma('tsma1', 'nsdb', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
'create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
||||||
## drop column, drop tag
|
self.create_tsma('tsma1', 'nsdb', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
|
# drop column, drop tag
|
||||||
tdSql.error('alter table meters drop column c1', -2147482637)
|
tdSql.error('alter table meters drop column c1', -2147482637)
|
||||||
tdSql.error('alter table meters drop tag t1', -2147482637)
|
tdSql.error('alter table meters drop tag t1', -2147482637)
|
||||||
tdSql.error('alter table meters drop tag t2', -2147482637) # Stream must be dropped first
|
tdSql.error('alter table meters drop tag t2', -
|
||||||
|
2147482637) # Stream must be dropped first
|
||||||
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
||||||
|
|
||||||
## add tag
|
# add tag
|
||||||
tdSql.execute('alter table meters add tag t3 int', queryTimes=1)
|
tdSql.execute('alter table meters add tag t3 int', queryTimes=1)
|
||||||
tdSql.execute('alter table meters drop tag t3', queryTimes=1)
|
tdSql.execute('alter table meters drop tag t3', queryTimes=1)
|
||||||
tdSql.execute('drop database nsdb')
|
tdSql.execute('drop database nsdb')
|
||||||
|
|
||||||
## TODO test drop stream
|
# TODO test drop stream
|
||||||
|
|
||||||
def test_create_tsma_on_stable(self):
|
def test_create_tsma_on_stable(self):
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
tdSql.execute('create database nsdb precision "ns"', queryTimes=1)
|
||||||
tdSql.execute('use nsdb', queryTimes=1)
|
tdSql.execute('use nsdb', queryTimes=1)
|
||||||
tdSql.execute('create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
tdSql.execute(
|
||||||
self.create_tsma('tsma1', 'nsdb', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
'create table meters(ts timestamp, c1 int, c2 int) tags(t1 int, t2 int)', queryTimes=1)
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(2h)', -2147471097) ## Invalid tsma interval, 1ms ~ 1h is allowed
|
self.create_tsma('tsma1', 'nsdb', 'meters', [
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3601s)', -2147471097)
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3600001a)', -2147471097)
|
# Invalid tsma interval, 1ms ~ 1h is allowed
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3600001000u)', -2147471097)
|
tdSql.error(
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(999999b)', -2147471097)
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(2h)', -2147471097)
|
||||||
tdSql.error('create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(999u)', -2147471097)
|
tdSql.error(
|
||||||
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3601s)', -2147471097)
|
||||||
|
tdSql.error(
|
||||||
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3600001a)', -2147471097)
|
||||||
|
tdSql.error(
|
||||||
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(3600001000u)', -2147471097)
|
||||||
|
tdSql.error(
|
||||||
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(999999b)', -2147471097)
|
||||||
|
tdSql.error(
|
||||||
|
'create tsma tsma2 on meters function(avg(c1), avg(c2)) interval(999u)', -2147471097)
|
||||||
|
|
||||||
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
tdSql.execute('drop tsma tsma1', queryTimes=1)
|
||||||
tdSql.execute('use test', queryTimes=1)
|
tdSql.execute('use test', queryTimes=1)
|
||||||
tdSql.execute('create tsma tsma1 on nsdb.meters function(avg(c1), avg(c2)) interval(10m)', queryTimes=1)
|
tdSql.execute(
|
||||||
self.wait_for_tsma_calculation(['avg(c1)', 'avg(c2)'], 'nsdb', 'meters', '10m', 'tsma1')
|
'create tsma tsma1 on nsdb.meters function(avg(c1), avg(c2)) interval(10m)', queryTimes=1)
|
||||||
|
self.wait_for_tsma_calculation(
|
||||||
|
['avg(c1)', 'avg(c2)'], 'nsdb', 'meters', '10m', 'tsma1')
|
||||||
tdSql.execute('drop tsma nsdb.tsma1', queryTimes=1)
|
tdSql.execute('drop tsma nsdb.tsma1', queryTimes=1)
|
||||||
|
|
||||||
tdSql.error('create tsma tsma1 on test.meters function(avg(c1), avg(c2)) interval(2h)', -2147471097)
|
tdSql.error(
|
||||||
|
'create tsma tsma1 on test.meters function(avg(c1), avg(c2)) interval(2h)', -2147471097)
|
||||||
tdSql.execute('drop database nsdb')
|
tdSql.execute('drop database nsdb')
|
||||||
|
|
||||||
def test_create_tsma_on_norm_table(self):
|
def test_create_tsma_on_norm_table(self):
|
||||||
|
@ -950,19 +1107,22 @@ class TDTestCase:
|
||||||
def test_create_tsma_on_child_table(self):
|
def test_create_tsma_on_child_table(self):
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
tdSql.error('create tsma tsma1 on test.t1 function(avg(c1), avg(c2)) interval(1m)', -2147471098) ## Invalid table to create tsma, only stable or normal table allowed
|
# Invalid table to create tsma, only stable or normal table allowed
|
||||||
|
tdSql.error(
|
||||||
|
'create tsma tsma1 on test.t1 function(avg(c1), avg(c2)) interval(1m)', -2147471098)
|
||||||
|
|
||||||
def test_create_recursive_tsma(self):
|
def test_create_recursive_tsma(self):
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
tdLog.debug(f'-----{function_name}------')
|
tdLog.debug(f'-----{function_name}------')
|
||||||
tdSql.execute('use test')
|
tdSql.execute('use test')
|
||||||
self.create_tsma('tsma1', 'test', 'meters', ['avg(c1)', 'avg(c2)'], '5m')
|
self.create_tsma('tsma1', 'test', 'meters', [
|
||||||
|
'avg(c1)', 'avg(c2)'], '5m')
|
||||||
sql = 'create recursive tsma tsma2 on tsma1 interval(1m)'
|
sql = 'create recursive tsma tsma2 on tsma1 interval(1m)'
|
||||||
tdSql.error(sql, -2147471099) ## invalid tsma parameter
|
tdSql.error(sql, -2147471099) # invalid tsma parameter
|
||||||
sql = 'create recursive tsma tsma2 on tsma1 interval(7m)'
|
sql = 'create recursive tsma tsma2 on tsma1 interval(7m)'
|
||||||
tdSql.error(sql, -2147471099) ## invalid tsma parameter
|
tdSql.error(sql, -2147471099) # invalid tsma parameter
|
||||||
sql = 'create recursive tsma tsma2 on tsma1 interval(11m)'
|
sql = 'create recursive tsma tsma2 on tsma1 interval(11m)'
|
||||||
tdSql.error(sql, -2147471099) ## invalid tsma parameter
|
tdSql.error(sql, -2147471099) # invalid tsma parameter
|
||||||
self.create_recursive_tsma('tsma1', 'tsma2', 'test', '20m', 'meters')
|
self.create_recursive_tsma('tsma1', 'tsma2', 'test', '20m', 'meters')
|
||||||
|
|
||||||
tdSql.execute('drop tsma tsma2', queryTimes=1)
|
tdSql.execute('drop tsma tsma2', queryTimes=1)
|
||||||
|
@ -972,6 +1132,7 @@ class TDTestCase:
|
||||||
tdSql.close()
|
tdSql.close()
|
||||||
tdLog.success(f"{__file__} successfully executed")
|
tdLog.success(f"{__file__} successfully executed")
|
||||||
|
|
||||||
|
|
||||||
event = threading.Event()
|
event = threading.Event()
|
||||||
|
|
||||||
tdCases.addLinux(__file__, TDTestCase())
|
tdCases.addLinux(__file__, TDTestCase())
|
||||||
|
|
Loading…
Reference in New Issue