204 lines
4 KiB
PHP
204 lines
4 KiB
PHP
|
<?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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
?>
|