CREATE AGGREGATE — создание новой агрегатной функции
CREATE [ OR REPLACE ] AGGREGATEname( [argmode] [argname]arg_data_type[ , ... ] ) ( SFUNC =sfunc, STYPE =state_data_type[ , SSPACE =state_data_size] [ , FINALFUNC =ffunc] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , COMBINEFUNC =combinefunc] [ , SERIALFUNC =serialfunc] [ , DESERIALFUNC =deserialfunc] [ , INITCOND =initial_condition] [ , MSFUNC =msfunc] [ , MINVFUNC =minvfunc] [ , MSTYPE =mstate_data_type] [ , MSSPACE =mstate_data_size] [ , MFINALFUNC =mffunc] [ , MFINALFUNC_EXTRA ] [ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , MINITCOND =minitial_condition] [ , SORTOP =sort_operator] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] ) CREATE [ OR REPLACE ] AGGREGATEname( [ [argmode] [argname]arg_data_type[ , ... ] ] ORDER BY [argmode] [argname]arg_data_type[ , ... ] ) ( SFUNC =sfunc, STYPE =state_data_type[ , SSPACE =state_data_size] [ , FINALFUNC =ffunc] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , INITCOND =initial_condition] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] [ , HYPOTHETICAL ] ) или старый синтаксис CREATE [ OR REPLACE ] AGGREGATEname( BASETYPE =base_type, SFUNC =sfunc, STYPE =state_data_type[ , SSPACE =state_data_size] [ , FINALFUNC =ffunc] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , COMBINEFUNC =combinefunc] [ , SERIALFUNC =serialfunc] [ , DESERIALFUNC =deserialfunc] [ , INITCOND =initial_condition] [ , MSFUNC =msfunc] [ , MINVFUNC =minvfunc] [ , MSTYPE =mstate_data_type] [ , MSSPACE =mstate_data_size] [ , MFINALFUNC =mffunc] [ , MFINALFUNC_EXTRA ] [ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , MINITCOND =minitial_condition] [ , SORTOP =sort_operator] )
CREATE AGGREGATE определяет новую агрегатную функцию.
CREATE OR REPLACE AGGREGATE либо определит новую
агрегатную функцию, либо заменит существующее определение. Некоторые базовые и
часто используемые агрегатные функции включены в дистрибутив; они
документированы в Раздел 2.6.21. Если определяются новые
типы или требуется агрегатная функция, которая еще не предоставлена, то
можно использовать CREATE AGGREGATE для обеспечения нужных
возможностей.
При замене существующего определения нельзя изменять типы аргументов, тип результата и количество прямых аргументов. Также новое определение должно быть того же вида (обычная агрегатная, упорядоченно-множественная или гипотетически-множественная), что и старое.
Если указано имя схемы (например, CREATE AGGREGATE
myschema.myagg ...), то агрегатная функция создается в указанной
схеме. В противном случае она создается в текущей схеме.
Агрегатная функция идентифицируется своим именем и типом(ами) входных данных. Две агрегатные функции в одной схеме могут иметь одинаковое имя, если они работают с разными типами входных данных. Имя и тип(ы) входных данных агрегатной функции также должны отличаться от имени и типов входных данных каждой обычной функции в той же схеме. Это поведение идентично перегрузке имен обычных функций (см. CREATE FUNCTION).
Простая агрегатная функция состоит из одной или двух обычных
функций:
функции перехода состояния
sfunc и
необязательной функции финального вычисления
ffunc.
Они используются следующим образом:
sfunc( внутреннее-состояние, следующие-значения-данных ) ---> следующее-внутреннее-состояниеffunc( внутреннее-состояние ) ---> агрегатное-значение
Digital Q.DataBase создает временную переменную
типа данных stype
для хранения текущего внутреннего состояния агрегата. Для каждой входной строки
вычисляется(ются) значение(я) аргумента(ов) агрегата и
вызывается функция перехода состояния с текущим значением состояния
и новым(ыми) значением(ями) аргумента(ов) для вычисления нового
значения внутреннего состояния. После обработки всех строк
один раз вызывается финальная функция для вычисления возвращаемого
значения агрегата. Если финальная функция отсутствует, то конечное значение состояния
возвращается как есть.
Агрегатная функция может предоставить начальное условие,
то есть начальное значение для внутреннего состояния.
Оно указывается и сохраняется в базе данных как значение типа
text, но должно быть допустимым внешним представлением
константы типа данных состояния. Если оно не предоставлено,
то значение состояния начинается как NULL.
Если функция перехода состояния объявлена как «строгая»,
то ее нельзя вызывать с NULL-входами. При использовании такой функции
выполнения агрегата поведение следующее. Строки с любыми NULL-значениями на входе
игнорируются (функция не вызывается, и предыдущее значение состояния
сохраняется). Если начальное значение состояния равно NULL, то на первой строке
со всеми не-NULL значениями на входе первое значение аргумента заменяет значение состояния,
и функция перехода вызывается для каждой последующей строки с
всеми не-NULL значениями на входе.
Это удобно для реализации агрегатов, таких как max.
Обратите внимание, что такое поведение доступно только когда
state_data_type
совпадает с первым
arg_data_type.
Когда эти типы различаются, вы должны предоставить не-NULL начальное
условие или использовать нестрогую функцию перехода.
Если функция перехода состояния не является строгой, то она будет вызываться безусловно для каждой входной строки и должна сама обрабатывать NULL-входы и NULL-значения состояния. Это позволяет автору агрегата иметь полный контроль над обработкой NULL-значений агрегатом.
Если финальная функция объявлена «строгой», то она не будет
вызываться, когда конечное значение состояния равно NULL; вместо этого автоматически
будет возвращен NULL-результат. (Разумеется, это обычное
поведение строгих функций.) В любом случае финальная функция имеет
возможность вернуть NULL-значение. Например, финальная функция для
avg возвращает NULL, когда видит, что было нулевое
количество входных строк.
Иногда полезно объявить финальную функцию как принимающую не только
значение состояния, но и дополнительные параметры, соответствующие входным
значениям агрегата. Основная причина для этого — если финальная функция
полиморфна и тип данных значения состояния был бы недостаточным для
определения типа результата. Эти дополнительные параметры всегда передаются как
NULL (и поэтому финальная функция не должна быть строгой, когда
используется опция FINALFUNC_EXTRA), но тем не менее они
являются допустимыми параметрами. Финальная функция может, например, использовать
get_fn_expr_argtype для определения фактического типа аргумента
в текущем вызове.
Агрегат может дополнительно поддерживать режим подвижного агрегата,
как описано в Раздел 5.1.12.1. Для этого требуется
указание параметров MSFUNC, MINVFUNC
и MSTYPE, и, опционально,
параметров MSSPACE, MFINALFUNC,
MFINALFUNC_EXTRA, MFINALFUNC_MODIFY
и MINITCOND. За исключением MINVFUNC,
эти параметры работают так же, как соответствующие параметры простого агрегата
без M; они определяют отдельную реализацию агрегата,
которая включает обратную функцию перехода.
Синтаксис с ORDER BY в списке параметров создает
специальный тип агрегата, называемый упорядоченно-множественным агрегатом;
или, если указан HYPOTHETICAL, создается
гипотетически-множественный агрегат. Эти
агрегаты работают с группами отсортированных значений зависящим от порядка способами,
поэтому указание порядка сортировки входных данных является важной частью
вызова. Также они могут иметь прямые аргументы, которые
вычисляются только один раз на агрегацию, а не один раз
на входную строку. Гипотетически-множественные агрегаты являются подклассом упорядоченно-множественных
агрегатов, в которых некоторые прямые аргументы должны совпадать,
по количеству и типам данных, с агрегируемыми столбцами аргументов. Это позволяет
добавлять значения этих прямых аргументов в коллекцию
строк агрегатного ввода как дополнительную «гипотетическую» строку.
Агрегат может дополнительно поддерживать частичную агрегацию,
как описано в Раздел 5.1.12.4.
Для этого требуется указание параметра COMBINEFUNC.
Если state_data_type
имеет тип internal, обычно также уместно предоставить
параметры SERIALFUNC и DESERIALFUNC, чтобы
была возможна параллельная агрегация. Обратите внимание, что агрегат также должен быть
помечен как PARALLEL SAFE, чтобы включить параллельную агрегацию.
Агрегаты, которые ведут себя как MIN или MAX,
иногда могут быть оптимизированы путем обращения к индексу вместо сканирования каждой
входной строки. Если этот агрегат может быть так оптимизирован, укажите это,
задав оператор сортировки. Базовое требование заключается в том, что
агрегат должен выдавать первый элемент в порядке сортировки, индуцированном
оператором; другими словами:
SELECT agg(col) FROM tab;
должно быть эквивалентно:
SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
Дополнительные предположения: агрегат игнорирует NULL-входы и
выдает NULL-результат тогда и только тогда, когда не было не-NULL-входов.
Обычно оператор < типа данных является подходящим оператором сортировки
для MIN, а > — подходящим оператором сортировки
для MAX. Обратите внимание, что оптимизация никогда
фактически не вступит в силу, если указанный оператор не является членом стратегии
«меньше чем» или «больше чем» класса операторов B-дерева индекса.
Чтобы иметь возможность создать агрегатную функцию, вы должны
иметь привилегию USAGE на типы аргументов, тип(ы) состояния
и тип возвращаемого значения, а также привилегию EXECUTE
на вспомогательные функции.
nameИмя (возможно, с указанием схемы) создаваемой агрегатной функции.
argmode
Режим аргумента: IN или VARIADIC.
(Агрегатные функции не поддерживают аргументы OUT).
Если опущено, по умолчанию используется IN. Только последний аргумент
может быть помечен как VARIADIC.
argnameИмя аргумента. В настоящее время это полезно только для целей документирования. Если опущено, аргумент не имеет имени.
arg_data_type
Тип входных данных, над которыми работает эта агрегатная функция.
Чтобы создать агрегатную функцию без аргументов, напишите *
вместо списка спецификаций аргументов. (Примером такого
агрегата является count(*).)
base_type
В старом синтаксисе CREATE AGGREGATE тип входных данных
указывается параметром basetype, а не записывается
рядом с именем агрегата. Обратите внимание, что этот синтаксис позволяет
только один входной параметр. Чтобы определить агрегатную функцию без аргументов
с этим синтаксисом, укажите basetype как
"ANY" (не *).
Упорядоченно-множественные агрегаты не могут быть определены со старым синтаксисом.
sfunc
Имя функции перехода состояния, вызываемой для каждой
входной строки. Для обычной агрегатной функции с N аргументами
функция sfunc
должна принимать N+1 аргументов,
первый из которых имеет тип state_data_type, а остальные
соответствуют объявленному(ым) типу(ам) входных данных агрегата.
Функция должна возвращать значение типа state_data_type. Эта функция
принимает текущее значение состояния и текущее(щие) значение(я) входных данных
и возвращает следующее значение состояния.
Для упорядоченно-множественных (включая гипотетически-множественные) агрегатов функция перехода состояния получает только текущее значение состояния и агрегированные аргументы, а не прямые аргументы. В остальном она такая же.
state_data_typeТип данных для значения состояния агрегата.
state_data_size
Приблизительный средний размер (в байтах) значения состояния агрегата.
Если этот параметр опущен или равен нулю, используется оценка по умолчанию,
основанная на state_data_type.
Планировщик использует это значение для оценки памяти, необходимой для
группированного агрегатного запроса.
ffunc
Имя финальной функции, вызываемой для вычисления результата агрегата
после обработки всех входных строк.
Для обычного агрегата эта функция
должна принимать один аргумент типа state_data_type.
Тип возвращаемых данных агрегата определяется как тип возвращаемого значения этой
функции. Если ffunc
не указана, то конечное значение состояния используется как
результат агрегата, а тип возвращаемого значения — state_data_type.
Для упорядоченно-множественных (включая гипотетически-множественные) агрегатов финальная функция получает не только конечное значение состояния, но и значения всех прямых аргументов.
Если указано FINALFUNC_EXTRA, то в дополнение к
конечному значению состояния и любым прямым аргументам финальная функция
получает дополнительные NULL-значения, соответствующие обычным
(агрегированным) аргументам агрегата. Это в основном полезно для обеспечения правильного
разрешения типа результата агрегата при определении
полиморфного агрегата.
FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }
Эта опция указывает, является ли финальная функция чистой функцией,
которая не изменяет свои аргументы. READ_ONLY указывает,
что она не изменяет; другие два значения указывают, что она может изменять
значение переходного состояния. См. Notes
ниже для более подробной информации.
По умолчанию используется READ_ONLY, за исключением упорядоченно-множественных агрегатов,
для которых по умолчанию используется READ_WRITE.
combinefunc
Функция combinefunc
может быть опционально указана, чтобы позволить агрегатной функции поддерживать
частичную агрегацию. Если предоставлена,
функция combinefunc должна
объединять два значения типа state_data_type,
каждое из которых содержит результат агрегации над некоторым подмножеством
входных значений, для получения нового значения типа state_data_type, которое
представляет результат агрегации над обоими наборами входных данных. Эту
функцию можно рассматривать как
sfunc, где вместо
действия на отдельной входной строке и добавления ее в текущее
агрегатное состояние она добавляет другое агрегатное состояние к текущему состоянию.
Функция combinefunc должна быть
объявлена как принимающая два аргумента типа
state_data_type и
возвращающая значение типа
state_data_type.
Опционально эта функция может быть «строгой». В этом случае
функция не будет вызываться, когда любое из входных состояний равно NULL;
другое состояние будет принято как правильный результат.
Для агрегатных функций, у которых
state_data_type
имеет тип internal,
функция combinefunc не должна
быть строгой. В этом случае
функция combinefunc должна
обеспечить корректную обработку NULL-состояний и то, что возвращаемое состояние
правильно сохранено в контексте памяти агрегата.
serialfunc
Агрегатная функция, у которой
state_data_type
имеет тип internal, может участвовать в параллельной агрегации только если у нее
есть функция serialfunc,
которая должна сериализовать состояние агрегата в значение bytea для
передачи другому процессу. Эта функция должна принимать один
аргумент типа internal и возвращать тип bytea. Также требуется
соответствующая функция deserialfunc.
deserialfunc
Десериализовать ранее сериализованное состояние агрегата обратно в
тип state_data_type. Эта
функция должна принимать два аргумента типов bytea
и internal и выдавать результат типа internal.
(Примечание: второй, internal аргумент не используется, но требуется
по соображениям безопасности типов.)
initial_condition
Начальная установка для значения состояния. Это должна быть строковая
константа в форме, принимаемой для типа данных state_data_type. Если не указана,
значение состояния начинается как NULL.
msfunc
Имя прямой функции перехода состояния, вызываемой для каждой
входной строки в режиме подвижного агрегата. Это точно такая же, как обычная
функция перехода, за исключением того, что ее первый аргумент и результат имеют тип
mstate_data_type, который может отличаться
от state_data_type.
minvfunc
Имя обратной функции перехода состояния, используемой в
режиме подвижного агрегата. Эта функция имеет те же типы аргументов и
результата, что и msfunc, но она используется для удаления
значения из текущего состояния агрегата, а не для добавления значения к нему.
Обратная функция перехода должна иметь тот же атрибут строгости,
что и прямая функция перехода состояния.
mstate_data_typeТип данных для значения состояния агрегата при использовании режима подвижного агрегата.
mstate_data_size
Приблизительный средний размер (в байтах) значения состояния агрегата
при использовании режима подвижного агрегата. Работает так же, как
state_data_size.
mffunc
Имя финальной функции, вызываемой для вычисления результата агрегата
после обработки всех входных строк при использовании
режима подвижного агрегата. Работает так же, как ffunc,
за исключением того, что тип ее первого аргумента
— mstate_data_type, а дополнительные фиктивные аргументы
указываются записью MFINALFUNC_EXTRA.
Тип результата агрегата, определяемый функцией mffunc
или типом mstate_data_type, должен совпадать с типом, определяемым
обычной реализацией агрегата.
MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }
Эта опция похожа на FINALFUNC_MODIFY, но описывает
поведение финальной функции подвижного агрегата.
minitial_condition
Начальная установка для значения состояния при использовании режима подвижного агрегата.
Работает так же, как initial_condition.
sort_operator
Связанный оператор сортировки для агрегата, подобного MIN или
MAX.
Это просто имя оператора (возможно, с указанием схемы).
Предполагается, что оператор имеет те же типы входных данных, что и
агрегат (который должен быть обычным агрегатом с одним аргументом).
PARALLEL = { SAFE | RESTRICTED | UNSAFE }
Значения PARALLEL SAFE, PARALLEL
RESTRICTED и PARALLEL UNSAFE означают то же самое, что и
в CREATE FUNCTION. Агрегат не будет
рассматриваться для параллелизации, если он помечен как PARALLEL
UNSAFE (что является значением по умолчанию!) или PARALLEL RESTRICTED.
Обратите внимание, что отметки безопасности для параллелизма вспомогательных функций агрегата
не учитываются планировщиком, учитывается только отметка самого
агрегата.
HYPOTHETICAL
Только для упорядоченно-множественных агрегатов: этот флаг указывает, что аргументы агрегата
должны обрабатываться в соответствии с требованиями для
гипотетически-множественных агрегатов: то есть последние несколько прямых аргументов должны
соответствовать типам данных агрегируемых (аргументов WITHIN GROUP).
Флаг HYPOTHETICAL не влияет на
поведение во время выполнения, только на разрешение типов данных и
правил сортировки аргументов агрегата на этапе разбора.
Параметры CREATE AGGREGATE могут быть записаны
в любом порядке, а не только в том, что показан выше.
В параметрах, указывающих имена вспомогательных функций, можно при необходимости
писать имя схемы, например SFUNC = public.sum.
Однако не пишите там типы аргументов — типы аргументов
вспомогательных функций определяются из других параметров.
Обычно от функций Digital Q.DataBase ожидается, что они будут истинными функциями, которые не изменяют свои входные значения. Однако функция перехода состояния агрегата, при использовании в контексте агрегата, может нарушать это правило и изменять аргумент состояния на месте. Это может обеспечить значительный выигрыш в производительности по сравнению с созданием новой копии состояния каждый раз.
Аналогично, хотя от финальной функции агрегата обычно ожидается, что она не будет
изменять свои входные значения, иногда практически невозможно избежать изменения
аргумента состояния. Такое поведение должно быть объявлено с использованием
параметра FINALFUNC_MODIFY.
Значение READ_WRITE
указывает, что финальная функция изменяет состояние неопределенным образом.
Это значение предотвращает использование агрегата в качестве оконной функции,
а также предотвращает слияние состояний для вызовов агрегатов,
которые имеют одинаковые входные значения и функции перехода.
Значение SHAREABLE указывает, что функцию перехода
нельзя применить после финальной функции, но можно выполнить несколько вызовов финальной функции
над конечным значением состояния. Это значение предотвращает использование агрегата
в качестве оконной функции, но позволяет объединять состояния.
(То есть интересующая оптимизация здесь — не многократное применение одной и той же финальной функции,
а применение разных финальных функций к одному и тому же конечному значению состояния.
Это разрешено до тех пор, пока ни одна из финальных функций не помечена как READ_WRITE.)
Если агрегат поддерживает режим подвижного агрегата, это повысит
эффективность вычислений, когда агрегат используется в качестве оконной функции
для окна с движущимся началом кадра (то есть режимом начала кадра, отличным от
UNBOUNDED PRECEDING). Концептуально прямая
функция перехода добавляет входные значения в состояние агрегата, когда
они входят в оконный кадр снизу, а обратная функция перехода
удаляет их, когда они покидают кадр сверху. Таким образом,
когда значения удаляются, они всегда удаляются в том же порядке, в котором
были добавлены. Всякий раз, когда вызывается обратная функция перехода, она
будет получать самое раннее добавленное, но еще не удаленное значение(я) аргумента.
Обратная функция перехода может предполагать, что по крайней мере одна строка останется
в текущем состоянии после удаления самой старой строки. (Когда это
было бы не так, механизм оконных функций просто начинает новую
агрегацию, а не использует обратную функцию перехода.)
Прямой функции перехода для режима подвижного агрегата запрещено возвращать NULL в качестве нового значения состояния. Если обратная функция перехода возвращает NULL, это воспринимается как указание, что обратная функция не может обратить вычисление состояния для этого конкретного входного значения, и поэтому вычисление агрегата будет переделано с нуля для текущей начальной позиции кадра. Это соглашение позволяет использовать режим подвижного агрегата в ситуациях, когда есть некоторые редкие случаи, которые непрактично обратить из текущего значения состояния.
Если реализация подвижного агрегата не предоставлена, агрегат все еще можно использовать с движущимися кадрами, но Digital Q.DataBase будет пересчитывать всю агрегацию всякий раз, когда начало кадра перемещается. Обратите внимание, что независимо от того, поддерживает ли агрегат режим подвижного агрегата, Digital Q.DataBase может обрабатывать движущийся конец кадра без пересчета; это делается путем продолжения добавления новых значений в состояние агрегата. Именно поэтому использование агрегата в качестве оконной функции требует, чтобы финальная функция была доступна только для чтения: она не должна повреждать значение состояния агрегата, чтобы агрегация могла быть продолжена даже после получения результата агрегата для одного набора границ кадра.
Синтаксис для упорядоченно-множественных агрегатов позволяет указывать VARIADIC
как для последнего прямого параметра, так и для последнего
агрегированного параметра (WITHIN GROUP). Однако текущая реализация
ограничивает использование VARIADIC
двумя способами. Во-первых, упорядоченно-множественные агрегаты могут использовать только
VARIADIC "any", а не другие вариативные типы массивов.
Во-вторых, если последний прямой параметр — VARIADIC "any",
то может быть только один агрегированный параметр, и он также
должен быть VARIADIC "any". (В представлении, используемом в
системных каталогах, эти два параметра объединяются в один
элемент VARIADIC "any", поскольку pg_proc не может
представлять функции с более чем одним параметром VARIADIC.)
Если агрегат является гипотетически-множественным, прямые аргументы,
которые соответствуют параметру VARIADIC "any", являются гипотетическими;
любые предшествующие параметры представляют дополнительные прямые аргументы,
которые не ограничены необходимостью соответствовать агрегированным аргументам.
В настоящее время упорядоченно-множественные агрегаты не нуждаются в поддержке режима подвижного агрегата, поскольку они не могут использоваться в качестве оконных функций.
Частичная (включая параллельную) агрегация в настоящее время не поддерживается для
упорядоченно-множественных агрегатов. Кроме того, она никогда не будет использоваться для вызовов агрегатов,
которые включают предложения DISTINCT или ORDER BY, поскольку
эта семантика не может поддерживаться во время частичной агрегации.
См. Раздел 5.1.12.
CREATE AGGREGATE является расширением языка
Digital Q.DataBase. Стандарт SQL
не предусматривает пользовательские агрегатные функции.