WIP on data (JSON Path queries)

This commit is contained in:
Daniel J. Summers 2023-08-25 12:20:48 -04:00
parent fa281124bb
commit dc31b65be8
5 changed files with 90 additions and 10 deletions

View File

@ -11,12 +11,20 @@ class Data
/** The prayer request table */ /** The prayer request table */
const REQ_TABLE = 'prayer_request'; const REQ_TABLE = 'prayer_request';
/**
* Configure the data connection
*/
public static function configure()
{
Configuration::$connectionString = 'pgsql:host=localhost;port=5432;dbname=leafjson;user=leaf;password=leaf';
//Configuration::$startUp = '\MyPrayerJournal\Data::startUp';
}
/** /**
* Ensure the table and index exist * Ensure the table and index exist
*/ */
public static function startUp() public static function startUp()
{ {
Configuration::$connectionString = "pgsql:host=localhost;port=5432;dbname=leafjson;user=leaf;password=leaf";
Definition::ensureTable(self::REQ_TABLE); Definition::ensureTable(self::REQ_TABLE);
Definition::ensureIndex(self::REQ_TABLE, DocumentIndex::Optimized); Definition::ensureIndex(self::REQ_TABLE, DocumentIndex::Optimized);
} }
@ -96,10 +104,10 @@ class Data
private static function getJournalByAnswered(string $userId, string $op): array private static function getJournalByAnswered(string $userId, string $op): array
{ {
$sql = Query::selectFromTable(self::REQ_TABLE) $sql = Query::selectFromTable(self::REQ_TABLE)
. ' WHERE ' . Query::whereDataContains(':criteria') . ' AND ' . Query::whereJsonPathMatches(':path'); . ' WHERE ' . Query::whereDataContains('$1') . ' AND ' . Query::whereJsonPathMatches('$2');
$params = [ $params = [
':criteria' => Query::jsonbDocParam([ 'userId' => $userId ]), Query::jsonbDocParam([ 'userId' => $userId ]),
':path' => '$.history[*].action (@ ' . $op . ' "' . RequestAction::Answered->name . '")' '$.history[*].action (@ ' . $op . ' "' . RequestAction::Answered->name . '")'
]; ];
return self::mapToJournalRequest( return self::mapToJournalRequest(
Document::customList($sql, $params, Request::class, Document::mapFromJson(...)), true); Document::customList($sql, $params, Request::class, Document::mapFromJson(...)), true);

View File

@ -3,6 +3,8 @@ declare(strict_types=1);
namespace BitBadger\PgSQL\Documents; namespace BitBadger\PgSQL\Documents;
use \PgSql\Connection;
/** /**
* Document table configuration * Document table configuration
*/ */
@ -14,6 +16,27 @@ class Configuration
/** @var ?\PDO $conn The active connection */ /** @var ?\PDO $conn The active connection */
private static ?\PDO $conn = null; private static ?\PDO $conn = null;
/** @var ?Connection $rawConn An active non-PDO PostgreSQL connection */
private static ?Connection $rawConn = null;
/** @var ?string $startUp The name of a function to run on first connection to the database */
public static ?string $startUp = null;
/**
* Ensure that the connection string is set, either explicity, by environment variables, or with defaults
*/
private static function ensureConnectionString()
{
if (self::$connectionString == "") {
$host = $_ENV['PGDOC_HOST'] ?? 'localhost';
$port = $_ENV['PGDOC_PORT'] ?? 5432;
$db = $_ENV['PGDOC_DB'] ?? 'postgres';
$user = $_ENV['PGDOC_USER'] ?? 'postgres';
$pass = $_ENV['PGDOC_PASS'] ?? 'postgres';
self::$connectionString = "pgsql:host=$host;port=$port;dbname=$db;user=$user;pass=$pass";
}
}
/** /**
* Get the database connection, connecting on first request * Get the database connection, connecting on first request
* *
@ -22,10 +45,31 @@ class Configuration
public static function getConn(): \PDO public static function getConn(): \PDO
{ {
if (is_null(self::$conn)) { if (is_null(self::$conn)) {
self::ensureConnectionString();
self::$conn = new \PDO(self::$connectionString); self::$conn = new \PDO(self::$connectionString);
if (!is_null(self::$startUp)) {
call_user_func(self::$startUp);
}
} }
return self::$conn; return self::$conn;
} }
/**
*
*/
public static function getRawConn(): Connection
{
if (is_null(self::$rawConn)) {
self::ensureConnectionString();
self::$rawConn = pg_connect(str_replace(';', ' ', self::$connectionString));
if (!is_null(self::$startUp)) {
call_user_func(self::$startUp);
}
}
return self::$rawConn;
}
} }
require('functions.php'); require('functions.php');

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace BitBadger\PgSQL\Documents; namespace BitBadger\PgSQL\Documents;
use PDOStatement; use PDOStatement;
use PgSql\Result;
/** Document manipulation functions */ /** Document manipulation functions */
class Document class Document
@ -402,8 +403,14 @@ class Document
*/ */
private static function createCustomQuery(string $sql, array $params): PDOStatement private static function createCustomQuery(string $sql, array $params): PDOStatement
{ {
$result = pg_query_params(pgconn(), $sql, $params);
echo "Preparing statement for $sql\n";
foreach ($params as $name => $value) {
echo "Binding $name to $value\n";
}
$query = pdo()->prepare($sql); $query = pdo()->prepare($sql);
foreach ($params as $name => $value) { foreach ($params as $name => $value) {
echo "Binding $name to $value\n";
$query->bindParam($name, $value); $query->bindParam($name, $value);
} }
$query->execute(); $query->execute();
@ -421,9 +428,14 @@ class Document
*/ */
public static function customList(string $sql, array $params, string $className, callable $mapFunc): array public static function customList(string $sql, array $params, string $className, callable $mapFunc): array
{ {
return array_map( $data = pg_query_params(pgconn(), $sql, $params);
fn ($it) => $mapFunc($it, $className), $result = [];
self::createCustomQuery($sql, $params)->fetchAll(\PDO::FETCH_ASSOC)); if (!$data) return $result;
while ($row = pg_fetch_array($data, mode: PGSQL_ASSOC)) {
array_push($result, $mapFunc($row, $className));
}
pg_free_result($data);
return $result;
} }
/** /**

View File

@ -13,3 +13,14 @@ if (!function_exists('pdo')) {
return Configuration::getConn(); return Configuration::getConn();
} }
} }
if (!function_exists('pgconn')) {
/**
* Return the active PostgreSQL connection
*
* @return \PgSql\Connection The open PostgreSQL connection
*/
function pgconn()
{
return Configuration::getRawConn();
}
}

View File

@ -4,11 +4,14 @@ require __DIR__ . '/vendor/autoload.php';
use MyPrayerJournal\Data; use MyPrayerJournal\Data;
Data::startUp(); Data::configure();
//Data::findFullRequestById('abc', 'def');
//echo "Returned from req\n";
//Data::getAnsweredRequests('abc');
app()->template->config('path', './pages'); app()->template->config('path', './pages');
app()->template->config('params', [ app()->template->config('params', [
// 'app' => function () { return app(); },
'page_link' => function (string $url, bool $checkActive = false) { 'page_link' => function (string $url, bool $checkActive = false) {
echo 'href="'. $url . '" hx-get="' . $url . '"'; echo 'href="'. $url . '" hx-get="' . $url . '"';
if ($checkActive && str_starts_with($_SERVER['REQUEST_URI'], $url)) { if ($checkActive && str_starts_with($_SERVER['REQUEST_URI'], $url)) {
@ -34,8 +37,10 @@ function renderPage(string $template, array $params, string $pageTitle)
response()->markup(app()->template->render('layout/full', $params)); response()->markup(app()->template->render('layout/full', $params));
} }
Data::getAnsweredRequests('abc');
app()->get('/', function () { app()->get('/', function () {
renderPage('home', [], 'Welcome'); phpinfo();
//renderPage('home', [], 'Welcome');
}); });
app()->get('/legal/privacy-policy', function () { app()->get('/legal/privacy-policy', function () {