rosavox/lib/alveolata/database/implementation-postgresql/functions.php

204 lines
4 KiB
PHP
Raw Normal View History

2025-05-23 07:33:29 +00:00
<?php
namespace alveolata\database;
// require_once(DIR_ALVEOLATA . '/definitions.php');
require_once(DIR_ALVEOLATA . '/report/functions.php');
require_once(DIR_ALVEOLATA . '/log/functions.php');
require_once(DIR_ALVEOLATA . '/sql/functions.php');
/**
* @author Christian Fraß <frass@greenscale.de>
* requires PHP module "pgsql" (Debian package name "php-pgsql")
*/
class struct_subject_postgresql {
/**
* @var string
* @author Christian Fraß <frass@greenscale.de>
*/
public $host;
/**
* @var int
* @author Christian Fraß <frass@greenscale.de>
*/
public $port;
/**
* @var string
* @author Christian Fraß <frass@greenscale.de>
*/
public $schema;
/**
* @var string
* @author Christian Fraß <frass@greenscale.de>
*/
public $username;
/**
* @var string
* @author Christian Fraß <frass@greenscale.de>
*/
public $password;
/**
* @author Christian Fraß <frass@greenscale.de>
*/
public function __construct(
string $host,
int $port,
string $schema,
string $username,
string $password
)
{
$this->host = $host;
$this->port = $port;
$this->schema = $schema;
$this->username = $username;
$this->password = $password;
}
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function postgresql_make(
string $host,
int $port,
string $schema,
string $username,
string $password
) : struct_subject_postgresql
{
return (
new struct_subject_postgresql(
$host,
$port,
$schema,
$username,
$password
)
);
}
/**
* @return string
* @author Christian Fraß <frass@greenscale.de>
*/
function postgresql_terminal_autoincrement(
) : string
{
return 'AUTO_INCREMENT';
}
/**
* @return string
* @author Christian Fraß <frass@greenscale.de>
*/
function postgresql_boilerplate_field_definition_for_integer_primary_key_with_auto_increment(
) : string
{
return 'SERIAL PRIMARY KEY';
}
/**
* @param struct_subject_postgresql $subject
* @param string $template
* @param array $arguments
* @return array
* @author Christian Fraß <frass@greenscale.de>
*/
function postgresql_query(
struct_subject_postgresql $subject,
string $template,
array $arguments
) : array
{
$connection = \pg_connect(
sprintf(
'host=%s port=%d user=%s password=%s dbname=%s',
$subject->host,
$subject->port,
$subject->username,
$subject->password,
$subject->schema
)
);
// \pg_set_client_encoding($connection, \UNICODE);
\pg_query($connection, "SET client_encoding TO 'UNICODE'");
$template_adjusted = $template;
$arguments_adjusted = [];
$counter = 0;
foreach ($arguments as $key => $value) {
$pattern = \sprintf(':%s', $key);
$replacement = \sprintf('$%d', $counter+1);
$counter += 1;
$template_adjusted = str_replace($pattern, $replacement, $template_adjusted);
\array_push($arguments_adjusted, $value);
}
$report = \alveolata\report\make(
'postgresl_query',
[
'template' => $template_adjusted,
'arguments' => $arguments,
]
);
\alveolata\log\debug_($report);
$result = \pg_query_params($connection, $template_adjusted, $arguments_adjusted);
if ($result === false) {
$report = \alveolata\report\make(
'postgresl_query_failed',
[
'template' => $template_adjusted,
'arguments' => $arguments_adjusted,
]
);
throw (\alveolata\report\as_exception($report));
}
else {
// $status = \pg_result_status($result, \PGSQL_STATUS_STRING);
$status = \pg_result_status($result, \PGSQL_STATUS_LONG);
switch ($status) {
default: {
$report = \alveolata\report\make(
'postgresl_query_bad_result',
[
'template' => $template_adjusted,
'arguments' => $arguments_adjusted,
'status' => $status,
]
);
throw (\alveolata\report\as_exception($report));
break;
}
case \PGSQL_COMMAND_OK:
case \PGSQL_TUPLES_OK: {
$id_raw = \pg_last_oid($result);
return [
'rows' => \pg_fetch_all($result, \PGSQL_ASSOC),
'id' => (($id_raw === false) ? null : $id_raw),
'affected' => \pg_affected_rows($result),
];
break;
}
}
}
}
?>