You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.1 KiB
121 lines
3.1 KiB
<?php
|
|
|
|
namespace DbCopy\Driver;
|
|
|
|
class Postgres implements IDriver
|
|
{
|
|
private $_options;
|
|
private $_pdo;
|
|
private $_insert_statement, $_insert_statement_size, $_insert_statement_fields;
|
|
|
|
public function open(array $params): void
|
|
{
|
|
$params = array_merge([
|
|
'dsn' => null,
|
|
'username' => null,
|
|
'password' => null,
|
|
'query' => null,
|
|
'table' => null
|
|
], $params);
|
|
|
|
$this->_options = $params;
|
|
|
|
$this->_pdo = new \PDO($params['dsn'], $params['username'], $params['password']);
|
|
$this->_pdo->query('SET AUTOCOMMIT');
|
|
}
|
|
|
|
public function close(): void
|
|
{
|
|
$this->_pdo = null;
|
|
}
|
|
|
|
public function get(array $params = []): \DbCopy\ICursor
|
|
{
|
|
$options = array_merge($this->_options, $params);
|
|
|
|
$statement = $this->_pdo->prepare($params['query']);
|
|
$statement->execute();
|
|
|
|
return new \DbCopy\Cursor(function() use ($options, $statement) {
|
|
$record = $statement->fetch(\PDO::FETCH_ASSOC);
|
|
if (!$record) return [];
|
|
return [$record];
|
|
});
|
|
|
|
|
|
}
|
|
|
|
public function put(array $record, array $params = []): void
|
|
{
|
|
$params = array_merge($this->_options, $params);
|
|
|
|
$sql = 'insert into "'.$params['table'].'"(';
|
|
$fields = array_keys($record);
|
|
$sql .= '"'.implode('", "', $fields).'"';
|
|
$sql .= ') VALUES ('.implode(', ', str_split(str_repeat('?', sizeof($fields)))).')';
|
|
$statement = $this->_pdo->prepare($sql);
|
|
$result = $statement->execute(array_values($record));
|
|
if ($result === false)
|
|
{
|
|
var_dump($record);
|
|
throw new \Exception("Error inserting record into Postgres: ".print_r($statement->errorInfo(), true));
|
|
}
|
|
}
|
|
|
|
public function putBatch(array $records, array $params = []): void
|
|
{
|
|
$params = array_merge($this->_options, $params);
|
|
|
|
// Find all possible fields in all records while sorting their keys
|
|
// so they're all consistent
|
|
$fields = [];
|
|
foreach ($records as &$record)
|
|
{
|
|
$fields = array_merge($fields, array_keys($record));
|
|
}
|
|
unset($record);
|
|
// Make unique
|
|
$fields = array_unique($fields);
|
|
// Sort so this is kinda stable
|
|
sort($fields);
|
|
|
|
// Generate prepared statement if one doesn't exist or it doesn't match
|
|
// the current batch
|
|
if (!isset($this->_insert_statement) ||
|
|
sizeof($records) != $this->_insert_statement_size ||
|
|
$fields !== $this->_insert_statement_fields)
|
|
{
|
|
echo 'new statement'.PHP_EOL;
|
|
$sql = 'insert into "'.$params['table'].'"(';
|
|
$sql .= '"'.implode('", "', $fields).'"';
|
|
$sql .= ') VALUES ';
|
|
$sql .= substr(str_repeat('('.implode(', ', str_split(str_repeat('?', sizeof($fields)))).'), ', sizeof($records)), 0, -2);
|
|
$this->_insert_statement = $this->_pdo->prepare($sql);
|
|
$this->_insert_statement_size = sizeof($records);
|
|
$this->_insert_statement_fields = $fields;
|
|
}
|
|
|
|
// Generate values from records
|
|
$values = [];
|
|
foreach ($records as $record)
|
|
{
|
|
foreach ($fields as $field)
|
|
{
|
|
if (isset($record[$field]))
|
|
$values[] = $record[$field];
|
|
else
|
|
$values[] = null;
|
|
}
|
|
}
|
|
|
|
// Execute statement
|
|
$result = $this->_insert_statement->execute($values);
|
|
|
|
if ($result === false)
|
|
{
|
|
throw new \Exception("Error inserting record into Postgres: ".print_r($this->_insert_statement->errorInfo(), true));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|