clickhouse-driver 0.2.1__cp39-cp39-win_amd64.whl → 0.2.8__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 +896 -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 +202 -207
  13. clickhouse_driver/columns/decimalcolumn.py +116 -118
  14. clickhouse_driver/columns/enumcolumn.py +119 -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 +143 -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 +60 -0
  43. clickhouse_driver/columns/uuidcolumn.py +64 -64
  44. clickhouse_driver/compression/__init__.py +28 -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 +784 -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 +55 -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 +25 -25
  61. clickhouse_driver/numpy/result.py +123 -123
  62. clickhouse_driver/opentelemetry.py +43 -0
  63. clickhouse_driver/progress.py +38 -32
  64. clickhouse_driver/protocol.py +114 -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 +102 -90
  74. clickhouse_driver/util/compat.py +39 -0
  75. clickhouse_driver/util/escape.py +94 -55
  76. clickhouse_driver/util/helpers.py +57 -57
  77. clickhouse_driver/varint.cp39-win_amd64.pyd +0 -0
  78. clickhouse_driver/writer.py +67 -67
  79. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.8.dist-info}/LICENSE +21 -21
  80. clickhouse_driver-0.2.8.dist-info/METADATA +201 -0
  81. clickhouse_driver-0.2.8.dist-info/RECORD +89 -0
  82. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.8.dist-info}/WHEEL +1 -1
  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.8.dist-info}/top_level.txt +0 -0
