mirror of
https://github.com/taosdata/TDengine
synced 2026-05-24 10:09:01 +00:00
149 lines
5.3 KiB
Python
149 lines
5.3 KiB
Python
from new_test_framework.utils import tdLog, tdSql, tdStream
|
|
import pytest
|
|
import time
|
|
import random
|
|
import string
|
|
import re
|
|
|
|
|
|
class TestStringFunctionInStream:
|
|
|
|
@pytest.mark.parametrize(
|
|
"string_func",
|
|
[
|
|
"char_length(val)",
|
|
"concat(val, 'abc')",
|
|
"concat_ws('-', val, 'abc')",
|
|
"length(val)",
|
|
"lower(val)",
|
|
"ltrim(val)",
|
|
"rtrim(val)",
|
|
"substr(val, 1, 3)",
|
|
"upper(val)",
|
|
],
|
|
)
|
|
def test_string_function(self, string_func):
|
|
"""OldPy: string function
|
|
|
|
旧用例 tests/system-test/8-stream/scalar_function.py
|
|
测试在流计算中使用字符串函数
|
|
旧的建流语句:
|
|
create stream XXX trigger at_once ignore expired 0 ignore update 0 fill_history 1 into XXX as select ts, char_length(c3) from scalar_tb
|
|
新的建流语句:
|
|
CREATE STREAM XXX SLIDING(10s) FROM tb INTO XXX AS SELECT ts, char_length(val) as val FROM %%trows;
|
|
|
|
Catalog:
|
|
- Streams:OldPyCases
|
|
|
|
Since: v3.3.7.0
|
|
|
|
Labels: common,ci
|
|
|
|
Jira: https://jira.taosdata.com:18080/browse/TD-36887
|
|
|
|
History:
|
|
- 2025-07-23: Created by zyyang90
|
|
"""
|
|
# create snode if not exists
|
|
snodes = tdSql.getResult("SHOW SNODES;")
|
|
if snodes is None or len(snodes) == 0:
|
|
tdStream.createSnode()
|
|
|
|
self.db = "test_string_func_in_stream"
|
|
self.stream = "stream_output"
|
|
|
|
# create database and table
|
|
tdSql.executes(
|
|
[
|
|
f"DROP DATABASE IF EXISTS `{self.db}`;",
|
|
f"CREATE DATABASE IF NOT EXISTS `{self.db}`;",
|
|
f"USE `{self.db}`;",
|
|
"CREATE TABLE tb(ts TIMESTAMP, val VARCHAR(20));",
|
|
],
|
|
queryTimes=1,
|
|
)
|
|
|
|
# create stream
|
|
tdSql.execute(
|
|
f"CREATE STREAM {self.stream} SLIDING(10s) FROM tb INTO {self.stream} AS SELECT _tprev_ts AS wstart, _tcurrent_ts AS wend, {string_func} AS val FROM %%trows;",
|
|
queryTimes=1,
|
|
)
|
|
tdStream.checkStreamStatus()
|
|
|
|
# insert data
|
|
ts = (int(time.time()) // 60) * 60 * 1000 # 当前时间取整分钟的时间戳
|
|
# 生成随机字符串
|
|
val = "".join(random.choices(string.ascii_letters + string.digits, k=10))
|
|
if string_func.startswith("ltrim"):
|
|
val = f" {val}" # 添加前后空格以测试 ltrim
|
|
elif string_func.startswith("rtrim"):
|
|
val = f"{val} "
|
|
tdSql.execute(f"INSERT INTO tb VALUES({ts}, '{val}');", queryTimes=1)
|
|
|
|
# 计算 expected value
|
|
if string_func.startswith("char_length") or string_func.startswith("length"):
|
|
expected = len(val)
|
|
elif string_func.startswith("concat_ws"):
|
|
# 解析 concat_ws 的参数并组合 expected 字符串
|
|
match = re.match(r"concat_ws\(([^,]+),\s*([^,]+),\s*([^)]+)\)", string_func)
|
|
if match:
|
|
sep = match.group(1).strip("'\"")
|
|
str1 = match.group(2).strip("'\"")
|
|
str2 = match.group(3).strip("'\"")
|
|
if str1 == "val":
|
|
str1 = val
|
|
elif str2 == "val":
|
|
str2 = val
|
|
expected = f"{str1}{sep}{str2}"
|
|
else:
|
|
tdLog.error(f"Invalid concat_ws function: {string_func}")
|
|
expected = None
|
|
elif string_func.startswith("concat"):
|
|
# 解析 concat 的参数并组合 expected 字符串
|
|
match = re.match(r"concat\(([^,]+),\s*([^,]+)\)", string_func)
|
|
if match:
|
|
str1 = match.group(1).strip("'\"")
|
|
str2 = match.group(2).strip("'\"")
|
|
if str1 == "val":
|
|
str1 = val
|
|
elif str2 == "val":
|
|
str2 = val
|
|
expected = f"{str1}{str2}"
|
|
else:
|
|
tdLog.error(f"Invalid concat function: {string_func}")
|
|
expected = None
|
|
elif string_func.startswith("lower"):
|
|
expected = val.lower()
|
|
elif string_func.startswith("upper"):
|
|
expected = val.upper()
|
|
elif string_func.startswith("ltrim"):
|
|
expected = val.lstrip()
|
|
elif string_func.startswith("rtrim"):
|
|
expected = val.rstrip()
|
|
elif string_func.startswith("substr"):
|
|
# 解析 substr 的参数并截取字符串
|
|
match = re.match(r"substr\(([^,]+),\s*([^,]+),\s*([^)]+)\)", string_func)
|
|
if match:
|
|
start = int(match.group(2)) - 1 # substr 的起始位置从 1 开始
|
|
length = int(match.group(3))
|
|
if start < 0:
|
|
start = 0
|
|
if start + length > len(val):
|
|
length = len(val) - start
|
|
expected = val[start : start + length]
|
|
else:
|
|
expected = None
|
|
tdLog.info(f"string_func: {string_func}, val: {val}, expected: {expected}")
|
|
|
|
# check result
|
|
tdSql.checkResultsByFunc(
|
|
sql=f"select * from {self.stream}",
|
|
func=lambda: tdSql.getRows() == 1
|
|
and tdSql.compareData(
|
|
0,
|
|
2,
|
|
expected,
|
|
),
|
|
)
|
|
|
|
tdLog.info("test string function done.")
|