Правила преобразования типов через оператор CAST
Правила преобразования примитивных типов данных
-
В процессе преобразования примитивных типов данных часть исходной информации может быть отброшена, если она не содержится в целевом типе. Например:
- Дробная часть
Float/Doubleпри преобразовании в целочисленные типы; - Время
Datetime/Timestampпри преобразовании вDate. - Таймзона при преобразовании из типов с таймзоной к типу даты/времени без таймзоны.
- Дробная часть
-
Если для определённого сочетания исходного и целевого типа преобразование не может быть выполнено для всех возможных значений исходного типа, то при неудачном преобразовании
CASTвернётNULL. В таких случаях к типу возвращаемого значения добавляется один уровеньOptional, если его не было. Например, конструкции:CAST("3.14" AS Float?)иCAST("3.14" AS Float)полностью эквиваленты и возвращаютFloat?. -
Если же преобразование возможно для всех значений исходного типа, то добавление '?' работает как
Justсверху:CAST(3.14 AS Utf8?)то же, что иJust(CAST(3.14 AS Utf8))
Все сочетания примитивных типов, для которых возможен CAST описаны тут.
Правила преобразований для контейнеров
Правила для Optional
- Если для целевого типа задан больший уровень
Optionalчем для исходного то это эквивалентно добавлениюJustповерхCASTс меньшим уровнемOptional. - Если же больший уровень
Optionalу исходного типа, тоNULLна любом уровне больше целевого приводит кNULLв результате. - При равных уровнях
OptionalзначениеNULLостаётся на том же уровне.
SELECT
CAST(1 AS Int32?), -- тоже что и Just(1)
CAST(Just(2/1) AS Float??), -- [2]
CAST(Just(3/0) AS Float??) IS NULL; -- false: результат Just(NULL)
Правила для List/Dict
- Список формируется путём выполнения
CASTдля каждого элемента исходного списка в тип элемента целевого типа. - Если тип элемента целевого типа не опциональный, а
CASTэлемента может быть неуспешным, то такие преобразования отбрасываются. В этом случае список в результате может быть меньшей длины или вовсе пустой, если успешных преобразований не было. - Для словарей преобразование выполняется полностью аналогично спискам, выполняя
CASTдля ключей и значений.
SELECT
CAST([-1, 0, 1] AS List<Uint8?>), -- [null, 0, 1]
CAST(["3.14", "bad", "42"] AS List<Float>), -- [3.14, 42]
CAST({-1:3.14, 7:1.6} AS Dict<Uint8, Utf8>), -- {7: "1.6"}
CAST({-1:3.14, 7:1.6} AS Dict<Uint8?, Utf8>); -- {7: "1.6", null:"3.14"}
Правила для Struct/Tuple
- Структура или кортеж формируется путём выполнения
CASTдля каждого элемента исходного типа в элемент с тем же именем или индексом целевого типа. - Если какое-то поле отсутствует в целевом типе, оно просто отбрасывается.
- Если какое-то поле отсутствует в типе исходного значения, то оно может быть добавлено только если является опциональным, и получает значение
NULL. - Если какое-то поле не является опциональным в целевом типе, но его преобразование может быть неуспешным, то
CASTдобавляет опциональность на уровень структуры или кортежа и может вернутьNULLдля всего результата.
SELECT
CAST((-1, 0, 1) AS Tuple<Uint16?, Uint16?, Utf8>), -- (null, 0, "1")
CAST((-2, 0) AS Tuple<Uint16, Utf8>), -- null
CAST((3, 4) AS Tuple<Uint16, String>), -- (3, "4") тип Tuple<Uint16, String>?
CAST(("4",) AS Tuple<Uint16, String?>), -- (4, null)
CAST((5, 6, null) AS Tuple<Uint8?>); -- (5,) элементы удалены.
SELECT -- Одно поле удалено и одно добавлено: ("three":null, "two": "42")
CAST(<|one:"8912", two:42|> AS Struct<two:Utf8, three:Date?>);
Правила для Variant
- Для варианта с определёнными именем или индексом выполняется преобразование в вариант с тем же именем или индексом.
- Если преобразование для варианта может быть неуспешным и тип этого варианта не опциональный, то
CASTдобавляет опциональность на верхний уровень и может вернутьNULL. - Если какой-то вариант отсутствует в целевом типе, то
CASTдобавляет опциональность на верхний уровень и для такого значения возвращаетNULL.
Вложенные контейнеры
- Все вышеперечисленные правила работают рекурсивно для вложенных контейнеров.