clickhouse-driver 0.2.1__cp39-cp39-win_amd64.whl → 0.2.10__cp39-cp39-win_amd64.whl

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.
Files changed (85) hide show
  1. clickhouse_driver/__init__.py +9 -9
  2. clickhouse_driver/block.py +227 -195
  3. clickhouse_driver/blockstreamprofileinfo.py +22 -22
  4. clickhouse_driver/bufferedreader.cp39-win_amd64.pyd +0 -0
  5. clickhouse_driver/bufferedwriter.cp39-win_amd64.pyd +0 -0
  6. clickhouse_driver/client.py +812 -666
  7. clickhouse_driver/clientinfo.py +119 -80
  8. clickhouse_driver/columns/arraycolumn.py +161 -150
  9. clickhouse_driver/columns/base.py +221 -147
  10. clickhouse_driver/columns/boolcolumn.py +7 -0
  11. clickhouse_driver/columns/datecolumn.py +108 -49
  12. clickhouse_driver/columns/datetimecolumn.py +203 -207
  13. clickhouse_driver/columns/decimalcolumn.py +116 -118
  14. clickhouse_driver/columns/enumcolumn.py +129 -119
  15. clickhouse_driver/columns/exceptions.py +12 -12
  16. clickhouse_driver/columns/floatcolumn.py +34 -34
  17. clickhouse_driver/columns/intcolumn.py +157 -157
  18. clickhouse_driver/columns/intervalcolumn.py +33 -33
  19. clickhouse_driver/columns/ipcolumn.py +118 -118
  20. clickhouse_driver/columns/jsoncolumn.py +37 -0
  21. clickhouse_driver/columns/largeint.cp39-win_amd64.pyd +0 -0
  22. clickhouse_driver/columns/lowcardinalitycolumn.py +142 -123
  23. clickhouse_driver/columns/mapcolumn.py +73 -58
  24. clickhouse_driver/columns/nestedcolumn.py +10 -0
  25. clickhouse_driver/columns/nothingcolumn.py +13 -13
  26. clickhouse_driver/columns/nullablecolumn.py +7 -7
  27. clickhouse_driver/columns/nullcolumn.py +15 -15
  28. clickhouse_driver/columns/numpy/base.py +47 -14
  29. clickhouse_driver/columns/numpy/boolcolumn.py +8 -0
  30. clickhouse_driver/columns/numpy/datecolumn.py +19 -12
  31. clickhouse_driver/columns/numpy/datetimecolumn.py +146 -145
  32. clickhouse_driver/columns/numpy/floatcolumn.py +24 -13
  33. clickhouse_driver/columns/numpy/intcolumn.py +43 -43
  34. clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +96 -83
  35. clickhouse_driver/columns/numpy/service.py +58 -80
  36. clickhouse_driver/columns/numpy/stringcolumn.py +78 -76
  37. clickhouse_driver/columns/numpy/tuplecolumn.py +37 -0
  38. clickhouse_driver/columns/service.py +185 -131
  39. clickhouse_driver/columns/simpleaggregatefunctioncolumn.py +7 -7
  40. clickhouse_driver/columns/stringcolumn.py +73 -73
  41. clickhouse_driver/columns/tuplecolumn.py +63 -65
  42. clickhouse_driver/columns/util.py +61 -0
  43. clickhouse_driver/columns/uuidcolumn.py +64 -64
  44. clickhouse_driver/compression/__init__.py +32 -28
  45. clickhouse_driver/compression/base.py +87 -52
  46. clickhouse_driver/compression/lz4.py +21 -55
  47. clickhouse_driver/compression/lz4hc.py +9 -9
  48. clickhouse_driver/compression/zstd.py +20 -51
  49. clickhouse_driver/connection.py +825 -632
  50. clickhouse_driver/context.py +36 -36
  51. clickhouse_driver/dbapi/__init__.py +62 -62
  52. clickhouse_driver/dbapi/connection.py +99 -96
  53. clickhouse_driver/dbapi/cursor.py +370 -368
  54. clickhouse_driver/dbapi/errors.py +40 -40
  55. clickhouse_driver/dbapi/extras.py +73 -0
  56. clickhouse_driver/defines.py +58 -42
  57. clickhouse_driver/errors.py +453 -446
  58. clickhouse_driver/log.py +48 -44
  59. clickhouse_driver/numpy/block.py +8 -8
  60. clickhouse_driver/numpy/helpers.py +28 -25
  61. clickhouse_driver/numpy/result.py +123 -123
  62. clickhouse_driver/opentelemetry.py +43 -0
  63. clickhouse_driver/progress.py +44 -32
  64. clickhouse_driver/protocol.py +130 -105
  65. clickhouse_driver/queryprocessingstage.py +8 -8
  66. clickhouse_driver/reader.py +69 -69
  67. clickhouse_driver/readhelpers.py +26 -26
  68. clickhouse_driver/result.py +144 -144
  69. clickhouse_driver/settings/available.py +405 -405
  70. clickhouse_driver/settings/types.py +50 -50
  71. clickhouse_driver/settings/writer.py +34 -29
  72. clickhouse_driver/streams/compressed.py +88 -88
  73. clickhouse_driver/streams/native.py +108 -90
  74. clickhouse_driver/util/compat.py +39 -0
  75. clickhouse_driver/util/escape.py +94 -55
  76. clickhouse_driver/util/helpers.py +173 -57
  77. clickhouse_driver/varint.cp39-win_amd64.pyd +0 -0
  78. clickhouse_driver/writer.py +67 -67
  79. clickhouse_driver-0.2.10.dist-info/METADATA +215 -0
  80. clickhouse_driver-0.2.10.dist-info/RECORD +89 -0
  81. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/WHEEL +1 -1
  82. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info/licenses}/LICENSE +21 -21
  83. clickhouse_driver-0.2.1.dist-info/METADATA +0 -24
  84. clickhouse_driver-0.2.1.dist-info/RECORD +0 -80
  85. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/top_level.txt +0 -0
