Rules for type casting using the operator CAST.
Rules for casting primitive data types
-
When casting primitive data types, some of the source information may be discarded unless contained in the target type. For example:
- The
Float/Doublefractional part, when casting to integer types. - The
Datetime/Timestamptime, when casting toDate. - The timezone, when casting from timezone types to date/time types without a timezone.
- The
-
If, in a certain combination of the source and target type, casting can't be performed for all possible values of the source type, then, if the casting fails,
CASTreturnsNULL. In such cases, oneOptionallevel is added to the return value type, unless already present. For example, the constructs:CAST("3.14" AS Float?)andCAST("3.14" AS Float)are fully equivalent and returnFloat?. -
If casting is possible for all values of the source type, then adding '?' works like
Justabove:CAST(3.14 AS Utf8?)is the same asJust(CAST(3.14 AS Utf8)).
All primitive type combinations for which CAST is possible are described here.
Rules for casting containers
Rules for Optional
- If a higher
Optionallevel is set for the target type than for the source type, it's same as addingJuston top ofCASTwith a lowerOptionallevel. - If the source type has a higher level of
Optionalfor the source type, thenNULLat any level higher than the target level results inNULL. - At equal levels of
Optional, theNULLvalue preserves the same level.
SELECT
CAST(1 AS Int32?), -- same as Just(1)
CAST(Just(2/1) AS Float??), -- [2]
CAST(Just(3/0) AS Float??) IS NULL; -- false: the result of Just(NULL)
Rules for List/Dict
- To create a list,
CASTis applied to each item in the source list to cast it to the target type. - If the target item type is non-optional and
CASTon the item might fail, then such casting is discarded. In this case, the resulting list might be shorter or even empty if every casting failed. - For dictionaries, the casting is totally similar to lists, with
CASTbeing applied to keys and values.
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"}
Rules for Struct/Tuple
- A structure or tuple is created by applying
CASTto each item of the source type to cast it to an item with the same name or target type index. - If some field is missing in the target type, it's simply discarded.
- If some field is missing in the source value type, then it can be added only if it's optional and accepts the
NULLvalue. - If some field is non-optional in the target type, but its casting might fail, then
CASTadds Optional to the structure or tuple level and might returnNULLfor the entire result.
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") type Tuple<Uint16, String>?
CAST(("4",) AS Tuple<Uint16, String?>), -- (4, null)
CAST((5, 6, null) AS Tuple<Uint8?>); -- (5,) elements are removed.
SELECT -- One field is removed and one is added: ("three":null, "two": "42")
CAST(<|one:"8912", two:42|> AS Struct<two:Utf8, three:Date?>).
Rules for Variant
- A variant with a specific name or index is cast to a variant with the same name or index.
- If casting of a variant might fail and the type of this variant is non-optional, then
CASTadds Optional to the top level and can returnNULL. - If some variant is missing in the target type, then
CASTadds Optional to the top level and returnsNULLfor such a value.
Nested containers
- All of the above rules are applied recursively for nested containers.