@@ -1,58 +1,73 @@
1
- from .base import Column
2
- from .intcolumn import UInt64Column
3
- from ..util.helpers import pairwise
4
-
5
-
6
- class MapColumn(Column):
7
- py_types = (dict, )
8
-
9
- def __init__(self, key_column, value_column, **kwargs):
10
- self.offset_column = UInt64Column()
11
- self.key_column = key_column
12
- self.value_column = value_column
13
- super(MapColumn, self).__init__(**kwargs)
14
-
15
- def read_state_prefix(self, buf):
16
- self.key_column.read_state_prefix(buf)
17
- self.value_column.read_state_prefix(buf)
18
-
19
- def write_state_prefix(self, buf):
20
- self.key_column.write_state_prefix(buf)
21
- self.value_column.write_state_prefix(buf)
22
-
23
- def read_items(self, n_items, buf):
24
- offsets = list(self.offset_column.read_items(n_items, buf))
25
- last_offset = offsets[-1]
26
- keys = self.key_column.read_data(last_offset, buf)
27
- values = self.value_column.read_data(last_offset, buf)
28
-
29
- offsets.insert(0, 0)
30
-
31
- return [
32
- dict(zip(keys[begin:end], values[begin:end]))
33
- for begin, end in pairwise(offsets)
34
- ]
35
-
36
- def write_items(self, items, buf):
37
- offsets = []
38
- keys = []
39
- values = []
40
-
41
- total = 0
42
- for x in items:
43
- total += len(x)
44
- offsets.append(total)
45
- keys.extend(x.keys())
46
- values.extend(x.values())
47
-
48
- self.offset_column.write_items(offsets, buf)
49
- self.key_column.write_data(keys, buf)
50
- self.value_column.write_data(values, buf)
51
-
52
-
53
- def create_map_column(spec, column_by_spec_getter):
54
- key, value = spec[4:-1].split(',')
55
- key_column = column_by_spec_getter(key.strip())
56
- value_column = column_by_spec_getter(value.strip())
57
-
58
- return MapColumn(key_column, value_column)
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
- from ..base import Column
4
-
5
-
6
- class NumpyColumn(Column):
7
- dtype = None
8
-
9
- def read_items(self, n_items, buf):
10
- data = buf.read(n_items * self.dtype.itemsize)
11
- return np.frombuffer(data, self.dtype, n_items)
12
-
13
- def write_items(self, items, buf):
14
- buf.write(items.astype(self.dtype).tobytes())
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
@@ -0,0 +1,8 @@
1
+ import numpy as np
2
+
3
+ from .base import NumpyColumn
4
+
5
+
6
+ class NumpyBoolColumn(NumpyColumn):
7
+ dtype = np.dtype(np.bool_)
8
+ ch_type = 'Bool'
@@ -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
- def read_items(self, n_items, buf):
11
- data = super(NumpyDateColumn, self).read_items(n_items, buf)
12
- return data.astype('datetime64[D]')
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,143 @@
1
- import numpy as np
2
- import pandas as pd
3
- from pytz import timezone as get_timezone
4
- from tzlocal import get_localzone
5
-
6
- from .base import NumpyColumn
7
-
8
-
9
- class NumpyDateTimeColumnBase(NumpyColumn):
10
- datetime_dtype = None
11
-
12
- def __init__(self, timezone=None, offset_naive=True, local_timezone=None,
13
- **kwargs):
14
- self.timezone = timezone
15
- self.offset_naive = offset_naive
16
- self.local_timezone = local_timezone
17
- super(NumpyDateTimeColumnBase, self).__init__(**kwargs)
18
-
19
- def apply_timezones_after_read(self, dt):
20
- timezone = self.timezone if self.timezone else self.local_timezone
21
-
22
- ts = pd.to_datetime(dt, utc=True).tz_convert(timezone)
23
-
24
- if self.offset_naive:
25
- ts = ts.tz_localize(None)
26
-
27
- return ts.to_numpy(self.datetime_dtype)
28
-
29
- def apply_timezones_before_write(self, items):
30
- if isinstance(items, pd.DatetimeIndex):
31
- ts = items
32
- else:
33
- timezone = self.timezone if self.timezone else self.local_timezone
34
- ts = pd.to_datetime(items).tz_localize(timezone)
35
-
36
- ts = ts.tz_convert('UTC')
37
- return ts.tz_localize(None).to_numpy(self.datetime_dtype)
38
-
39
- def is_items_integer(self, items):
40
- return (
41
- isinstance(items, np.ndarray) and
42
- np.issubdtype(items.dtype, np.integer)
43
- )
44
-
45
-
46
- class NumpyDateTimeColumn(NumpyDateTimeColumnBase):
47
- dtype = np.dtype(np.uint32)
48
- datetime_dtype = 'datetime64[s]'
49
-
50
- def write_items(self, items, buf):
51
- # write int 'as is'.
52
- if self.is_items_integer(items):
53
- super(NumpyDateTimeColumn, self).write_items(items, buf)
54
- return
55
-
56
- items = self.apply_timezones_before_write(items)
57
-
58
- super(NumpyDateTimeColumn, self).write_items(items, buf)
59
-
60
- def read_items(self, n_items, buf):
61
- items = super(NumpyDateTimeColumn, self).read_items(n_items, buf)
62
- return self.apply_timezones_after_read(items.astype('datetime64[s]'))
63
-
64
-
65
- class NumpyDateTime64Column(NumpyDateTimeColumnBase):
66
- dtype = np.dtype(np.uint64)
67
- datetime_dtype = 'datetime64[ns]'
68
-
69
- max_scale = 6
70
-
71
- def __init__(self, scale=0, **kwargs):
72
- self.scale = scale
73
- super(NumpyDateTime64Column, self).__init__(**kwargs)
74
-
75
- def read_items(self, n_items, buf):
76
- scale = 10 ** self.scale
77
- frac_scale = 10 ** (self.max_scale - self.scale)
78
-
79
- items = super(NumpyDateTime64Column, self).read_items(n_items, buf)
80
-
81
- seconds = (items // scale).astype('datetime64[s]')
82
- microseconds = ((items % scale) * frac_scale).astype('timedelta64[us]')
83
-
84
- dt = seconds + microseconds
85
- return self.apply_timezones_after_read(dt)
86
-
87
- def write_items(self, items, buf):
88
- # write int 'as is'.
89
- if self.is_items_integer(items):
90
- super(NumpyDateTime64Column, self).write_items(items, buf)
91
- return
92
-
93
- scale = 10 ** self.scale
94
- frac_scale = 10 ** (self.max_scale - self.scale)
95
-
96
- items = self.apply_timezones_before_write(items)
97
-
98
- seconds = items.astype('datetime64[s]')
99
- microseconds = (items - seconds).astype(dtype='timedelta64[us]') \
100
- .astype(np.uint32) // frac_scale
101
-
102
- items = seconds.astype(self.dtype) * scale + microseconds
103
-
104
- super(NumpyDateTime64Column, self).write_items(items, buf)
105
-
106
-
107
- def create_numpy_datetime_column(spec, column_options):
108
- if spec.startswith('DateTime64'):
109
- cls = NumpyDateTime64Column
110
- spec = spec[11:-1]
111
- params = spec.split(',', 1)
112
- column_options['scale'] = int(params[0])
113
- if len(params) > 1:
114
- spec = params[1].strip() + ')'
115
- else:
116
- cls = NumpyDateTimeColumn
117
- spec = spec[9:]
118
-
119
- context = column_options['context']
120
-
121
- tz_name = timezone = None
122
- offset_naive = True
123
- local_timezone = None
124
-
125
- # As Numpy do not use local timezone for converting timestamp to
126
- # datetime we need always detect local timezone for manual converting.
127
- try:
128
- local_timezone = get_localzone().zone
129
- except Exception:
130
- pass
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
- if local_timezone != context.server_info.timezone:
139
- tz_name = context.server_info.timezone
140
-
141
- if tz_name:
142
- timezone = get_timezone(tz_name)
143
-
144
- return cls(timezone=timezone, offset_naive=offset_naive,
145
- local_timezone=local_timezone, **column_options)
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).tz_localize(timezone)
37
+
38
+ ts = ts.tz_convert('UTC')
39
+ return ts.tz_localize(None).to_numpy(self.datetime_dtype)
40
+
41
+ def is_items_integer(self, items):
42
+ return (
43
+ isinstance(items, np.ndarray) and
44
+ np.issubdtype(items.dtype, np.integer)
45
+ )
46
+
47
+
48
+ class NumpyDateTimeColumn(NumpyDateTimeColumnBase):
49
+ dtype = np.dtype(np.uint32)
50
+ datetime_dtype = 'datetime64[s]'
51
+
52
+ def write_items(self, items, buf):
53
+ # write int 'as is'.
54
+ if self.is_items_integer(items):
55
+ super(NumpyDateTimeColumn, self).write_items(items, buf)
56
+ return
57
+
58
+ items = self.apply_timezones_before_write(items)
59
+
60
+ super(NumpyDateTimeColumn, self).write_items(items, buf)
61
+
62
+ def read_items(self, n_items, buf):
63
+ items = super(NumpyDateTimeColumn, self).read_items(n_items, buf)
64
+ return self.apply_timezones_after_read(items.astype('datetime64[s]'))
65
+
66
+
67
+ class NumpyDateTime64Column(NumpyDateTimeColumnBase):
68
+ dtype = np.dtype(np.int64)
69
+ datetime_dtype = 'datetime64[ns]'
70
+
71
+ max_scale = 9
72
+
73
+ def __init__(self, scale=0, **kwargs):
74
+ self.scale = scale
75
+ super(NumpyDateTime64Column, self).__init__(**kwargs)
76
+
77
+ def read_items(self, n_items, buf):
78
+ # Clickhouse: t seconds is represented as t * 10^scale.
79
+ # datetime64[ns]: t seconds is represented as t * 10^9.
80
+ # Since 0 <= scale <= 9, multiply by the integer 10^(9 - scale).
81
+ items = super(NumpyDateTime64Column, self).read_items(n_items, buf)
82
+
83
+ tmp = np.copy(items)
84
+ tmp *= 10 ** (9 - self.scale)
85
+ dt = tmp.view(dtype='datetime64[ns]')
86
+
87
+ return self.apply_timezones_after_read(dt)
88
+
89
+ def write_items(self, items, buf):
90
+ # write int 'as is'.
91
+ if self.is_items_integer(items):
92
+ super(NumpyDateTime64Column, self).write_items(items, buf)
93
+ return
94
+
95
+ scale = 10 ** self.scale
96
+ frac_scale = 10 ** (self.max_scale - self.scale)
97
+
98
+ items = self.apply_timezones_before_write(items)
99
+
100
+ seconds = items.astype('datetime64[s]')
101
+ microseconds = (items - seconds).astype(dtype='timedelta64[ns]') \
102
+ .astype(np.uint32) // frac_scale
103
+
104
+ items = seconds.astype(self.dtype) * scale + microseconds
105
+
106
+ super(NumpyDateTime64Column, self).write_items(items, buf)
107
+
108
+
109
+ def create_numpy_datetime_column(spec, column_options):
110
+ if spec.startswith('DateTime64'):
111
+ cls = NumpyDateTime64Column
112
+ spec = spec[11:-1]
113
+ params = spec.split(',', 1)
114
+ column_options['scale'] = int(params[0])
115
+ if len(params) > 1:
116
+ spec = params[1].strip() + ')'
117
+ else:
118
+ cls = NumpyDateTimeColumn
119
+ spec = spec[9:]
120
+
121
+ context = column_options['context']
122
+
123
+ tz_name = None
124
+ offset_naive = True
125
+
126
+ # As Numpy do not use local timezone for converting timestamp to
127
+ # datetime we need always detect local timezone for manual converting.
128
+ local_tz_name = get_localzone_name_compat()
129
+
130
+ # Use column's timezone if it's specified.
131
+ if spec and spec[-1] == ')':
132
+ tz_name = spec[1:-2]
133
+ offset_naive = False
134
+ else:
135
+ if not context.settings.get('use_client_time_zone', False):
136
+ if local_tz_name != context.server_info.timezone:
137
+ tz_name = context.server_info.timezone
138
+
139
+ timezone = get_timezone(tz_name) if tz_name else None
140
+ local_timezone = get_timezone(local_tz_name) if local_tz_name else None
141
+
142
+ return cls(timezone=timezone, offset_naive=offset_naive,
143
+ local_timezone=local_timezone, **column_options)
@@ -1,13 +1,24 @@
1
- import numpy as np
2
-
3
- from .base import NumpyColumn
4
-
5
-
6
- class NumpyFloat32Column(NumpyColumn):
7
- dtype = np.dtype(np.float32)
8
- ch_type = 'Float32'
9
-
10
-
11
- class NumpyFloat64Column(NumpyColumn):
12
- dtype = np.dtype(np.float64)
13
- ch_type = 'Float64'
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]