(PHP 5 >= 5.3.0, PHP 7, PHP 8)
SQLite3::createAggregate — Зарегистрировать функцию PHP в качестве агрегирующей функции SQL
$name
,$stepCallback
,$finalCallback
,$argCount
= -1Регистрирует функцию PHP или пользовательскую функцию в качестве агрегирующей функции SQL для использования в запросах.
name
Имя агрегирующей функции SQL, которая должна быть создана или переопределена.
stepCallback
Функция обратного вызова, которая будет вызвана для каждой строки результирующего набора. Ваша PHP-функция должна аккумулировать результат и хранить его в контексте агрегации.
Эта функция должна быть определена следующим образом:
context
Для первой строки должно равняться null
;
Для всех последующих строк его значение должно быть равно значению,
возвращённому на предыдущем шаге; вы должны использовать его для сохранения
состояния агрегации.
rownumber
Номер текущей строки.
value
Первый аргумент переданный агрегатору.
values
Последующие аргументы.
context
при следующем запуске функции, либо как
значение передаваемое финализирующей функции.
finalCallback
Функция обратного вызова для вычисление итогового агрегированного значения. Она будет вызвана как только все строки результирующего набора будут обработаны, ей будет передан агрегирующий контекст и она вернёт финальное значение. Данная функция должна вернуть значение типа понятного SQLite (т.е. скалярный тип).
Эта функция должна быть определена следующим образом:
context
Содержит результат самого последнего вызова агрегирующей функции.
rownumber
Всегда 0
.
argCount
Количество аргументов, которое принимает функция агрегирования SQL. Если значение отрицательное, то функция может использовать любое количество аргументов.
Возвращает true
в случае успешного выполнения или false
в случае возникновения ошибки.
Пример #1 Пример агрегирующей функции max_length
<?php
$data = array(
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
);
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE strings(a)");
$insert = $db->prepare('INSERT INTO strings VALUES (?)');
foreach ($data as $str) {
$insert->bindValue(1, $str);
$insert->execute();
}
$insert = null;
function max_len_step($context, $rownumber, $string)
{
if (strlen($string) > $context) {
$context = strlen($string);
}
return $context;
}
function max_len_finalize($context, $rownumber)
{
return $context === null ? 0 : $context;
}
$db->createAggregate('max_len', 'max_len_step', 'max_len_finalize');
var_dump($db->querySingle('SELECT max_len(a) from strings'));
?>
Результат выполнения данного примера:
int(5)
В этом примере мы написали агрегирующую функцию, которая
вычисляет самой длинной строки в одной колонке таблицы.
Для каждой строки вызывается функция max_len_step
и ей
передаётся параметр $context
. Этот параметр ничем не отличается
от обычной переменной PHP и спокойно может содержать массив или объект.
В этом примере мы используем её для хранения максимальной найденной
длины строки. Если $string
будет иметь длину больше, чем
текущая сохранённая, то значение контекста будет обновлено.
После того, как все строки обработаны, SQLite вызовет функцию
max_len_finalize
, для окончательной подготовки результата.
Тут мы можем произвести необходимые расчёты на основе данных из
$context
. В нашем простом примере никакая постобработке не нужна
и мы просто возвращаем полученное значение.
НЕ рекомендуется хранить копию значений в контексте, а обработку производить в финализирующей функции, так как это может привести к большому потреблению памяти при обработке запроса. Просто представьте, сколько памяти вам понадобится для хранения миллиона строк, по 32 байта каждая, в памяти.
Для переопределения встроенных в SQLite агрегирующих функций вы можете использовать SQLite3::createAggregate().