SQLite UDF 及 UDAF 的实现

SQLite UDF/UDAF 的实现

<?php
// sqlite UDF/UDAF 支持
// https://blog.csdn.net/wyqwilliam/article/details/84500578

// 参考:
// php 版本实现:https://www.php.net/manual/en/ref.pdo-sqlite.connection.php
// go 版本实现:https://github.com/mattn/go-sqlite3/pull/229/files

$db = new \PDO('sqlite::memory:');
//$db->setAttribute(PDO::ATTR)
// $db = new \PDO('sqlite:');
// $db = new \PDO('sqlite:tmp.db');
$db->exec('
    CREATE TABLE "role" (
      "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
      "actor" TEXT,
      "movie" TEXT,
      "year" INTEGER
    );
');
$insert = $db->exec('
    INSERT INTO role
     (actor, movie, year)
    VALUES 
    ("杨幂", "新聊斋志异", 2005),
    ("杨幂", "仙剑奇侠传", 2009),
    ("胡歌", "仙剑奇侠传", 2005),
    ("胡歌", "琅琊榜", 2015),
    ("胡歌", "神话", 2010),
    ("周迅", "大明宫词", 2000),
    ("周迅", "人间四月天", 2000)
;
');

$db->sqliteCreateFunction('IF', function ($expr, $value1, $value2) {
    if ($expr) {
        return $value1;
    }
    return $value2;
});

$db->sqliteCreateFunction('GREATEST', function ($value1, $value2) {
    return max([$value1, $value2]);
});

$query = $db
    ->query('SELECT actor, movie, year, IF (year <= 2005, "old", "new") AS `type` FROM role');
while ($data = $query->fetchObject()) {
    print_r($data);
}
/*
stdClass Object
(
    [actor] => 杨幂
    [movie] => 新聊斋志异
    [year] => 2005
    [type] => old
)
stdClass Object
(
    [actor] => 杨幂
    [movie] => 仙剑奇侠传
    [year] => 2009
    [type] => new
)
stdClass Object
(
    [actor] => 胡歌
    [movie] => 仙剑奇侠传
    [year] => 2005
    [type] => old
)
stdClass Object
(
    [actor] => 胡歌
    [movie] => 琅琊榜
    [year] => 2015
    [type] => new
)
stdClass Object
(
    [actor] => 胡歌
    [movie] => 神话
    [year] => 2010
    [type] => new
)
stdClass Object
(
    [actor] => 周迅
    [movie] => 大明宫词
    [year] => 2000
    [type] => old
)
stdClass Object
(
    [actor] => 周迅
    [movie] => 人间四月天
    [year] => 2000
    [type] => old
)
*/

$query = $db
    ->query('SELECT actor, GROUP_CONCAT(movie) AS all_movies FROM role GROUP BY actor');
while ($data = $query->fetchObject()) {
    print_r($data);
}
/*
stdClass Object
(
    [actor] => 周迅
    [all_movies] => 大明宫词,人间四月天
)
stdClass Object
(
    [actor] => 杨幂
    [all_movies] => 新聊斋志异,仙剑奇侠传
)
stdClass Object
(
    [actor] => 胡歌
    [all_movies] => 仙剑奇侠传,琅琊榜,神话
)
*/

$db->sqliteCreateAggregate('GROUP_CONCAT', function ($context, $row_number, $field) {
    if (is_null($context)) {
        return $field;
    }
    return $context . '/' . $field;
}, function ($context, $rowcount) { return $context; });
/*
 stdClass Object
(
    [actor] => 周迅
    [all_movies] => 大明宫词/人间四月天
)
stdClass Object
(
    [actor] => 杨幂
    [all_movies] => 新聊斋志异/仙剑奇侠传
)
stdClass Object
(
    [actor] => 胡歌
    [all_movies] => 仙剑奇侠传/琅琊榜/神话
)
*/