clickhouse-driver 0.0.4__tar.gz → 0.2.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clickhouse-driver-0.2.9/LICENSE +21 -0
- clickhouse-driver-0.2.9/MANIFEST.in +1 -0
- clickhouse-driver-0.2.9/PKG-INFO +193 -0
- clickhouse-driver-0.2.9/README.rst +155 -0
- clickhouse-driver-0.2.9/clickhouse_driver/__init__.py +9 -0
- clickhouse-driver-0.2.9/clickhouse_driver/block.py +227 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/blockstreamprofileinfo.py +2 -1
- clickhouse-driver-0.2.9/clickhouse_driver/bufferedreader.c +17131 -0
- clickhouse-driver-0.2.9/clickhouse_driver/bufferedreader.pyx +255 -0
- clickhouse-driver-0.2.9/clickhouse_driver/bufferedwriter.c +16613 -0
- clickhouse-driver-0.2.9/clickhouse_driver/bufferedwriter.pyx +147 -0
- clickhouse-driver-0.2.9/clickhouse_driver/client.py +812 -0
- clickhouse-driver-0.2.9/clickhouse_driver/clientinfo.py +119 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/arraycolumn.py +161 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/base.py +221 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/boolcolumn.py +7 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/datecolumn.py +108 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/datetimecolumn.py +203 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/decimalcolumn.py +116 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/enumcolumn.py +129 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/exceptions.py +12 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/floatcolumn.py +34 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/intcolumn.py +157 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/intervalcolumn.py +33 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/ipcolumn.py +118 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/jsoncolumn.py +37 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/largeint.c +10957 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/largeint.pyx +243 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/lowcardinalitycolumn.py +142 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/mapcolumn.py +73 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/nestedcolumn.py +10 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/nothingcolumn.py +13 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/nullablecolumn.py +7 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/nullcolumn.py +15 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/base.py +47 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/boolcolumn.py +8 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/datecolumn.py +19 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/datetimecolumn.py +146 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/floatcolumn.py +24 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/intcolumn.py +43 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +96 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/service.py +58 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/stringcolumn.py +78 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy/tuplecolumn.py +37 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/service.py +185 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/simpleaggregatefunctioncolumn.py +7 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/stringcolumn.py +73 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/tuplecolumn.py +63 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/util.py +61 -0
- clickhouse-driver-0.2.9/clickhouse_driver/columns/uuidcolumn.py +64 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/compression/__init__.py +1 -4
- clickhouse-driver-0.2.9/clickhouse_driver/compression/base.py +87 -0
- clickhouse-driver-0.2.9/clickhouse_driver/compression/lz4.py +21 -0
- clickhouse-driver-0.2.9/clickhouse_driver/compression/zstd.py +20 -0
- clickhouse-driver-0.2.9/clickhouse_driver/connection.py +793 -0
- clickhouse-driver-0.2.9/clickhouse_driver/context.py +36 -0
- clickhouse-driver-0.2.9/clickhouse_driver/dbapi/__init__.py +62 -0
- clickhouse-driver-0.2.9/clickhouse_driver/dbapi/connection.py +99 -0
- clickhouse-driver-0.2.9/clickhouse_driver/dbapi/cursor.py +370 -0
- clickhouse-driver-0.2.9/clickhouse_driver/dbapi/errors.py +40 -0
- clickhouse-driver-0.2.9/clickhouse_driver/dbapi/extras.py +73 -0
- clickhouse-driver-0.2.9/clickhouse_driver/defines.py +58 -0
- clickhouse-driver-0.2.9/clickhouse_driver/errors.py +453 -0
- clickhouse-driver-0.2.9/clickhouse_driver/log.py +48 -0
- clickhouse-driver-0.2.9/clickhouse_driver/numpy/block.py +8 -0
- clickhouse-driver-0.2.9/clickhouse_driver/numpy/helpers.py +28 -0
- clickhouse-driver-0.2.9/clickhouse_driver/numpy/result.py +123 -0
- clickhouse-driver-0.2.9/clickhouse_driver/opentelemetry.py +43 -0
- clickhouse-driver-0.2.9/clickhouse_driver/progress.py +44 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/protocol.py +41 -4
- clickhouse-driver-0.2.9/clickhouse_driver/reader.py +69 -0
- clickhouse-driver-0.2.9/clickhouse_driver/result.py +144 -0
- clickhouse-driver-0.2.9/clickhouse_driver/settings/available.py +405 -0
- clickhouse-driver-0.2.9/clickhouse_driver/settings/types.py +50 -0
- clickhouse-driver-0.2.9/clickhouse_driver/settings/writer.py +34 -0
- clickhouse-driver-0.2.9/clickhouse_driver/streams/__init__.py +0 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/streams/compressed.py +18 -35
- clickhouse-driver-0.2.9/clickhouse_driver/streams/native.py +108 -0
- clickhouse-driver-0.2.9/clickhouse_driver/util/__init__.py +0 -0
- clickhouse-driver-0.2.9/clickhouse_driver/util/compat.py +39 -0
- clickhouse-driver-0.2.9/clickhouse_driver/util/escape.py +94 -0
- clickhouse-driver-0.2.9/clickhouse_driver/util/helpers.py +171 -0
- clickhouse-driver-0.2.9/clickhouse_driver/varint.c +8292 -0
- clickhouse-driver-0.2.9/clickhouse_driver/varint.pyx +68 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/writer.py +10 -33
- clickhouse-driver-0.2.9/clickhouse_driver.egg-info/PKG-INFO +193 -0
- clickhouse-driver-0.2.9/clickhouse_driver.egg-info/SOURCES.txt +113 -0
- clickhouse-driver-0.2.9/clickhouse_driver.egg-info/requires.txt +19 -0
- {clickhouse-driver-0.0.4 → clickhouse-driver-0.2.9}/setup.cfg +11 -0
- clickhouse-driver-0.2.9/setup.py +139 -0
- clickhouse-driver-0.2.9/tests/test_blocks.py +247 -0
- clickhouse-driver-0.2.9/tests/test_buffered_reader.py +22 -0
- clickhouse-driver-0.2.9/tests/test_client.py +290 -0
- clickhouse-driver-0.2.9/tests/test_compression.py +103 -0
- clickhouse-driver-0.2.9/tests/test_connect.py +412 -0
- clickhouse-driver-0.2.9/tests/test_dbapi.py +496 -0
- clickhouse-driver-0.2.9/tests/test_errors.py +17 -0
- clickhouse-driver-0.2.9/tests/test_external_tables.py +36 -0
- clickhouse-driver-0.2.9/tests/test_insert.py +235 -0
- clickhouse-driver-0.2.9/tests/test_opentelemetry.py +89 -0
- clickhouse-driver-0.2.9/tests/test_query_info.py +164 -0
- clickhouse-driver-0.2.9/tests/test_settings.py +167 -0
- clickhouse-driver-0.2.9/tests/test_substitution.py +280 -0
- clickhouse-driver-0.2.9/tests/test_varint.py +19 -0
- clickhouse-driver-0.2.9/tests/testcase.py +131 -0
- clickhouse-driver-0.0.4/PKG-INFO +0 -203
- clickhouse-driver-0.0.4/README.rst +0 -178
- clickhouse-driver-0.0.4/clickhouse_driver.egg-info/PKG-INFO +0 -203
- clickhouse-driver-0.0.4/clickhouse_driver.egg-info/SOURCES.txt +0 -43
- clickhouse-driver-0.0.4/clickhouse_driver.egg-info/requires.txt +0 -14
- clickhouse-driver-0.0.4/setup.py +0 -80
- clickhouse-driver-0.0.4/src/block.py +0 -74
- clickhouse-driver-0.0.4/src/client.py +0 -111
- clickhouse-driver-0.0.4/src/clientinfo.py +0 -72
- clickhouse-driver-0.0.4/src/columns/arraycolumn.py +0 -128
- clickhouse-driver-0.0.4/src/columns/base.py +0 -50
- clickhouse-driver-0.0.4/src/columns/datecolumn.py +0 -21
- clickhouse-driver-0.0.4/src/columns/datetimecolumn.py +0 -22
- clickhouse-driver-0.0.4/src/columns/enumcolumn.py +0 -71
- clickhouse-driver-0.0.4/src/columns/floatcolumn.py +0 -33
- clickhouse-driver-0.0.4/src/columns/intcolumn.py +0 -75
- clickhouse-driver-0.0.4/src/columns/service.py +0 -56
- clickhouse-driver-0.0.4/src/columns/stringcolumn.py +0 -35
- clickhouse-driver-0.0.4/src/compression/base.py +0 -41
- clickhouse-driver-0.0.4/src/compression/lz4.py +0 -55
- clickhouse-driver-0.0.4/src/compression/quicklz.py +0 -60
- clickhouse-driver-0.0.4/src/compression/zstd.py +0 -51
- clickhouse-driver-0.0.4/src/connection.py +0 -381
- clickhouse-driver-0.0.4/src/defines.py +0 -24
- clickhouse-driver-0.0.4/src/errors.py +0 -106
- clickhouse-driver-0.0.4/src/progress.py +0 -19
- clickhouse-driver-0.0.4/src/reader.py +0 -101
- clickhouse-driver-0.0.4/src/streams/native.py +0 -77
- clickhouse-driver-0.0.4/src/util/tzinfo.py +0 -19
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver/columns}/__init__.py +0 -0
- {clickhouse-driver-0.0.4/src/columns → clickhouse-driver-0.2.9/clickhouse_driver/columns/numpy}/__init__.py +0 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/compression/lz4hc.py +0 -0
- {clickhouse-driver-0.0.4/src/streams → clickhouse-driver-0.2.9/clickhouse_driver/numpy}/__init__.py +0 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/queryprocessingstage.py +0 -0
- {clickhouse-driver-0.0.4/src → clickhouse-driver-0.2.9/clickhouse_driver}/readhelpers.py +0 -0
- {clickhouse-driver-0.0.4/src/util → clickhouse-driver-0.2.9/clickhouse_driver/settings}/__init__.py +0 -0
- {clickhouse-driver-0.0.4 → clickhouse-driver-0.2.9}/clickhouse_driver.egg-info/dependency_links.txt +0 -0
- {clickhouse-driver-0.0.4 → clickhouse-driver-0.2.9}/clickhouse_driver.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
This is the MIT license: http://www.opensource.org/licenses/mit-license.php
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 by Konstantin Lebedev.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include clickhouse_driver *.pyx
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: clickhouse-driver
|
|
3
|
+
Version: 0.2.9
|
|
4
|
+
Summary: Python driver with native interface for ClickHouse
|
|
5
|
+
Home-page: https://github.com/mymarilyn/clickhouse-driver
|
|
6
|
+
Author: Konstantin Lebedev
|
|
7
|
+
Author-email: kostyan.lebedev@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://clickhouse-driver.readthedocs.io
|
|
10
|
+
Project-URL: Changes, https://github.com/mymarilyn/clickhouse-driver/blob/master/CHANGELOG.md
|
|
11
|
+
Description: ClickHouse Python Driver
|
|
12
|
+
========================
|
|
13
|
+
|
|
14
|
+
.. image:: https://img.shields.io/pypi/v/clickhouse-driver.svg
|
|
15
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
16
|
+
|
|
17
|
+
.. image:: https://coveralls.io/repos/github/mymarilyn/clickhouse-driver/badge.svg?branch=master
|
|
18
|
+
:target: https://coveralls.io/github/mymarilyn/clickhouse-driver?branch=master
|
|
19
|
+
|
|
20
|
+
.. image:: https://img.shields.io/pypi/l/clickhouse-driver.svg
|
|
21
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
22
|
+
|
|
23
|
+
.. image:: https://img.shields.io/pypi/pyversions/clickhouse-driver.svg
|
|
24
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
25
|
+
|
|
26
|
+
.. image:: https://img.shields.io/pypi/dm/clickhouse-driver.svg
|
|
27
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
28
|
+
|
|
29
|
+
.. image:: https://github.com/mymarilyn/clickhouse-driver/actions/workflows/actions.yml/badge.svg
|
|
30
|
+
:target: https://github.com/mymarilyn/clickhouse-driver/actions/workflows/actions.yml
|
|
31
|
+
|
|
32
|
+
ClickHouse Python Driver with native (TCP) interface support.
|
|
33
|
+
|
|
34
|
+
Asynchronous wrapper is available here: https://github.com/mymarilyn/aioch
|
|
35
|
+
|
|
36
|
+
Features
|
|
37
|
+
========
|
|
38
|
+
|
|
39
|
+
- External data for query processing.
|
|
40
|
+
|
|
41
|
+
- Query settings.
|
|
42
|
+
|
|
43
|
+
- Compression support.
|
|
44
|
+
|
|
45
|
+
- TLS support.
|
|
46
|
+
|
|
47
|
+
- Types support:
|
|
48
|
+
|
|
49
|
+
* Float32/64
|
|
50
|
+
* [U]Int8/16/32/64/128/256
|
|
51
|
+
* Date/Date32/DateTime('timezone')/DateTime64('timezone')
|
|
52
|
+
* String/FixedString(N)
|
|
53
|
+
* Enum8/16
|
|
54
|
+
* Array(T)
|
|
55
|
+
* Nullable(T)
|
|
56
|
+
* Bool
|
|
57
|
+
* UUID
|
|
58
|
+
* Decimal
|
|
59
|
+
* IPv4/IPv6
|
|
60
|
+
* LowCardinality(T)
|
|
61
|
+
* SimpleAggregateFunction(F, T)
|
|
62
|
+
* Tuple(T1, T2, ...)
|
|
63
|
+
* Nested
|
|
64
|
+
* Map(key, value)
|
|
65
|
+
|
|
66
|
+
- Query progress information.
|
|
67
|
+
|
|
68
|
+
- Block by block results streaming.
|
|
69
|
+
|
|
70
|
+
- Reading query profile info.
|
|
71
|
+
|
|
72
|
+
- Receiving server logs.
|
|
73
|
+
|
|
74
|
+
- Multiple hosts support.
|
|
75
|
+
|
|
76
|
+
- Python DB API 2.0 specification support.
|
|
77
|
+
|
|
78
|
+
- Optional NumPy arrays support.
|
|
79
|
+
|
|
80
|
+
Documentation
|
|
81
|
+
=============
|
|
82
|
+
|
|
83
|
+
Documentation is available at https://clickhouse-driver.readthedocs.io.
|
|
84
|
+
|
|
85
|
+
Usage
|
|
86
|
+
=====
|
|
87
|
+
|
|
88
|
+
There are two ways to communicate with server:
|
|
89
|
+
|
|
90
|
+
- using pure Client;
|
|
91
|
+
- using DB API.
|
|
92
|
+
|
|
93
|
+
Pure Client example:
|
|
94
|
+
|
|
95
|
+
.. code-block:: python
|
|
96
|
+
|
|
97
|
+
>>> from clickhouse_driver import Client
|
|
98
|
+
>>>
|
|
99
|
+
>>> client = Client('localhost')
|
|
100
|
+
>>>
|
|
101
|
+
>>> client.execute('SHOW TABLES')
|
|
102
|
+
[('test',)]
|
|
103
|
+
>>> client.execute('DROP TABLE IF EXISTS test')
|
|
104
|
+
[]
|
|
105
|
+
>>> client.execute('CREATE TABLE test (x Int32) ENGINE = Memory')
|
|
106
|
+
[]
|
|
107
|
+
>>> client.execute(
|
|
108
|
+
... 'INSERT INTO test (x) VALUES',
|
|
109
|
+
... [{'x': 100}]
|
|
110
|
+
... )
|
|
111
|
+
1
|
|
112
|
+
>>> client.execute('INSERT INTO test (x) VALUES', [[200]])
|
|
113
|
+
1
|
|
114
|
+
>>> client.execute(
|
|
115
|
+
... 'INSERT INTO test (x) '
|
|
116
|
+
... 'SELECT * FROM system.numbers LIMIT %(limit)s',
|
|
117
|
+
... {'limit': 3}
|
|
118
|
+
... )
|
|
119
|
+
[]
|
|
120
|
+
>>> client.execute('SELECT sum(x) FROM test')
|
|
121
|
+
[(303,)]
|
|
122
|
+
|
|
123
|
+
DB API example:
|
|
124
|
+
|
|
125
|
+
.. code-block:: python
|
|
126
|
+
|
|
127
|
+
>>> from clickhouse_driver import connect
|
|
128
|
+
>>>
|
|
129
|
+
>>> conn = connect('clickhouse://localhost')
|
|
130
|
+
>>> cursor = conn.cursor()
|
|
131
|
+
>>>
|
|
132
|
+
>>> cursor.execute('SHOW TABLES')
|
|
133
|
+
>>> cursor.fetchall()
|
|
134
|
+
[('test',)]
|
|
135
|
+
>>> cursor.execute('DROP TABLE IF EXISTS test')
|
|
136
|
+
>>> cursor.fetchall()
|
|
137
|
+
[]
|
|
138
|
+
>>> cursor.execute('CREATE TABLE test (x Int32) ENGINE = Memory')
|
|
139
|
+
>>> cursor.fetchall()
|
|
140
|
+
[]
|
|
141
|
+
>>> cursor.executemany(
|
|
142
|
+
... 'INSERT INTO test (x) VALUES',
|
|
143
|
+
... [{'x': 100}]
|
|
144
|
+
... )
|
|
145
|
+
>>> cursor.rowcount
|
|
146
|
+
1
|
|
147
|
+
>>> cursor.executemany('INSERT INTO test (x) VALUES', [[200]])
|
|
148
|
+
>>> cursor.rowcount
|
|
149
|
+
1
|
|
150
|
+
>>> cursor.execute(
|
|
151
|
+
... 'INSERT INTO test (x) '
|
|
152
|
+
... 'SELECT * FROM system.numbers LIMIT %(limit)s',
|
|
153
|
+
... {'limit': 3}
|
|
154
|
+
... )
|
|
155
|
+
>>> cursor.rowcount
|
|
156
|
+
0
|
|
157
|
+
>>> cursor.execute('SELECT sum(x) FROM test')
|
|
158
|
+
>>> cursor.fetchall()
|
|
159
|
+
[(303,)]
|
|
160
|
+
|
|
161
|
+
License
|
|
162
|
+
=======
|
|
163
|
+
|
|
164
|
+
ClickHouse Python Driver is distributed under the `MIT license
|
|
165
|
+
<http://www.opensource.org/licenses/mit-license.php>`_.
|
|
166
|
+
|
|
167
|
+
Keywords: ClickHouse db database cloud analytics
|
|
168
|
+
Platform: UNKNOWN
|
|
169
|
+
Classifier: Development Status :: 4 - Beta
|
|
170
|
+
Classifier: Environment :: Console
|
|
171
|
+
Classifier: Intended Audience :: Developers
|
|
172
|
+
Classifier: Intended Audience :: Information Technology
|
|
173
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
174
|
+
Classifier: Operating System :: OS Independent
|
|
175
|
+
Classifier: Programming Language :: SQL
|
|
176
|
+
Classifier: Programming Language :: Python :: 3
|
|
177
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
178
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
179
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
180
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
181
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
182
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
183
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
184
|
+
Classifier: Topic :: Database
|
|
185
|
+
Classifier: Topic :: Software Development
|
|
186
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
187
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
188
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
189
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
190
|
+
Requires-Python: >=3.7, <4
|
|
191
|
+
Provides-Extra: lz4
|
|
192
|
+
Provides-Extra: zstd
|
|
193
|
+
Provides-Extra: numpy
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
ClickHouse Python Driver
|
|
2
|
+
========================
|
|
3
|
+
|
|
4
|
+
.. image:: https://img.shields.io/pypi/v/clickhouse-driver.svg
|
|
5
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
6
|
+
|
|
7
|
+
.. image:: https://coveralls.io/repos/github/mymarilyn/clickhouse-driver/badge.svg?branch=master
|
|
8
|
+
:target: https://coveralls.io/github/mymarilyn/clickhouse-driver?branch=master
|
|
9
|
+
|
|
10
|
+
.. image:: https://img.shields.io/pypi/l/clickhouse-driver.svg
|
|
11
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
12
|
+
|
|
13
|
+
.. image:: https://img.shields.io/pypi/pyversions/clickhouse-driver.svg
|
|
14
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
15
|
+
|
|
16
|
+
.. image:: https://img.shields.io/pypi/dm/clickhouse-driver.svg
|
|
17
|
+
:target: https://pypi.org/project/clickhouse-driver
|
|
18
|
+
|
|
19
|
+
.. image:: https://github.com/mymarilyn/clickhouse-driver/actions/workflows/actions.yml/badge.svg
|
|
20
|
+
:target: https://github.com/mymarilyn/clickhouse-driver/actions/workflows/actions.yml
|
|
21
|
+
|
|
22
|
+
ClickHouse Python Driver with native (TCP) interface support.
|
|
23
|
+
|
|
24
|
+
Asynchronous wrapper is available here: https://github.com/mymarilyn/aioch
|
|
25
|
+
|
|
26
|
+
Features
|
|
27
|
+
========
|
|
28
|
+
|
|
29
|
+
- External data for query processing.
|
|
30
|
+
|
|
31
|
+
- Query settings.
|
|
32
|
+
|
|
33
|
+
- Compression support.
|
|
34
|
+
|
|
35
|
+
- TLS support.
|
|
36
|
+
|
|
37
|
+
- Types support:
|
|
38
|
+
|
|
39
|
+
* Float32/64
|
|
40
|
+
* [U]Int8/16/32/64/128/256
|
|
41
|
+
* Date/Date32/DateTime('timezone')/DateTime64('timezone')
|
|
42
|
+
* String/FixedString(N)
|
|
43
|
+
* Enum8/16
|
|
44
|
+
* Array(T)
|
|
45
|
+
* Nullable(T)
|
|
46
|
+
* Bool
|
|
47
|
+
* UUID
|
|
48
|
+
* Decimal
|
|
49
|
+
* IPv4/IPv6
|
|
50
|
+
* LowCardinality(T)
|
|
51
|
+
* SimpleAggregateFunction(F, T)
|
|
52
|
+
* Tuple(T1, T2, ...)
|
|
53
|
+
* Nested
|
|
54
|
+
* Map(key, value)
|
|
55
|
+
|
|
56
|
+
- Query progress information.
|
|
57
|
+
|
|
58
|
+
- Block by block results streaming.
|
|
59
|
+
|
|
60
|
+
- Reading query profile info.
|
|
61
|
+
|
|
62
|
+
- Receiving server logs.
|
|
63
|
+
|
|
64
|
+
- Multiple hosts support.
|
|
65
|
+
|
|
66
|
+
- Python DB API 2.0 specification support.
|
|
67
|
+
|
|
68
|
+
- Optional NumPy arrays support.
|
|
69
|
+
|
|
70
|
+
Documentation
|
|
71
|
+
=============
|
|
72
|
+
|
|
73
|
+
Documentation is available at https://clickhouse-driver.readthedocs.io.
|
|
74
|
+
|
|
75
|
+
Usage
|
|
76
|
+
=====
|
|
77
|
+
|
|
78
|
+
There are two ways to communicate with server:
|
|
79
|
+
|
|
80
|
+
- using pure Client;
|
|
81
|
+
- using DB API.
|
|
82
|
+
|
|
83
|
+
Pure Client example:
|
|
84
|
+
|
|
85
|
+
.. code-block:: python
|
|
86
|
+
|
|
87
|
+
>>> from clickhouse_driver import Client
|
|
88
|
+
>>>
|
|
89
|
+
>>> client = Client('localhost')
|
|
90
|
+
>>>
|
|
91
|
+
>>> client.execute('SHOW TABLES')
|
|
92
|
+
[('test',)]
|
|
93
|
+
>>> client.execute('DROP TABLE IF EXISTS test')
|
|
94
|
+
[]
|
|
95
|
+
>>> client.execute('CREATE TABLE test (x Int32) ENGINE = Memory')
|
|
96
|
+
[]
|
|
97
|
+
>>> client.execute(
|
|
98
|
+
... 'INSERT INTO test (x) VALUES',
|
|
99
|
+
... [{'x': 100}]
|
|
100
|
+
... )
|
|
101
|
+
1
|
|
102
|
+
>>> client.execute('INSERT INTO test (x) VALUES', [[200]])
|
|
103
|
+
1
|
|
104
|
+
>>> client.execute(
|
|
105
|
+
... 'INSERT INTO test (x) '
|
|
106
|
+
... 'SELECT * FROM system.numbers LIMIT %(limit)s',
|
|
107
|
+
... {'limit': 3}
|
|
108
|
+
... )
|
|
109
|
+
[]
|
|
110
|
+
>>> client.execute('SELECT sum(x) FROM test')
|
|
111
|
+
[(303,)]
|
|
112
|
+
|
|
113
|
+
DB API example:
|
|
114
|
+
|
|
115
|
+
.. code-block:: python
|
|
116
|
+
|
|
117
|
+
>>> from clickhouse_driver import connect
|
|
118
|
+
>>>
|
|
119
|
+
>>> conn = connect('clickhouse://localhost')
|
|
120
|
+
>>> cursor = conn.cursor()
|
|
121
|
+
>>>
|
|
122
|
+
>>> cursor.execute('SHOW TABLES')
|
|
123
|
+
>>> cursor.fetchall()
|
|
124
|
+
[('test',)]
|
|
125
|
+
>>> cursor.execute('DROP TABLE IF EXISTS test')
|
|
126
|
+
>>> cursor.fetchall()
|
|
127
|
+
[]
|
|
128
|
+
>>> cursor.execute('CREATE TABLE test (x Int32) ENGINE = Memory')
|
|
129
|
+
>>> cursor.fetchall()
|
|
130
|
+
[]
|
|
131
|
+
>>> cursor.executemany(
|
|
132
|
+
... 'INSERT INTO test (x) VALUES',
|
|
133
|
+
... [{'x': 100}]
|
|
134
|
+
... )
|
|
135
|
+
>>> cursor.rowcount
|
|
136
|
+
1
|
|
137
|
+
>>> cursor.executemany('INSERT INTO test (x) VALUES', [[200]])
|
|
138
|
+
>>> cursor.rowcount
|
|
139
|
+
1
|
|
140
|
+
>>> cursor.execute(
|
|
141
|
+
... 'INSERT INTO test (x) '
|
|
142
|
+
... 'SELECT * FROM system.numbers LIMIT %(limit)s',
|
|
143
|
+
... {'limit': 3}
|
|
144
|
+
... )
|
|
145
|
+
>>> cursor.rowcount
|
|
146
|
+
0
|
|
147
|
+
>>> cursor.execute('SELECT sum(x) FROM test')
|
|
148
|
+
>>> cursor.fetchall()
|
|
149
|
+
[(303,)]
|
|
150
|
+
|
|
151
|
+
License
|
|
152
|
+
=======
|
|
153
|
+
|
|
154
|
+
ClickHouse Python Driver is distributed under the `MIT license
|
|
155
|
+
<http://www.opensource.org/licenses/mit-license.php>`_.
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
from .columns.util import get_inner_spec, get_inner_columns_with_types
|
|
2
|
+
from .reader import read_varint, read_binary_uint8, read_binary_int32
|
|
3
|
+
from .varint import write_varint
|
|
4
|
+
from .writer import write_binary_uint8, write_binary_int32
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BlockInfo(object):
|
|
8
|
+
is_overflows = False
|
|
9
|
+
bucket_num = -1
|
|
10
|
+
|
|
11
|
+
def write(self, buf):
|
|
12
|
+
# Set of pairs (`FIELD_NUM`, value) in binary form. Then 0.
|
|
13
|
+
write_varint(1, buf)
|
|
14
|
+
write_binary_uint8(self.is_overflows, buf)
|
|
15
|
+
|
|
16
|
+
write_varint(2, buf)
|
|
17
|
+
write_binary_int32(self.bucket_num, buf)
|
|
18
|
+
|
|
19
|
+
write_varint(0, buf)
|
|
20
|
+
|
|
21
|
+
def read(self, buf):
|
|
22
|
+
while True:
|
|
23
|
+
field_num = read_varint(buf)
|
|
24
|
+
if not field_num:
|
|
25
|
+
break
|
|
26
|
+
|
|
27
|
+
if field_num == 1:
|
|
28
|
+
self.is_overflows = bool(read_binary_uint8(buf))
|
|
29
|
+
|
|
30
|
+
elif field_num == 2:
|
|
31
|
+
self.bucket_num = read_binary_int32(buf)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BaseBlock(object):
|
|
35
|
+
def __init__(self, columns_with_types=None, data=None,
|
|
36
|
+
info=None, types_check=False):
|
|
37
|
+
self.columns_with_types = columns_with_types or []
|
|
38
|
+
self.types_check = types_check
|
|
39
|
+
self.info = info or BlockInfo()
|
|
40
|
+
self.data = self.normalize(data or [])
|
|
41
|
+
|
|
42
|
+
super(BaseBlock, self).__init__()
|
|
43
|
+
|
|
44
|
+
def normalize(self, data):
|
|
45
|
+
return data
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def num_columns(self):
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def num_rows(self):
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
55
|
+
def get_columns(self):
|
|
56
|
+
raise NotImplementedError
|
|
57
|
+
|
|
58
|
+
def get_rows(self):
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
|
|
61
|
+
def get_column_by_index(self, index):
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
|
|
64
|
+
def transposed(self):
|
|
65
|
+
return list(zip(*self.data))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ColumnOrientedBlock(BaseBlock):
|
|
69
|
+
def normalize(self, data):
|
|
70
|
+
if not data:
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
self._check_number_of_columns(data)
|
|
74
|
+
self._check_all_columns_equal_length(data)
|
|
75
|
+
return data
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def num_columns(self):
|
|
79
|
+
return len(self.data)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def num_rows(self):
|
|
83
|
+
return len(self.data[0]) if self.num_columns else 0
|
|
84
|
+
|
|
85
|
+
def get_columns(self):
|
|
86
|
+
return self.data
|
|
87
|
+
|
|
88
|
+
def get_rows(self):
|
|
89
|
+
return self.transposed()
|
|
90
|
+
|
|
91
|
+
def get_column_by_index(self, index):
|
|
92
|
+
return self.data[index]
|
|
93
|
+
|
|
94
|
+
def _check_number_of_columns(self, data):
|
|
95
|
+
expected_row_len = len(self.columns_with_types)
|
|
96
|
+
|
|
97
|
+
got = len(data)
|
|
98
|
+
if expected_row_len != got:
|
|
99
|
+
msg = 'Expected {} columns, got {}'.format(expected_row_len, got)
|
|
100
|
+
raise ValueError(msg)
|
|
101
|
+
|
|
102
|
+
def _check_all_columns_equal_length(self, data):
|
|
103
|
+
expected = len(data[0])
|
|
104
|
+
|
|
105
|
+
for column in data:
|
|
106
|
+
got = len(column)
|
|
107
|
+
if got != expected:
|
|
108
|
+
msg = 'Expected {} rows, got {}'.format(expected, got)
|
|
109
|
+
raise ValueError(msg)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class RowOrientedBlock(BaseBlock):
|
|
113
|
+
dict_row_types = (dict, )
|
|
114
|
+
tuple_row_types = (list, tuple)
|
|
115
|
+
supported_row_types = dict_row_types + tuple_row_types
|
|
116
|
+
|
|
117
|
+
def normalize(self, data):
|
|
118
|
+
if not data:
|
|
119
|
+
return []
|
|
120
|
+
|
|
121
|
+
# Guessing about whole data format by first row.
|
|
122
|
+
first_row = data[0]
|
|
123
|
+
|
|
124
|
+
if self.types_check:
|
|
125
|
+
self._check_row_type(first_row)
|
|
126
|
+
|
|
127
|
+
if isinstance(first_row, dict):
|
|
128
|
+
self._mutate_dicts_to_rows(data)
|
|
129
|
+
else:
|
|
130
|
+
self._check_rows(data)
|
|
131
|
+
|
|
132
|
+
return data
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def num_columns(self):
|
|
136
|
+
if self.columns_with_types is not None:
|
|
137
|
+
return len(self.columns_with_types)
|
|
138
|
+
|
|
139
|
+
return len(self.data[0]) if self.num_rows else 0
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def num_rows(self):
|
|
143
|
+
return len(self.data)
|
|
144
|
+
|
|
145
|
+
def get_columns(self):
|
|
146
|
+
return self.transposed()
|
|
147
|
+
|
|
148
|
+
def get_rows(self):
|
|
149
|
+
return self.data
|
|
150
|
+
|
|
151
|
+
def get_column_by_index(self, index):
|
|
152
|
+
return [row[index] for row in self.data]
|
|
153
|
+
|
|
154
|
+
def _mutate_dicts_to_rows(self, data):
|
|
155
|
+
check_row_type = False
|
|
156
|
+
if self.types_check:
|
|
157
|
+
check_row_type = self._check_dict_row_type
|
|
158
|
+
|
|
159
|
+
return self._pure_mutate_dicts_to_rows(
|
|
160
|
+
data,
|
|
161
|
+
self.columns_with_types,
|
|
162
|
+
check_row_type,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def _pure_mutate_dicts_to_rows(
|
|
166
|
+
self,
|
|
167
|
+
data,
|
|
168
|
+
columns_with_types,
|
|
169
|
+
check_row_type,
|
|
170
|
+
):
|
|
171
|
+
columns_with_cwt = []
|
|
172
|
+
for name, type_ in columns_with_types:
|
|
173
|
+
cwt = None
|
|
174
|
+
if type_.startswith('Nested'):
|
|
175
|
+
inner_spec = get_inner_spec('Nested', type_)
|
|
176
|
+
cwt = get_inner_columns_with_types(inner_spec)
|
|
177
|
+
columns_with_cwt.append((name, cwt))
|
|
178
|
+
|
|
179
|
+
for i, row in enumerate(data):
|
|
180
|
+
if check_row_type:
|
|
181
|
+
check_row_type(row)
|
|
182
|
+
|
|
183
|
+
new_data = []
|
|
184
|
+
for name, cwt in columns_with_cwt:
|
|
185
|
+
if cwt is None:
|
|
186
|
+
new_data.append(row[name])
|
|
187
|
+
else:
|
|
188
|
+
new_data.append(self._pure_mutate_dicts_to_rows(
|
|
189
|
+
row[name], cwt, check_row_type
|
|
190
|
+
))
|
|
191
|
+
data[i] = new_data
|
|
192
|
+
# return for recursion
|
|
193
|
+
return data
|
|
194
|
+
|
|
195
|
+
def _check_rows(self, data):
|
|
196
|
+
expected_row_len = len(self.columns_with_types)
|
|
197
|
+
|
|
198
|
+
got = len(data[0])
|
|
199
|
+
if expected_row_len != got:
|
|
200
|
+
msg = 'Expected {} columns, got {}'.format(expected_row_len, got)
|
|
201
|
+
raise ValueError(msg)
|
|
202
|
+
|
|
203
|
+
if self.types_check:
|
|
204
|
+
check_row_type = self._check_tuple_row_type
|
|
205
|
+
for row in data:
|
|
206
|
+
check_row_type(row)
|
|
207
|
+
|
|
208
|
+
def _check_row_type(self, row):
|
|
209
|
+
if not isinstance(row, self.supported_row_types):
|
|
210
|
+
raise TypeError(
|
|
211
|
+
'Unsupported row type: {}. dict, list or tuple is expected.'
|
|
212
|
+
.format(type(row))
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def _check_tuple_row_type(self, row):
|
|
216
|
+
if not isinstance(row, self.tuple_row_types):
|
|
217
|
+
raise TypeError(
|
|
218
|
+
'Unsupported row type: {}. list or tuple is expected.'
|
|
219
|
+
.format(type(row))
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
def _check_dict_row_type(self, row):
|
|
223
|
+
if not isinstance(row, self.dict_row_types):
|
|
224
|
+
raise TypeError(
|
|
225
|
+
'Unsupported row type: {}. dict is expected.'
|
|
226
|
+
.format(type(row))
|
|
227
|
+
)
|