From fd2477ff1025f8822dd7a498d1e72bf51c2cbdf5 Mon Sep 17 00:00:00 2001 From: slguan Date: Tue, 30 Jul 2019 15:15:26 +0800 Subject: [PATCH] Fix the issue #222, add win64 python connector --- src/connector/python/windows/python2/LICENSE | 12 + .../python/windows/python2/README.md | 1 + .../python2/dist/taos-1.4.11-py3-none-any.whl | Bin 0 -> 4515 bytes .../windows/python2/dist/taos-1.4.11.tar.gz | Bin 0 -> 3966 bytes src/connector/python/windows/python2/setup.py | 20 + .../windows/python2/taos.egg-info/SOURCES.txt | 8 + .../taos.egg-info/dependency_links.txt | 1 + .../python2/taos.egg-info/top_level.txt | 1 + .../python/windows/python2/taos/__init__.py | 4 + .../python/windows/python2/taos/pytdengine.py | 391 ++++++++++++++++++ src/connector/python/windows/python3/LICENSE | 12 + .../python/windows/python3/README.md | 1 + .../python3/dist/taos-1.4.15-py3-none-any.whl | Bin 0 -> 8986 bytes .../windows/python3/dist/taos-1.4.15.tar.gz | Bin 0 -> 6992 bytes src/connector/python/windows/python3/setup.py | 20 + .../windows/python3/taos.egg-info/SOURCES.txt | 13 + .../taos.egg-info/dependency_links.txt | 1 + .../python3/taos.egg-info/top_level.txt | 1 + .../python/windows/python3/taos/__init__.py | 24 ++ .../python/windows/python3/taos/cinterface.py | 370 +++++++++++++++++ .../python/windows/python3/taos/connection.py | 81 ++++ .../python/windows/python3/taos/constants.py | 33 ++ .../python/windows/python3/taos/cursor.py | 178 ++++++++ .../python/windows/python3/taos/dbapi.py | 38 ++ .../python/windows/python3/taos/error.py | 57 +++ 25 files changed, 1267 insertions(+) create mode 100644 src/connector/python/windows/python2/LICENSE create mode 100644 src/connector/python/windows/python2/README.md create mode 100644 src/connector/python/windows/python2/dist/taos-1.4.11-py3-none-any.whl create mode 100644 src/connector/python/windows/python2/dist/taos-1.4.11.tar.gz create mode 100644 src/connector/python/windows/python2/setup.py create mode 100644 src/connector/python/windows/python2/taos.egg-info/SOURCES.txt create mode 100644 src/connector/python/windows/python2/taos.egg-info/dependency_links.txt create mode 100644 src/connector/python/windows/python2/taos.egg-info/top_level.txt create mode 100644 src/connector/python/windows/python2/taos/__init__.py create mode 100644 src/connector/python/windows/python2/taos/pytdengine.py create mode 100644 src/connector/python/windows/python3/LICENSE create mode 100644 src/connector/python/windows/python3/README.md create mode 100644 src/connector/python/windows/python3/dist/taos-1.4.15-py3-none-any.whl create mode 100644 src/connector/python/windows/python3/dist/taos-1.4.15.tar.gz create mode 100644 src/connector/python/windows/python3/setup.py create mode 100644 src/connector/python/windows/python3/taos.egg-info/SOURCES.txt create mode 100644 src/connector/python/windows/python3/taos.egg-info/dependency_links.txt create mode 100644 src/connector/python/windows/python3/taos.egg-info/top_level.txt create mode 100644 src/connector/python/windows/python3/taos/__init__.py create mode 100644 src/connector/python/windows/python3/taos/cinterface.py create mode 100644 src/connector/python/windows/python3/taos/connection.py create mode 100644 src/connector/python/windows/python3/taos/constants.py create mode 100644 src/connector/python/windows/python3/taos/cursor.py create mode 100644 src/connector/python/windows/python3/taos/dbapi.py create mode 100644 src/connector/python/windows/python3/taos/error.py diff --git a/src/connector/python/windows/python2/LICENSE b/src/connector/python/windows/python2/LICENSE new file mode 100644 index 0000000000..2d032e65d8 --- /dev/null +++ b/src/connector/python/windows/python2/LICENSE @@ -0,0 +1,12 @@ + Copyright (c) 2019 TAOS Data, Inc. + +This program is free software: you can use, redistribute, and/or modify +it under the terms of the GNU Affero General Public License, version 3 +or later ("AGPL"), as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/src/connector/python/windows/python2/README.md b/src/connector/python/windows/python2/README.md new file mode 100644 index 0000000000..353bc84752 --- /dev/null +++ b/src/connector/python/windows/python2/README.md @@ -0,0 +1 @@ +# TDengine python client interface diff --git a/src/connector/python/windows/python2/dist/taos-1.4.11-py3-none-any.whl b/src/connector/python/windows/python2/dist/taos-1.4.11-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..efe772206da6af5de1680507e89e070ef7aaf770 GIT binary patch literal 4515 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 literal 0 HcmV?d00001 diff --git a/src/connector/python/windows/python2/dist/taos-1.4.11.tar.gz b/src/connector/python/windows/python2/dist/taos-1.4.11.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..984228e3bb00bca2a0a735a440b4feb8cc306b79 GIT binary patch literal 3966 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 Yr72BmN>iHBls|U)FH_;G@c?)L0Mj7M%m4rY literal 0 HcmV?d00001 diff --git a/src/connector/python/windows/python2/setup.py b/src/connector/python/windows/python2/setup.py new file mode 100644 index 0000000000..d31cd37525 --- /dev/null +++ b/src/connector/python/windows/python2/setup.py @@ -0,0 +1,20 @@ +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="taos", + version="1.4.11", + author="Taosdata Inc.", + author_email="support@taosdata.com", + description="TDengine python client package", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/pypa/sampleproject", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 2", + "Operating System :: Windows", + ], +) diff --git a/src/connector/python/windows/python2/taos.egg-info/SOURCES.txt b/src/connector/python/windows/python2/taos.egg-info/SOURCES.txt new file mode 100644 index 0000000000..52b5647c6a --- /dev/null +++ b/src/connector/python/windows/python2/taos.egg-info/SOURCES.txt @@ -0,0 +1,8 @@ +README.md +setup.py +taos/__init__.py +taos/pytdengine.py +taos.egg-info/PKG-INFO +taos.egg-info/SOURCES.txt +taos.egg-info/dependency_links.txt +taos.egg-info/top_level.txt \ No newline at end of file diff --git a/src/connector/python/windows/python2/taos.egg-info/dependency_links.txt b/src/connector/python/windows/python2/taos.egg-info/dependency_links.txt new file mode 100644 index 0000000000..d3f5a12faa --- /dev/null +++ b/src/connector/python/windows/python2/taos.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/connector/python/windows/python2/taos.egg-info/top_level.txt b/src/connector/python/windows/python2/taos.egg-info/top_level.txt new file mode 100644 index 0000000000..bb442feabd --- /dev/null +++ b/src/connector/python/windows/python2/taos.egg-info/top_level.txt @@ -0,0 +1 @@ +taos diff --git a/src/connector/python/windows/python2/taos/__init__.py b/src/connector/python/windows/python2/taos/__init__.py new file mode 100644 index 0000000000..508a35f1dd --- /dev/null +++ b/src/connector/python/windows/python2/taos/__init__.py @@ -0,0 +1,4 @@ +from .pytdengine import TaosCursor +from .pytdengine import TaosConnection +from .pytdengine import connector +# from .pytdengine import TaosClass diff --git a/src/connector/python/windows/python2/taos/pytdengine.py b/src/connector/python/windows/python2/taos/pytdengine.py new file mode 100644 index 0000000000..1a73558b2d --- /dev/null +++ b/src/connector/python/windows/python2/taos/pytdengine.py @@ -0,0 +1,391 @@ +import ctypes +import numpy as np +import pandas as pd + +class TaosField(ctypes.Structure): + _fields_ = [('name' , ctypes.c_char * 64), + ('bytes' , ctypes.c_short), + ('type' , ctypes.c_char)] + +class TaosClass(object): + ''' + ''' + TSDB_DATA_TYPE_NULL = 0 + TSDB_DATA_TYPE_BOOL = 1 + TSDB_DATA_TYPE_TINYINT = 2 + TSDB_DATA_TYPE_SMALLINT = 3 + TSDB_DATA_TYPE_INT = 4 + TSDB_DATA_TYPE_BIGINT = 5 + TSDB_DATA_TYPE_FLOAT = 6 + TSDB_DATA_TYPE_DOUBLE = 7 + TSDB_DATA_TYPE_BINARY = 8 + TSDB_DATA_TYPE_TIMESTAMP = 9 + TSDB_DATA_TYPE_NCHAR = 10 + + libtaos = ctypes.windll.LoadLibrary('taos') + + libtaos.taos_fetch_fields.restype = ctypes.POINTER(TaosField) + libtaos.taos_init.restype = None + libtaos.taos_connect.restype = ctypes.c_void_p + libtaos.taos_use_result.restype = ctypes.c_void_p + libtaos.taos_fetch_row.restype = ctypes.POINTER(ctypes.c_void_p) + libtaos.taos_errstr.restype = ctypes.c_char_p + + def __init__(self, host=None, user='root', password='taosdata', db=None, port=0, config=None): + ''' + Function to initialize the class + @host : str, hostname to connect + @user : str, username to connect to server + @password : str, password to connect to server + @db : str, default db to use when log in + @config : str, config directory + + @rtype : None + ''' + self.host = ctypes.c_char_p(host) + self.user = ctypes.c_char_p(user) + self.password = ctypes.c_char_p(password) + self.db = ctypes.c_char_p(db) + self.config = ctypes.c_char_p(config) + self.port = ctypes.c_int(port) + + if config != None: + TaosClass.libtaos.taos_options(2, self.config) + + TaosClass.libtaos.taos_init() + + def connect(self): + ''' + Function to connect to server + + @rtype: c_void_p, TDengine handle + ''' + connection = ctypes.c_void_p(TaosClass.libtaos.taos_connect(self.host, self.user, self.password, self.db, self.port)) + + if connection.value == None: + print('connect to TDengine failed') + # sys.exit(1) + else: + print('connect to TDengine success') + + return connection + + @staticmethod + def close(connection): + ''' + Close the TDengine handle + ''' + TaosClass.libtaos.taos_close(connection) + print('connection is closed') + + @staticmethod + def fetchBlock(result, fields): + pblock = ctypes.c_void_p(0) + num_of_rows = TaosClass.libtaos.taos_fetch_block(result, ctypes.byref(pblock)) + + if num_of_rows == 0: + return None, 0 + + blocks = [None] * len(fields) + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + + if (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_BOOL): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_TINYINT): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_SMALLINT): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_INT): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_BIGINT): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_FLOAT): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_DOUBLE): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_TIMESTAMP): + if num_of_rows > 0: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] + else: + blocks[i] = ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] + # TODO : Make it more efficient + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_BINARY): + if num_of_rows > 0: + blocks[i] = [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * fields[i]['bytes'])))[:abs(num_of_rows)][::-1]] + else: + blocks[i] = [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * fields[i]['bytes'])))[:abs(num_of_rows)]] + elif (fields[i]['type'] == TaosClass.TSDB_DATA_TYPE_NCHAR): + if num_of_rows > 0: + blocks[i] = [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (fields[i]['bytes']/4))))[:abs(num_of_rows)][::-1]] + else: + blocks[i] = [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (fields[i]['bytes']/4))))[:abs(num_of_rows)]] + + return blocks, abs(num_of_rows) + + @staticmethod + def query(connection, sql): + ''' + Run SQL + + @sql: str, sql string to run + + @rtype: 0 on success and -1 on failure + ''' + return TaosClass.libtaos.taos_query(connection, ctypes.c_char_p(sql)) + + @staticmethod + def useResult(connection): + ''' + Use result after calling self.query + ''' + result = ctypes.c_void_p(TaosClass.libtaos.taos_use_result(connection)) + fields = [] + pfields = TaosClass.fetchFields(result) + for i in range(TaosClass.fieldsCount(connection)): + fields.append({'name': pfields[i].name, 'bytes':pfields[i].bytes, 'type': ord(pfields[i].type)}) + + return result, fields + + @staticmethod + def freeResult(result): + TaosClass.libtaos.taos_free_result(result) + result.value = None + + @staticmethod + def fieldsCount(connection): + return TaosClass.libtaos.taos_field_count(connection) + + @staticmethod + def fetchFields(result): + return TaosClass.libtaos.taos_fetch_fields(result) + + @staticmethod + def fetchRow(result, fields): + l = [] + row = TaosClass.libtaos.taos_fetch_row(result) + if not row: return None + + for i in range(len(fields)): + l.append(TaosClass.getDataValue(row[i], fields[i]['type'], fields[i]['bytes'])) + + return tuple(l) + + @staticmethod + def getDataValue(data, dtype, byte): + ''' + ''' + if not data: return None + + if (dtype == TaosClass.TSDB_DATA_TYPE_BOOL): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_TINYINT): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_SMALLINT): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_INT): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_BIGINT): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_FLOAT): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_DOUBLE): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_BINARY): + return (ctypes.cast(data, ctypes.POINTER(ctypes.c_char))[0:byte]).rstrip('\x00') + elif (dtype == TaosClass.TSDB_DATA_TYPE_TIMESTAMP): + return ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[0] + elif (dtype == TaosClass.TSDB_DATA_TYPE_NCHAR): + return (ctypes.cast(data, ctypes.c_char_p).value).rstrip('\x00') + + @staticmethod + def affectedRows(connection): + return TaosClass.libtaos.taos_affected_rows(connection) + + @staticmethod + def errno(connection): + return TaosClass.libtaos.taos_errno(connection) + + @staticmethod + def errStr(connection): + return TaosClass.libtaos.taos_errstr(connection) + + +class TaosCursor(): + ''' + Object in TDengine python client which the same as a connection to TDengine server. + ''' + def __init__(self, connection): + self.connection = connection + # self.buffered = buffered; + self.result = ctypes.c_void_p(0) + self.fields = [] + + self.buffer = None + self.iter = 0 + + # def __iter__(self): + # self.iter = 0 + # return self + # + # def next(self): + # if self.buffered: + # if self.iter >= len(self.buffer[0]): + # raise StopIteration + # else: + # return tuple(row[self.iter] for row in self.buffer) + # else: + # if self.iter >= len(self.buffer[0]): + # self.buffer, num_of_fields = TaosClass.fetchBlock(self.result, self.fields) + # if num_of_fields == 0: + # raise StopIteration + # else: + # self.iter = 1 + # return tuple(row[self.iter-1] for row in self.buffer) + # else: + # self.iter += 1 + # l = tuple(row[self.iter-1] for row in self.buffer) + + def fetchall(self, format=list): + ''' + Fetch data after run commands like 'show/select/describe' TaosCursor.execute. + + @format: list -> return a list of list, default and the fastest + dict -> return a dictionary with the name of each column as the key + numpy.array->return an array + pandas.DataFrame->return data as the form of pandas.DataFram + + @rtype: depends on the format + ''' + if TaosClass.fieldsCount(self.connection) != 0: + # select or show command + self.result, self.fields = TaosClass.useResult(self.connection) + self.iter = 0 + # if self.buffered: + self.buffer = [[] for i in range(len(self.fields))] + while True: + block, num_of_fields = TaosClass.fetchBlock(self.result, self.fields) + if num_of_fields == 0: break; + for i in range(len(self.fields)): + self.buffer[i].extend(block[i]) + self.freeResult() + + if format == list: + return self.buffer + elif format == dict: + return dict(zip(self.columns(), self.buffer)) + elif format == np.array: + return [np.asarray(self.buffer[i]) for i in range(len(self.columns()))] + elif format == pd.DataFrame: + l = [np.asarray(self.buffer[i]) for i in range(len(self.columns()))] + return pd.DataFrame.from_records(dict(zip(self.columns(), l))) + else: + return None + else: + return None + + def execute(self, sql): + ''' + run sql command + + @rtype: int, 0 for succeed and others for failure + ''' + # release previous result + self.freeResult() + + res = TaosClass.query(self.connection, sql) + if res != 0: return res + else: return 0 + + def freeResult(self): + if self.result.value != None: + TaosClass.freeResult(self.result) + + def columns(self): + ''' + return the column names when query using TaosCursor.execute. + + @rtype: list of str + ''' + return [self.fields[col]['name'] for col in range(len(self.fields))] + + def error(self): + ''' + return error string of if execute is wrong + + @rtype: str + ''' + return TaosClass.errStr(self.connection) + + def close(self): + self.freeResult() + TaosClass.close(self.connection) + self.connection.value = None + +class TaosConnection: + ''' + TDengine connection object + ''' + def __init__(self, host=None, user='root', passwd='taosdata', database=None, port=0, config=None): + ''' + @host : IP address of the TDengine server host + @user : user name to log in + @password : password used to log in + @database : database to use when logging in + @port : port number + @config : configuration directory + ''' + self.taos = TaosClass(host, user, passwd, database, port, config) + self.cursors = [] + + def cursor(self): + ''' + Generate a TaosCursor object, each object is the same as a connection to TDengine + + @rtype: TaosCursor + ''' + self.cursors.append(TaosCursor(self.taos.connect())) + return self.cursors[-1] + + def close(self): + ''' + Close the connection + ''' + for cur in self.cursors: + cur.close() + +def connector(host=None, user='root', passwd='taosdata', database=None, port=0, config=None): + ''' + Function to create a TaosConnection object + + @host : str, ipaddr of the TDengine server + @user : str, username used to login + @passwd : str, password used to login + @database : str, database to use when connect, if database is not None and not exists on server, it will result in a connection failure + @port : port number + @config : configuration directory + + @rtype : TaosConnection object + ''' + return TaosConnection(host, user, passwd, database, port, config) diff --git a/src/connector/python/windows/python3/LICENSE b/src/connector/python/windows/python3/LICENSE new file mode 100644 index 0000000000..2d032e65d8 --- /dev/null +++ b/src/connector/python/windows/python3/LICENSE @@ -0,0 +1,12 @@ + Copyright (c) 2019 TAOS Data, Inc. + +This program is free software: you can use, redistribute, and/or modify +it under the terms of the GNU Affero General Public License, version 3 +or later ("AGPL"), as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/src/connector/python/windows/python3/README.md b/src/connector/python/windows/python3/README.md new file mode 100644 index 0000000000..70db6bba13 --- /dev/null +++ b/src/connector/python/windows/python3/README.md @@ -0,0 +1 @@ +# TDengine python client interface \ No newline at end of file diff --git a/src/connector/python/windows/python3/dist/taos-1.4.15-py3-none-any.whl b/src/connector/python/windows/python3/dist/taos-1.4.15-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..3c4c8a34a6afd0121fe6c560f0d9499d8dbf5a9c GIT binary patch literal 8986 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 literal 0 HcmV?d00001 diff --git a/src/connector/python/windows/python3/dist/taos-1.4.15.tar.gz b/src/connector/python/windows/python3/dist/taos-1.4.15.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6294828f6db7768f6b307b36f1cc3d43b4da0749 GIT binary patch literal 6992 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 literal 0 HcmV?d00001 diff --git a/src/connector/python/windows/python3/setup.py b/src/connector/python/windows/python3/setup.py new file mode 100644 index 0000000000..7cac04b723 --- /dev/null +++ b/src/connector/python/windows/python3/setup.py @@ -0,0 +1,20 @@ +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="taos", + version="1.4.15", + author="Taosdata Inc.", + author_email="support@taosdata.com", + description="TDengine python client package", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/pypa/sampleproject", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "Operating System :: Windows", + ], +) diff --git a/src/connector/python/windows/python3/taos.egg-info/SOURCES.txt b/src/connector/python/windows/python3/taos.egg-info/SOURCES.txt new file mode 100644 index 0000000000..0dbf14e5b6 --- /dev/null +++ b/src/connector/python/windows/python3/taos.egg-info/SOURCES.txt @@ -0,0 +1,13 @@ +README.md +setup.py +taos/__init__.py +taos/cinterface.py +taos/connection.py +taos/constants.py +taos/cursor.py +taos/dbapi.py +taos/error.py +taos.egg-info/PKG-INFO +taos.egg-info/SOURCES.txt +taos.egg-info/dependency_links.txt +taos.egg-info/top_level.txt \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos.egg-info/dependency_links.txt b/src/connector/python/windows/python3/taos.egg-info/dependency_links.txt new file mode 100644 index 0000000000..d3f5a12faa --- /dev/null +++ b/src/connector/python/windows/python3/taos.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/connector/python/windows/python3/taos.egg-info/top_level.txt b/src/connector/python/windows/python3/taos.egg-info/top_level.txt new file mode 100644 index 0000000000..bb442feabd --- /dev/null +++ b/src/connector/python/windows/python3/taos.egg-info/top_level.txt @@ -0,0 +1 @@ +taos diff --git a/src/connector/python/windows/python3/taos/__init__.py b/src/connector/python/windows/python3/taos/__init__.py new file mode 100644 index 0000000000..2fec471a1a --- /dev/null +++ b/src/connector/python/windows/python3/taos/__init__.py @@ -0,0 +1,24 @@ + +from .connection import TDengineConnection +from .cursor import TDengineCursor + +# Globals +apilevel = '2.0' +threadsafety = 0 +paramstyle = 'pyformat' + +__all__ = ['connection', 'cursor'] + +def connect(*args, **kwargs): + """ Function to return a TDengine connector object + + Current supporting keyword parameters: + @dsn: Data source name as string + @user: Username as string(optional) + @password: Password as string(optional) + @host: Hostname(optional) + @database: Database name(optional) + + @rtype: TDengineConnector + """ + return TDengineConnection(*args, **kwargs) \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos/cinterface.py b/src/connector/python/windows/python3/taos/cinterface.py new file mode 100644 index 0000000000..aa43e10492 --- /dev/null +++ b/src/connector/python/windows/python3/taos/cinterface.py @@ -0,0 +1,370 @@ +import ctypes +from .constants import FieldType +from .error import * +import math +import datetime + +def _convert_millisecond_to_datetime(milli): + return datetime.datetime.fromtimestamp(milli/1000.0) + +def _convert_microsecond_to_datetime(micro): + return datetime.datetime.fromtimestamp(micro/1000000.0) + +def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C bool row to python row + """ + _timestamp_converter = _convert_millisecond_to_datetime + if micro: + _timestamp_converter = _convert_microsecond_to_datetime + + if num_of_rows > 0: + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1])) + else: + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)])) + +def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C bool row to python row + """ + if num_of_rows > 0: + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + else: + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] + +def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C tinyint row to python row + """ + if num_of_rows > 0: + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + else: + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] + +def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C smallint row to python row + """ + if num_of_rows > 0: + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + else: + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] + +def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C int row to python row + """ + if num_of_rows > 0: + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + else: + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] + +def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C bigint row to python row + """ + if num_of_rows > 0: + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] ] + else: + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] ] + +def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C float row to python row + """ + if num_of_rows > 0: + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + else: + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] + +def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C double row to python row + """ + if num_of_rows > 0: + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + else: + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] + +def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C binary row to python row + """ + if num_of_rows > 0: + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + else: + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] + +def _crow_nchar_to_python(data, num_of_rows, nbytes=None, micro=False): + """Function to convert C nchar row to python row + """ + assert(nbytes is not None) + + res = [] + + for i in range(abs(num_of_rows)): + try: + if num_of_rows >= 0: + res.append( (ctypes.cast(data+nbytes*(abs(num_of_rows - i -1)), ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[0].value ) + else: + res.append( (ctypes.cast(data+nbytes*i, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[0].value ) + except ValueError: + res.append(None) + + return res + # if num_of_rows > 0: + # for i in range(abs(num_of_rows)): + # try: + # res.append( (ctypes.cast(data+nbytes*i, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[0].value ) + # except ValueError: + # res.append(None) + # return res + # # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)][::-1]] + # else: + # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)]] + +_CONVERT_FUNC = { + FieldType.C_BOOL: _crow_bool_to_python, + FieldType.C_TINYINT : _crow_tinyint_to_python, + FieldType.C_SMALLINT : _crow_smallint_to_python, + FieldType.C_INT : _crow_int_to_python, + FieldType.C_BIGINT : _crow_bigint_to_python, + FieldType.C_FLOAT : _crow_float_to_python, + FieldType.C_DOUBLE : _crow_double_to_python, + FieldType.C_BINARY: _crow_binary_to_python, + FieldType.C_TIMESTAMP : _crow_timestamp_to_python, + FieldType.C_NCHAR : _crow_nchar_to_python +} + +# Corresponding TAOS_FIELD structure in C +class TaosField(ctypes.Structure): + _fields_ = [('name', ctypes.c_char * 64), + ('bytes', ctypes.c_short), + ('type', ctypes.c_char)] + +# C interface class +class CTaosInterface(object): + + libtaos = ctypes.windll.LoadLibrary('taos') + + libtaos.taos_fetch_fields.restype = ctypes.POINTER(TaosField) + libtaos.taos_init.restype = None + libtaos.taos_connect.restype = ctypes.c_void_p + libtaos.taos_use_result.restype = ctypes.c_void_p + libtaos.taos_fetch_row.restype = ctypes.POINTER(ctypes.c_void_p) + libtaos.taos_errstr.restype = ctypes.c_char_p + + def __init__(self, config=None): + ''' + Function to initialize the class + @host : str, hostname to connect + @user : str, username to connect to server + @password : str, password to connect to server + @db : str, default db to use when log in + @config : str, config directory + + @rtype : None + ''' + if config is None: + self._config = ctypes.c_char_p(None) + else: + try: + self._config = ctypes.c_char_p(config.encode('utf-8')) + except AttributeError: + raise AttributeError("config is expected as a str") + + if config != None: + CTaosInterface.libtaos.taos_options(3, self._config) + + CTaosInterface.libtaos.taos_init() + + @property + def config(self): + """ Get current config + """ + return self._config + + def connect(self, host=None, user="root", password="taosdata", db=None, port=0): + ''' + Function to connect to server + + @rtype: c_void_p, TDengine handle + ''' + # host + try: + _host = ctypes.c_char_p(host.encode( + "utf-8")) if host != None else ctypes.c_char_p(None) + except AttributeError: + raise AttributeError("host is expected as a str") + + # user + try: + _user = ctypes.c_char_p(user.encode("utf-8")) + except AttributeError: + raise AttributeError("user is expected as a str") + + # password + try: + _password = ctypes.c_char_p(password.encode("utf-8")) + except AttributeError: + raise AttributeError("password is expected as a str") + + # db + try: + _db = ctypes.c_char_p( + db.encode("utf-8")) if db != None else ctypes.c_char_p(None) + except AttributeError: + raise AttributeError("db is expected as a str") + + # port + try: + _port = ctypes.c_int(port) + except TypeError: + raise TypeError("port is expected as an int") + + connection = ctypes.c_void_p(CTaosInterface.libtaos.taos_connect( + _host, _user, _password, _db, _port)) + + if connection.value == None: + print('connect to TDengine failed') + # sys.exit(1) + else: + print('connect to TDengine success') + + return connection + + @staticmethod + def close(connection): + '''Close the TDengine handle + ''' + CTaosInterface.libtaos.taos_close(connection) + print('connection is closed') + + @staticmethod + def query(connection, sql): + '''Run SQL + + @sql: str, sql string to run + + @rtype: 0 on success and -1 on failure + ''' + try: + return CTaosInterface.libtaos.taos_query(connection, ctypes.c_char_p(sql.encode('utf-8'))) + except AttributeError: + raise AttributeError("sql is expected as a string") + finally: + CTaosInterface.libtaos.close(connection) + + @staticmethod + def affectedRows(connection): + """The affected rows after runing query + """ + return CTaosInterface.libtaos.taos_affected_rows(connection) + + @staticmethod + def useResult(connection): + '''Use result after calling self.query + ''' + result = ctypes.c_void_p(CTaosInterface.libtaos.taos_use_result(connection)) + fields = [] + pfields = CTaosInterface.fetchFields(result) + for i in range(CTaosInterface.fieldsCount(connection)): + fields.append({'name': pfields[i].name.decode('utf-8'), + 'bytes': pfields[i].bytes, + 'type': ord(pfields[i].type)}) + + return result, fields + + @staticmethod + def fetchBlock(result, fields): + pblock = ctypes.c_void_p(0) + num_of_rows = CTaosInterface.libtaos.taos_fetch_block( + result, ctypes.byref(pblock)) + + if num_of_rows == 0: + return None, 0 + + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fields[i]['bytes'], isMicro) + + return blocks, abs(num_of_rows) + + @staticmethod + def freeResult(result): + CTaosInterface.libtaos.taos_free_result(result) + result.value = None + + @staticmethod + def fieldsCount(connection): + return CTaosInterface.libtaos.taos_field_count(connection) + + @staticmethod + def fetchFields(result): + return CTaosInterface.libtaos.taos_fetch_fields(result) + + # @staticmethod + # def fetchRow(result, fields): + # l = [] + # row = CTaosInterface.libtaos.taos_fetch_row(result) + # if not row: + # return None + + # for i in range(len(fields)): + # l.append(CTaosInterface.getDataValue( + # row[i], fields[i]['type'], fields[i]['bytes'])) + + # return tuple(l) + + # @staticmethod + # def getDataValue(data, dtype, byte): + # ''' + # ''' + # if not data: + # return None + + # if (dtype == CTaosInterface.TSDB_DATA_TYPE_BOOL): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_TINYINT): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_SMALLINT): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_INT): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_BIGINT): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_FLOAT): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_DOUBLE): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_BINARY): + # return (ctypes.cast(data, ctypes.POINTER(ctypes.c_char))[0:byte]).rstrip('\x00') + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_TIMESTAMP): + # return ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[0] + # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_NCHAR): + # return (ctypes.cast(data, ctypes.c_char_p).value).rstrip('\x00') + + @staticmethod + def errno(connection): + """Return the error number. + """ + return CTaosInterface.libtaos.taos_errno(connection) + + @staticmethod + def errStr(connection): + """Return the error styring + """ + return CTaosInterface.libtaos.taos_errstr(connection).decode('utf-8') + + +if __name__ == '__main__': + cinter = CTaosInterface() + conn = cinter.connect() + + print('Query return value: {}'.format(cinter.query(conn, 'show databases'))) + print('Affected rows: {}'.format(cinter.affectedRows(conn))) + + result, des = CTaosInterface.useResult(conn) + + data, num_of_rows = CTaosInterface.fetchBlock(result, des) + + print(data) + + cinter.close(conn) \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos/connection.py b/src/connector/python/windows/python3/taos/connection.py new file mode 100644 index 0000000000..a88e25a6db --- /dev/null +++ b/src/connector/python/windows/python3/taos/connection.py @@ -0,0 +1,81 @@ +# from .cursor import TDengineCursor +from .cursor import TDengineCursor +from .cinterface import CTaosInterface + +class TDengineConnection(object): + """ TDengine connection object + """ + def __init__(self, *args, **kwargs): + self._conn = None + self._host = None + self._user = "root" + self._password = "taosdata" + self._database = None + self._port = 0 + self._config = None + self._chandle = None + + if len(kwargs) > 0: + self.config(**kwargs) + + def config(self, **kwargs): + # host + if 'host' in kwargs: + self._host = kwargs['host'] + + # user + if 'user' in kwargs: + self._user = kwargs['user'] + + # password + if 'password' in kwargs: + self._password = kwargs['password'] + + # database + if 'database' in kwargs: + self._database = kwargs['database'] + + # port + if 'port' in kwargs: + self._port = kwargs['port'] + + # config + if 'config' in kwargs: + self._config = kwargs['config'] + + self._chandle = CTaosInterface(self._config) + self._conn = self._chandle.connect(self._host, self._user, self._password, self._database, self._port) + + def close(self): + """Close current connection. + """ + return CTaosInterface.close(self._conn) + + def cursor(self): + """Return a new Cursor object using the connection. + """ + return TDengineCursor(self) + + def commit(self): + """Commit any pending transaction to the database. + + Since TDengine do not support transactions, the implement is void functionality. + """ + pass + + def rollback(self): + """Void functionality + """ + pass + + def clear_result_set(self): + """Clear unused result set on this connection. + """ + result = self._chandle.useResult(self._conn)[0] + if result: + self._chandle.freeResult(result) + +if __name__ == "__main__": + conn = TDengineConnection(host='192.168.1.107') + conn.close() + print("Hello world") \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos/constants.py b/src/connector/python/windows/python3/taos/constants.py new file mode 100644 index 0000000000..def2bbc0a8 --- /dev/null +++ b/src/connector/python/windows/python3/taos/constants.py @@ -0,0 +1,33 @@ +"""Constants in TDengine python +""" + +from .dbapi import * + +class FieldType(object): + """TDengine Field Types + """ + # type_code + C_NULL = 0 + C_BOOL = 1 + C_TINYINT = 2 + C_SMALLINT = 3 + C_INT = 4 + C_BIGINT = 5 + C_FLOAT = 6 + C_DOUBLE = 7 + C_BINARY = 8 + C_TIMESTAMP = 9 + C_NCHAR = 10 + # NULL value definition + # NOTE: These values should change according to C definition in tsdb.h + C_BOOL_NULL = 0x02 + C_TINYINT_NULL = -128 + C_SMALLINT_NULL = -32768 + C_INT_NULL = -2147483648 + C_BIGINT_NULL = -9223372036854775808 + C_FLOAT_NULL = float('nan') + C_DOUBLE_NULL = float('nan') + C_BINARY_NULL = bytearray([int('0xff', 16)]) + # Timestamp precision definition + C_TIMESTAMP_MILLI = 0 + C_TIMESTAMP_MICRO = 1 diff --git a/src/connector/python/windows/python3/taos/cursor.py b/src/connector/python/windows/python3/taos/cursor.py new file mode 100644 index 0000000000..ac70c37958 --- /dev/null +++ b/src/connector/python/windows/python3/taos/cursor.py @@ -0,0 +1,178 @@ +from .cinterface import CTaosInterface +from .error import * + +class TDengineCursor(object): + """Database cursor which is used to manage the context of a fetch operation. + + Attributes: + .description: Read-only attribute consists of 7-item sequences: + + > name (mondatory) + > type_code (mondatory) + > display_size + > internal_size + > precision + > scale + > null_ok + + This attribute will be None for operations that do not return rows or + if the cursor has not had an operation invoked via the .execute*() method yet. + + .rowcount:This read-only attribute specifies the number of rows that the last + .execute*() produced (for DQL statements like SELECT) or affected + """ + + def __init__(self, connection=None): + self._description = None + self._rowcount = -1 + self._connection = None + self._result = None + self._fields = None + self._block = None + self._block_rows = -1 + self._block_iter = 0 + + if connection is not None: + self._connection = connection + + def __iter__(self): + return self + + def __next__(self): + if self._result is None or self._fields is None: + raise OperationalError("Invalid use of fetch iterator") + + if self._block_rows <= self._block_iter: + block, self._block_rows = CTaosInterface.fetchBlock(self._result, self._fields) + if self._block_rows == 0: + raise StopIteration + self._block = list(map(tuple, zip(*block))) + self._block_iter = 0 + + data = self._block[self._block_iter] + self._block_iter += 1 + + return data + + @property + def description(self): + """Return the description of the object. + """ + return self._description + + @property + def rowcount(self): + """Return the rowcount of the object + """ + return self._rowcount + + def callproc(self, procname, *args): + """Call a stored database procedure with the given name. + + Void functionality since no stored procedures. + """ + pass + + def close(self): + """Close the cursor. + """ + if self._connection is None: + return False + + self._connection.clear_result_set() + self._reset_result() + self._connection = None + + return True + + def execute(self, operation, params=None): + """Prepare and execute a database operation (query or command). + """ + if not operation: + return None + + if not self._connection: + # TODO : change the exception raised here + raise ProgrammingError("Cursor is not connected") + + self._connection.clear_result_set() + self._reset_result() + + stmt = operation + if params is not None: + pass + + res = CTaosInterface.query(self._connection._conn, stmt) + if res == 0: + if CTaosInterface.fieldsCount(self._connection._conn) == 0: + return CTaosInterface.affectedRows(self._connection._conn) + else: + self._result, self._fields = CTaosInterface.useResult(self._connection._conn) + return self._handle_result() + else: + raise ProgrammingError(CTaosInterface.errStr(self._connection._conn)) + + def executemany(self, operation, seq_of_parameters): + """Prepare a database operation (query or command) and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters. + """ + pass + + def fetchone(self): + """Fetch the next row of a query result set, returning a single sequence, or None when no more data is available. + """ + pass + + def fetchmany(self): + pass + + def fetchall(self): + """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute can affect the performance of this operation. + """ + if self._result is None or self._fields is None: + raise OperationalError("Invalid use of fetchall") + + buffer = [[] for i in range(len(self._fields))] + self._rowcount = 0 + while True: + block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields) + if num_of_fields == 0: break + self._rowcount += num_of_fields + for i in range(len(self._fields)): + buffer[i].extend(block[i]) + + self._connection.clear_result_set() + + return list(map(tuple, zip(*buffer))) + + + + def nextset(self): + """ + """ + pass + + def setinputsize(self, sizes): + pass + + def setutputsize(self, size, column=None): + pass + + def _reset_result(self): + """Reset the result to unused version. + """ + self._description = None + self._rowcount = -1 + self._result = None + self._fields = None + self._block = None + self._block_rows = -1 + self._block_iter = 0 + + def _handle_result(self): + """Handle the return result from query. + """ + self._description = [] + for ele in self._fields: + self._description.append((ele['name'], ele['type'], None, None, None, None, False)) + + return self._result \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos/dbapi.py b/src/connector/python/windows/python3/taos/dbapi.py new file mode 100644 index 0000000000..9b1cb1321c --- /dev/null +++ b/src/connector/python/windows/python3/taos/dbapi.py @@ -0,0 +1,38 @@ +"""Type Objects and Constructors. +""" + +import time +import datetime + +class DBAPITypeObject(object): + def __init__(self, *values): + self.values = values + + def __com__(self, other): + if other in self.values: + return 0 + if other < self.values: + return 1 + else: + return -1 + +Date = datetime.date +Time = datetime.time +Timestamp = datetime.datetime + +def DataFromTicks(ticks): + return Date(*time.localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + return Time(*time.localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + return Timestamp(*time.localtime(ticks)[:6]) + +Binary = bytes + +# STRING = DBAPITypeObject(*constants.FieldType.get_string_types()) +# BINARY = DBAPITypeObject(*constants.FieldType.get_binary_types()) +# NUMBER = BAPITypeObject(*constants.FieldType.get_number_types()) +# DATETIME = DBAPITypeObject(*constants.FieldType.get_timestamp_types()) +# ROWID = DBAPITypeObject() \ No newline at end of file diff --git a/src/connector/python/windows/python3/taos/error.py b/src/connector/python/windows/python3/taos/error.py new file mode 100644 index 0000000000..ccc0e61d84 --- /dev/null +++ b/src/connector/python/windows/python3/taos/error.py @@ -0,0 +1,57 @@ +"""Python exceptions +""" + +class Error(Exception): + def __init__(self, msg=None, errno=None): + self.msg = msg + self._full_msg = self.msg + self.errno = errno + + def __str__(self): + return self._full_msg + +class Warning(Exception): + """Exception raised for important warnings like data truncations while inserting. + """ + pass + +class InterfaceError(Error): + """Exception raised for errors that are related to the database interface rather than the database itself. + """ + pass + +class DatabaseError(Error): + """Exception raised for errors that are related to the database. + """ + pass + +class DataError(DatabaseError): + """Exception raised for errors that are due to problems with the processed data like division by zero, numeric value out of range. + """ + pass + +class OperationalError(DatabaseError): + """Exception raised for errors that are related to the database's operation and not necessarily under the control of the programmer + """ + pass + + +class IntegrityError(DatabaseError): + """Exception raised when the relational integrity of the database is affected. + """ + pass + +class InternalError(DatabaseError): + """Exception raised when the database encounters an internal error. + """ + pass + +class ProgrammingError(DatabaseError): + """Exception raised for programming errors. + """ + pass + +class NotSupportedError(DatabaseError): + """Exception raised in case a method or database API was used which is not supported by the database,. + """ + pass \ No newline at end of file -- GitLab