CREATE CAST
Определяет новое приведение типов.
Синтаксис
CREATE CAST (<sourcetype> AS <targettype>)
WITH FUNCTION <funcname> (<argtype> [, ...])
[AS ASSIGNMENT | AS IMPLICIT]
CREATE CAST (<sourcetype> AS <targettype>)
WITHOUT FUNCTION
[AS ASSIGNMENT | AS IMPLICIT]
CREATE CAST (<sourcetype> AS <targettype>)
WITH INOUT
[AS ASSIGNMENT | AS IMPLICIT]
Описание
CREATE CAST определяет новое приведение типов.
Приведение указывает, как выполнить преобразование между двумя типами данных.
Например,
SELECT CAST(42 AS float8);
преобразует целочисленную константу 42 в тип float8, вызывая ранее указанную функцию, в данном случае float8(int4).
Если подходящее приведение типа не было определено, преобразование завершается ошибкой.
Два типа могут быть двоично-приводимыми (binary coercible), что означает, что типы могут быть преобразованы друг в друга без вызова какой-либо функции.
Это требует, чтобы соответствующие значения использовали одинаковое внутреннее представление.
Например, типы text и varchar являются двоично-приводимыми в обоих направлениях.
Двоичная совместимость не обязательно является симметричным отношением.
Например, приведение от xml к text может быть выполнено без вызова какой-либо функции в текущей реализации, но обратное направление требует функции, которая выполняет как минимум синтаксическую проверку.
Два типа, которые двоично-приводимы в обе стороны, также называются двоично-совместимыми (binary compatible).
Вы можете определить приведение как приведение ввода-вывода (I/O conversion cast), используя синтаксис WITH INOUT.
Приведение ввода-вывода выполняется путем вызова функции вывода исходного типа данных и передачи результирующей строки функции ввода целевого типа данных.
Во многих распространенных случаях эта возможность позволяет избежать необходимости написания отдельной функции приведения для преобразования.
Приведение ввода-вывода действует так же, как и обычное приведение на основе функции; отличается только реализация.
По умолчанию приведение может быть вызвано только явным запросом приведения, то есть конструкцией CAST(x AS typename) или x:: typename.
Если приведение помечено как AS ASSIGNMENT, то оно может быть вызвано неявно при присваивании значения столбцу целевого типа данных.
Например, предположим, что foo.f1 — это столбец с типом text, тогда:
INSERT INTO foo (f1) VALUES (42);
будет разрешено, если приведение от типа integer к типу text помечено как AS ASSIGNMENT, в противном случае — не разрешено.
Термин приведение присваивания (assignment cast) обычно используется для описания этого вида приведения.
Если приведение помечено как AS IMPLICIT, то оно может быть вызвано неявно в любом контексте, будь то присваивание или внутри выражения.
Термин неявное приведение (implicit cast) обычно используется для описания этого вида приведения.
Например, рассмотрим следующий запрос:
SELECT 2 + 4.0;
Парсер изначально помечает константы как имеющие тип integer и numeric соответственно.
В системных каталогах нет оператора integer + numeric, но есть оператор numeric + numeric.
Этот запрос выполняется успешно, если существует приведение от integer к numeric (оно существует) и помечено как AS IMPLICIT (что на самом деле так и есть).
Парсер применяет только неявное приведение и разрешает запрос так, как если бы он был написан следующим образом:
SELECT CAST ( 2 AS numeric ) + 4.0;
Каталоги также предоставляют приведение от numeric к integer.
Если бы это приведение было помечено как AS IMPLICIT (что не так), то парсер столкнулся бы с выбором между вышеупомянутой интерпретацией и альтернативой приведения константы numeric к integer и применения оператора integer + integer.
Не зная, какой выбор предпочесть, парсер бы не смог разрешить запрос и объявил бы его неоднозначным.
Благодаря тому, что только одно из двух приведений является неявным, парсер понимает, что предпочитаемым является преобразование выражения numeric-и-integer как numeric; у парсера нет встроенной информации об этом.
Определяя, объявлять ли приведения неявными, разумно проявлять консерватизм.
Избыток путей неявного приведения может заставить Greengage DB выбирать неожиданные интерпретации команд или вообще не иметь возможности разрешать команды из-за наличия нескольких возможных интерпретаций.
Общее правило — делать приведение неявно вызываемым только для преобразований, сохраняющих информацию, между типами в одной и той же общей категории типов.
Например, приведение от int2 к int4 вполне может быть неявным, но приведение от float8 к int4, возможно, лучше сделать только приведением присваивания.
Приведения между категориями типов, такие как text к int4, лучше делать только явными.
Иногда по соображениям удобства использования или соответствия стандартам необходимо предоставить несколько неявных приведений среди набора типов, что приводит к неоднозначности, которую нельзя избежать описанным выше способом. Парсер использует резервную эвристику, основанную на категориях типов и предпочитаемых типах, которая помогает обеспечить желаемое поведение в таких случаях. Для получения дополнительной информации см. CREATE TYPE .
Чтобы создать приведение, вы должны быть владельцем исходного или целевого типа данных и иметь привилегию USAGE для другого типа.
Чтобы создать двоично-приводимое приведение, вы должны быть суперпользователем.
Это ограничение введено потому, что ошибочное преобразование двоично-приводимого приведения может легко привести к сбою сервера.
Параметры
| Параметр | Описание |
|---|---|
sourcetype |
Имя исходного типа данных приведения |
targettype |
Имя целевого типа данных приведения |
funcname(<argtype> [, …]) |
Функция, используемая для выполнения приведения. Имя функции может быть дополнено схемой. Если схема не указана, Greengage DB ищет функцию в пути поиска (search path) схемы. Тип данных результата функции должен соответствовать целевому типу приведения. Функции реализации приведения могут иметь от одного до трех аргументов.
Тип первого аргумента должен быть идентичным или двоично-приводимым с исходным типом приведения.
Второй аргумент, если он присутствует, должен быть типа Возвращаемый тип функции приведения должен быть идентичным или двоично-приводимым с целевым типом приведения. Обычно приведение должно иметь разные исходные и целевые типы данных. Однако разрешено объявлять приведение с идентичными исходными и целевыми типами, если у него есть функция реализации приведения, принимающая более одного аргумента. Это используется для представления функций приведения длины, специфичных для типа, в системных каталогах. Указанная функция используется для приведения значения типа к значению модификатора типа, заданному его вторым аргументом. Когда приведение имеет разные исходные и целевые типы и функцию, принимающую более одного аргумента, приведение преобразует из одного типа в другой и применяет приведение длины за один шаг. Когда такая запись недоступна, приведение к типу, использующему модификатор типа, включает два шага: один для преобразования между типами данных и второй для применения модификатора. Приведение к доменному типу или от него в настоящее время не имеет эффекта. Приведение к домену или от него использует приведения, связанные с его базовым типом |
WITHOUT FUNCTION |
Указывает, что исходный тип двоично-приводим с целевым типом, поэтому для выполнения приведения функция не требуется |
WITH INOUT |
Указывает, что приведение является приведением ввода-вывода, выполняемым путем вызова функции вывода исходного типа данных и передачи результирующей строки функции ввода целевого типа данных |
AS ASSIGNMENT |
Указывает, что приведение может быть вызвано неявно в контекстах присваивания |
AS IMPLICIT |
Указывает, что приведение может быть вызвано неявно в любом контексте |
Примечания
Обратите внимание, что пользовательские функции в пользовательском приведении должны быть определены как IMMUTABLE.
Любой скомпилированный код (файлы общих библиотек) для пользовательских функций должен быть размещен в одном и том же месте на каждом хосте в кластере Greengage DB (мастер и все сегменты).
Это местоположение также должно находиться в LD_LIBRARY_PATH, чтобы сервер мог найти файлы.
Помните, что если вы хотите иметь возможность преобразовывать типы в обе стороны, нужно явно объявить приведения в обе стороны.
Обычно нет необходимости создавать приведения между пользовательскими типами и стандартными строковыми типами (text, varchar и char(n), а также между пользовательскими типами, которые определены как находящиеся в строковой категории).
Greengage DB предоставляет для них автоматические приведения ввода-вывода.
Автоматические приведения к строковым типам рассматриваются как приведения присваивания, в то время как автоматические приведения от строковых типов являются только явными.
Вы можете переопределить это поведение, объявив свое собственное приведение для замены автоматического приведения, но обычно единственная причина сделать это — если вы хотите, чтобы преобразование вызывалось легче, чем стандартная настройка "только присваивание" или "только явное".
Другая возможная причина — вы хотите, чтобы преобразование вело себя иначе, чем функция ввода-вывода типа — хорошо подумайте, прежде чем делать это.
Небольшое количество встроенных типов действительно имеют разное поведение для преобразований, в основном из-за требований стандарта SQL.
Рекомендуется следовать соглашению об именовании функций реализации приведения по имени целевого типа данных, как именуются встроенные функции реализации приведения.
Многие пользователи привыкли иметь возможность приводить типы данных, используя нотацию в стиле функции, то есть typename(x).
Существует два случая, в которых конструкция вызова функции рассматривается как запрос приведения без сопоставления с фактической функцией.
Если вызов функции name(x) не совпадает точно ни с одной существующей функцией, но name является именем типа данных, и pg_cast предоставляет двоично-приводимое приведение к этому типу от типа x, то вызов будет истолкован как двоично-приводимое приведение.
Greengage DB делает это исключение, чтобы двоично-приводимые приведения могли вызываться с использованием функционального синтаксиса, даже если у них отсутствует какая-либо функция.
Аналогично, если записи pg_cast нет, но приведение должно быть к строковому типу или от него, вызов воспринимается как приведение ввода-вывода.
Это исключение позволяет вызывать приведения ввода-вывода с использованием функционального синтаксиса.
Существует исключение из вышеуказанного исключения: приведения ввода-вывода от составных типов к строковым типам не могут быть вызваны с использованием функционального синтаксиса, а должны быть записаны в синтаксисе явного приведения (либо CAST, либо нотация ::).
Это исключение существует потому, что после введения автоматически предоставляемых приведений ввода-вывода выяснилось, что слишком легко случайно вызвать такое приведение, когда вы намеревались использовать функцию или ссылку на столбец.
Примеры
Чтобы создать приведение присваивания от типа bigint к типу int4, используя функцию int4(bigint) (это приведение уже предопределено в системе):
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;
Совместимость
Команда CREATE CAST соответствует стандарту SQL, за исключением того, что SQL не предусматривает двоично-приводимые типы или дополнительные аргументы для функций реализации.
AS IMPLICIT также является расширением Greengage DB.