From aea32365978df8defb117d2b9372a260f4bd2abb Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 14:44:49 +0800 Subject: [PATCH 01/12] stmt2 document for python connector --- docs/examples/python/insert_with_stmt2.py | 626 ++++++++++++++++++ .../14-reference/05-connector/30-python.mdx | 131 ++-- tests/docs-examples-test/python.sh | 2 + 3 files changed, 688 insertions(+), 71 deletions(-) create mode 100644 docs/examples/python/insert_with_stmt2.py diff --git a/docs/examples/python/insert_with_stmt2.py b/docs/examples/python/insert_with_stmt2.py new file mode 100644 index 0000000000..433b283fe3 --- /dev/null +++ b/docs/examples/python/insert_with_stmt2.py @@ -0,0 +1,626 @@ +# encoding:UTF-8 +from ctypes import * +from datetime import datetime +# geometry support +from shapely.wkb import dumps, loads +from shapely.wkt import dumps as wkt_dumps, loads as wkt_loads + +import taos +import math +import traceback +from taos.statement2 import * +from taos.constants import FieldType +from taos import log +from taos import bind2 + +# input WKT return WKB (bytes object) +def WKB(wkt, hex = False): + if wkt is None: + return None + wkb = wkt_loads(wkt) + wkb_bytes = dumps(wkb, hex) + return wkb_bytes + +def compareLine(oris, rows): + n = len(oris) + if len(rows) != n: + return False + log.debug(f" len is {n} oris={oris} rows={rows}") + for i in range(n): + if oris[i] != rows[i]: + if type(rows[i]) == bool: + if bool(oris[i]) != rows[i]: + log.debug1(f" diff bool i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + return False + else: + log.debug1(f" float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + elif type(rows[i]) == float: + if math.isclose(oris[i], rows[i], rel_tol=1e-3) is False: + log.debug1(f" diff float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + return False + else: + log.debug1(f" float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + else: + log.debug1(f" diff i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + return False + else: + log.debug1(f" i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") + + return True + + +def checkResultCorrect(conn, sql, tagsTb, datasTb): + # column to rows + log.debug(f"check sql correct: {sql}\n") + oris = [] + ncol = len(datasTb) + nrow = len(datasTb[0]) + + for i in range(nrow): + row = [] + for j in range(ncol): + if j == 0: + # ts column + c0 = datasTb[j][i] + if type(c0) is int : + row.append(datasTb[j][i]) + else: + ts = int(bind2.datetime_to_timestamp(c0, PrecisionEnum.Milliseconds).value) + row.append(ts) + else: + row.append(datasTb[j][i]) + + if tagsTb is not None: + row += tagsTb + oris.append(row) + + # fetch all + lres = [] + log.debug(sql) + res = conn.query(sql) + i = 0 + for row in res: + lrow = list(row) + lrow[0] = int(lrow[0].timestamp()*1000) + if compareLine(oris[i], lrow) is False: + log.info(f"insert data differet. i={i} expect ori data={oris[i]} query from db ={lrow}") + raise(BaseException("check insert data correct failed.")) + else: + log.debug(f"i={i} origin data same with get from db\n") + log.debug(f" origin data = {oris[i]} \n") + log.debug(f" get from db = {lrow} \n") + i += 1 + + +def checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas): + count = len(tbnames) + for i in range(count): + if stbname is None: + sql = f"select * from {dbname}.{tbnames[i]} " + else: + sql = f"select * from {dbname}.{stbname} where tbname='{tbnames[i]}' " + + checkResultCorrect(conn, sql, tags[i], datas[i]) + + print("insert data check correct ..................... ok\n") + + +def prepare(conn, dbname, stbname, ntb1, ntb2): + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s precision 'ms' " % dbname) + conn.select_db(dbname) + # stable + sql = f"create table if not exists {dbname}.{stbname}(ts timestamp, name binary(32), sex bool, score int) tags(grade nchar(8), class int)" + conn.execute(sql) + # normal table + sql = f"create table if not exists {dbname}.{ntb1} (ts timestamp, name varbinary(32), sex bool, score float, geo geometry(128))" + conn.execute(sql) + sql = f"create table if not exists {dbname}.{ntb2} (ts timestamp, name varbinary(32), sex bool, score float, geo geometry(128))" + conn.execute(sql) + + +# performace is high +def insert_bind_param(conn, stmt2, dbname, stbname): + # + # table info , write 5 lines to 3 child tables d0, d1, d2 with super table + # + tbnames = ["d1","d2","d3"] + + tags = [ + ["grade1", 1], + ["grade1", None], + [None , 3] + ] + datas = [ + # class 1 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], + ["Mary", "Tom", "Jack", "Jane", "alex" ,None ], + [0, 1, 1, 0, 1 ,None ], + [98, 80, 60, 100, 99 ,None ] + ], + # class 2 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], + ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ,None ], + [0, 1, 1, 0, 1 ,0 ], + [298, 280, 260, 2100, 299 ,None ] + ], + # class 3 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], + ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ,"Mark" ], + [0, 1, 1, 0, 1 ,None ], + [398, 380, 360, 3100, 399 ,None ] + ] + ] + + stmt2.bind_param(tbnames, tags, datas) + stmt2.execute() + + # check correct + checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas) + + +def insert_bind_param_normal_tables(conn, stmt2, dbname, ntb): + tbnames = [ntb] + tags = None + wkts = [None, b"POINT(121.213 31.234)", b"POINT(122.22 32.222)", None, b"POINT(124.22 34.222)"] + wkbs = [WKB(wkt) for wkt in wkts] + + datas = [ + # table 1 + [ + # student + [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], + [b"Mary", b"tom", b"Jack", b"Jane", None ], + [0, 3.14, True, 0, 1 ], + [98, 99.87, 60, 100, 99 ], + wkbs + ] + ] + + stmt2.bind_param(tbnames, tags, datas) + stmt2.execute() + + # check correct + checkResultCorrects(conn, dbname, None, tbnames, [None], datas) + +def insert_bind_param_with_table(conn, stmt2, dbname, stbname, ctb): + + tbnames = None + tags = [ + ["grade2", 1] + ] + + # prepare data + datas = [ + # table 1 + [ + # student + [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], + ["Mary", "Tom", "Jack", "Jane", "alex" ], + [0, 1, 1, 0, 1 ], + [98, 80, 60, 100, 99 ] + ] + ] + + stmt2.bind_param(tbnames, tags, datas) + stmt2.execute() + + # check correct + checkResultCorrects(conn, dbname, stbname, [ctb], tags, datas) + + +# insert with single table (performance is lower) +def insert_bind_param_with_tables(conn, stmt2, dbname, stbname): + + tbnames = ["t1", "t2", "t3"] + tags = [ + ["grade2", 1], + ["grade2", 2], + ["grade2", 3] + ] + + # prepare data + datas = [ + # table 1 + [ + # student + [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], + ["Mary", "Tom", "Jack", "Jane", "alex" ], + [0, 1, 1, 0, 1 ], + [98, 80, 60, 100, 99 ] + ], + # table 2 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], + ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ], + [0, 1, 1, 0, 1 ], + [298, 280, 260, 2100, 299 ] + ], + # table 3 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], + ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ], + [0, 1, 1, 0, 1 ], + [398, 380, 360, 3100, 399 ] + ] + ] + + table0 = BindTable(tbnames[0], tags[0]) + table1 = BindTable(tbnames[1], tags[1]) + table2 = BindTable(tbnames[2], tags[2]) + + for data in datas[0]: + table0.add_col_data(data) + for data in datas[1]: + table1.add_col_data(data) + for data in datas[2]: + table2.add_col_data(data) + + # bind with single table + stmt2.bind_param_with_tables([table0, table1, table2]) + stmt2.execute() + + # check correct + checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas) + + +def do_check_invalid(stmt2, tbnames, tags, datas): + table0 = BindTable(tbnames[0], tags[0]) + table1 = BindTable(tbnames[1], tags[1]) + table2 = BindTable(tbnames[2], tags[2]) + + for data in datas[0]: + table0.add_col_data(data) + for data in datas[1]: + table1.add_col_data(data) + for data in datas[2]: + table2.add_col_data(data) + + # bind with single table + try: + stmt2.bind_param_with_tables([table0, table1, table2]) + stmt2.execute() + except Exception as err: + #traceback.print_stack() + print(f"failed to do_check_invalid. err={err}") + return + + print(f"input invalid data passed , unexpect. \ntbnames={tbnames}\ntags={tags} \ndatas={datas} \n") + assert False + + +def check_input_invalid_param(conn, stmt2, dbname, stbname): + + tbnames = ["t1", "t2", "t3"] + tags = [ + ["grade2", 1], + ["grade2", 2], + ["grade2", 3] + ] + + # prepare data + datas = [ + # table 1 + [ + # student + [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], + ["Mary", "Tom", "Jack", "Jane", "alex" ], + [0, 1, 1, 0, 1 ], + [98, 80, 60, 100, 99 ] + ], + # table 2 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], + ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ], + [0, 1, 1, 0, 1 ], + [298, 280, 260, 2100, 299 ] + ], + # table 3 + [ + # student + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], + ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ], + [0, 1, 1, 0, 1 ], + [398, 380, 360, 3100, 399 ] + ] + ] + + # some tags is none + tags1 = [ ["grade2", 1], None, ["grade2", 3] ] + do_check_invalid(stmt2, tbnames, tags1, datas) + + # timestamp is over range + origin = datas[0][0][0] + datas[0][0][0] = 100000000000000000000000 + do_check_invalid(stmt2, tbnames, tags, datas) + datas[0][0][0] = origin # restore + + +# insert with single table (performance is lower) +def insert_with_normal_tables(conn, stmt2, dbname, ntb): + + tbnames = [ntb] + tags = [None] + # prepare data + + wkts = [None, "POINT(121.213 31.234)", "POINT(122.22 32.222)", None, "POINT(124.22 34.222)"] + wkbs = [WKB(wkt) for wkt in wkts] + + datas = [ + # table 1 + [ + # student + [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], + [b"Mary", b"tom", b"Jack", b"Jane", None ], + [0, 3.14, True, 0, 1 ], + [98, 99.87, 60, 100, 99 ], + wkbs + ] + ] + + table0 = BindTable(tbnames[0], tags[0]) + for data in datas[0]: + table0.add_col_data(data) + + # bind with single table + stmt2.bind_param_with_tables([table0]) + stmt2.execute() + + # check correct + checkResultCorrects(conn, dbname, None, tbnames, tags, datas) + + +def test_stmt2_prepare_empty_sql(conn): + if not IS_V3: + print(" test_stmt2_prepare_empty_sql not support TDengine 2.X version.") + return + + try: + # prepare + stmt2 = conn.statement2() + stmt2.prepare(sql='') + + # should not run here + conn.close() + print("prepare empty sql ............................. failed\n") + assert False + + except StatementError as err: + print("prepare empty sql ............................. ok\n") + conn.close() + + +def test_bind_invalid_tbnames_type(): + if not IS_V3: + print(" test_bind_invalid_tbnames_type not support TDengine 2.X version.") + return + + dbname = "stmt2" + stbname = "stmt2_stable" + subtbname = "stmt2_subtable" + + try: + conn = taos.connect() + conn.execute(f"drop database if exists {dbname}") + conn.execute(f"create database {dbname}") + conn.select_db(dbname) + conn.execute(f"create stable {stbname} (ts timestamp, a int) tags (b int);") + conn.execute(f"create table {subtbname} using {stbname} tags(0);") + + stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?) values(?,?)") + + tags = [[1]] + datas = [[[1626861392589], [1]]] + + stmt2.bind_param(subtbname, tags, datas) + + # should not run here + conn.close() + print("bind invalid tbnames type ..................... failed\n") + assert False + + except StatementError as err: + print("bind invalid tbnames type ..................... ok\n") + conn.close() + + +# +# insert +# +def test_stmt2_insert(conn): + if not IS_V3: + print(" test_stmt2_query not support TDengine 2.X version.") + return + + dbname = "stmt2" + stbname = "meters" + ntb1 = "ntb1" + ntb2 = "ntb2" + + try: + prepare(conn, dbname, stbname, ntb1, ntb2) + + ctb = 'ctb' # child table + stmt2 = conn.statement2(f"insert into {dbname}.{ctb} using {dbname}.{stbname} tags (?,?) values(?,?,?,?)") + insert_bind_param_with_table(conn, stmt2, dbname, stbname, ctb) + print("insert child table ........................... ok\n") + stmt2.close() + + # # prepare + # stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?,?) values(?,?,?,?)") + # print("insert prepare sql ............................ ok\n") + # + # # insert with table + # insert_bind_param_with_tables(conn, stmt2, dbname, stbname) + # print("insert bind with tables ....................... ok\n") + # check_input_invalid_param(conn, stmt2, dbname, stbname) + # print("check input invalid params .................... ok\n") + # + # # insert with split args + # insert_bind_param(conn, stmt2, dbname, stbname) + # print("insert bind ................................... ok\n") + # print("insert execute ................................ ok\n") + # stmt2.close() + + # ntb1 + stmt2 = conn.statement2(f"insert into {dbname}.{ntb1} values(?,?,?,?,?)") + insert_with_normal_tables(conn, stmt2, dbname, ntb1) + print("insert normal tables .......................... ok\n") + stmt2.close() + + # ntb2 + stmt2 = conn.statement2(f"insert into {dbname}.{ntb2} values(?,?,?,?,?)") + insert_bind_param_normal_tables(conn, stmt2, dbname, ntb2) + print("insert normal tables (bind param) ............. ok\n") + stmt2.close() + + conn.close() + print("test_stmt2_insert ............................. [passed]\n") + except Exception as err: + #conn.execute("drop database if exists %s" % dbname) + print("test_stmt2_insert ............................. failed\n") + conn.close() + raise err + + +# +# ------------------------ query ------------------- +# +def query_bind_param(conn, stmt2): + # set param + #tbnames = ["d2"] + tbnames = None + tags = None + datas = [ + # class 1 + [ + # where name in ('Tom2','alex2') or score > 1000;" + ["Tom2"], + [1000] + ] + ] + + # set param + types = [FieldType.C_BINARY, FieldType.C_INT] + stmt2.set_columns_type(types) + + # bind + stmt2.bind_param(tbnames, tags, datas) + + +# compare +def compare_result(conn, sql2, res2): + lres1 = [] + lres2 = [] + + # shor res2 + for row in res2: + log.debug(f" res2 rows = {row} \n") + lres2.append(row) + + res1 = conn.query(sql2) + for row in res1: + log.debug(f" res1 rows = {row} \n") + lres1.append(row) + + row1 = len(lres1) + row2 = len(lres2) + col1 = len(lres1[0]) + col2 = len(lres2[0]) + + # check number + if row1 != row2: + err = f"two results row count different. row1={row1} row2={row2}" + raise(BaseException(err)) + if col1 != col2: + err = f" two results column count different. col1={col1} col2={col2}" + raise(BaseException(err)) + + for i in range(row1): + for j in range(col1): + if lres1[i][j] != lres2[i][j]: + raise(f" two results data different. i={i} j={j} data1={res1[i][j]} data2={res2[i][j]}\n") + +# query +def test_stmt2_query(conn): + if not IS_V3: + print(" test_stmt2_query not support TDengine 2.X version.") + return + + dbname = "stmt2" + stbname = "meters" + ntb1 = "ntb1" + ntb2 = "ntb2" + sql1 = f"select * from {dbname}.d2 where name in (?) or score > ? ;" + sql2 = f"select * from {dbname}.d2 where name in ('Tom2') or score > 1000;" + + try: + # prepare + prepare(conn, dbname, stbname, ntb1, ntb2) + + # prepare + # stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?,?) values(?,?,?,?)") + # insert_bind_param_with_tables(conn, stmt2, dbname, stbname) + # insert_bind_param(conn, stmt2, dbname, stbname) + # stmt2.close() + # print("insert bind & execute ......................... ok\n") + + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.000', 'Mary2', false, 298)") + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.001', 'Tom2', true, 280)") + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.002', 'Jack2', true, 260)") + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.003', 'Jane2', false, 2100)") + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.004', 'alex2', true, 299)") + conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.005', NULL, false, NULL)") + + + # statement2 + stmt2 = conn.statement2(sql1) + print("query prepare sql ............................. ok\n") + + + # insert with table + #insert_bind_param_with_tables(conn, stmt2) + + + # bind + query_bind_param(conn, stmt2) + print("query bind param .............................. ok\n") + + # query execute + stmt2.execute() + + # fetch result + res2 = stmt2.result() + + # check result + compare_result(conn, sql2, res2) + print("query check corrent ........................... ok\n") + + #conn.execute("drop database if exists %s" % dbname) + stmt2.close() + conn.close() + print("test_stmt2_query .............................. [passed]\n") + + except Exception as err: + print("query ......................................... failed\n") + conn.close() + raise err + + +if __name__ == "__main__": + print("start stmt2 test case...\n") + taos.log.setting(True, True, True, True, True, False) + # insert + test_stmt2_insert(taos.connect()) + # query + test_stmt2_query(taos.connect()) + print("end stmt2 test case.\n") \ No newline at end of file diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index d724fc796c..c91e9775f4 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -246,43 +246,43 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `reqId`: 用于问题追踪。 - **异常**:操作失败抛出 `DataError` 或 `OperationalError` 异常。 -#### 参数绑定 -- `fn statement(&self) -> PyResult` - - **接口说明**:使用 连接 对象创建 stmt 对象。 - - **返回值**:stmt 对象。 +#### 参数绑定 STMT2 +- `def statement2(self, sql=None, option=None)` + - **接口说明**:使用连接对象创建 stmt2 对象 + - **参数说明** + - `sql`: 绑定的 SQL 语句,如果不为空会调用`prepare`函数 + - `option` 传入 TaosStmt2Option 类实例选项 + - **返回值**:stmt2 对象。 - **异常**:操作失败抛出 `ConnectionError` 异常。 -- `fn prepare(&mut self, sql: &str) -> PyResult<()>` - - **接口说明**:绑定预编译 sql 语句。 +- `def prepare(self, sql)` + - **接口说明**:绑定预编译 sql 语句 - **参数说明**: - - `sql`: 预编译的 SQL 语句。 + - `sql`: 绑定的 SQL 语句 - **异常**:操作失败抛出 `ProgrammingError` 异常。 -- `fn set_tbname(&mut self, table_name: &str) -> PyResult<()>` - - **接口说明**:设置将要写入数据的表名。 +- `def bind_param(self, tbnames, tags, datas)` + - **接口说明**:以独立数组方式绑定数据 - **参数说明**: - - `tableName`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 -- `fn set_tags(&mut self, tags: Vec) -> PyResult<()>` - - **接口说明**:设置表 Tags 数据, 用于自动建表。 + - `tbnames`: 绑定表名数组,数据类型为 list + - `tags`: 绑定 tag 列值数组,数据类型为 list + - `tags`: 绑定普通列值数组,数据类型为 list + - **异常**:操作失败抛出 `StatementError` 异常 +- `def bind_param_with_tables(self, tables)` + - **接口说明**:以独立表方式绑定数据,独立表是以表为组织单位,每张表中有表名,TAG 值及普通列数值属性 - **参数说明**: - - `paramsArray`: Tags 数据。 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 -- `fn bind_param(&mut self, params: Vec) -> PyResult<()>` - - **接口说明**:绑定数据。 - - **参数说明**: - - `paramsArray`: 绑定数据。 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 -- `fn add_batch(&mut self) -> PyResult<()>` - - **接口说明**:提交绑定数据。 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 -- `fn execute(&mut self) -> PyResult` - - **接口说明**:执行将绑定的数据全部写入。 - - **返回值**:写入条数。 + - `tables`: `BindTable` 独立表对象数组 + - **异常**:操作失败抛出 `StatementError` 异常。 +- `def execute(self) -> int:` + - **接口说明**:执行将绑定数据全部写入 + - **返回值**:影响行数 - **异常**:操作失败抛出 `QueryError` 异常。 -- `fn affect_rows(&mut self) -> PyResult` - - **接口说明**: 获取写入条数。 - - **返回值**:写入条数。 -- `fn close(&self) -> PyResult<()>` - - **接口说明**: 关闭 stmt 对象。 +- `def result(self)` + - **接口说明**: 获取参数绑定查询结果集 + - **返回值**:返回 TaosResult 对象 +- `def close(self)` + - **接口说明**: 关闭 stmt2 对象 + +[示例](http://example.code.stmt2) + #### 数据订阅 - **创建消费者支持属性列表**: @@ -423,51 +423,40 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - **返回值**:影响的条数。 - **异常**:操作失败抛出 `SchemalessError` 异常。 -#### 参数绑定 -- `def statement(self, sql=None)` - - **接口说明**:使用连接对象创建 stmt 对象, 如果 sql 不空会进行调用 prepare。 - - `sql`: 预编译的 SQL 语句。 - - **返回值**:stmt 对象。 - - **异常**:操作失败抛出 `StatementError` 异常。 +#### 参数绑定 STMT2 +- `def statement2(self, sql=None, option=None)` + - **接口说明**:使用连接对象创建 stmt2 对象 + - **参数说明** + - `sql`: 绑定的 SQL 语句,如果不为空会调用`prepare`函数 + - `option` 传入 TaosStmt2Option 类实例选项 + - **返回值**:stmt2 对象。 + - **异常**:操作失败抛出 `ConnectionError` 异常。 - `def prepare(self, sql)` - - **接口说明**:绑定预编译 sql 语句。 + - **接口说明**:绑定预编译 sql 语句 - **参数说明**: - - `sql`: 预编译的 SQL 语句。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def set_tbname(self, name)` - - **接口说明**:设置将要写入数据的表名。 + - `sql`: 绑定的 SQL 语句 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `def bind_param(self, tbnames, tags, datas)` + - **接口说明**:以独立数组方式绑定数据 - **参数说明**: - - `name`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def set_tbname_tags(self, name, tags):` - - **接口说明**:设置表和 Tags 数据, 用于自动建表。 + - `tbnames`: 绑定表名数组,数据类型为 list + - `tags`: 绑定 tag 列值数组,数据类型为 list + - `tags`: 绑定普通列值数组,数据类型为 list + - **异常**:操作失败抛出 `StatementError` 异常 +- `def bind_param_with_tables(self, tables)` + - **接口说明**:以独立表方式绑定数据,独立表是以表为组织单位,每张表中有表名,TAG 值及普通列数值属性 - **参数说明**: - - `name`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。 - - `tags`: Tags 数据。 + - `tables`: `BindTable` 独立表对象数组 - **异常**:操作失败抛出 `StatementError` 异常。 -- `def bind_param(self, params, add_batch=True)` - - **接口说明**:绑定一组数据并提交。 - - **参数说明**: - - `params`: 绑定数据。 - - `add_batch`: 是否提交绑定数据。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def bind_param_batch(self, binds, add_batch=True)` - - **接口说明**:绑定多组数据并提交。 - - **参数说明**: - - `binds`: 绑定数据。 - - `add_batch`: 是否提交绑定数据。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def add_batch(self)` - - **接口说明**:提交绑定数据。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def execute(self)` - - **接口说明**:执行将绑定的数据全部写入。 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def affected_rows(self)` - - **接口说明**: 获取写入条数。 - - **返回值**:写入条数。 -- `def close(&self)` - - **接口说明**: 关闭 stmt 对象。 +- `def execute(self) -> int:` + - **接口说明**:执行将绑定数据全部写入 + - **返回值**:影响行数 + - **异常**:操作失败抛出 `QueryError` 异常。 +- `def result(self)` + - **接口说明**: 获取参数绑定查询结果集 + - **返回值**:返回 TaosResult 对象 +- `def close(self)` + - **接口说明**: 关闭 stmt2 对象 #### 数据订阅 - **创建消费者支持属性列表**: diff --git a/tests/docs-examples-test/python.sh b/tests/docs-examples-test/python.sh index 3a9812637c..f7f94db1f2 100644 --- a/tests/docs-examples-test/python.sh +++ b/tests/docs-examples-test/python.sh @@ -196,3 +196,5 @@ check_transactions || exit 1 reset_cache || exit 1 python3 tmq_websocket_example.py +# stmt2 +python3 insert_with_stmt2.py \ No newline at end of file From e6ec05e155e8ef7f0088595ca7187176db664a59 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 14:59:26 +0800 Subject: [PATCH 02/12] docs: update document for python --- docs/zh/14-reference/05-connector/30-python.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index c91e9775f4..0c15d866d5 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -258,7 +258,7 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - **接口说明**:绑定预编译 sql 语句 - **参数说明**: - `sql`: 绑定的 SQL 语句 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 + - **异常**:操作失败抛出 `StatementError` 异常。 - `def bind_param(self, tbnames, tags, datas)` - **接口说明**:以独立数组方式绑定数据 - **参数说明**: @@ -281,7 +281,7 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `def close(self)` - **接口说明**: 关闭 stmt2 对象 -[示例](http://example.code.stmt2) +[使用示例](http://https://github.com/taosdata/TDengine/tree/main/docs/examples/python/insert_with_stmt2.py) #### 数据订阅 @@ -435,7 +435,7 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - **接口说明**:绑定预编译 sql 语句 - **参数说明**: - `sql`: 绑定的 SQL 语句 - - **异常**:操作失败抛出 `ProgrammingError` 异常。 + - **异常**:操作失败抛出 `StatementError` 异常。 - `def bind_param(self, tbnames, tags, datas)` - **接口说明**:以独立数组方式绑定数据 - **参数说明**: @@ -458,6 +458,8 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `def close(self)` - **接口说明**: 关闭 stmt2 对象 +[使用示例](http://https://github.com/taosdata/TDengine/tree/main/docs/examples/python/insert_with_stmt2.py) + #### 数据订阅 - **创建消费者支持属性列表**: - td.connect.ip:主机地址。 From f0627fd7e8042102a9843f205d741928062a0342 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 15:25:25 +0800 Subject: [PATCH 03/12] fix: remove tdengine case to python-connector repo --- docs/examples/python/insert_with_stmt2.py | 626 ------------------ .../14-reference/05-connector/30-python.mdx | 8 +- tests/docs-examples-test/python.sh | 2 - 3 files changed, 4 insertions(+), 632 deletions(-) delete mode 100644 docs/examples/python/insert_with_stmt2.py diff --git a/docs/examples/python/insert_with_stmt2.py b/docs/examples/python/insert_with_stmt2.py deleted file mode 100644 index 433b283fe3..0000000000 --- a/docs/examples/python/insert_with_stmt2.py +++ /dev/null @@ -1,626 +0,0 @@ -# encoding:UTF-8 -from ctypes import * -from datetime import datetime -# geometry support -from shapely.wkb import dumps, loads -from shapely.wkt import dumps as wkt_dumps, loads as wkt_loads - -import taos -import math -import traceback -from taos.statement2 import * -from taos.constants import FieldType -from taos import log -from taos import bind2 - -# input WKT return WKB (bytes object) -def WKB(wkt, hex = False): - if wkt is None: - return None - wkb = wkt_loads(wkt) - wkb_bytes = dumps(wkb, hex) - return wkb_bytes - -def compareLine(oris, rows): - n = len(oris) - if len(rows) != n: - return False - log.debug(f" len is {n} oris={oris} rows={rows}") - for i in range(n): - if oris[i] != rows[i]: - if type(rows[i]) == bool: - if bool(oris[i]) != rows[i]: - log.debug1(f" diff bool i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - return False - else: - log.debug1(f" float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - elif type(rows[i]) == float: - if math.isclose(oris[i], rows[i], rel_tol=1e-3) is False: - log.debug1(f" diff float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - return False - else: - log.debug1(f" float i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - else: - log.debug1(f" diff i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - return False - else: - log.debug1(f" i={i} oris[i] == rows[i] {oris[i]} == {rows[i]}") - - return True - - -def checkResultCorrect(conn, sql, tagsTb, datasTb): - # column to rows - log.debug(f"check sql correct: {sql}\n") - oris = [] - ncol = len(datasTb) - nrow = len(datasTb[0]) - - for i in range(nrow): - row = [] - for j in range(ncol): - if j == 0: - # ts column - c0 = datasTb[j][i] - if type(c0) is int : - row.append(datasTb[j][i]) - else: - ts = int(bind2.datetime_to_timestamp(c0, PrecisionEnum.Milliseconds).value) - row.append(ts) - else: - row.append(datasTb[j][i]) - - if tagsTb is not None: - row += tagsTb - oris.append(row) - - # fetch all - lres = [] - log.debug(sql) - res = conn.query(sql) - i = 0 - for row in res: - lrow = list(row) - lrow[0] = int(lrow[0].timestamp()*1000) - if compareLine(oris[i], lrow) is False: - log.info(f"insert data differet. i={i} expect ori data={oris[i]} query from db ={lrow}") - raise(BaseException("check insert data correct failed.")) - else: - log.debug(f"i={i} origin data same with get from db\n") - log.debug(f" origin data = {oris[i]} \n") - log.debug(f" get from db = {lrow} \n") - i += 1 - - -def checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas): - count = len(tbnames) - for i in range(count): - if stbname is None: - sql = f"select * from {dbname}.{tbnames[i]} " - else: - sql = f"select * from {dbname}.{stbname} where tbname='{tbnames[i]}' " - - checkResultCorrect(conn, sql, tags[i], datas[i]) - - print("insert data check correct ..................... ok\n") - - -def prepare(conn, dbname, stbname, ntb1, ntb2): - conn.execute("drop database if exists %s" % dbname) - conn.execute("create database if not exists %s precision 'ms' " % dbname) - conn.select_db(dbname) - # stable - sql = f"create table if not exists {dbname}.{stbname}(ts timestamp, name binary(32), sex bool, score int) tags(grade nchar(8), class int)" - conn.execute(sql) - # normal table - sql = f"create table if not exists {dbname}.{ntb1} (ts timestamp, name varbinary(32), sex bool, score float, geo geometry(128))" - conn.execute(sql) - sql = f"create table if not exists {dbname}.{ntb2} (ts timestamp, name varbinary(32), sex bool, score float, geo geometry(128))" - conn.execute(sql) - - -# performace is high -def insert_bind_param(conn, stmt2, dbname, stbname): - # - # table info , write 5 lines to 3 child tables d0, d1, d2 with super table - # - tbnames = ["d1","d2","d3"] - - tags = [ - ["grade1", 1], - ["grade1", None], - [None , 3] - ] - datas = [ - # class 1 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], - ["Mary", "Tom", "Jack", "Jane", "alex" ,None ], - [0, 1, 1, 0, 1 ,None ], - [98, 80, 60, 100, 99 ,None ] - ], - # class 2 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], - ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ,None ], - [0, 1, 1, 0, 1 ,0 ], - [298, 280, 260, 2100, 299 ,None ] - ], - # class 3 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], - ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ,"Mark" ], - [0, 1, 1, 0, 1 ,None ], - [398, 380, 360, 3100, 399 ,None ] - ] - ] - - stmt2.bind_param(tbnames, tags, datas) - stmt2.execute() - - # check correct - checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas) - - -def insert_bind_param_normal_tables(conn, stmt2, dbname, ntb): - tbnames = [ntb] - tags = None - wkts = [None, b"POINT(121.213 31.234)", b"POINT(122.22 32.222)", None, b"POINT(124.22 34.222)"] - wkbs = [WKB(wkt) for wkt in wkts] - - datas = [ - # table 1 - [ - # student - [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], - [b"Mary", b"tom", b"Jack", b"Jane", None ], - [0, 3.14, True, 0, 1 ], - [98, 99.87, 60, 100, 99 ], - wkbs - ] - ] - - stmt2.bind_param(tbnames, tags, datas) - stmt2.execute() - - # check correct - checkResultCorrects(conn, dbname, None, tbnames, [None], datas) - -def insert_bind_param_with_table(conn, stmt2, dbname, stbname, ctb): - - tbnames = None - tags = [ - ["grade2", 1] - ] - - # prepare data - datas = [ - # table 1 - [ - # student - [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], - ["Mary", "Tom", "Jack", "Jane", "alex" ], - [0, 1, 1, 0, 1 ], - [98, 80, 60, 100, 99 ] - ] - ] - - stmt2.bind_param(tbnames, tags, datas) - stmt2.execute() - - # check correct - checkResultCorrects(conn, dbname, stbname, [ctb], tags, datas) - - -# insert with single table (performance is lower) -def insert_bind_param_with_tables(conn, stmt2, dbname, stbname): - - tbnames = ["t1", "t2", "t3"] - tags = [ - ["grade2", 1], - ["grade2", 2], - ["grade2", 3] - ] - - # prepare data - datas = [ - # table 1 - [ - # student - [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], - ["Mary", "Tom", "Jack", "Jane", "alex" ], - [0, 1, 1, 0, 1 ], - [98, 80, 60, 100, 99 ] - ], - # table 2 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], - ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ], - [0, 1, 1, 0, 1 ], - [298, 280, 260, 2100, 299 ] - ], - # table 3 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], - ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ], - [0, 1, 1, 0, 1 ], - [398, 380, 360, 3100, 399 ] - ] - ] - - table0 = BindTable(tbnames[0], tags[0]) - table1 = BindTable(tbnames[1], tags[1]) - table2 = BindTable(tbnames[2], tags[2]) - - for data in datas[0]: - table0.add_col_data(data) - for data in datas[1]: - table1.add_col_data(data) - for data in datas[2]: - table2.add_col_data(data) - - # bind with single table - stmt2.bind_param_with_tables([table0, table1, table2]) - stmt2.execute() - - # check correct - checkResultCorrects(conn, dbname, stbname, tbnames, tags, datas) - - -def do_check_invalid(stmt2, tbnames, tags, datas): - table0 = BindTable(tbnames[0], tags[0]) - table1 = BindTable(tbnames[1], tags[1]) - table2 = BindTable(tbnames[2], tags[2]) - - for data in datas[0]: - table0.add_col_data(data) - for data in datas[1]: - table1.add_col_data(data) - for data in datas[2]: - table2.add_col_data(data) - - # bind with single table - try: - stmt2.bind_param_with_tables([table0, table1, table2]) - stmt2.execute() - except Exception as err: - #traceback.print_stack() - print(f"failed to do_check_invalid. err={err}") - return - - print(f"input invalid data passed , unexpect. \ntbnames={tbnames}\ntags={tags} \ndatas={datas} \n") - assert False - - -def check_input_invalid_param(conn, stmt2, dbname, stbname): - - tbnames = ["t1", "t2", "t3"] - tags = [ - ["grade2", 1], - ["grade2", 2], - ["grade2", 3] - ] - - # prepare data - datas = [ - # table 1 - [ - # student - [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], - ["Mary", "Tom", "Jack", "Jane", "alex" ], - [0, 1, 1, 0, 1 ], - [98, 80, 60, 100, 99 ] - ], - # table 2 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], - ["Mary2", "Tom2", "Jack2", "Jane2", "alex2" ], - [0, 1, 1, 0, 1 ], - [298, 280, 260, 2100, 299 ] - ], - # table 3 - [ - # student - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004], - ["Mary3", "Tom3", "Jack3", "Jane3", "alex3" ], - [0, 1, 1, 0, 1 ], - [398, 380, 360, 3100, 399 ] - ] - ] - - # some tags is none - tags1 = [ ["grade2", 1], None, ["grade2", 3] ] - do_check_invalid(stmt2, tbnames, tags1, datas) - - # timestamp is over range - origin = datas[0][0][0] - datas[0][0][0] = 100000000000000000000000 - do_check_invalid(stmt2, tbnames, tags, datas) - datas[0][0][0] = origin # restore - - -# insert with single table (performance is lower) -def insert_with_normal_tables(conn, stmt2, dbname, ntb): - - tbnames = [ntb] - tags = [None] - # prepare data - - wkts = [None, "POINT(121.213 31.234)", "POINT(122.22 32.222)", None, "POINT(124.22 34.222)"] - wkbs = [WKB(wkt) for wkt in wkts] - - datas = [ - # table 1 - [ - # student - [1601481600000,1601481600004,"2024-09-19 10:00:00", "2024-09-19 10:00:01.123", datetime(2024,9,20,10,11,12,456)], - [b"Mary", b"tom", b"Jack", b"Jane", None ], - [0, 3.14, True, 0, 1 ], - [98, 99.87, 60, 100, 99 ], - wkbs - ] - ] - - table0 = BindTable(tbnames[0], tags[0]) - for data in datas[0]: - table0.add_col_data(data) - - # bind with single table - stmt2.bind_param_with_tables([table0]) - stmt2.execute() - - # check correct - checkResultCorrects(conn, dbname, None, tbnames, tags, datas) - - -def test_stmt2_prepare_empty_sql(conn): - if not IS_V3: - print(" test_stmt2_prepare_empty_sql not support TDengine 2.X version.") - return - - try: - # prepare - stmt2 = conn.statement2() - stmt2.prepare(sql='') - - # should not run here - conn.close() - print("prepare empty sql ............................. failed\n") - assert False - - except StatementError as err: - print("prepare empty sql ............................. ok\n") - conn.close() - - -def test_bind_invalid_tbnames_type(): - if not IS_V3: - print(" test_bind_invalid_tbnames_type not support TDengine 2.X version.") - return - - dbname = "stmt2" - stbname = "stmt2_stable" - subtbname = "stmt2_subtable" - - try: - conn = taos.connect() - conn.execute(f"drop database if exists {dbname}") - conn.execute(f"create database {dbname}") - conn.select_db(dbname) - conn.execute(f"create stable {stbname} (ts timestamp, a int) tags (b int);") - conn.execute(f"create table {subtbname} using {stbname} tags(0);") - - stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?) values(?,?)") - - tags = [[1]] - datas = [[[1626861392589], [1]]] - - stmt2.bind_param(subtbname, tags, datas) - - # should not run here - conn.close() - print("bind invalid tbnames type ..................... failed\n") - assert False - - except StatementError as err: - print("bind invalid tbnames type ..................... ok\n") - conn.close() - - -# -# insert -# -def test_stmt2_insert(conn): - if not IS_V3: - print(" test_stmt2_query not support TDengine 2.X version.") - return - - dbname = "stmt2" - stbname = "meters" - ntb1 = "ntb1" - ntb2 = "ntb2" - - try: - prepare(conn, dbname, stbname, ntb1, ntb2) - - ctb = 'ctb' # child table - stmt2 = conn.statement2(f"insert into {dbname}.{ctb} using {dbname}.{stbname} tags (?,?) values(?,?,?,?)") - insert_bind_param_with_table(conn, stmt2, dbname, stbname, ctb) - print("insert child table ........................... ok\n") - stmt2.close() - - # # prepare - # stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?,?) values(?,?,?,?)") - # print("insert prepare sql ............................ ok\n") - # - # # insert with table - # insert_bind_param_with_tables(conn, stmt2, dbname, stbname) - # print("insert bind with tables ....................... ok\n") - # check_input_invalid_param(conn, stmt2, dbname, stbname) - # print("check input invalid params .................... ok\n") - # - # # insert with split args - # insert_bind_param(conn, stmt2, dbname, stbname) - # print("insert bind ................................... ok\n") - # print("insert execute ................................ ok\n") - # stmt2.close() - - # ntb1 - stmt2 = conn.statement2(f"insert into {dbname}.{ntb1} values(?,?,?,?,?)") - insert_with_normal_tables(conn, stmt2, dbname, ntb1) - print("insert normal tables .......................... ok\n") - stmt2.close() - - # ntb2 - stmt2 = conn.statement2(f"insert into {dbname}.{ntb2} values(?,?,?,?,?)") - insert_bind_param_normal_tables(conn, stmt2, dbname, ntb2) - print("insert normal tables (bind param) ............. ok\n") - stmt2.close() - - conn.close() - print("test_stmt2_insert ............................. [passed]\n") - except Exception as err: - #conn.execute("drop database if exists %s" % dbname) - print("test_stmt2_insert ............................. failed\n") - conn.close() - raise err - - -# -# ------------------------ query ------------------- -# -def query_bind_param(conn, stmt2): - # set param - #tbnames = ["d2"] - tbnames = None - tags = None - datas = [ - # class 1 - [ - # where name in ('Tom2','alex2') or score > 1000;" - ["Tom2"], - [1000] - ] - ] - - # set param - types = [FieldType.C_BINARY, FieldType.C_INT] - stmt2.set_columns_type(types) - - # bind - stmt2.bind_param(tbnames, tags, datas) - - -# compare -def compare_result(conn, sql2, res2): - lres1 = [] - lres2 = [] - - # shor res2 - for row in res2: - log.debug(f" res2 rows = {row} \n") - lres2.append(row) - - res1 = conn.query(sql2) - for row in res1: - log.debug(f" res1 rows = {row} \n") - lres1.append(row) - - row1 = len(lres1) - row2 = len(lres2) - col1 = len(lres1[0]) - col2 = len(lres2[0]) - - # check number - if row1 != row2: - err = f"two results row count different. row1={row1} row2={row2}" - raise(BaseException(err)) - if col1 != col2: - err = f" two results column count different. col1={col1} col2={col2}" - raise(BaseException(err)) - - for i in range(row1): - for j in range(col1): - if lres1[i][j] != lres2[i][j]: - raise(f" two results data different. i={i} j={j} data1={res1[i][j]} data2={res2[i][j]}\n") - -# query -def test_stmt2_query(conn): - if not IS_V3: - print(" test_stmt2_query not support TDengine 2.X version.") - return - - dbname = "stmt2" - stbname = "meters" - ntb1 = "ntb1" - ntb2 = "ntb2" - sql1 = f"select * from {dbname}.d2 where name in (?) or score > ? ;" - sql2 = f"select * from {dbname}.d2 where name in ('Tom2') or score > 1000;" - - try: - # prepare - prepare(conn, dbname, stbname, ntb1, ntb2) - - # prepare - # stmt2 = conn.statement2(f"insert into ? using {dbname}.{stbname} tags(?,?) values(?,?,?,?)") - # insert_bind_param_with_tables(conn, stmt2, dbname, stbname) - # insert_bind_param(conn, stmt2, dbname, stbname) - # stmt2.close() - # print("insert bind & execute ......................... ok\n") - - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.000', 'Mary2', false, 298)") - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.001', 'Tom2', true, 280)") - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.002', 'Jack2', true, 260)") - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.003', 'Jane2', false, 2100)") - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.004', 'alex2', true, 299)") - conn.execute(f"insert into d2 using {stbname} tags('grade1', 2) values('2020-10-01 00:00:00.005', NULL, false, NULL)") - - - # statement2 - stmt2 = conn.statement2(sql1) - print("query prepare sql ............................. ok\n") - - - # insert with table - #insert_bind_param_with_tables(conn, stmt2) - - - # bind - query_bind_param(conn, stmt2) - print("query bind param .............................. ok\n") - - # query execute - stmt2.execute() - - # fetch result - res2 = stmt2.result() - - # check result - compare_result(conn, sql2, res2) - print("query check corrent ........................... ok\n") - - #conn.execute("drop database if exists %s" % dbname) - stmt2.close() - conn.close() - print("test_stmt2_query .............................. [passed]\n") - - except Exception as err: - print("query ......................................... failed\n") - conn.close() - raise err - - -if __name__ == "__main__": - print("start stmt2 test case...\n") - taos.log.setting(True, True, True, True, True, False) - # insert - test_stmt2_insert(taos.connect()) - # query - test_stmt2_query(taos.connect()) - print("end stmt2 test case.\n") \ No newline at end of file diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index 0c15d866d5..cdf63f918c 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -52,7 +52,8 @@ Python Connector 历史版本(建议使用最新版本的 `taospy`): | Python Connector 版本 | 主要变化 | TDengine 版本 | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -| 2.7.18 | 支持 Apache Superset BI 产品 | - | +| 2.7.19 | 支持 Apache Superset 连接 TDengine Cloud 数据源 | - | +| 2.7.18 | 支持 Apache Superset 产品连接本地 TDengine 数据源 | - | | 2.7.16 | 新增订阅配置 (session.timeout.ms, max.poll.interval.ms) | - | | 2.7.15 | 新增 VARBINARY 和 GEOMETRY 类型支持 | - | | 2.7.14 | 修复已知问题 | - | @@ -131,7 +132,8 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Python 对 | [json_tag.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/json-tag.py) | 使用 JSON 类型的标签 | | [tmq_consumer.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq_consumer.py) | tmq 订阅 | | [native_all_type_query.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_query.py) | 支持全部类型示例 | -| [native_all_type_stmt.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_stmt.py) | 参数绑定支持全部类型示例 | +| [native_all_type_stmt.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_stmt.py) | 参数绑定 stmt 全部类型示例 | +| [insert_with_stmt2.py](https://github.com/taosdata/taos-connector-python/blob/main/tests/test_stmt2.py) | 参数绑定 stmt2 写入示例 | 示例程序源码请参考: @@ -281,7 +283,6 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `def close(self)` - **接口说明**: 关闭 stmt2 对象 -[使用示例](http://https://github.com/taosdata/TDengine/tree/main/docs/examples/python/insert_with_stmt2.py) #### 数据订阅 @@ -458,7 +459,6 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `def close(self)` - **接口说明**: 关闭 stmt2 对象 -[使用示例](http://https://github.com/taosdata/TDengine/tree/main/docs/examples/python/insert_with_stmt2.py) #### 数据订阅 - **创建消费者支持属性列表**: diff --git a/tests/docs-examples-test/python.sh b/tests/docs-examples-test/python.sh index f7f94db1f2..3a9812637c 100644 --- a/tests/docs-examples-test/python.sh +++ b/tests/docs-examples-test/python.sh @@ -196,5 +196,3 @@ check_transactions || exit 1 reset_cache || exit 1 python3 tmq_websocket_example.py -# stmt2 -python3 insert_with_stmt2.py \ No newline at end of file From 2c35ec8ae9a8859871cc4330add7872e9f257dcb Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 16:11:11 +0800 Subject: [PATCH 04/12] docs: add stmt2_native.py example --- docs/en/07-develop/05-stmt.md | 2 +- docs/examples/python/stmt2_native.py | 78 ++++++++++++++++++++++++++++ docs/zh/07-develop/05-stmt.md | 2 +- tests/docs-examples-test/python.sh | 1 + 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 docs/examples/python/stmt2_native.py diff --git a/docs/en/07-develop/05-stmt.md b/docs/en/07-develop/05-stmt.md index 485315bc93..11b055bcf9 100644 --- a/docs/en/07-develop/05-stmt.md +++ b/docs/en/07-develop/05-stmt.md @@ -98,7 +98,7 @@ This is a [more detailed parameter binding example](https://github.com/taosdata/ ```python -{{#include docs/examples/python/stmt_native.py}} +{{#include docs/examples/python/stmt2_native.py}} ``` diff --git a/docs/examples/python/stmt2_native.py b/docs/examples/python/stmt2_native.py new file mode 100644 index 0000000000..7e6d59466e --- /dev/null +++ b/docs/examples/python/stmt2_native.py @@ -0,0 +1,78 @@ +import taos +from datetime import datetime +import random + +conn = None +stmt2 = None +host="localhost" +port=6030 +try: + # 1 connect + conn = taos.connect( + user="root", + password="taosdata", + host=host, + port=port, + ) + + # 2 create db and table + conn.execute("CREATE DATABASE IF NOT EXISTS power") + conn.execute("USE power") + conn.execute( + "CREATE TABLE IF NOT EXISTS `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS (`groupid` INT, `location` BINARY(16))" + ) + + # 3 prepare + sql = "INSERT INTO ? USING meters (groupid, location) TAGS(?,?) VALUES (?,?,?,?)" + stmt2 = conn.statement2(sql) + + # table name array + tbnames = ["d0","d1","d2"] + # tag data array + tags = [ + [1, "BeiJing"], + [2, None], + [3, "ShangHai"] + ] + # column data array + datas = [ + # d0 tabled + [ + [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], + [10.1, 10.2, 10.3, 10.4, 10.5 ,None ], + [98, None, 60, 100, 99 ,128 ], + [0, 1, 0, 0, 1 ,0 ] + ], + # d1 tabled + [ + [1601481700000,1601481700001,1601481700002,1601481700003,1601481700004,1601481700005], + [10.1, 10.2, 10.3, 10.4, 10.5 ,11.2 ], + [98, 80, 60, 100, 99 ,128 ], + [0, 1, 0, 0, 1 ,0 ] + ], + # d2 tabled + [ + [1601481800000,1601481800001,1601481800002,1601481800003,1601481800004,1601481800005], + [10.1, 10.2, 10.3, 10.4, 10.5 ,13.4 ], + [98, 80, 60, 100, 99 ,128 ], + [0, 1, 0, None, 1 ,0 ] + ], + ] + + # 4 bind param + stmt2.bind_param(tbnames, tags, datas) + + # 5 execute + stmt2.execute() + + # show + print(f"Successfully inserted with stmt2 to power.meters.") + +except Exception as err: + print(f"Failed to insert to table meters using stmt2, ErrMessage:{err}") + raise err +finally: + if stmt2: + stmt2.close() + if conn: + conn.close() diff --git a/docs/zh/07-develop/05-stmt.md b/docs/zh/07-develop/05-stmt.md index 045126b333..1917a86e74 100644 --- a/docs/zh/07-develop/05-stmt.md +++ b/docs/zh/07-develop/05-stmt.md @@ -93,7 +93,7 @@ import TabItem from "@theme/TabItem"; ```python -{{#include docs/examples/python/stmt_native.py}} +{{#include docs/examples/python/stmt2_native.py}} ``` diff --git a/tests/docs-examples-test/python.sh b/tests/docs-examples-test/python.sh index 3a9812637c..536155437b 100644 --- a/tests/docs-examples-test/python.sh +++ b/tests/docs-examples-test/python.sh @@ -196,3 +196,4 @@ check_transactions || exit 1 reset_cache || exit 1 python3 tmq_websocket_example.py +python3 stmt2_native.py \ No newline at end of file From f6b180ff569aab9ba859a6ec84be019a7fc5c4fd Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 16:57:16 +0800 Subject: [PATCH 05/12] fix: use old case model --- docs/examples/python/stmt2_native.py | 59 ++++++++++++---------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/docs/examples/python/stmt2_native.py b/docs/examples/python/stmt2_native.py index 7e6d59466e..72f01c9038 100644 --- a/docs/examples/python/stmt2_native.py +++ b/docs/examples/python/stmt2_native.py @@ -2,6 +2,9 @@ import taos from datetime import datetime import random +numOfSubTable = 10 +numOfRow = 10 + conn = None stmt2 = None host="localhost" @@ -26,38 +29,28 @@ try: sql = "INSERT INTO ? USING meters (groupid, location) TAGS(?,?) VALUES (?,?,?,?)" stmt2 = conn.statement2(sql) - # table name array - tbnames = ["d0","d1","d2"] - # tag data array - tags = [ - [1, "BeiJing"], - [2, None], - [3, "ShangHai"] - ] - # column data array - datas = [ - # d0 tabled - [ - [1601481600000,1601481600001,1601481600002,1601481600003,1601481600004,1601481600005], - [10.1, 10.2, 10.3, 10.4, 10.5 ,None ], - [98, None, 60, 100, 99 ,128 ], - [0, 1, 0, 0, 1 ,0 ] - ], - # d1 tabled - [ - [1601481700000,1601481700001,1601481700002,1601481700003,1601481700004,1601481700005], - [10.1, 10.2, 10.3, 10.4, 10.5 ,11.2 ], - [98, 80, 60, 100, 99 ,128 ], - [0, 1, 0, 0, 1 ,0 ] - ], - # d2 tabled - [ - [1601481800000,1601481800001,1601481800002,1601481800003,1601481800004,1601481800005], - [10.1, 10.2, 10.3, 10.4, 10.5 ,13.4 ], - [98, 80, 60, 100, 99 ,128 ], - [0, 1, 0, None, 1 ,0 ] - ], - ] + tbnames = [] + tags = [] + datas = [] + + for i in range(numOfSubTable): + # tbnames + tbnames.append(f"d_bind_{i}") + # tags + tags.append([i, f"location_{i}"]) + # datas + current = int(datetime.now().timestamp() * 1000) + timestamps = [] + currents = [] + voltages = [] + phases = [] + for j in range (numOfRow): + timestamps.append(current + i*1000 + j) + currents.append(float(random.random() * 30)) + voltages.append(random.randint(100, 300)) + phases.append(float(random.random())) + data = [timestamps, currents, voltages, phases] + datas.append(data) # 4 bind param stmt2.bind_param(tbnames, tags, datas) @@ -66,7 +59,7 @@ try: stmt2.execute() # show - print(f"Successfully inserted with stmt2 to power.meters.") + print(f"Successfully inserted with stmt2 to power.meters. child={numOfSubTable} rows={numOfRow} \n") except Exception as err: print(f"Failed to insert to table meters using stmt2, ErrMessage:{err}") From 62d3df49d1d5513433b114dc02cc20dd22417c13 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 17:16:23 +0800 Subject: [PATCH 06/12] docs: remove STMT2 --- .../14-reference/05-connector/30-python.mdx | 65 ++++++++++--------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index cdf63f918c..ad43ce19df 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -52,6 +52,7 @@ Python Connector 历史版本(建议使用最新版本的 `taospy`): | Python Connector 版本 | 主要变化 | TDengine 版本 | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | +| 2.7.20 | Native 支持 STMT2 写入 | - | | 2.7.19 | 支持 Apache Superset 连接 TDengine Cloud 数据源 | - | | 2.7.18 | 支持 Apache Superset 产品连接本地 TDengine 数据源 | - | | 2.7.16 | 新增订阅配置 (session.timeout.ms, max.poll.interval.ms) | - | @@ -248,41 +249,43 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - `reqId`: 用于问题追踪。 - **异常**:操作失败抛出 `DataError` 或 `OperationalError` 异常。 -#### 参数绑定 STMT2 -- `def statement2(self, sql=None, option=None)` - - **接口说明**:使用连接对象创建 stmt2 对象 - - **参数说明** - - `sql`: 绑定的 SQL 语句,如果不为空会调用`prepare`函数 - - `option` 传入 TaosStmt2Option 类实例选项 - - **返回值**:stmt2 对象。 +#### 参数绑定 +- `fn statement(&self) -> PyResult` + - **接口说明**:使用 连接 对象创建 stmt 对象。 + - **返回值**:stmt 对象。 - **异常**:操作失败抛出 `ConnectionError` 异常。 -- `def prepare(self, sql)` - - **接口说明**:绑定预编译 sql 语句 +- `fn prepare(&mut self, sql: &str) -> PyResult<()>` + - **接口说明**:绑定预编译 sql 语句。 - **参数说明**: - - `sql`: 绑定的 SQL 语句 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def bind_param(self, tbnames, tags, datas)` - - **接口说明**:以独立数组方式绑定数据 + - `sql`: 预编译的 SQL 语句。 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `fn set_tbname(&mut self, table_name: &str) -> PyResult<()>` + - **接口说明**:设置将要写入数据的表名。 - **参数说明**: - - `tbnames`: 绑定表名数组,数据类型为 list - - `tags`: 绑定 tag 列值数组,数据类型为 list - - `tags`: 绑定普通列值数组,数据类型为 list - - **异常**:操作失败抛出 `StatementError` 异常 -- `def bind_param_with_tables(self, tables)` - - **接口说明**:以独立表方式绑定数据,独立表是以表为组织单位,每张表中有表名,TAG 值及普通列数值属性 + - `tableName`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `fn set_tags(&mut self, tags: Vec) -> PyResult<()>` + - **接口说明**:设置表 Tags 数据, 用于自动建表。 - **参数说明**: - - `tables`: `BindTable` 独立表对象数组 - - **异常**:操作失败抛出 `StatementError` 异常。 -- `def execute(self) -> int:` - - **接口说明**:执行将绑定数据全部写入 - - **返回值**:影响行数 + - `paramsArray`: Tags 数据。 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `fn bind_param(&mut self, params: Vec) -> PyResult<()>` + - **接口说明**:绑定数据。 + - **参数说明**: + - `paramsArray`: 绑定数据。 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `fn add_batch(&mut self) -> PyResult<()>` + - **接口说明**:提交绑定数据。 + - **异常**:操作失败抛出 `ProgrammingError` 异常。 +- `fn execute(&mut self) -> PyResult` + - **接口说明**:执行将绑定的数据全部写入。 + - **返回值**:写入条数。 - **异常**:操作失败抛出 `QueryError` 异常。 -- `def result(self)` - - **接口说明**: 获取参数绑定查询结果集 - - **返回值**:返回 TaosResult 对象 -- `def close(self)` - - **接口说明**: 关闭 stmt2 对象 - +- `fn affect_rows(&mut self) -> PyResult` + - **接口说明**: 获取写入条数。 + - **返回值**:写入条数。 +- `fn close(&self) -> PyResult<()>` + - **接口说明**: 关闭 stmt 对象。 #### 数据订阅 @@ -424,7 +427,7 @@ TaosResult 对象可以通过循环遍历获取查询到的数据。 - **返回值**:影响的条数。 - **异常**:操作失败抛出 `SchemalessError` 异常。 -#### 参数绑定 STMT2 +#### 参数绑定 - `def statement2(self, sql=None, option=None)` - **接口说明**:使用连接对象创建 stmt2 对象 - **参数说明** From e8232129651cd56ae9a7ce4cf7a142b90c09741a Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 17:53:28 +0800 Subject: [PATCH 07/12] docs: update english documents --- .../en/14-reference/05-connector/30-python.md | 81 +++++++++---------- .../14-reference/05-connector/30-python.mdx | 2 +- 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/docs/en/14-reference/05-connector/30-python.md b/docs/en/14-reference/05-connector/30-python.md index 58cff75c90..d1e922da8d 100644 --- a/docs/en/14-reference/05-connector/30-python.md +++ b/docs/en/14-reference/05-connector/30-python.md @@ -55,6 +55,8 @@ Python Connector historical versions (it is recommended to use the latest versio |Python Connector Version | Major Changes | TDengine Version| | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | +|2.7.20 | Native supports STMT2 writing | - | +|2.7.19 | Support Apache Superset connection to TDengine Cloud data source | - | |2.7.18 | Support Apache SuperSet BI Tools. | - | |2.7.16 | Add subscription configuration (session. timeout. ms, Max. roll. interval. ms). | - | |2.7.15 | Added support for VARBINRY and GEOMETRY types. | - | @@ -136,7 +138,7 @@ TDengine currently supports timestamp, numeric, character, boolean types, and th | [tmq_consumer.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq_consumer.py) | tmq subscription | | [native_all_type_query.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_query.py) | Example supporting all types | | [native_all_type_stmt.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_stmt.py) | Parameter binding example supporting all types | - +| [test_stmt2.py](https://github.com/taosdata/taos-connector-python/blob/main/tests/test_stmt2.py) | Example of STMT2 writing | Example program source code can be found at: 1. [More native example programs](https://github.com/taosdata/taos-connector-python/tree/main/examples) @@ -429,51 +431,40 @@ TaosResult object can be iterated over to retrieve queried data. - **Exceptions**: Throws `SchemalessError` if operation fails. #### Parameter Binding - -- `def statement(self, sql=None)` - - **Interface Description**: Creates a stmt object using the connection object, if sql is not empty it will call prepare. - - `sql`: Precompiled SQL statement. - - **Return Value**: stmt object. - - **Exception**: Throws `StatementError` exception on failure. +- `def statement2(self, sql=None, option=None)` + - **Interface Description**:Creating an STMT2 object using a connection object + - **Parameter Description** + - `sql`: The bound SQL statement will call the `prepare` function if it is not empty + - `option` Pass in TaoStmt2Option class instance options + - **Return Value**:stmt2 object + - **Exception**:Throws `ConnectionError` on failure - `def prepare(self, sql)` - - **Interface Description**: Binds a precompiled sql statement. - - **Parameter Description**: - - `sql`: Precompiled SQL statement. - - **Exception**: Throws `StatementError` exception on failure. -- `def set_tbname(self, name)` - - **Interface Description**: Sets the table name for data to be written to. - - **Parameter Description**: - - `name`: Table name, if you need to specify a database, for example: `db_name.table_name`. - - **Exception**: Throws `StatementError` exception on failure. -- `def set_tbname_tags(self, name, tags):` - - **Interface Description**: Sets the table and Tags data, used for automatic table creation. - - **Parameter Description**: - - `name`: Table name, if you need to specify a database, for example: `db_name.table_name`. - - `tags`: Tags data. - - **Exception**: Throws `StatementError` exception on failure. -- `def bind_param(self, params, add_batch=True)` - - **Interface Description**: Binds a set of data and submits. - - **Parameter Description**: - - `params`: Data to bind. - - `add_batch`: Whether to submit the bound data. - - **Exception**: Throws `StatementError` exception on failure. -- `def bind_param_batch(self, binds, add_batch=True)` - - **Interface Description**: Binds multiple sets of data and submits. - - **Parameter Description**: - - `binds`: Data to bind. - - `add_batch`: Whether to submit the bound data. - - **Exception**: Throws `StatementError` exception on failure. -- `def add_batch(self)` - - **Interface Description**: Submits the bound data. - - **Exception**: Throws `StatementError` exception on failure. -- `def execute(self)` - - **Interface Description**: Executes and writes all the bound data. - - **Exception**: Throws `StatementError` exception on failure. -- `def affected_rows(self)` - - **Interface Description**: Gets the number of rows written. - - **Return Value**: Number of rows written. -- `def close(&self)` - - **Interface Description**: Closes the stmt object. + - **Interface Description**:Bind a precompiled SQL statement + - **Parameter Description**: + - `sql`: Precompiled SQL statement + - **Exception**:Throws `StatementError` on failure +- `def bind_param(self, tbnames, tags, datas)` + - **Interface Description**:Binding Data as an Independent Array + - **Parameter Description**: + - `tbnames`:Bind table name array, data type is list + - `tags`: Bind tag column value array, data type is list + - `tags`: Bind a regular column value array with a data type of list + - **Exception**:Throws `StatementError` on failure +- `def bind_param_with_tables(self, tables)` + - **Interface Description**:Bind data in an independent table format. Independent tables are organized by table units, with table names, TAG values, and regular column numerical attributes in each table + - **Parameter Description**: + - `tables`: `BindTable` Independent Table Object Array + - **Exception**:Throws `StatementError` on failure +- `def execute(self) -> int:` + - **Interface Description**:Execute to write all bound data + - **Return Value**:Affects the number of rows + - **Exception**:Throws `QueryError` on failure +- `def result(self)` + - **Interface Description**:Get parameter binding query result set + - **Return Value**:Returns the TaosResult object +- `def close(self)` + - **Interface Description**: close the STMT2 object + #### Data Subscription diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index ad43ce19df..a1fedfd92c 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -134,7 +134,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Python 对 | [tmq_consumer.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq_consumer.py) | tmq 订阅 | | [native_all_type_query.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_query.py) | 支持全部类型示例 | | [native_all_type_stmt.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/native_all_type_stmt.py) | 参数绑定 stmt 全部类型示例 | -| [insert_with_stmt2.py](https://github.com/taosdata/taos-connector-python/blob/main/tests/test_stmt2.py) | 参数绑定 stmt2 写入示例 | +| [test_stmt2.py](https://github.com/taosdata/taos-connector-python/blob/main/tests/test_stmt2.py) | 参数绑定 stmt2 写入示例 | 示例程序源码请参考: From 3e55011e983ce2724ad0c3bf79fc91a7a6281f55 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 18:13:59 +0800 Subject: [PATCH 08/12] fix: add top level to 4 --- docs/en/14-reference/05-connector/30-python.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/14-reference/05-connector/30-python.md b/docs/en/14-reference/05-connector/30-python.md index d1e922da8d..05ae323f9a 100644 --- a/docs/en/14-reference/05-connector/30-python.md +++ b/docs/en/14-reference/05-connector/30-python.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: Python title: Python Client Library slug: /tdengine-reference/client-libraries/python From 9e701eaf2a47006835ac661849370e2cb3c1bcae Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 18:18:43 +0800 Subject: [PATCH 09/12] add toc_max_heading_level 4 --- docs/en/14-reference/05-connector/10-cpp.md | 1 + docs/en/14-reference/05-connector/14-java.md | 1 + docs/en/14-reference/05-connector/20-go.md | 1 + docs/en/14-reference/05-connector/26-rust.md | 1 + docs/en/14-reference/05-connector/35-node.md | 1 + docs/en/14-reference/05-connector/40-csharp.md | 1 + 6 files changed, 6 insertions(+) diff --git a/docs/en/14-reference/05-connector/10-cpp.md b/docs/en/14-reference/05-connector/10-cpp.md index fe7574d416..940d4c359e 100644 --- a/docs/en/14-reference/05-connector/10-cpp.md +++ b/docs/en/14-reference/05-connector/10-cpp.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: C/C++ title: C/C++ Client Library slug: /tdengine-reference/client-libraries/cpp diff --git a/docs/en/14-reference/05-connector/14-java.md b/docs/en/14-reference/05-connector/14-java.md index 48302b9d3b..2781f26c24 100644 --- a/docs/en/14-reference/05-connector/14-java.md +++ b/docs/en/14-reference/05-connector/14-java.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: Java title: Java Client Library slug: /tdengine-reference/client-libraries/java diff --git a/docs/en/14-reference/05-connector/20-go.md b/docs/en/14-reference/05-connector/20-go.md index bf0e6dd979..578150f0fa 100644 --- a/docs/en/14-reference/05-connector/20-go.md +++ b/docs/en/14-reference/05-connector/20-go.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: Go title: Go Client Library slug: /tdengine-reference/client-libraries/go diff --git a/docs/en/14-reference/05-connector/26-rust.md b/docs/en/14-reference/05-connector/26-rust.md index 637d009b8c..8de5d628de 100644 --- a/docs/en/14-reference/05-connector/26-rust.md +++ b/docs/en/14-reference/05-connector/26-rust.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: Rust title: Rust Client Library slug: /tdengine-reference/client-libraries/rust diff --git a/docs/en/14-reference/05-connector/35-node.md b/docs/en/14-reference/05-connector/35-node.md index 19dae0357f..49b1d200cf 100644 --- a/docs/en/14-reference/05-connector/35-node.md +++ b/docs/en/14-reference/05-connector/35-node.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: Node.js title: Node.js Client Library slug: /tdengine-reference/client-libraries/node diff --git a/docs/en/14-reference/05-connector/40-csharp.md b/docs/en/14-reference/05-connector/40-csharp.md index 8e51cb319b..c9c9f95228 100644 --- a/docs/en/14-reference/05-connector/40-csharp.md +++ b/docs/en/14-reference/05-connector/40-csharp.md @@ -1,4 +1,5 @@ --- +toc_max_heading_level: 4 sidebar_label: C# title: C# Client Library slug: /tdengine-reference/client-libraries/csharp From 24f6828b9f90b5ef571756dbeabb6881455b78ba Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 18:27:39 +0800 Subject: [PATCH 10/12] docs: fix tags double mistaken --- docs/en/14-reference/05-connector/30-python.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/14-reference/05-connector/30-python.md b/docs/en/14-reference/05-connector/30-python.md index 05ae323f9a..7cf5858c2f 100644 --- a/docs/en/14-reference/05-connector/30-python.md +++ b/docs/en/14-reference/05-connector/30-python.md @@ -436,8 +436,8 @@ TaosResult object can be iterated over to retrieve queried data. - **Interface Description**:Creating an STMT2 object using a connection object - **Parameter Description** - `sql`: The bound SQL statement will call the `prepare` function if it is not empty - - `option` Pass in TaoStmt2Option class instance options - - **Return Value**:stmt2 object + - `option` Pass in `TaoStmt2Option` class instance + - **Return Value**:STMT2 object - **Exception**:Throws `ConnectionError` on failure - `def prepare(self, sql)` - **Interface Description**:Bind a precompiled SQL statement @@ -449,12 +449,12 @@ TaosResult object can be iterated over to retrieve queried data. - **Parameter Description**: - `tbnames`:Bind table name array, data type is list - `tags`: Bind tag column value array, data type is list - - `tags`: Bind a regular column value array with a data type of list + - `datas`: Bind data column value array, data type of list - **Exception**:Throws `StatementError` on failure - `def bind_param_with_tables(self, tables)` - - **Interface Description**:Bind data in an independent table format. Independent tables are organized by table units, with table names, TAG values, and regular column numerical attributes in each table + - **Interface Description**:Bind data in an independent table format. Independent tables are organized by table units, with table name, TAG value, and data column attributes in table object - **Parameter Description**: - - `tables`: `BindTable` Independent Table Object Array + - `tables`: `BindTable` Independent table object array - **Exception**:Throws `StatementError` on failure - `def execute(self) -> int:` - **Interface Description**:Execute to write all bound data From 6bcbf6cc37a0243e28a868d0dd5b92d2d0e17a92 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 20:22:29 +0800 Subject: [PATCH 11/12] fix: taospy version update to 2.7.21 --- docs/en/14-reference/05-connector/30-python.md | 2 +- docs/zh/14-reference/05-connector/30-python.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/14-reference/05-connector/30-python.md b/docs/en/14-reference/05-connector/30-python.md index 7cf5858c2f..19247e5364 100644 --- a/docs/en/14-reference/05-connector/30-python.md +++ b/docs/en/14-reference/05-connector/30-python.md @@ -56,7 +56,7 @@ Python Connector historical versions (it is recommended to use the latest versio |Python Connector Version | Major Changes | TDengine Version| | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -|2.7.20 | Native supports STMT2 writing | - | +|2.7.21 | Native supports STMT2 writing | - | |2.7.19 | Support Apache Superset connection to TDengine Cloud data source | - | |2.7.18 | Support Apache SuperSet BI Tools. | - | |2.7.16 | Add subscription configuration (session. timeout. ms, Max. roll. interval. ms). | - | diff --git a/docs/zh/14-reference/05-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx index a1fedfd92c..42ed67e927 100644 --- a/docs/zh/14-reference/05-connector/30-python.mdx +++ b/docs/zh/14-reference/05-connector/30-python.mdx @@ -52,7 +52,7 @@ Python Connector 历史版本(建议使用最新版本的 `taospy`): | Python Connector 版本 | 主要变化 | TDengine 版本 | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -| 2.7.20 | Native 支持 STMT2 写入 | - | +| 2.7.21 | Native 支持 STMT2 写入 | - | | 2.7.19 | 支持 Apache Superset 连接 TDengine Cloud 数据源 | - | | 2.7.18 | 支持 Apache Superset 产品连接本地 TDengine 数据源 | - | | 2.7.16 | 新增订阅配置 (session.timeout.ms, max.poll.interval.ms) | - | From 9bf4e232895c384582569cd91a46aefe459b4cd4 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 30 Dec 2024 20:53:06 +0800 Subject: [PATCH 12/12] fix: set latest taospy version --- tests/parallel_test/cases.task | 20 ++++++++++---------- tests/parallel_test/run_case.sh | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 9047b0f3af..a3e87a5334 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -6,6 +6,16 @@ ,,n,unit-test,bash test.sh +#docs-examples test +,,n,docs-examples-test,bash c.sh +,,n,docs-examples-test,bash python.sh +,,n,docs-examples-test,bash node.sh +,,n,docs-examples-test,bash csharp.sh +,,n,docs-examples-test,bash jdbc.sh +,,n,docs-examples-test,bash rust.sh +,,n,docs-examples-test,bash go.sh +,,n,docs-examples-test,bash test_R.sh + # # army-test # @@ -1661,13 +1671,3 @@ ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/sml_json_alltypes.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py -R ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/telnet_tcp.py -R - -#docs-examples test -,,n,docs-examples-test,bash c.sh -,,n,docs-examples-test,bash python.sh -,,n,docs-examples-test,bash node.sh -,,n,docs-examples-test,bash csharp.sh -,,n,docs-examples-test,bash jdbc.sh -,,n,docs-examples-test,bash rust.sh -,,n,docs-examples-test,bash go.sh -,,n,docs-examples-test,bash test_R.sh diff --git a/tests/parallel_test/run_case.sh b/tests/parallel_test/run_case.sh index a78d0aa4a4..5dc1cef673 100755 --- a/tests/parallel_test/run_case.sh +++ b/tests/parallel_test/run_case.sh @@ -77,7 +77,7 @@ md5sum /usr/lib/libtaos.so.1 md5sum /home/TDinternal/debug/build/lib/libtaos.so #get python connector and update: taospy 2.7.16 taos-ws-py 0.3.5 -pip3 install taospy==2.7.16 +pip3 install taospy==2.7.21 pip3 install taos-ws-py==0.3.5 $TIMEOUT_CMD $cmd RET=$?