@@ -1,55 +1,94 @@
1
- from datetime import date, datetime
2
- from enum import Enum
3
- from uuid import UUID
4
-
5
-
6
- escape_chars_map = {
7
- "\b": "\\b",
8
- "\f": "\\f",
9
- "\r": "\\r",
10
- "\n": "\\n",
11
- "\t": "\\t",
12
- "\0": "\\0",
13
- "\a": "\\a",
14
- "\v": "\\v",
15
- "\\": "\\\\",
16
- "'": "\\'"
17
- }
18
-
19
-
20
- def escape_param(item):
21
- if item is None:
22
- return 'NULL'
23
-
24
- elif isinstance(item, datetime):
25
- return "'%s'" % item.strftime('%Y-%m-%d %H:%M:%S')
26
-
27
- elif isinstance(item, date):
28
- return "'%s'" % item.strftime('%Y-%m-%d')
29
-
30
- elif isinstance(item, str):
31
- return "'%s'" % ''.join(escape_chars_map.get(c, c) for c in item)
32
-
33
- elif isinstance(item, list):
34
- return "[%s]" % ', '.join(str(escape_param(x)) for x in item)
35
-
36
- elif isinstance(item, tuple):
37
- return "(%s)" % ', '.join(str(escape_param(x)) for x in item)
38
-
39
- elif isinstance(item, Enum):
40
- return escape_param(item.value)
41
-
42
- elif isinstance(item, UUID):
43
- return "'%s'" % str(item)
44
-
45
- else:
46
- return item
47
-
48
-
49
- def escape_params(params):
50
- escaped = {}
51
-
52
- for key, value in params.items():
53
- escaped[key] = escape_param(value)
54
-
55
- return escaped
1
+ from datetime import date, datetime, time
2
+ from enum import Enum
3
+ from functools import wraps
4
+ from uuid import UUID
5
+
6
+ from pytz import timezone
7
+
8
+
9
+ escape_chars_map = {
10
+ "\b": "\\b",
11
+ "\f": "\\f",
12
+ "\r": "\\r",
13
+ "\n": "\\n",
14
+ "\t": "\\t",
15
+ "\0": "\\0",
16
+ "\a": "\\a",
17
+ "\v": "\\v",
18
+ "\\": "\\\\",
19
+ "'": "\\'"
20
+ }
21
+
22
+
23
+ def escape_datetime(item, context):
24
+ server_tz = timezone(context.server_info.get_timezone())
25
+
26
+ if item.tzinfo is not None:
27
+ item = item.astimezone(server_tz)
28
+
29
+ return "'%s'" % item.strftime('%Y-%m-%d %H:%M:%S')
30
+
31
+
32
+ def maybe_enquote_for_server(f):
33
+ @wraps(f)
34
+ def wrapper(*args, **kwargs):
35
+ rv = f(*args, **kwargs)
36
+
37
+ if kwargs.get('for_server'):
38
+ is_str = isinstance(rv, str)
39
+
40
+ if not is_str or (is_str and not rv.startswith("'")):
41
+ rv = "'%s'" % rv
42
+
43
+ return rv
44
+
45
+ return wrapper
46
+
47
+
48
+ @maybe_enquote_for_server
49
+ def escape_param(item, context, for_server=False):
50
+ if item is None:
51
+ return 'NULL'
52
+
53
+ elif isinstance(item, datetime):
54
+ return escape_datetime(item, context)
55
+
56
+ elif isinstance(item, date):
57
+ return "'%s'" % item.strftime('%Y-%m-%d')
58
+
59
+ elif isinstance(item, time):
60
+ return "'%s'" % item.strftime('%H:%M:%S')
61
+
62
+ elif isinstance(item, str):
63
+ # We need double escaping for server-side parameters.
64
+ if for_server:
65
+ item = ''.join(escape_chars_map.get(c, c) for c in item)
66
+ return "'%s'" % ''.join(escape_chars_map.get(c, c) for c in item)
67
+
68
+ elif isinstance(item, list):
69
+ return "[%s]" % ', '.join(
70
+ str(escape_param(x, context, for_server=for_server)) for x in item
71
+ )
72
+
73
+ elif isinstance(item, tuple):
74
+ return "(%s)" % ', '.join(
75
+ str(escape_param(x, context, for_server=for_server)) for x in item
76
+ )
77
+
78
+ elif isinstance(item, Enum):
79
+ return escape_param(item.value, context, for_server=for_server)
80
+
81
+ elif isinstance(item, UUID):
82
+ return "'%s'" % str(item)
83
+
84
+ else:
85
+ return item
86
+
87
+
88
+ def escape_params(params, context, for_server=False):
89
+ escaped = {}
90
+
91
+ for key, value in params.items():
92
+ escaped[key] = escape_param(value, context, for_server=for_server)
93
+
94
+ return escaped
@@ -1,57 +1,173 @@
1
- from itertools import islice, tee
2
-
3
-
4
- def chunks(seq, n):
5
- # islice is MUCH slower than slice for lists and tuples.
6
- if isinstance(seq, (list, tuple)):
7
- i = 0
8
- item = seq[i:i+n]
9
- while item:
10
- yield list(item)
11
- i += n
12
- item = seq[i:i+n]
13
-
14
- else:
15
- it = iter(seq)
16
- item = list(islice(it, n))
17
- while item:
18
- yield item
19
- item = list(islice(it, n))
20
-
21
-
22
- def pairwise(iterable):
23
- a, b = tee(iterable)
24
- next(b, None)
25
- return zip(a, b)
26
-
27
-
28
- def column_chunks(columns, n):
29
- for column in columns:
30
- if not isinstance(column, (list, tuple)):
31
- raise TypeError(
32
- 'Unsupported column type: {}. list or tuple is expected.'
33
- .format(type(column))
34
- )
35
-
36
- # create chunk generator for every column
37
- g = [chunks(column, n) for column in columns]
38
-
39
- while True:
40
- # get next chunk for every column
41
- item = [next(column, []) for column in g]
42
- if not any(item):
43
- break
44
- yield item
45
-
46
-
47
- # from paste.deploy.converters
48
- def asbool(obj):
49
- if isinstance(obj, str):
50
- obj = obj.strip().lower()
51
- if obj in ['true', 'yes', 'on', 'y', 't', '1']:
52
- return True
53
- elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
54
- return False
55
- else:
56
- raise ValueError('String is not true/false: %r' % obj)
57
- return bool(obj)
1
+ import ssl
2
+ from itertools import islice, tee
3
+ from urllib.parse import urlparse, parse_qs, unquote
4
+
5
+
6
+ def chunks(seq, n):
7
+ # islice is MUCH slower than slice for lists and tuples.
8
+ if isinstance(seq, (list, tuple)):
9
+ i = 0
10
+ item = seq[i:i+n]
11
+ while item:
12
+ yield list(item)
13
+ i += n
14
+ item = seq[i:i+n]
15
+
16
+ else:
17
+ it = iter(seq)
18
+ item = list(islice(it, n))
19
+ while item:
20
+ yield item
21
+ item = list(islice(it, n))
22
+
23
+
24
+ def pairwise(iterable):
25
+ a, b = tee(iterable)
26
+ next(b, None)
27
+ return zip(a, b)
28
+
29
+
30
+ def column_chunks(columns, n):
31
+ for column in columns:
32
+ if not isinstance(column, (list, tuple)):
33
+ raise TypeError(
34
+ 'Unsupported column type: {}. list or tuple is expected.'
35
+ .format(type(column))
36
+ )
37
+
38
+ # create chunk generator for every column
39
+ g = [chunks(column, n) for column in columns]
40
+
41
+ while True:
42
+ # get next chunk for every column
43
+ item = [next(column, []) for column in g]
44
+ if not any(item):
45
+ break
46
+ yield item
47
+
48
+
49
+ # from paste.deploy.converters
50
+ def asbool(obj):
51
+ if isinstance(obj, str):
52
+ obj = obj.strip().lower()
53
+ if obj in ['true', 'yes', 'on', 'y', 't', '1']:
54
+ return True
55
+ elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
56
+ return False
57
+ else:
58
+ raise ValueError('String is not true/false: %r' % obj)
59
+ return bool(obj)
60
+
61
+
62
+ def parse_url(url):
63
+ """
64
+ Parses url into host and kwargs suitable for further Client construction.
65
+ Return host and kwargs.
66
+
67
+ For example::
68
+
69
+ clickhouse://[user:password]@localhost:9000/default
70
+ clickhouses://[user:password]@localhost:9440/default
71
+
72
+ Three URL schemes are supported:
73
+
74
+ * clickhouse:// creates a normal TCP socket connection
75
+ * clickhouses:// creates a SSL wrapped TCP socket connection
76
+
77
+ Any additional querystring arguments will be passed along to
78
+ the Connection class's initializer.
79
+ """
80
+ url = urlparse(url)
81
+
82
+ settings = {}
83
+ kwargs = {}
84
+
85
+ host = url.hostname
86
+
87
+ if url.port is not None:
88
+ kwargs['port'] = url.port
89
+
90
+ path = url.path.replace('/', '', 1)
91
+ if path:
92
+ kwargs['database'] = path
93
+
94
+ if url.username is not None:
95
+ kwargs['user'] = unquote(url.username)
96
+
97
+ if url.password is not None:
98
+ kwargs['password'] = unquote(url.password)
99
+
100
+ if url.scheme == 'clickhouses':
101
+ kwargs['secure'] = True
102
+
103
+ compression_algs = {'lz4', 'lz4hc', 'zstd'}
104
+ timeouts = {
105
+ 'connect_timeout',
106
+ 'send_receive_timeout',
107
+ 'sync_request_timeout'
108
+ }
109
+
110
+ for name, value in parse_qs(url.query).items():
111
+ if not value or not len(value):
112
+ continue
113
+
114
+ value = value[0]
115
+
116
+ if name == 'compression':
117
+ value = value.lower()
118
+ if value in compression_algs:
119
+ kwargs[name] = value
120
+ else:
121
+ kwargs[name] = asbool(value)
122
+
123
+ elif name == 'secure':
124
+ kwargs[name] = asbool(value)
125
+
126
+ elif name == 'use_numpy':
127
+ settings[name] = asbool(value)
128
+
129
+ elif name == 'round_robin':
130
+ kwargs[name] = asbool(value)
131
+
132
+ elif name == 'client_name':
133
+ kwargs[name] = value
134
+
135
+ elif name in timeouts:
136
+ kwargs[name] = float(value)
137
+
138
+ elif name == 'compress_block_size':
139
+ kwargs[name] = int(value)
140
+
141
+ elif name == 'settings_is_important':
142
+ kwargs[name] = asbool(value)
143
+
144
+ elif name == 'tcp_keepalive':
145
+ try:
146
+ kwargs[name] = asbool(value)
147
+ except ValueError:
148
+ parts = value.split(',')
149
+ kwargs[name] = (
150
+ int(parts[0]), int(parts[1]), int(parts[2])
151
+ )
152
+ elif name == 'client_revision':
153
+ kwargs[name] = int(value)
154
+
155
+ # ssl
156
+ elif name == 'verify':
157
+ kwargs[name] = asbool(value)
158
+ elif name == 'check_hostname':
159
+ kwargs[name] = asbool(value)
160
+ elif name == 'ssl_version':
161
+ kwargs[name] = getattr(ssl, value)
162
+ elif name in ['ca_certs', 'ciphers', 'keyfile', 'keypass', 'certfile',
163
+ 'server_hostname']:
164
+ kwargs[name] = value
165
+ elif name == 'alt_hosts':
166
+ kwargs['alt_hosts'] = value
167
+ else:
168
+ settings[name] = value
169
+
170
+ if settings:
171
+ kwargs['settings'] = settings
172
+
173
+ return host, kwargs
Binary file
@@ -1,67 +1,67 @@
1
- import struct
2
-
3
- from .varint import write_varint
4
-
5
-
6
- MAX_UINT64 = (1 << 64) - 1
7
- MAX_INT64 = (1 << 63) - 1
8
-
9
-
10
- def _byte(b):
11
- return bytes((b, ))
12
-
13
-
14
- def write_binary_str(text, buf):
15
- text = text.encode('utf-8')
16
- write_binary_bytes(text, buf)
17
-
18
-
19
- def write_binary_bytes(text, buf):
20
- write_varint(len(text), buf)
21
- buf.write(text)
22
-
23
-
24
- def write_binary_int(number, buf, fmt):
25
- """
26
- Writes int from buffer with provided format.
27
- """
28
- fmt = '<' + fmt
29
- buf.write(struct.pack(fmt, number))
30
-
31
-
32
- def write_binary_int8(number, buf):
33
- write_binary_int(number, buf, 'b')
34
-
35
-
36
- def write_binary_int16(number, buf):
37
- write_binary_int(number, buf, 'h')
38
-
39
-
40
- def write_binary_int32(number, buf):
41
- write_binary_int(number, buf, 'i')
42
-
43
-
44
- def write_binary_int64(number, buf):
45
- write_binary_int(number, buf, 'q')
46
-
47
-
48
- def write_binary_uint8(number, buf):
49
- write_binary_int(number, buf, 'B')
50
-
51
-
52
- def write_binary_uint16(number, buf):
53
- write_binary_int(number, buf, 'H')
54
-
55
-
56
- def write_binary_uint32(number, buf):
57
- write_binary_int(number, buf, 'I')
58
-
59
-
60
- def write_binary_uint64(number, buf):
61
- write_binary_int(number, buf, 'Q')
62
-
63
-
64
- def write_binary_uint128(number, buf):
65
- fmt = '<QQ'
66
- packed = struct.pack(fmt, (number >> 64) & MAX_UINT64, number & MAX_UINT64)
67
- buf.write(packed)
1
+ import struct
2
+
3
+ from .varint import write_varint
4
+
5
+
6
+ MAX_UINT64 = (1 << 64) - 1
7
+ MAX_INT64 = (1 << 63) - 1
8
+
9
+
10
+ def _byte(b):
11
+ return bytes((b, ))
12
+
13
+
14
+ def write_binary_str(text, buf):
15
+ text = text.encode('utf-8')
16
+ write_binary_bytes(text, buf)
17
+
18
+
19
+ def write_binary_bytes(text, buf):
20
+ write_varint(len(text), buf)
21
+ buf.write(text)
22
+
23
+
24
+ def write_binary_int(number, buf, fmt):
25
+ """
26
+ Writes int from buffer with provided format.
27
+ """
28
+ fmt = '<' + fmt
29
+ buf.write(struct.pack(fmt, number))
30
+
31
+
32
+ def write_binary_int8(number, buf):
33
+ write_binary_int(number, buf, 'b')
34
+
35
+
36
+ def write_binary_int16(number, buf):
37
+ write_binary_int(number, buf, 'h')
38
+
39
+
40
+ def write_binary_int32(number, buf):
41
+ write_binary_int(number, buf, 'i')
42
+
43
+
44
+ def write_binary_int64(number, buf):
45
+ write_binary_int(number, buf, 'q')
46
+
47
+
48
+ def write_binary_uint8(number, buf):
49
+ write_binary_int(number, buf, 'B')
50
+
51
+
52
+ def write_binary_uint16(number, buf):
53
+ write_binary_int(number, buf, 'H')
54
+
55
+
56
+ def write_binary_uint32(number, buf):
57
+ write_binary_int(number, buf, 'I')
58
+
59
+
60
+ def write_binary_uint64(number, buf):
61
+ write_binary_int(number, buf, 'Q')
62
+
63
+
64
+ def write_binary_uint128(number, buf):
65
+ fmt = '<QQ'
66
+ packed = struct.pack(fmt, (number >> 64) & MAX_UINT64, number & MAX_UINT64)
67
+ buf.write(packed)