Правила преобразования типов через оператор 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
.
Вложенные контейнеры
- Все вышеперечисленные правила работают рекурсивно для вложенных контейнеров.