# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['aiovertica',
 'aiovertica.messages',
 'aiovertica.messages.backend_messages',
 'aiovertica.messages.frontend_messages',
 'aiovertica.mixins']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'aiovertica',
    'version': '0.0.2',
    'description': 'Small asynchronous driver for Vertica based on vertica_python',
    'long_description': '# aiovertica\nSmall asynchronous driver for Vertica based on [vertica_python](https://github.com/vertica/vertica-python/).\n\n## WARNING\n\nThis project was written "in haste" literally overnight, so it may not be stable.\nOf course, most of the mechanisms are identical to the "project", but in any case, \ntests have not yet been written to be sure of this at least to some extent.\n\nAt the moment, the project has rewritten the mechanisms responsible for working \nwith the network from a synchronous model to an asynchronous one, as well as \nin the `Connection` and` Cursor` modules, the synchronous methods have been replaced \nby asynchronous ones (where necessary), the code formatting has been slightly improved \nand type annotations have been added (but not always correct).\n\n### Foreword\nI would really like to see a ready-made library, ideally the same as `asyncpg`, \nbut unfortunately it is not there. I would like to express my deep gratitude to the team \nthat worked on the `vertica_python` for writing at least a synchronous driver - this greatly \nsimplified the work. I have tried to keep all the licenses and the list of authors from \nthe original project.\n\nI would also be glad if the guys from `vertica_python` added something similar to the \nofficial driver and we would have a simple opportunity to work with the driver in \nasynchronous mode as well.\n\nPerhaps in the future I will create a PR in the official driver (I have several \nproposals for the architecture), but at the moment it would take too long to implement \nthe "correct" embedding into the existing implementation - the code was needed "yesterday".\n\nI will be glad for any help in the development of the project. The `Issues` and` PRs` \nsections are looking forward to seeing you :).\n\n\n## Installation\n\nTo install vertica-python with pip:\n```bash\n# Latest release version\npip install aiovertica\n\n# Latest commit on master branch\npip install git+https://github.com/i8enn/aiovertica.git@master\n```\n\nTo install vertica-python from source, run the following command from the root directory:\n\n    python setup.py install\n\nSource code for vertica-python can be found at:\n\n    https://github.com/i8enn/aiovertica\n\n#### Using Kerberos authentication\n\n> #### WARNING: `Kerberos` not supported in currently version\n\nvertica-python has optional Kerberos authentication support for Unix-like systems, which requires you to install the [kerberos](https://pypi.org/project/kerberos/) package:\n\n    pip install kerberos\n\nNote that `kerberos` is a python extension module, which means you need to install `python-dev`. The command depends on the package manager and will look like\n\n    sudo [yum|apt-get|etc] install python-dev\n\n## Usage\n\n\n**Create connection**\n\n```python\nimport aiovertica\n\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             # autogenerated session label by default,\n             \'session_label\': \'some_label\',\n             # default throw error on invalid UTF-8 results\n             \'unicode_error\': \'strict\',\n             # SSL is disabled by default\n             \'ssl\': False,\n             # autocommit is off by default\n             \'autocommit\': True,\n             # using server-side prepared statements is disabled by default\n             \'use_prepared_statements\': False,\n             # connection timeout is not enabled by default\n             # 5 seconds timeout for a socket operation (Establishing a TCP connection or read/write operation)\n             \'connection_timeout\': 5}\n\n# simple connection, with manual close\ntry:\n    connection = await aiovertica.connect(**conn_info)\n    # do things\nfinally:\n    await connection.close()\n\n# using with for auto connection closing after usage\nasync with vertica_python.connect(**conn_info) as connection:\n    # do things\n```\n\nYou can pass an `ssl.SSLContext` to `ssl` to customize the SSL connection options. For example,\n\n```python\nimport aiovertica\nimport ssl\n\nssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\nssl_context.verify_mode = ssl.CERT_REQUIRED\nssl_context.check_hostname = True\nssl_context.load_verify_locations(cafile=\'/path/to/ca_file.pem\')\n\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'ssl\': ssl_context}\nconnection = await aiovertica.connect(**conn_info)\n\n```\n\nSee more on SSL options [here](https://docs.python.org/3/library/ssl.html).\n\n> #### WARNING: `Kerberos` not supported in currently version\n\nIn order to use Kerberos authentication, install [dependencies](#using-kerberos-authentication) first, and it is the user\'s responsibility to ensure that an Ticket-Granting Ticket (TGT) is available and valid. Whether a TGT is available can be easily determined by running the `klist` command. If no TGT is available, then it first must be obtained by running the `kinit` command or by logging in. You can pass in optional arguments to customize the authentication. The arguments are `kerberos_service_name`, which defaults to "vertica", and `kerberos_host_name`, which defaults to the value of argument `host`. For example,\n\n```python\nimport aiovertica\n\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             # The service name portion of the Vertica Kerberos principal\n             \'kerberos_service_name\': \'vertica_krb\',\n             # The instance or host name portion of the Vertica Kerberos principal\n             \'kerberos_host_name\': \'vcluster.example.com\'}\n\nasync with aiovertica.connect(**conn_info) as conn:\n    # do things\n```\n\nLogging is disabled by default if you do not pass values to both ```log_level``` and ```log_path```.  The default value of ```log_level``` is logging.WARNING. You can find all levels [here](https://docs.python.org/3/library/logging.html#logging-levels). The default value of ```log_path``` is \'vertica_python.log\', the log file will be in the current execution directory. If ```log_path``` is set to ```\'\'``` (empty string) or ```None```, no file handler is set, logs will be processed by root handlers. For example,\n\n```python\nimport aiovertica\nimport logging\n\n## Example 1: write DEBUG level logs to \'./vertica_python.log\'\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'log_level\': logging.DEBUG}\nasync with aiovertica.connect(**conn_info) as connection:\n    # do things\n\n## Example 2: write WARNING level logs to \'./path/to/logs/client.log\'\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'log_path\': \'path/to/logs/client.log\'}\nasync with aiovertica.connect(**conn_info) as connection:\n   # do things\n\n## Example 3: write INFO level logs to \'/home/admin/logs/vClient.log\'\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'log_level\': logging.INFO,\n             \'log_path\': \'/home/admin/logs/vClient.log\'}\nasync with aiovertica.connect(**conn_info) as connection:\n   # do things\n\n## Example 4: use root handlers to process logs by setting \'log_path\' to \'\' (empty string) \nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'log_level\': logging.DEBUG,\n             \'log_path\': \'\'}\nasync with aiovertica.connect(**conn_info) as connection:\n    # do things\n```\n\nConnection Failover: Supply a list of backup hosts to ```backup_server_node``` for the client to try if the primary host you specify in the connection parameters (```host```, ```port```) is unreachable. Each item in the list should be either a host string (using default port 5433) or a (host, port) tuple. A host can be a host name or an IP address.\n\n```python\nimport aiovertica\n\nconn_info = {\'host\': \'unreachable.server.com\',\n             \'port\': 888,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             \'backup_server_node\': [\'123.456.789.123\', \'invalid.com\', (\'10.20.82.77\', 6000)]}\nconnection = await aiovertica.connect(**conn_info)\n```\n\nConnection Load Balancing helps automatically spread the overhead caused by client connections across the cluster by having hosts redirect client connections to other hosts. Both the server and the client need to enable load balancing for it to function. If the server disables connection load balancing, the load balancing request from client will be ignored.\n\n```python\nimport aiovertica\n\nconn_info = {\'host\': \'127.0.0.1\',\n             \'port\': 5433,\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'vdb\',\n             \'connection_load_balance\': True}\n\n# Server enables load balancing\nasync with aiovertica.connect(**conn_info) as conn:\n    cur = conn.cursor()\n    await cur.execute("SELECT NODE_NAME FROM V_MONITOR.CURRENT_SESSION")\n    result = await cur.fetchone()\n    print("Client connects to primary node:", result[0])\n    await cur.execute("SELECT SET_LOAD_BALANCE_POLICY(\'ROUNDROBIN\')")\n\nasync with aiovertica.connect(**conn_info) as conn:\n    cur = conn.cursor()\n    await cur.execute("SELECT NODE_NAME FROM V_MONITOR.CURRENT_SESSION")\n    result = await cur.fetchone()\n    print("Client redirects to node:", result[0])\n\n## Output\n#  Client connects to primary node: v_vdb_node0003\n#  Client redirects to node: v_vdb_node0005\n```\n\nAnother way to set connection properties is passing a connection string to the keyword parameter `dsn` of `vertica_python.connect(dsn=\'...\', **kwargs)`. The connection string is of the form:\n```\nvertica://(user):(password)@(host):(port)/(database)?(arg1=val1&arg2=val2&...)\n```\nThe connection string would be parsed by `vertica_python.parse_dsn(connection_str)`, and the parsing result (a dictionary of keywords and values) would be merged with _kwargs_. If the same keyword is specified in both the sources, the _kwargs_ value overrides the parsed _dsn_ value. The `(arg1=val1&arg2=val2&...)` section can handle string/numeric/boolean values, blank and invalid value would be ignored.\n\n```python\nimport aiovertica\n\nconnection_str = (\n    \'vertica://admin@localhost:5433/db1?connection_load_balance=True&connection_timeout=1.5&session_label=vpclient+123%7E456\'\n)\nprint(aiovertica.parse_dsn(connection_str))\n# {\'user\': \'admin\', \'host\': \'localhost\', \'port\': 5433, \'database\': \'db1\',\n#  \'connection_load_balance\': True, \'connection_timeout\': 1.5, \'session_label\': \'vpclient 123~456\'}\n\nadditional_info = {\n    \'password\': \'some_password\', \n    \'backup_server_node\': [\'10.6.7.123\', (\'10.20.82.77\', 6000)]  # invalid value to be set in a connection string\n}\n\nasync with aiovertica.connect(dsn=connection_str, **additional_info) as conn:\n   # do things\n```\n\n\n**Stream query results**:\n\n```python\ncur = connection.cursor()\nawait cur.execute("SELECT * FROM a_table LIMIT 2")\n\nasync for row in cur.iterate():\n    print(row)\n# [ 1, \'some text\', datetime.datetime(2014, 5, 18, 6, 47, 1, 928014) ]\n# [ 2, \'something else\', None ]\n\n```\nStreaming is recommended if you want to further process each row, save the results in a non-list/dict format (e.g. Pandas DataFrame), or save the results in a file.\n\n\n**In-memory results as list**:\n\n```python\ncur = connection.cursor()\nawait cur.execute("SELECT * FROM a_table LIMIT 2")\nawait cur.fetchall()\n# [ [1, \'something\'], [2, \'something_else\'] ]\n```\n\n\n**In-memory results as dictionary**:\n\n```python\ncur = connection.cursor(\'dict\')\nawait cur.execute("SELECT * FROM a_table LIMIT 2")\nawait cur.fetchall()\n# [ {\'id\': 1, \'value\': \'something\'}, {\'id\': 2, \'value\': \'something_else\'} ]\nawait connection.close()\n```\n\n\n**Query using named parameters or format parameters**:\n\nvertica-python can automatically convert Python objects to SQL literals: using this feature your code will be more robust and reliable to prevent SQL injection attacks.\n\nPrerequisites: Only SQL literals (i.e. query values) should be bound via these methods: they shouldn’t be used to merge table or field names to the query (_vertica-python_ will try quoting the table name as a string value, generating invalid SQL as it is actually a SQL Identifier). If you need to generate dynamically SQL queries (for instance choosing dynamically a table name) you have to construct the full query yourself.\n\nVariables can be specified with named (__:name__) placeholders.\n```python\ncur = connection.cursor()\ndata = {\'propA\': 1, \'propB\': \'stringValue\'}\nawait cur.execute("SELECT * FROM a_table WHERE a = :propA AND b = :propB", data)\n# converted into a SQL command similar to: "SELECT * FROM a_table WHERE a = 1 AND b = \'stringValue\'"\n\nawait cur.fetchall()\n# [ [1, \'stringValue\'] ]\n```\n\nVariables can also be specified with positional format (__%s__) placeholders. The placeholder __must always be a %s__, even if a different placeholder (such as a %d for integers or %f for floats) may look more appropriate. __Never__ use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string.\n```python\ncur = connection.cursor()\ndata = (1, "O\'Reilly")\nawait cur.execute("SELECT * FROM a_table WHERE a = %s AND b = %s" % data) # WRONG: % operator\nawait cur.execute("SELECT * FROM a_table WHERE a = %d AND b = %s", data)  # WRONG: %d placeholder\nawait cur.execute("SELECT * FROM a_table WHERE a = %s AND b = %s", data)  # correct\n# converted into a SQL command similar to: "SELECT * FROM a_table WHERE a = 1 AND b = \'O\'\'Reilly\'"\n\nawait cur.fetchall()\n# [ [1, "O\'Reilly"] ]\n```\n\nThe placeholder must not be quoted. _vertica-python_ will add quotes where needed.\n```python\ncur = connection.cursor()\nawait cur.execute("INSERT INTO table VALUES (\':propA\')", {\'propA\': "someString"}) # WRONG\nawait cur.execute("INSERT INTO table VALUES (:propA)", {\'propA\': "someString"})   # correct\nawait cur.execute("INSERT INTO table VALUES (\'%s\')", ("someString",)) # WRONG\nawait cur.execute("INSERT INTO table VALUES (%s)", ("someString",))   # correct\n```\n\n_vertica-python_ supports default mapping for many standard Python types. It is possible to adapt new Python types to SQL literals via `Cursor.register_sql_literal_adapter(py_class_or_type, adapter_function)` function. Example:\n```python\nclass Point(object):\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n# Adapter should return a string value\ndef adapt_point(point):\n    return "STV_GeometryPoint({},{})".format(point.x, point.y)\n\ncur = conn.cursor()\ncur.register_sql_literal_adapter(Point, adapt_point)\n\nawait cur.execute("INSERT INTO geom_data (geom) VALUES (%s)", [Point(1.23, 4.56)])\nawait cur.execute("select ST_asText(geom) from geom_data")\nawait cur.fetchall()\n# [[\'POINT (1.23 4.56)\']]\n```\n\nTo help you debug the binding process during Cursor.execute*(), `Cursor.object_to_sql_literal(py_object)` function can be used to inspect the SQL literal string converted from a Python object.\n```python\ncur = conn.cursor\ncur.object_to_sql_literal("O\'Reilly")  # "\'O\'\'Reilly\'"\ncur.object_to_sql_literal(None)  # "NULL"\ncur.object_to_sql_literal(True)  # "True"\ncur.object_to_sql_literal(Decimal("10.00000"))  # "10.00000"\ncur.object_to_sql_literal(datetime.date(2018, 9, 7))  # "\'2018-09-07\'"\ncur.object_to_sql_literal(Point(-71.13, 42.36))  # "STV_GeometryPoint(-71.13,42.36)" if you registered in previous step\n```\n\n\n**Query using server-side prepared statements**:\n\nVertica server-side prepared statements let you define a statement once and then run it many times with different parameters. Placeholders in the statement are represented by question marks (?). Server-side prepared statements are useful for preventing SQL injection attacks.\n\n```python\nimport aiovertica\n\n# Enable using server-side prepared statements at connection level\nconn_info = {\n    \'host\': \'127.0.0.1\',\n    \'user\': \'some_user\',\n    \'password\': \'some_password\',\n    \'database\': \'a_database\',\n    \'use_prepared_statements\': True,\n}\n\nasync with aiovertica.connect(**conn_info) as connection:\n    cur = connection.cursor()\n    await cur.execute("CREATE TABLE tbl (a INT, b VARCHAR)")\n    await cur.execute("INSERT INTO tbl VALUES (?, ?)", [1, \'aa\'])\n    await cur.execute("INSERT INTO tbl VALUES (?, ?)", [2, \'bb\'])\n    await cur.executemany("INSERT INTO tbl VALUES (?, ?)", [(3, \'foo\'), (4, \'xx\'), (5, \'bar\')])\n    await cur.execute("COMMIT")\n\n    await cur.execute("SELECT * FROM tbl WHERE a>=? AND a<=? ORDER BY a", (2,4))\n    await cur.fetchall()\n    # [[2, \'bb\'], [3, \'foo\'], [4, \'xx\']]\n```\n\nVertica does not support executing a command string containing multiple statements using server-side prepared statements. You can set ```use_prepared_statements``` option in ```cursor.execute*()``` functions to override the connection level setting.\n\n```python\nimport aiovertica\n\n# Enable using server-side prepared statements at connection level\nconn_info = {\n    \'host\': \'127.0.0.1\',\n    \'user\': \'some_user\',\n    \'password\': \'some_password\',\n    \'database\': \'a_database\',\n    \'use_prepared_statements\': True,\n}\n\nasync with aiovertica.connect(**conn_info) as connection:\n    cur = connection.cursor()\n    await cur.execute("CREATE TABLE tbl (a INT, b VARCHAR)")\n\n    # Executing compound statements\n    await cur.execute("INSERT INTO tbl VALUES (?, ?); COMMIT", [1, \'aa\'])\n    # Error message: Cannot insert multiple commands into a prepared statement\n\n    # Disable prepared statements but forget to change placeholders (?)\n    await cur.execute("INSERT INTO tbl VALUES (?, ?); COMMIT;", [1, \'aa\'], use_prepared_statements=False)\n    # TypeError: not all arguments converted during string formatting\n\n    await cur.execute("INSERT INTO tbl VALUES (%s, %s); COMMIT;", [1, \'aa\'], use_prepared_statements=False)\n    await cur.execute("INSERT INTO tbl VALUES (:a, :b); COMMIT;", {\'a\': 2, \'b\': \'bb\'}, use_prepared_statements=False)\n\n# Disable using server-side prepared statements at connection level\nconn_info[\'use_prepared_statements\'] = False\nasync with aiovertica.connect(**conn_info) as connection:\n    cur = connection.cursor()\n\n    # Try using prepared statements\n    await cur.execute("INSERT INTO tbl VALUES (?, ?)", [3, \'foo\'])\n    # TypeError: not all arguments converted during string formatting\n\n    await cur.execute("INSERT INTO tbl VALUES (?, ?)", [3, \'foo\'], use_prepared_statements=True)\n\n    # Query using named parameters\n    await cur.execute("SELECT * FROM tbl WHERE a>=:n1 AND a<=:n2 ORDER BY a", {\'n1\': 2, \'n2\': 4})\n    await cur.fetchall()\n    # [[2, \'bb\'], [3, \'foo\']]\n```\nNote: In other drivers, the batch insert is converted into a COPY statement by using prepared statements. vertica-python currently does not support that.\n\n**Insert and commits**:\n\n```python\ncur = connection.cursor()\n\n# inline commit (when \'use_prepared_statements\' is False)\nawait cur.execute("INSERT INTO a_table (a, b) VALUES (1, \'aa\'); commit;")\n\n# commit in execution\nawait cur.execute("INSERT INTO a_table (a, b) VALUES (1, \'aa\')")\nawait cur.execute("INSERT INTO a_table (a, b) VALUES (2, \'bb\')")\nawait cur.execute("commit;")\n\n# connection.commit()\nawait cur.execute("INSERT INTO a_table (a, b) VALUES (1, \'aa\')")\nawait connection.commit()\n\n# connection.rollback()\nawait cur.execute("INSERT INTO a_table (a, b) VALUES (0, \'bad\')")\nawait connection.rollback()\n```\n\n**Autocommit**:\n\nSession parameter AUTOCOMMIT can be configured by the connection option and the `Connection.autocommit` read/write attribute:\n```python\nimport aiovertica\n\n# Enable autocommit at startup\nconn_info = {\n    \'host\': \'127.0.0.1\',\n    \'user\': \'some_user\',\n    \'password\': \'some_password\',\n    \'database\': \'a_database\',\n    # autocommit is off by default\n    \'autocommit\': True,\n}\n\nasync with aiovertica.connect(**conn_info) as connection:\n    # Check current session autocommit setting\n    print(connection.autocommit)    # should be True\n    # If autocommit is True, statements automatically commit their transactions when they complete.\n    \n    # Set autocommit setting with attribute\n    connection.autocommit = False\n    print(connection.autocommit)    # should be False\n    # If autocommit is False, the methods commit() or rollback() must be manually invoked to terminate the transaction.\n```\n\n> #### WARNING: set attr `autocommit` with instance may not work correctly in the current version\n\nTo set AUTOCOMMIT to a new value, vertica-python uses `Cursor.execute()` to execute a command internally, and that would clear your previous query results, so be sure to call `Cursor.fetch*()` to save your results before you set autocommit.\n\n\n**Copy**:\n\nThere are 2 methods to do copy:\n\nMethod 1: "COPY FROM STDIN" sql with Cursor.copy()\n```python\ncur = connection.cursor()\nawait cur.copy("COPY test_copy (id, name) from stdin DELIMITER \',\' ",  csv)\n```\n\nWhere `csv` is either a string or a file-like object (specifically, any object with a `read()` method). If using a file, the data is streamed (in chunks of `buffer_size` bytes, which defaults to 128 * 2 ** 10).\n\n```python\nwith open("/tmp/binary_file.csv", "rb") as fs:\n    await cursor.copy(\n        "COPY table(field1, field2) FROM STDIN DELIMITER \',\' ENCLOSED BY \'\\"\'",\n        fs,\n        buffer_size=65536\n    )\n```\n\nMethod 2: "COPY FROM LOCAL" sql with Cursor.execute() \n\n```python\nimport sys\nimport aiovertica\n\nconn_info = {\'host\': \'127.0.0.1\',\n             \'user\': \'some_user\',\n             \'password\': \'some_password\',\n             \'database\': \'a_database\',\n             # False by default\n             #\'disable_copy_local\': True,\n             # Don\'t support executing COPY LOCAL operations with prepared statements\n             \'use_prepared_statements\': False\n             }\n\nasync with aiovertica.connect(**conn_info) as connection:\n    cur = connection.cursor()\n    \n    # Copy from local file\n    await cur.execute(\n        "COPY table(field1, field2) FROM LOCAL"\n        " \'data_Jan_*.csv\',\'data_Feb_01.csv\' DELIMITER \',\'"\n        " REJECTED DATA \'path/to/write/rejects.txt\'"\n        " EXCEPTIONS \'path/to/write/exceptions.txt\'",\n        buffer_size=65536\n    )\n    result = await cur.fetchall()\n    print("Rows loaded:", result)\n    \n    # Copy from local stdin\n    await cur.execute(\n        "COPY table(field1, field2) FROM LOCAL STDIN DELIMITER \',\'",\n        copy_stdin=sys.stdin\n    )\n    result = await cur.fetchall()\n    print("Rows loaded:", result)\n\n    # Copy from local stdin (compound statements)\n    with open(\'f1.csv\', \'r\') as fs1, open(\'f2.csv\', \'r\') as fs2:\n        await cur.execute(\n            "COPY tlb1(field1, field2) FROM LOCAL STDIN DELIMITER \',\';"\n            "COPY tlb2(field1, field2) FROM LOCAL STDIN DELIMITER \',\';",\n            copy_stdin=[fs1, fs2], buffer_size=65536\n        )\n    result = await cur.fetchall()\n    print("Rows loaded 1:", result)\n    await cur.nextset()\n    result = await cur.fetchall()\n    print("Rows loaded 2:", result)\n```\nWhen connection option `disable_copy_local` set to True, disables COPY LOCAL operations, including copying data from local files/stdin and using local files to store data and exceptions. You can use this property to prevent users from writing to and copying from files on a Vertica host, including an MC host. Note that this property doesn\'t apply to `Cursor.copy()`.\n\nThe data for copying from/writing to local files is streamed in chunks of `buffer_size` bytes, which defaults to 128 * 2 ** 10.\n\nWhen executing "COPY FROM LOCAL STDIN", `copy_stdin` should be a file-like object or a list of file-like objects (specifically, any object with a `read()` method).\n\n**Cancel the current database operation**:\n\n`Connection.cancel()` interrupts the processing of the current operation. Interrupting query execution will cause the cancelled method to raise a `vertica_python.errors.QueryCanceled`. If no query is being executed, it does nothing. You can call this function from a different thread/process than the one currently executing a database operation.\n\n```python\nfrom multiprocessing import Process\nimport asyncio\nimport aiovertica\n\nasync def cancel_query(connection, timeout=5):\n    await asyncio.sleep(timeout)\n    await connection.cancel()\n\n# Example 1: Cancel the query before Cursor.execute() return.\n#            The query stops executing in a shorter time after the cancel message is sent.\nasync with aiovertica.connect(**conn_info) as conn:\n    cur = conn.cursor()\n\n    # Call cancel() from a different process\n    p1 = Process(target=cancel_query, args=(conn,))\n    p1.start()\n\n    try:\n        cur.execute("<Long running query>")\n    except aiovertica.errors.QueryCanceled as e:\n        pass\n\n    p1.join()\n    \n# Example 2: Cancel the query after Cursor.execute() return.\n#            Less number of rows read after the cancel message is sent.\nwith aiovertica.connect(**conn_info) as conn:\n    cur = conn.cursor()\n    await cur.execute("SELECT id, time FROM large_table")\n    nCount = 0\n    try:\n        result = await cur.fetchone()\n        while result:\n            nCount += 1\n            if nCount == 100:\n                conn.cancel()\n            result = await cur.fetchone()\n    except aiovertica.errors.QueryCanceled as e:\n        pass\n        # nCount is less than the number of rows in large_table\n\n```\n\n\n\n## Rowcount oddities\n\nvertica_python behaves a bit differently than dbapi when returning rowcounts.\n\nAfter a select execution, the rowcount will be -1, indicating that the row count is unknown. The rowcount value will be updated as data is streamed.\n\n```python\nawait cur.execute(\'SELECT 10 things\')\n\ncur.rowcount == -1  # indicates unknown rowcount\n\nawait cur.fetchone()\ncur.rowcount == 1\nawait cur.fetchone()\ncur.rowcount == 2\nawait cur.fetchall()\ncur.rowcount == 10\n```\n\nAfter an insert/update/delete, the rowcount will be returned as a single element row:\n\n```python\nawait cur.execute("DELETE 3 things")\n\ncur.rowcount == -1  # indicates unknown rowcount\nresult = await cur.fetchone()\nresult[0] == 3\n```\n\n## Nextset\n\nIf you execute multiple statements in a single call to execute(), you can use cursor.nextset() to retrieve all of the data.\n\n```python\nawait cur.execute(\'SELECT 1; SELECT 2;\')\n\nawait cur.fetchone()\n# [1]\nawait cur.fetchone()\n# None\n\nawait cur.nextset()\n# True\n\nawait cur.fetchone()\n# [2]\nawait cur.fetchone()\n# None\n\nawait cur.nextset()\n# None\n```\n\n## UTF-8 encoding issues\n\nWhile Vertica expects varchars stored to be UTF-8 encoded, sometimes invalid strings get into the database. You can specify how to handle reading these characters using the unicode_error connection option. This uses the same values as the unicode type (https://docs.python.org/2/library/functions.html#unicode)\n\n```python\nimport aiovertica\n\nconn = await aiovertica.connect({..., \'unicode_error\': \'strict\'})\ncur = conn.cursor()\nawait cur.execute(r"SELECT E\'\\xC2\'")\nawait cur.fetchone()\n# caught \'utf8\' codec can\'t decode byte 0xc2 in position 0: unexpected end of data\n\nconn = await aiovertica.connect({..., \'unicode_error\': \'strict\'})\ncur = conn.cursor()\nawait cur.execute(r"SELECT E\'\\xC2\'")\nawait cur.fetchone()\n# �\n\nconn = await aiovertica.connect({..., \'unicode_error\': \'strict\'})\ncur = conn.cursor()\nawait cur.execute(r"SELECT E\'\\xC2\'")\nawait cur.fetchone()\n# \n```\n\n## License\n\nApache 2.0 License, please see `LICENSE` for details.\n\n## Contributing guidelines\n\nHave a bug or an idea? Please see `CONTRIBUTING.md` for details.\n\n## Acknowledgements\n\nI would like to express my deep gratitude to the team \nthat worked on the [vertica_python](https://github.com/vertica/vertica-python/) for writing at least a synchronous driver - this greatly \nsimplified the work. I have tried to keep all the licenses and the list of authors from \nthe original project.\n',
    'author': 'Ivan Galin',
    'author_email': 'i.galin@devartsteam.ru',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/i8enn/aiovertica',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.8,<3.10',
}


setup(**setup_kwargs)
