(PHP 5 >= 5.3.0, PHP 7, PHP 8)
SQLite3::createAggregate — SQL の集約関数として使用する PHP 関数を登録する
$name
,$stepCallback
,$finalCallback
,$argCount
= -1SQL の集約関数として使用する PHP 関数を登録します。 これは SQL 文の中で使用されるものです。
name
作成あるいは再定義したい SQL 集約関数の名前。
stepCallback
結果セットの各行ごとにコールされるコールバック関数。 この関数で結果を集約し、集約処理のコンテキストに保存すべきです。
このコールバック関数は、以下のように定義すべきです:
context
最初の行では null
です。
2行目以降は、step 関数から返された値をとります。
これは、集約の状況を管理するのに使います。
rownumber
現在の行番号
value
集約に渡されるはじめの引数
values
集約に渡されるふたつめ以降の引数
context
の引数として使われます。
finalCallback
各行からの "段階的に処理された" データを集約するコールバック関数です。 いったん全データが処理されると、この関数が呼ばれます。 集約処理のコンテキストからデータを取り出し、結果を返すべきです。 このコールバック関数は SQLite が理解する型を返します。 (例: スカラー型)
このコールバック関数は、以下のように定義すべきです:
context
最後に呼ばれた step 関数から返された値を保持します。
rownumber
常に 0
.
argCount
SQL 集約関数が受け取るパラメータの数。 負の値を指定すると、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)
この例では、テーブルのカラムに入っている一番長い文字列を集約する関数を作っています。
1行ごとに、max_len_step
関数が呼ばれ、
$context
パラメータが渡されます。 context パラメータ
は他のPHPの変数のように振る舞いますし、配列やオブジェクトを格納することさえできます。
この例では、単にこれまで見てきたものの中から一番大きな長さを保持するのに使っています。
つまり、$string
が現在の最大値より大きな長さをもっていたら、
context を新しい最大値に更新しています。
全ての行を処理し終わったら、SQLite は
集約結果を決めるために max_len_finalize
関数を呼び出します。
ここでは、$context
で見つかったデータを基にして、
ある種の計算を行うことができます。
私達のシンプルな例では、結果を段階的に計算してきているので、
単に context に入っている値を返すだけで済みます。
値のコピーを context に保存し、一番最後に処理することは推奨できません。 なぜなら、SQLite がクエリを処理するのにたくさんのメモリを使うことになるからです。 - 100万行の情報がメモリに格納されていたとして、 それぞれの行が32バイトの長さを持っていたとすると、 どれくらいのメモリが必要になるのかを考えてみてください。
SQLite のネイティブなSQL関数を上書きするために SQLite3::createAggregate() を使うことができます。