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.
- clickhouse_driver/__init__.py +9 -9
- clickhouse_driver/block.py +227 -195
- clickhouse_driver/blockstreamprofileinfo.py +22 -22
- clickhouse_driver/bufferedreader.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/bufferedwriter.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/client.py +812 -666
- clickhouse_driver/clientinfo.py +119 -80
- clickhouse_driver/columns/arraycolumn.py +161 -150
- clickhouse_driver/columns/base.py +221 -147
- clickhouse_driver/columns/boolcolumn.py +7 -0
- clickhouse_driver/columns/datecolumn.py +108 -49
- clickhouse_driver/columns/datetimecolumn.py +203 -207
- clickhouse_driver/columns/decimalcolumn.py +116 -118
- clickhouse_driver/columns/enumcolumn.py +129 -119
- clickhouse_driver/columns/exceptions.py +12 -12
- clickhouse_driver/columns/floatcolumn.py +34 -34
- clickhouse_driver/columns/intcolumn.py +157 -157
- clickhouse_driver/columns/intervalcolumn.py +33 -33
- clickhouse_driver/columns/ipcolumn.py +118 -118
- clickhouse_driver/columns/jsoncolumn.py +37 -0
- clickhouse_driver/columns/largeint.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/columns/lowcardinalitycolumn.py +142 -123
- clickhouse_driver/columns/mapcolumn.py +73 -58
- clickhouse_driver/columns/nestedcolumn.py +10 -0
- clickhouse_driver/columns/nothingcolumn.py +13 -13
- clickhouse_driver/columns/nullablecolumn.py +7 -7
- clickhouse_driver/columns/nullcolumn.py +15 -15
- clickhouse_driver/columns/numpy/base.py +47 -14
- clickhouse_driver/columns/numpy/boolcolumn.py +8 -0
- clickhouse_driver/columns/numpy/datecolumn.py +19 -12
- clickhouse_driver/columns/numpy/datetimecolumn.py +146 -145
- clickhouse_driver/columns/numpy/floatcolumn.py +24 -13
- clickhouse_driver/columns/numpy/intcolumn.py +43 -43
- clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +96 -83
- clickhouse_driver/columns/numpy/service.py +58 -80
- clickhouse_driver/columns/numpy/stringcolumn.py +78 -76
- clickhouse_driver/columns/numpy/tuplecolumn.py +37 -0
- clickhouse_driver/columns/service.py +185 -131
- clickhouse_driver/columns/simpleaggregatefunctioncolumn.py +7 -7
- clickhouse_driver/columns/stringcolumn.py +73 -73
- clickhouse_driver/columns/tuplecolumn.py +63 -65
- clickhouse_driver/columns/util.py +61 -0
- clickhouse_driver/columns/uuidcolumn.py +64 -64
- clickhouse_driver/compression/__init__.py +32 -28
- clickhouse_driver/compression/base.py +87 -52
- clickhouse_driver/compression/lz4.py +21 -55
- clickhouse_driver/compression/lz4hc.py +9 -9
- clickhouse_driver/compression/zstd.py +20 -51
- clickhouse_driver/connection.py +825 -632
- clickhouse_driver/context.py +36 -36
- clickhouse_driver/dbapi/__init__.py +62 -62
- clickhouse_driver/dbapi/connection.py +99 -96
- clickhouse_driver/dbapi/cursor.py +370 -368
- clickhouse_driver/dbapi/errors.py +40 -40
- clickhouse_driver/dbapi/extras.py +73 -0
- clickhouse_driver/defines.py +58 -42
- clickhouse_driver/errors.py +453 -446
- clickhouse_driver/log.py +48 -44
- clickhouse_driver/numpy/block.py +8 -8
- clickhouse_driver/numpy/helpers.py +28 -25
- clickhouse_driver/numpy/result.py +123 -123
- clickhouse_driver/opentelemetry.py +43 -0
- clickhouse_driver/progress.py +44 -32
- clickhouse_driver/protocol.py +130 -105
- clickhouse_driver/queryprocessingstage.py +8 -8
- clickhouse_driver/reader.py +69 -69
- clickhouse_driver/readhelpers.py +26 -26
- clickhouse_driver/result.py +144 -144
- clickhouse_driver/settings/available.py +405 -405
- clickhouse_driver/settings/types.py +50 -50
- clickhouse_driver/settings/writer.py +34 -29
- clickhouse_driver/streams/compressed.py +88 -88
- clickhouse_driver/streams/native.py +108 -90
- clickhouse_driver/util/compat.py +39 -0
- clickhouse_driver/util/escape.py +94 -55
- clickhouse_driver/util/helpers.py +173 -57
- clickhouse_driver/varint.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/writer.py +67 -67
- clickhouse_driver-0.2.10.dist-info/METADATA +215 -0
- clickhouse_driver-0.2.10.dist-info/RECORD +89 -0
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/WHEEL +1 -1
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info/licenses}/LICENSE +21 -21
- clickhouse_driver-0.2.1.dist-info/METADATA +0 -24
- clickhouse_driver-0.2.1.dist-info/RECORD +0 -80
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/top_level.txt +0 -0
|
@@ -1,58 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
from .
|
|
3
|
-
from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def
|
|
16
|
-
self.
|
|
17
|
-
self.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
offsets =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
1
|
+
import re
|
|
2
|
+
from .base import Column
|
|
3
|
+
from .intcolumn import UInt64Column
|
|
4
|
+
from ..util.helpers import pairwise
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
comma_re = re.compile(r',(?![^()]*\))')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MapColumn(Column):
|
|
11
|
+
py_types = (dict, )
|
|
12
|
+
|
|
13
|
+
null_value = {}
|
|
14
|
+
|
|
15
|
+
def __init__(self, key_column, value_column, **kwargs):
|
|
16
|
+
self.offset_column = UInt64Column(**kwargs)
|
|
17
|
+
self.key_column = key_column
|
|
18
|
+
self.value_column = value_column
|
|
19
|
+
super(MapColumn, self).__init__(**kwargs)
|
|
20
|
+
|
|
21
|
+
def read_state_prefix(self, buf):
|
|
22
|
+
super(MapColumn, self).read_state_prefix(buf)
|
|
23
|
+
|
|
24
|
+
self.key_column.read_state_prefix(buf)
|
|
25
|
+
self.value_column.read_state_prefix(buf)
|
|
26
|
+
|
|
27
|
+
def write_state_prefix(self, buf):
|
|
28
|
+
super(MapColumn, self).write_state_prefix(buf)
|
|
29
|
+
|
|
30
|
+
self.key_column.write_state_prefix(buf)
|
|
31
|
+
self.value_column.write_state_prefix(buf)
|
|
32
|
+
|
|
33
|
+
def read_items(self, n_items, buf):
|
|
34
|
+
if not n_items:
|
|
35
|
+
return [{}]
|
|
36
|
+
|
|
37
|
+
offsets = list(self.offset_column.read_items(n_items, buf))
|
|
38
|
+
last_offset = offsets[-1]
|
|
39
|
+
keys = self.key_column.read_data(last_offset, buf)
|
|
40
|
+
values = self.value_column.read_data(last_offset, buf)
|
|
41
|
+
|
|
42
|
+
offsets.insert(0, 0)
|
|
43
|
+
|
|
44
|
+
return [
|
|
45
|
+
dict(zip(keys[begin:end], values[begin:end]))
|
|
46
|
+
for begin, end in pairwise(offsets)
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def write_items(self, items, buf):
|
|
50
|
+
offsets = []
|
|
51
|
+
keys = []
|
|
52
|
+
values = []
|
|
53
|
+
|
|
54
|
+
total = 0
|
|
55
|
+
for x in items:
|
|
56
|
+
total += len(x)
|
|
57
|
+
offsets.append(total)
|
|
58
|
+
keys.extend(x.keys())
|
|
59
|
+
values.extend(x.values())
|
|
60
|
+
|
|
61
|
+
self.offset_column.write_items(offsets, buf)
|
|
62
|
+
self.key_column.write_data(keys, buf)
|
|
63
|
+
self.value_column.write_data(values, buf)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def create_map_column(spec, column_by_spec_getter, column_options):
|
|
67
|
+
# Match commas outside of parentheses, so we don't match the comma in
|
|
68
|
+
# Decimal types.
|
|
69
|
+
key, value = comma_re.split(spec[4:-1])
|
|
70
|
+
key_column = column_by_spec_getter(key.strip())
|
|
71
|
+
value_column = column_by_spec_getter(value.strip())
|
|
72
|
+
|
|
73
|
+
return MapColumn(key_column, value_column, **column_options)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
from .arraycolumn import create_array_column
|
|
3
|
+
from .util import get_inner_spec
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_nested_column(spec, column_by_spec_getter, column_options):
|
|
7
|
+
return create_array_column(
|
|
8
|
+
'Array(Tuple({}))'.format(get_inner_spec('Nested', spec)),
|
|
9
|
+
column_by_spec_getter, column_options
|
|
10
|
+
)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
from .intcolumn import FormatColumn
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class NothingColumn(FormatColumn):
|
|
5
|
-
ch_type = 'Nothing'
|
|
6
|
-
format = 'B'
|
|
7
|
-
|
|
8
|
-
@property
|
|
9
|
-
def size(self):
|
|
10
|
-
return 1
|
|
11
|
-
|
|
12
|
-
def after_read_items(self, items, nulls_map=None):
|
|
13
|
-
return (None, ) * len(items)
|
|
1
|
+
from .intcolumn import FormatColumn
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class NothingColumn(FormatColumn):
|
|
5
|
+
ch_type = 'Nothing'
|
|
6
|
+
format = 'B'
|
|
7
|
+
|
|
8
|
+
@property
|
|
9
|
+
def size(self):
|
|
10
|
+
return 1
|
|
11
|
+
|
|
12
|
+
def after_read_items(self, items, nulls_map=None):
|
|
13
|
+
return (None, ) * len(items)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
def create_nullable_column(spec, column_by_spec_getter):
|
|
4
|
-
inner = spec[9:-1]
|
|
5
|
-
nested = column_by_spec_getter(inner)
|
|
6
|
-
nested.nullable = True
|
|
7
|
-
return nested
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
def create_nullable_column(spec, column_by_spec_getter):
|
|
4
|
+
inner = spec[9:-1]
|
|
5
|
+
nested = column_by_spec_getter(inner)
|
|
6
|
+
nested.nullable = True
|
|
7
|
+
return nested
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
from .intcolumn import FormatColumn
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# TODO: Drop Null column support in future.
|
|
5
|
-
# Compatibility with old servers.
|
|
6
|
-
class NullColumn(FormatColumn):
|
|
7
|
-
ch_type = 'Null'
|
|
8
|
-
format = 'B'
|
|
9
|
-
|
|
10
|
-
@property
|
|
11
|
-
def size(self):
|
|
12
|
-
return 1
|
|
13
|
-
|
|
14
|
-
def after_read_items(self, items, nulls_map=None):
|
|
15
|
-
return (None, ) * len(items)
|
|
1
|
+
from .intcolumn import FormatColumn
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# TODO: Drop Null column support in future.
|
|
5
|
+
# Compatibility with old servers.
|
|
6
|
+
class NullColumn(FormatColumn):
|
|
7
|
+
ch_type = 'Null'
|
|
8
|
+
format = 'B'
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def size(self):
|
|
12
|
+
return 1
|
|
13
|
+
|
|
14
|
+
def after_read_items(self, items, nulls_map=None):
|
|
15
|
+
return (None, ) * len(items)
|
|
@@ -1,14 +1,47 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
from ..base import Column
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class NumpyColumn(Column):
|
|
8
|
+
dtype = None
|
|
9
|
+
|
|
10
|
+
normalize_null_value = True
|
|
11
|
+
|
|
12
|
+
def read_items(self, n_items, buf):
|
|
13
|
+
data = buf.read(n_items * self.dtype.itemsize)
|
|
14
|
+
return np.frombuffer(data, self.dtype.newbyteorder('<'), n_items)
|
|
15
|
+
|
|
16
|
+
def write_items(self, items, buf):
|
|
17
|
+
buf.write(items.astype(self.dtype.newbyteorder('<')).tobytes())
|
|
18
|
+
|
|
19
|
+
def _write_nulls_map(self, items, buf):
|
|
20
|
+
s = self.make_null_struct(len(items))
|
|
21
|
+
nulls_map = self._get_nulls_map(items)
|
|
22
|
+
buf.write(s.pack(*nulls_map))
|
|
23
|
+
|
|
24
|
+
def _get_nulls_map(self, items):
|
|
25
|
+
return [bool(x) for x in pd.isnull(items)]
|
|
26
|
+
|
|
27
|
+
def _read_data(self, n_items, buf, nulls_map=None):
|
|
28
|
+
items = self.read_items(n_items, buf)
|
|
29
|
+
|
|
30
|
+
if self.after_read_items:
|
|
31
|
+
return self.after_read_items(items, nulls_map)
|
|
32
|
+
elif nulls_map is not None:
|
|
33
|
+
items = np.array(items, dtype=object)
|
|
34
|
+
np.place(items, nulls_map, None)
|
|
35
|
+
|
|
36
|
+
return items
|
|
37
|
+
|
|
38
|
+
def prepare_items(self, items):
|
|
39
|
+
nulls_map = pd.isnull(items)
|
|
40
|
+
|
|
41
|
+
# Always replace null values to null_value for proper inserts into
|
|
42
|
+
# non-nullable columns.
|
|
43
|
+
if isinstance(items, np.ndarray) and self.normalize_null_value:
|
|
44
|
+
items = np.array(items)
|
|
45
|
+
np.place(items, nulls_map, self.null_value)
|
|
46
|
+
|
|
47
|
+
return items
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
from .base import NumpyColumn
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class NumpyDateColumn(NumpyColumn):
|
|
7
|
-
dtype = np.dtype(np.uint16)
|
|
8
|
-
ch_type = 'Date'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from .base import NumpyColumn
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NumpyDateColumn(NumpyColumn):
|
|
7
|
+
dtype = np.dtype(np.uint16)
|
|
8
|
+
ch_type = 'Date'
|
|
9
|
+
|
|
10
|
+
null_value = np.datetime64(0, 'Y')
|
|
11
|
+
|
|
12
|
+
def read_items(self, n_items, buf):
|
|
13
|
+
data = super(NumpyDateColumn, self).read_items(n_items, buf)
|
|
14
|
+
return data.astype('datetime64[D]')
|
|
15
|
+
|
|
16
|
+
def write_items(self, items, buf):
|
|
17
|
+
super(NumpyDateColumn, self).write_items(
|
|
18
|
+
items.astype('datetime64[D]'), buf
|
|
19
|
+
)
|
|
@@ -1,145 +1,146 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import pandas as pd
|
|
3
|
-
from pytz import timezone as get_timezone
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from .
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class NumpyDateTimeColumnBase(NumpyColumn):
|
|
10
|
-
datetime_dtype = None
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
self.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if self.offset_naive:
|
|
25
|
-
ts =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def
|
|
76
|
-
scale =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
seconds
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# Use column's timezone if it's specified.
|
|
133
|
-
if spec and spec[-1] == ')':
|
|
134
|
-
tz_name = spec[1:-2]
|
|
135
|
-
offset_naive = False
|
|
136
|
-
else:
|
|
137
|
-
if not context.settings.get('use_client_time_zone', False):
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from pytz import timezone as get_timezone
|
|
4
|
+
|
|
5
|
+
from .base import NumpyColumn
|
|
6
|
+
from ...util.compat import get_localzone_name_compat
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NumpyDateTimeColumnBase(NumpyColumn):
|
|
10
|
+
datetime_dtype = None
|
|
11
|
+
|
|
12
|
+
null_value = np.datetime64(0, 'Y')
|
|
13
|
+
|
|
14
|
+
def __init__(self, timezone=None, offset_naive=True, local_timezone=None,
|
|
15
|
+
**kwargs):
|
|
16
|
+
self.timezone = timezone
|
|
17
|
+
self.offset_naive = offset_naive
|
|
18
|
+
self.local_timezone = local_timezone
|
|
19
|
+
super(NumpyDateTimeColumnBase, self).__init__(**kwargs)
|
|
20
|
+
|
|
21
|
+
def apply_timezones_after_read(self, dt):
|
|
22
|
+
timezone = self.timezone if self.timezone else self.local_timezone
|
|
23
|
+
|
|
24
|
+
if self.offset_naive and timezone.zone != 'UTC':
|
|
25
|
+
ts = pd.to_datetime(dt, utc=True).tz_convert(timezone)
|
|
26
|
+
ts = ts.tz_localize(None)
|
|
27
|
+
return ts.to_numpy(self.datetime_dtype)
|
|
28
|
+
|
|
29
|
+
return dt
|
|
30
|
+
|
|
31
|
+
def apply_timezones_before_write(self, items):
|
|
32
|
+
if isinstance(items, pd.DatetimeIndex):
|
|
33
|
+
ts = items
|
|
34
|
+
else:
|
|
35
|
+
timezone = self.timezone if self.timezone else self.local_timezone
|
|
36
|
+
ts = pd.to_datetime(items)
|
|
37
|
+
if not getattr(ts.dtype, 'tz', None):
|
|
38
|
+
ts = ts.tz_localize(timezone)
|
|
39
|
+
|
|
40
|
+
ts = ts.tz_convert('UTC')
|
|
41
|
+
return ts.tz_localize(None).to_numpy(self.datetime_dtype)
|
|
42
|
+
|
|
43
|
+
def is_items_integer(self, items):
|
|
44
|
+
return (
|
|
45
|
+
isinstance(items, np.ndarray) and
|
|
46
|
+
np.issubdtype(items.dtype, np.integer)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class NumpyDateTimeColumn(NumpyDateTimeColumnBase):
|
|
51
|
+
dtype = np.dtype(np.uint32)
|
|
52
|
+
datetime_dtype = 'datetime64[s]'
|
|
53
|
+
|
|
54
|
+
def write_items(self, items, buf):
|
|
55
|
+
# write int 'as is'.
|
|
56
|
+
if self.is_items_integer(items):
|
|
57
|
+
super(NumpyDateTimeColumn, self).write_items(items, buf)
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
items = self.apply_timezones_before_write(items)
|
|
61
|
+
|
|
62
|
+
super(NumpyDateTimeColumn, self).write_items(items, buf)
|
|
63
|
+
|
|
64
|
+
def read_items(self, n_items, buf):
|
|
65
|
+
items = super(NumpyDateTimeColumn, self).read_items(n_items, buf)
|
|
66
|
+
return self.apply_timezones_after_read(items.astype('datetime64[s]'))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class NumpyDateTime64Column(NumpyDateTimeColumnBase):
|
|
70
|
+
dtype = np.dtype(np.int64)
|
|
71
|
+
datetime_dtype = 'datetime64[ns]'
|
|
72
|
+
|
|
73
|
+
max_scale = 9
|
|
74
|
+
|
|
75
|
+
def __init__(self, scale=0, **kwargs):
|
|
76
|
+
self.scale = scale
|
|
77
|
+
super(NumpyDateTime64Column, self).__init__(**kwargs)
|
|
78
|
+
|
|
79
|
+
def read_items(self, n_items, buf):
|
|
80
|
+
# Clickhouse: t seconds is represented as t * 10^scale.
|
|
81
|
+
# datetime64[ns]: t seconds is represented as t * 10^9.
|
|
82
|
+
# Since 0 <= scale <= 9, multiply by the integer 10^(9 - scale).
|
|
83
|
+
items = super(NumpyDateTime64Column, self).read_items(n_items, buf)
|
|
84
|
+
|
|
85
|
+
tmp = np.copy(items)
|
|
86
|
+
tmp *= 10 ** (9 - self.scale)
|
|
87
|
+
dt = tmp.view(dtype='datetime64[ns]')
|
|
88
|
+
|
|
89
|
+
return self.apply_timezones_after_read(dt)
|
|
90
|
+
|
|
91
|
+
def write_items(self, items, buf):
|
|
92
|
+
# write int 'as is'.
|
|
93
|
+
if self.is_items_integer(items):
|
|
94
|
+
super(NumpyDateTime64Column, self).write_items(items, buf)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
scale = 10 ** self.scale
|
|
98
|
+
frac_scale = 10 ** (self.max_scale - self.scale)
|
|
99
|
+
|
|
100
|
+
items = self.apply_timezones_before_write(items)
|
|
101
|
+
|
|
102
|
+
seconds = items.astype('datetime64[s]')
|
|
103
|
+
microseconds = (items - seconds).astype(dtype='timedelta64[ns]') \
|
|
104
|
+
.astype(np.uint32) // frac_scale
|
|
105
|
+
|
|
106
|
+
items = seconds.astype(self.dtype) * scale + microseconds
|
|
107
|
+
|
|
108
|
+
super(NumpyDateTime64Column, self).write_items(items, buf)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def create_numpy_datetime_column(spec, column_options):
|
|
112
|
+
if spec.startswith('DateTime64'):
|
|
113
|
+
cls = NumpyDateTime64Column
|
|
114
|
+
spec = spec[11:-1]
|
|
115
|
+
params = spec.split(',', 1)
|
|
116
|
+
column_options['scale'] = int(params[0])
|
|
117
|
+
if len(params) > 1:
|
|
118
|
+
spec = params[1].strip() + ')'
|
|
119
|
+
else:
|
|
120
|
+
cls = NumpyDateTimeColumn
|
|
121
|
+
spec = spec[9:]
|
|
122
|
+
|
|
123
|
+
context = column_options['context']
|
|
124
|
+
|
|
125
|
+
tz_name = None
|
|
126
|
+
offset_naive = True
|
|
127
|
+
|
|
128
|
+
# As Numpy do not use local timezone for converting timestamp to
|
|
129
|
+
# datetime we need always detect local timezone for manual converting.
|
|
130
|
+
local_tz_name = get_localzone_name_compat()
|
|
131
|
+
|
|
132
|
+
# Use column's timezone if it's specified.
|
|
133
|
+
if spec and spec[-1] == ')':
|
|
134
|
+
tz_name = spec[1:-2]
|
|
135
|
+
offset_naive = False
|
|
136
|
+
else:
|
|
137
|
+
if not context.settings.get('use_client_time_zone', False):
|
|
138
|
+
remote_timezone = context.server_info.get_timezone()
|
|
139
|
+
if local_tz_name != remote_timezone:
|
|
140
|
+
tz_name = remote_timezone
|
|
141
|
+
|
|
142
|
+
timezone = get_timezone(tz_name) if tz_name else None
|
|
143
|
+
local_timezone = get_timezone(local_tz_name) if local_tz_name else None
|
|
144
|
+
|
|
145
|
+
return cls(timezone=timezone, offset_naive=offset_naive,
|
|
146
|
+
local_timezone=local_timezone, **column_options)
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
from .base import NumpyColumn
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from .base import NumpyColumn
|
|
4
|
+
|
|
5
|
+
# normalize_null_value = False due to float('nan')
|
|
6
|
+
# With normalization pandas.isnull will threat float('nan') as NULL value.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NumpyFloat32Column(NumpyColumn):
|
|
10
|
+
dtype = np.dtype(np.float32)
|
|
11
|
+
ch_type = 'Float32'
|
|
12
|
+
normalize_null_value = False
|
|
13
|
+
|
|
14
|
+
def _get_nulls_map(self, items):
|
|
15
|
+
return [x is None for x in items]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NumpyFloat64Column(NumpyColumn):
|
|
19
|
+
dtype = np.dtype(np.float64)
|
|
20
|
+
ch_type = 'Float64'
|
|
21
|
+
normalize_null_value = False
|
|
22
|
+
|
|
23
|
+
def _get_nulls_map(self, items):
|
|
24
|
+
return [x is None for x in items]
|