mirror of
https://github.com/vrana/adminer.git
synced 2025-08-13 18:14:07 +02:00
PostgreSQL: Support COPY FROM stdin in SQL query (fix #942)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
## Adminer dev
|
## Adminer dev
|
||||||
- Do not edit NULL values by Modify (bug #967)
|
- Do not edit NULL values by Modify (bug #967)
|
||||||
|
- PostgreSQL: Support COPY FROM stdin in SQL query (bug #942)
|
||||||
- MySQL: Display number of found rows in group queries (regression from 5.1.1)
|
- MySQL: Display number of found rows in group queries (regression from 5.1.1)
|
||||||
- non-MySQL: Parse '--' as comment in SQL command (bug SF-842)
|
- non-MySQL: Parse '--' as comment in SQL command (bug SF-842)
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ add_driver("pgsql", "PostgreSQL");
|
|||||||
if (isset($_GET["pgsql"])) {
|
if (isset($_GET["pgsql"])) {
|
||||||
define('Adminer\DRIVER', "pgsql");
|
define('Adminer\DRIVER', "pgsql");
|
||||||
if (extension_loaded("pgsql") && $_GET["ext"] != "pdo") {
|
if (extension_loaded("pgsql") && $_GET["ext"] != "pdo") {
|
||||||
class Db extends SqlDb {
|
class PgsqlDb extends SqlDb {
|
||||||
public string $extension = "PgSQL";
|
public string $extension = "PgSQL";
|
||||||
public int $timeout = 0;
|
public int $timeout = 0;
|
||||||
private $link, $string, $database = true;
|
private $link, $string, $database = true;
|
||||||
@@ -88,6 +88,19 @@ if (isset($_GET["pgsql"])) {
|
|||||||
function warnings() {
|
function warnings() {
|
||||||
return h(pg_last_notice($this->link)); // second parameter is available since PHP 7.1.0
|
return h(pg_last_notice($this->link)); // second parameter is available since PHP 7.1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Copy from array into a table
|
||||||
|
* @param list<string> $rows
|
||||||
|
*/
|
||||||
|
function copyFrom(string $table, array $rows): bool {
|
||||||
|
$this->error = '';
|
||||||
|
set_error_handler(function ($errno, $error) {
|
||||||
|
$this->error = (ini_bool('html_errors') ? html_entity_decode($error) : $error);
|
||||||
|
});
|
||||||
|
$return = pg_copy_from($this->link, $table, $rows);
|
||||||
|
restore_error_handler();
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Result {
|
class Result {
|
||||||
@@ -123,7 +136,7 @@ if (isset($_GET["pgsql"])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} elseif (extension_loaded("pdo_pgsql")) {
|
} elseif (extension_loaded("pdo_pgsql")) {
|
||||||
class Db extends PdoDb {
|
class PgsqlDb extends PdoDb {
|
||||||
public string $extension = "PDO_PgSQL";
|
public string $extension = "PDO_PgSQL";
|
||||||
public int $timeout = 0;
|
public int $timeout = 0;
|
||||||
|
|
||||||
@@ -155,6 +168,12 @@ if (isset($_GET["pgsql"])) {
|
|||||||
// not implemented in PDO_PgSQL as of PHP 7.2.1
|
// not implemented in PDO_PgSQL as of PHP 7.2.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyFrom(string $table, array $rows): bool {
|
||||||
|
$return = $this->pdo->pgsqlCopyFromArray($table, $rows);
|
||||||
|
$this->error = idx($this->pdo->errorInfo(), 2) ?: '';
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,6 +182,21 @@ if (isset($_GET["pgsql"])) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (class_exists('Adminer\PgsqlDb')) {
|
||||||
|
class Db extends PgsqlDb {
|
||||||
|
function multi_query(string $query) {
|
||||||
|
if (preg_match('~\bCOPY\s+(.+?)\s+FROM\s+stdin;\n?(.*)\n\\\\\.$~is', str_replace("\r\n", "\n", $query), $match)) { // no ^ to allow leading comments
|
||||||
|
$rows = explode("\n", $match[2]);
|
||||||
|
$this->affected_rows = count($rows);
|
||||||
|
return $this->copyFrom($match[1], $rows);
|
||||||
|
}
|
||||||
|
return parent::multi_query($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Driver extends SqlDriver {
|
class Driver extends SqlDriver {
|
||||||
static array $extensions = array("PgSQL", "PDO_PgSQL");
|
static array $extensions = array("PgSQL", "PDO_PgSQL");
|
||||||
static string $jush = "pgsql";
|
static string $jush = "pgsql";
|
||||||
|
@@ -72,10 +72,13 @@ if (!$error && $_POST) {
|
|||||||
|
|
||||||
while ($query != "") {
|
while ($query != "") {
|
||||||
if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) {
|
if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) {
|
||||||
$delimiter = $match[1];
|
$delimiter = preg_quote($match[1]);
|
||||||
$query = substr($query, strlen($match[0]));
|
$query = substr($query, strlen($match[0]));
|
||||||
|
} elseif (!$offset && JUSH == 'pgsql' && preg_match("~^($space*+COPY\\s+)[^;]+\\s+FROM\\s+stdin;~i", $query, $match)) {
|
||||||
|
$delimiter = "\n\\\\\\.\r?\n";
|
||||||
|
$offset = strlen($match[0]);
|
||||||
} else {
|
} else {
|
||||||
preg_match('(' . preg_quote($delimiter) . "\\s*|$parse)", $query, $match, PREG_OFFSET_CAPTURE, $offset); // should always match
|
preg_match("($delimiter\\s*|$parse)", $query, $match, PREG_OFFSET_CAPTURE, $offset); // always matches
|
||||||
list($found, $pos) = $match[0];
|
list($found, $pos) = $match[0];
|
||||||
if (!$found && $fp && !feof($fp)) {
|
if (!$found && $fp && !feof($fp)) {
|
||||||
$query .= fread($fp, 1e5);
|
$query .= fread($fp, 1e5);
|
||||||
@@ -85,14 +88,15 @@ if (!$error && $_POST) {
|
|||||||
}
|
}
|
||||||
$offset = $pos + strlen($found);
|
$offset = $pos + strlen($found);
|
||||||
|
|
||||||
if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
|
if ($found && !preg_match("(^$delimiter)", $found)) { // find matching quote or comment end
|
||||||
$c_style_escapes = driver()->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
|
$c_style_escapes = driver()->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
|
||||||
|
|
||||||
$pattern = ($found == '/*' ? '\*/'
|
$pattern =
|
||||||
: ($found == '[' ? ']'
|
($found == '/*' ? '\*/' :
|
||||||
: (preg_match('~^-- |^#~', $found) ? "\n"
|
($found == '[' ? ']' :
|
||||||
: preg_quote($found) . ($c_style_escapes ? "|\\\\." : "")))
|
(preg_match('~^-- |^#~', $found) ? "\n" :
|
||||||
);
|
preg_quote($found) . ($c_style_escapes ? '|\\\\.' : ''))))
|
||||||
|
;
|
||||||
|
|
||||||
while (preg_match("($pattern|\$)s", $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
|
while (preg_match("($pattern|\$)s", $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
|
||||||
$s = $match[0][0];
|
$s = $match[0][0];
|
||||||
@@ -108,7 +112,7 @@ if (!$error && $_POST) {
|
|||||||
|
|
||||||
} else { // end of a query
|
} else { // end of a query
|
||||||
$empty = false;
|
$empty = false;
|
||||||
$q = substr($query, 0, $pos);
|
$q = substr($query, 0, $pos + ($delimiter[0] == "\n" ? 3 : 0)); // 3 - pass "\n\\." to PostgreSQL COPY
|
||||||
$commands++;
|
$commands++;
|
||||||
$print = "<pre id='sql-$commands'><code class='jush-" . JUSH . "'>" . adminer()->sqlCommandQuery($q) . "</code></pre>\n";
|
$print = "<pre id='sql-$commands'><code class='jush-" . JUSH . "'>" . adminer()->sqlCommandQuery($q) . "</code></pre>\n";
|
||||||
if (JUSH == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
|
if (JUSH == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
|
||||||
|
Reference in New Issue
Block a user