Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Reintegrate sqlite branch

git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@1466 7c3ca157-0c34-0410-bff1-cbf682f78f5c
  • Loading branch information...
commit 3f5b683456ad1eab9083f3384bf02bc040a59c2a 1 parent 2df25ba
jakubvrana authored
Showing with 3,005 additions and 1,090 deletions.
  1. +6 −3 adminer/call.inc.php
  2. +33 −44 adminer/create.inc.php
  3. +21 −31 adminer/database.inc.php
  4. +75 −45 adminer/db.inc.php
  5. +1 −1  adminer/download.inc.php
  6. +406 −0 adminer/drivers/mssql.inc.php
  7. +713 −0 adminer/drivers/mysql.inc.php
  8. +443 −0 adminer/drivers/pgsql.inc.php
  9. +479 −0 adminer/drivers/sqlite.inc.php
  10. +49 −27 adminer/dump.inc.php
  11. +12 −17 adminer/edit.inc.php
  12. +8 −2 adminer/foreign.inc.php
  13. +65 −67 adminer/include/adminer.inc.php
  14. +58 −46 adminer/include/auth.inc.php
  15. +20 −11 adminer/include/bootstrap.inc.php
  16. +19 −11 adminer/include/connect.inc.php
  17. +38 −19 adminer/include/design.inc.php
  18. +22 −23 adminer/include/editing.inc.php
  19. +10 −11 adminer/include/export.inc.php
  20. +116 −33 adminer/include/functions.inc.php
  21. +0 −406 adminer/include/mysql.inc.php
  22. +11 −9 adminer/include/pdo.inc.php
  23. +1 −1  adminer/include/version.inc.php
  24. +1 −1  adminer/index.php
  25. +12 −8 adminer/indexes.inc.php
  26. +8 −4 adminer/lang/cs.inc.php
  27. +3 −6 adminer/lang/de.inc.php
  28. +3 −6 adminer/lang/es.inc.php
  29. +3 −6 adminer/lang/et.inc.php
  30. +3 −6 adminer/lang/fr.inc.php
  31. +3 −6 adminer/lang/it.inc.php
  32. +3 −6 adminer/lang/nl.inc.php
  33. +3 −6 adminer/lang/ru.inc.php
  34. +3 −6 adminer/lang/sk.inc.php
  35. +3 −6 adminer/lang/zh-tw.inc.php
  36. +3 −6 adminer/lang/zh.inc.php
  37. +1 −2  adminer/privileges.inc.php
  38. +2 −2 adminer/schema.inc.php
  39. +72 −42 adminer/select.inc.php
  40. +15 −12 adminer/sql.inc.php
  41. +8 −6 adminer/static/default.css
  42. +2 −3 adminer/static/editing.js
  43. BIN  adminer/static/favicon.ico
  44. +16 −1 adminer/static/functions.js
  45. +13 −11 adminer/table.inc.php
  46. +3 −4 adminer/trigger.inc.php
  47. +1 −1  adminer/user.inc.php
  48. +1 −1  adminer/view.inc.php
  49. +10 −0 changes.txt
  50. +44 −5 compile.php
  51. +1 −1  coverage.php
  52. +2 −2 editor/db.inc.php
  53. +65 −73 editor/include/adminer.inc.php
  54. +31 −9 editor/include/editing.inc.php
  55. +2 −1  editor/index.php
  56. +1 −0  lang.php
  57. +2 −2 tests/0-login.html
  58. +1 −1  tests/1-create-database.html
  59. +1 −1  tests/10-clone.html
  60. +1 −1  tests/11-reference.html
  61. +1 −1  tests/12-update.html
  62. +1 −1  tests/13-delete.html
  63. +1 −1  tests/14-truncate.html
  64. +1 −1  tests/15-privileges.html
  65. +1 −1  tests/16-processlist.html
  66. +1 −1  tests/17-export.html
  67. +1 −1  tests/18-events.html
  68. +1 −1  tests/19-procedures.html
  69. +1 −1  tests/2-create-table.html
  70. +1 −1  tests/20-partitioning.html
  71. +1 −1  tests/21-variables.html
  72. +1 −1  tests/22-history.html
  73. +1 −1  tests/23-editor.html
  74. +1 −1  tests/24-explain.html
  75. +1 −1  tests/3-create-index.html
  76. +1 −1  tests/4-create-table-2.html
  77. +1 −1  tests/5-foreign-key.html
  78. +1 −1  tests/6-alter-table.html
  79. +1 −1  tests/7-create-trigger.html
  80. +1 −1  tests/8-create-view.html
  81. +2 −2 tests/9-insert.html
  82. +2 −2 tests/logout.html
  83. +28 −4 todo.txt
  84. +1 −1  version.js
View
9 adminer/call.inc.php
@@ -28,7 +28,9 @@
}
$call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val);
}
- if (!$connection->multi_query((isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")")) {
+ $query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")";
+ echo "<p><code class='jush-$driver'>" . h($query) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
+ if (!$connection->multi_query($query)) {
echo "<p class='error'>" . error() . "\n";
} else {
do {
@@ -52,8 +54,9 @@
echo "<table cellspacing='0'>\n";
foreach ($in as $key) {
$field = $routine["fields"][$key];
- echo "<tr><th>" . h($field["field"]);
- $value = $_POST["fields"][$key];
+ $name = $field["field"];
+ echo "<tr><th>" . h($name);
+ $value = $_POST["fields"][$name];
if ($value != "" && ereg("enum|set", $field["type"])) {
$value = intval($value);
}
View
77 adminer/create.inc.php
@@ -19,20 +19,8 @@
if ($_POST["drop"]) {
query_redirect("DROP TABLE " . idf_escape($_GET["create"]), substr(ME, 0, -1), lang('Table has been dropped.'));
} else {
- $auto_increment_index = " PRIMARY KEY";
- // don't overwrite primary key by auto_increment
- if ($TABLE != "" && $_POST["auto_increment_col"]) {
- foreach (indexes($TABLE) as $index) {
- if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
- $auto_increment_index = "";
- break;
- }
- if ($index["type"] == "PRIMARY") {
- $auto_increment_index = " UNIQUE";
- }
- }
- }
- $fields = "";
+ $fields = array();
+ $foreign = array();
ksort($_POST["fields"]);
$orig_field = reset($orig_fields);
$after = "FIRST";
@@ -48,33 +36,26 @@
$field["on_update"] = "CURRENT_TIMESTAMP";
$field["default"] = $default;
}
+ if ($key == $_POST["auto_increment_col"]) {
+ $field["auto_increment"] = true;
+ }
$process_field = process_field($field, $type_field);
- $auto_increment = ($key == $_POST["auto_increment_col"]);
- if ($process_field != process_field($orig_field, $orig_field) || $orig_field["auto_increment"] != $auto_increment) {
- $fields .= "\n" . ($TABLE != "" ? ($field["orig"] != "" ? "CHANGE " . idf_escape($field["orig"]) : "ADD") : " ")
- . " $process_field"
- . ($auto_increment ? " AUTO_INCREMENT$auto_increment_index" : "")
- . ($TABLE != "" ? " $after" : "") . ","
- ;
+ if ($process_field != process_field($orig_field, $orig_field)) {
+ $fields[] = array($field["orig"], $process_field, $after);
}
if (!isset($types[$field["type"]])) {
- $fields .= ($TABLE != "" ? "\nADD" : "") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . "),";
+ $foreign[] = ($TABLE != "" ? "ADD " : " ") . "FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")";
}
}
$after = "AFTER " . idf_escape($field["field"]);
- //! drop and create foreign keys with renamed columns
} elseif ($field["orig"] != "") {
- $fields .= "\nDROP " . idf_escape($field["orig"]) . ",";
+ $fields[] = array($field["orig"]);
}
if ($field["orig"] != "") {
$orig_field = next($orig_fields);
}
}
- $status = "COMMENT=" . $connection->quote($_POST["Comment"])
- . ($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? " ENGINE=" . $connection->quote($_POST["Engine"]) : "")
- . ($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? " COLLATE " . $connection->quote($_POST["Collation"]) : "")
- . ($_POST["Auto_increment"] != "" ? " AUTO_INCREMENT=" . preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : "")
- ;
+ $partitioning = "";
if (in_array($_POST["partition_by"], $partition_by)) {
$partitions = array();
if ($_POST["partition_by"] == 'RANGE' || $_POST["partition_by"] == 'LIST') {
@@ -83,20 +64,29 @@
$partitions[] = "\nPARTITION " . idf_escape($val) . " VALUES " . ($_POST["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
}
}
- $status .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column
+ $partitioning .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column
? " (" . implode(",", $partitions) . "\n)"
: ($_POST["partitions"] ? " PARTITIONS " . intval($_POST["partitions"]) : "")
);
- } elseif ($connection->server_info >= 5.1 && $TABLE != "") {
- $status .= "\nREMOVE PARTITIONING";
+ } elseif ($TABLE != "") {
+ $partitioning .= "\nREMOVE PARTITIONING";
}
- $location = ME . "table=" . urlencode($_POST["name"]);
- if ($TABLE != "") {
- query_redirect("ALTER TABLE " . idf_escape($TABLE) . "$fields\nRENAME TO " . idf_escape($_POST["name"]) . ",\n$status", $location, lang('Table has been altered.'));
- } else {
+ $message = lang('Table has been altered.');
+ if ($TABLE == "") {
cookie("adminer_engine", $_POST["Engine"]);
- query_redirect("CREATE TABLE " . idf_escape($_POST["name"]) . " (" . substr($fields, 0, -1) . "\n) $status", $location, lang('Table has been created.'));
+ $message = lang('Table has been created.');
}
+ queries_redirect(ME . "table=" . urlencode($_POST["name"]), $message, alter_table(
+ $TABLE,
+ $_POST["name"],
+ $fields,
+ $foreign,
+ $_POST["Comment"],
+ ($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""),
+ ($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? $_POST["Collation"] : ""),
+ ($_POST["Auto_increment"] != "" ? preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : ""),
+ $partitioning
+ ));
}
}
@@ -127,9 +117,9 @@
}
$row["fields"][] = $field;
}
- if ($connection->server_info >= 5.1) {
+ if (support("partitioning")) {
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . $connection->quote(DB) . " AND TABLE_NAME = " . $connection->quote($TABLE);
- $result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
+ $result = $connection->query("SELECT" . limit("PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION", 1));
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row();
$row["partition_names"] = array();
$row["partition_values"] = array();
@@ -162,24 +152,23 @@
<p>
<?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>">
<?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) : ""); ?>
- <?php echo html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]); ?>
+ <?php echo ($collations ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<table cellspacing="0" id="edit-fields" class="nowrap">
-<?php $column_comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys); ?>
+<?php $comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys, $row["Comment"] != ""); ?>
</table>
<p>
<?php echo lang('Auto Increment'); ?>: <input name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
-<?php echo lang('Comment'); ?>: <input name="Comment" value="<?php echo h($row["Comment"]); ?>" maxlength="60">
<script type="text/javascript">
document.write('<label><input type="checkbox" onclick="columnShow(this.checked, 5);"><?php echo lang('Default values'); ?><\/label>');
-document.write('<label><input type="checkbox"<?php if ($column_comments) { ?> checked<?php } ?> onclick="columnShow(this.checked, 6);"><?php echo lang('Show column comments'); ?><\/label>');
</script>
+<?php echo (support("comment") ? checkbox("", "", $comments, lang('Comment'), "columnShow(this.checked, 6); toggle('Comment');") . ' <input id="Comment" name="Comment" value="' . h($row["Comment"]) . '" maxlength="60"' . ($comments ? '' : ' class="hidden"') . '>' : ''); ?>
<p>
<input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php if (strlen($_GET["create"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo $confirm; ?>><?php } ?>
<?php
-if ($connection->server_info >= 5.1) {
+if (support("partitioning")) {
$partition_table = ereg('RANGE|LIST', $row["partition_by"]);
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
?>
View
52 adminer/database.inc.php
@@ -2,35 +2,26 @@
if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x
restart_session();
if ($_POST["drop"]) {
- unset($_SESSION["databases"][$_GET["server"]]);
+ set_session("databases", null);
query_redirect("DROP DATABASE " . idf_escape(DB), remove_from_uri("db|database"), lang('Database has been dropped.'));
} elseif (DB !== $_POST["name"]) {
// create or rename database
- unset($_SESSION["databases"][$_GET["server"]]); // clear cache
- $dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
- $failed = false;
- $last = "";
- foreach ($dbs as $db) {
- if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
- if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
- $failed = true;
+ set_session("databases", null); // clear cache
+ if (DB != "") {
+ queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), rename_database($_POST["name"], $_POST["collation"]));
+ } else {
+ $dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
+ $success = true;
+ $last = "";
+ foreach ($dbs as $db) {
+ if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
+ if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
+ $success = false;
+ }
+ $last = $db;
}
- $last = $db;
}
- }
- if (query_redirect(queries(), ME . "db=" . urlencode($last), lang('Database has been created.'), DB == "", false, $failed)) {
- //! move triggers
- $result = $connection->query("SHOW TABLES");
- while ($row = $result->fetch_row()) {
- if (!queries("RENAME TABLE " . idf_escape($row[0]) . " TO " . idf_escape($_POST["name"]) . "." . idf_escape($row[0]))) {
- break;
- }
- }
- if (!$row) {
- queries("DROP DATABASE " . idf_escape(DB));
- //! saved to history of removed database
- }
- queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), !$row);
+ queries_redirect(ME . "db=" . urlencode($last), lang('Database has been created.'), $success);
}
} else {
// alter database
@@ -49,17 +40,16 @@
if ($_POST) {
$name = $_POST["name"];
$collate = $_POST["collation"];
-} elseif (DB == "") {
+} elseif (DB != "") {
+ $collate = db_collation(DB, $collations);
+} elseif ($driver == "sql") {
// propose database name with limited privileges
- $result = $connection->query("SHOW GRANTS");
- while ($row = $result->fetch_row()) {
- if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $row[0], $match) && $match[1]) {
- $name = stripcslashes(idf_unescape($match[2]));
+ foreach (get_vals("SHOW GRANTS") as $grant) {
+ if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $grant, $match) && $match[1]) {
+ $name = stripcslashes(idf_unescape("`$match[2]`"));
break;
}
}
-} else {
- $collate = db_collation(DB, $collations);
}
?>
View
120 adminer/db.inc.php
@@ -4,18 +4,15 @@
if ($tables_views && !$error && !$_POST["search"]) {
$result = true;
$message = "";
- if (count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) {
+ if ($driver == "sql" && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) {
queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once
}
- if (isset($_POST["truncate"])) {
- foreach ((array) $_POST["tables"] as $table) {
- if (!queries("TRUNCATE " . idf_escape($table))) {
- $result = false;
- break;
- }
+ if ($_POST["truncate"]) {
+ if ($_POST["tables"]) {
+ $result = truncate_tables($_POST["tables"]);
}
$message = lang('Tables have been truncated.');
- } elseif (isset($_POST["move"])) {
+ } elseif ($_POST["move"]) {
$rename = array();
foreach ($tables_views as $table) {
$rename[] = idf_escape($table) . " TO " . idf_escape($_POST["target"]) . "." . idf_escape($table);
@@ -23,66 +20,65 @@
$result = queries("RENAME TABLE " . implode(", ", $rename));
//! move triggers
$message = lang('Tables have been moved.');
- } elseif ((!isset($_POST["drop"]) || !$_POST["views"] || queries("DROP VIEW " . implode(", ", array_map('idf_escape', $_POST["views"]))))
- && (!$_POST["tables"] || ($result = queries((isset($_POST["optimize"]) ? "OPTIMIZE" : (isset($_POST["check"]) ? "CHECK" : (isset($_POST["repair"]) ? "REPAIR" : (isset($_POST["drop"]) ? "DROP" : "ANALYZE")))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"])))))
- ) {
- if (isset($_POST["drop"])) {
- $message = lang('Tables have been dropped.');
- } else {
- while ($row = $result->fetch_assoc()) {
- $message .= h("$row[Table]: $row[Msg_text]") . "<br>";
- }
+ } elseif ($_POST["drop"]) {
+ if ($_POST["views"]) {
+ $result = drop_views($_POST["views"]);
+ }
+ if ($result && $_POST["tables"]) {
+ $result = drop_tables($_POST["tables"]);
+ }
+ $message = lang('Tables have been dropped.');
+ } elseif ($_POST["tables"] && ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"]))))) {
+ while ($row = $result->fetch_assoc()) {
+ $message .= h("$row[Table]: $row[Msg_text]") . "<br>";
}
}
queries_redirect(substr(ME, 0, -1), $message, $result);
}
-page_header(lang('Database') . ": " . h(DB), $error, false);
+page_header(lang('Database') . ": " . h(DB), $error, true);
echo '<p><a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n";
echo '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n";
+$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
echo "<h3>" . lang('Tables and views') . "</h3>\n";
-$table_status = table_status();
-if (!$table_status) {
+$tables_list = tables_list();
+if (!$tables_list) {
echo "<p class='message'>" . lang('No tables.') . "\n";
} else {
echo "<form action='' method='post'>\n";
echo "<p><input name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n";
if ($_POST["search"] && $_POST["query"] != "") {
- $_GET["where"][0]["op"] = "LIKE";
- $_GET["where"][0]["val"] = "%$_POST[query]%";
+ $_GET["where"][0]["op"] = "LIKE %%";
+ $_GET["where"][0]["val"] = $_POST["query"];
search_tables();
}
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
- echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . '<td>' . lang('Comment') . "</thead>\n";
- $sums = array();
- foreach ($table_status as $row) {
- $name = $row["Name"];
- echo '<tr' . odd() . '><td>' . checkbox((isset($row["Rows"]) ? "tables[]" : "views[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
+ echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . (support("comment") ? '<td>' . lang('Comment') : '') . "</thead>\n";
+ foreach ($tables_list as $name => $type) {
+ $view = (isset($type) && !eregi("table", $type));
+ echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
echo '<th><a href="' . h(ME) . 'table=' . urlencode($name) . '">' . h($name) . '</a>';
- if (isset($row["Rows"])) {
- echo "<td>$row[Engine]<td>$row[Collation]";
- foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
- $val = number_format($row[$key], 0, '.', lang(','));
- echo '<td align="right">' . ($row[$key] != "" ? '<a href="' . h(ME . "$link=") . urlencode($name) . '">' . str_replace(" ", "&nbsp;", ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? lang('~ %s', $val) : $val)) . '</a>' : '&nbsp;');
- $sums[$link] += ($row["Engine"] != "InnoDB" || $link != "edit" ? $row[$key] : 0);
- }
- echo "<td>" . nbsp($row["Comment"]);
- } else {
+ if ($view) {
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '">' . lang('View') . '</a>';
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '">?</a>';
- echo '<td>&nbsp;';
+ } else {
+ echo "<td id='Engine-" . h($name) . "'>&nbsp;<td id='Collation-" . h($name) . "'>&nbsp;";
+ foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
+ echo "<td align='right'><a href='" . h(ME . "$link=") . urlencode($name) . "' id='$key-" . h($name) . "'>?</a>";
+ }
}
+ echo (support("comment") ? "<td id='Comment-" . h($name) . "'>&nbsp;" : "");
}
- echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($table_status));
- echo "<td>" . $connection->result($connection->query("SELECT @@storage_engine"));
+ echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($tables_list));
+ echo "<td>" . $connection->result("SELECT @@storage_engine");
echo "<td>" . db_collation(DB, collations());
- foreach (array("create", "indexes", "edit") as $val) {
- echo "<td align='right'>" . number_format($sums[$val], 0, '.', lang(','));
+ foreach ($sums as $key => $val) {
+ echo "<td align='right' id='sum-$key'>&nbsp;";
}
echo "</table>\n";
if (!information_schema(DB)) {
- echo "<p><input type='hidden' name='token' value='$token'><input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> <input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n";
+ echo "<p><input type='hidden' name='token' value='$token'>" . ($driver == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> " : "") . "<input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n";
$dbs = get_databases();
if (count($dbs) != 1) {
$db = (isset($_POST["target"]) ? $_POST["target"] : DB);
@@ -93,8 +89,10 @@
}
echo '<p><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n";
-if ($connection->server_info >= 5) {
+if (support("view")) {
echo '<a href="' . h(ME) . 'view=">' . lang('Create view') . "</a>\n";
+}
+if (support("routine")) {
echo "<h3>" . lang('Routines') . "</h3>\n";
$result = $connection->query("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . $connection->quote(DB));
if ($result->num_rows) {
@@ -110,9 +108,10 @@
echo '<p><a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a> <a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n";
}
-if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENTS"))) {
+if (support("event")) {
echo "<h3>" . lang('Events') . "</h3>\n";
- if ($result->num_rows) {
+ $result = $connection->query("SHOW EVENTS");
+ if ($result && $result->num_rows) {
echo "<table cellspacing='0'>\n";
echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "</thead>\n";
while ($row = $result->fetch_assoc()) {
@@ -125,3 +124,34 @@
}
echo '<p><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n";
}
+
+page_footer();
+$table_status = table_status();
+if ($table_status) {
+ echo "<script type='text/javascript'>\n";
+ foreach ($table_status as $row) {
+ $id = addcslashes($row["Name"], "\\'/");
+ echo "setHtml('Comment-$id', '" . nbsp($row["Comment"]) . "');\n";
+ if (!eregi("view", $row["Engine"])) {
+ foreach (array("Engine", "Collation") as $key) {
+ echo "setHtml('$key-$id', '" . nbsp($row[$key]) . "');\n";
+ }
+ foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
+ if ($row[$key] != "") {
+ $val = number_format($row[$key], 0, '.', lang(','));
+ echo "setHtml('$key-$id', '" . ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? "~ $val" : $val) . "');\n";
+ if (isset($sums[$key])) {
+ $sums[$key] += ($row["Engine"] != "InnoDB" || $key != "Data_free" ? $row[$key] : 0);
+ }
+ } elseif (array_key_exists($key, $row)) {
+ echo "setHtml('$key-$id');\n";
+ }
+ }
+ }
+ }
+ foreach ($sums as $key => $val) {
+ echo "setHtml('sum-$key', '" . number_format($val, 0, '.', lang(',')) . "');\n";
+ }
+ echo "</script>\n";
+}
+exit; // page_footer() already called
View
2  adminer/download.inc.php
@@ -2,5 +2,5 @@
$TABLE = $_GET["download"];
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=" . friendly_url("$TABLE-" . implode("_", $_GET["where"])) . "." . friendly_url($_GET["field"]));
-echo $connection->result($connection->query("SELECT " . idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET) . " LIMIT 1"));
+echo $connection->result("SELECT" . limit(idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET), 1));
exit; // don't output footer
View
406 adminer/drivers/mssql.inc.php
@@ -0,0 +1,406 @@
+<?php
+/**
+* @author Jakub Cernohuby
+* @author Vladimir Stastka
+* @author Jakub Vrana
+*/
+
+$possible_drivers[] = "SQLSRV";
+$possible_drivers[] = "MSSQL";
+if (extension_loaded("sqlsrv") || extension_loaded("mssql")) {
+ $drivers["mssql"] = "MS SQL";
+}
+
+if (isset($_GET["mssql"])) {
+ define("DRIVER", "mssql");
+ if (extension_loaded("sqlsrv")) {
+ class Min_DB {
+ var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $error;
+
+ function _get_error() {
+ $this->error = "";
+ foreach (sqlsrv_errors() as $error) {
+ $this->error .= "$error[message]\n";
+ }
+ $this->error = rtrim($this->error);
+ }
+
+ function connect($server, $username, $password) {
+ $this->_link = @sqlsrv_connect($server, array("UID" => $username, "PWD" => $password));
+ if ($this->_link) {
+ $info = sqlsrv_server_info($this->_link);
+ $this->server_info = $info['SQLServerVersion'];
+ } else {
+ $this->_get_error();
+ }
+ return (bool) $this->_link;
+ }
+
+ function quote($string) {
+ return "'" . str_replace("'", "''", $string) . "'";
+ }
+
+ function select_db($database) {
+ return $this->query("USE $database");
+ }
+
+
+ function query($query, $unbuffered = false) {
+ $result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
+ if (!$result) {
+ $this->_get_error();
+ return false;
+ }
+ return $this->store_result($result);
+ }
+
+ function multi_query($query) {
+ $this->_result = sqlsrv_query($this->_link, $query);
+ if (!$this->_result) {
+ $this->_get_error();
+ return false;
+ }
+ return true;
+ }
+
+ function store_result($result = null) {
+ if (!$result) {
+ $result = $this->_result;
+ }
+ if (sqlsrv_field_metadata($result)) {
+ return new Min_Result($result);
+ }
+ $this->affected_rows = sqlsrv_rows_affected($result);
+ return true;
+ }
+
+ function next_result() {
+ return sqlsrv_next_result($this->_result);
+ }
+
+ function result($query, $field = 0) {
+ $result = $this->query($query);
+ if (!is_object($result)) {
+ return false;
+ }
+ $row = $result->fetch_row();
+ return $row[$field];
+ }
+ }
+
+ class Min_Result {
+ var $_result, $_offset = 0, $_fields, $num_rows;
+
+ function Min_Result($result) {
+ $this->_result = $result;
+ $this->num_rows = sqlsrv_has_rows($result); //! sqlsrv_num_rows($result)
+ }
+
+ function _convert($row) {
+ foreach ((array) $row as $key => $val) {
+ if (is_a($val, 'DateTime')) {
+ $row[$key] = $val->format("Y-m-d H:i:s");
+ }
+ //! stream
+ }
+ return $row;
+ }
+
+ function fetch_assoc() {
+ return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_ASSOC, SQLSRV_SCROLL_NEXT));
+ }
+
+ function fetch_row() {
+ return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_NUMERIC, SQLSRV_SCROLL_NEXT));
+ }
+
+ function fetch_field() {
+ if (!$this->_fields) {
+ $this->_fields = sqlsrv_field_metadata($this->_result);
+ }
+ $field = $this->_fields[$this->_offset++];
+ $return = new stdClass;
+ $return->name = $field["Name"];
+ $return->orgname = $field["Name"];
+ $return->type = ($field["Type"] == 1 ? 254 : 0);
+ return $return;
+ }
+
+ function __destruct() {
+ sqlsrv_free_stmt($this->_result);
+ }
+ }
+
+ } elseif (extension_loaded("mssql")) {
+ class Min_DB {
+ var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
+
+ function connect($server, $username, $password) {
+ $this->_link = @mssql_connect($server, $username, $password);
+ if ($this->_link) {
+ $result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
+ $row = $result->fetch_row();
+ $this->server_info = $this->result("sp_server_info 2", 2)." [$row[0]] $row[1]";
+ } else {
+ $this->error = mssql_get_last_message();
+ }
+ return (bool) $this->_link;
+ }
+
+ function quote($string) {
+ return "'" . str_replace("'", "''", $string) . "'";
+ }
+
+ function select_db($database) {
+ return mssql_select_db($database);
+ }
+
+ function query($query, $unbuffered = false) {
+ $result = mssql_query($query, $this->_link); //! $unbuffered
+ if (!$result) {
+ $this->error = mssql_get_last_message();
+ return false;
+ }
+ if ($result === true) {
+ $this->affected_rows = mssql_rows_affected($this->_link);
+ return true;
+ }
+ return new Min_Result($result);
+ }
+
+ function multi_query($query) {
+ return $this->_result = $this->query($query);
+ }
+
+ function store_result() {
+ return $this->_result;
+ }
+
+ function next_result() {
+ return mssql_next_result($this->_result);
+ }
+
+ function result($query, $field = 0) {
+ $result = $this->query($query);
+ if (!is_object($result)) {
+ return false;
+ }
+ return mssql_result($result->_result, 0, $field);
+ }
+ }
+
+ class Min_Result {
+ var $_result, $_offset = 0, $_fields, $num_rows;
+
+ function Min_Result($result) {
+ $this->_result = $result;
+ $this->num_rows = mssql_num_rows($result);
+ }
+
+ function fetch_assoc() {
+ return mssql_fetch_assoc($this->_result);
+ }
+
+ function fetch_row() {
+ return mssql_fetch_row($this->_result);
+ }
+
+ function num_rows() {
+ return mssql_num_rows($this->_result);
+ }
+
+ function fetch_field() {
+ $return = mssql_fetch_field($this->_result);
+ $return->orgtable = $return->table;
+ $return->orgname = $return->name;
+ return $return;
+ }
+
+ function __destruct() {
+ mssql_free_result($this->_result);
+ }
+ }
+
+ }
+
+ function idf_escape($idf) {
+ return "[" . str_replace("]", "]]", $idf) . "]";
+ }
+
+ function connect() {
+ global $adminer;
+ $connection = new Min_DB;
+ $credentials = $adminer->credentials();
+ if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
+ return $connection;
+ }
+ return $connection->error;
+ }
+
+ function get_databases() {
+ return get_vals("EXEC sp_databases");
+ }
+
+ function limit($query, $limit, $offset = 0) {
+ return (isset($limit) ? " TOP ($limit)" : "") . " $query"; //! offset
+ }
+
+ function limit1($query, $limit, $offset = 0) {
+ return limit($query, 1);
+ }
+
+ function db_collation($db, $collations) {
+ global $connection;
+ return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . $connection->quote($db));
+ }
+
+ function engines() {
+ return array();
+ }
+
+ function logged_user() {
+ global $connection;
+ return $connection->result("SELECT SUSER_NAME()");
+ }
+
+ function tables_list() {
+ return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES");
+ }
+
+ function count_tables($databases) {
+ global $connection;
+ $return = array();
+ foreach ($databases as $db) {
+ $connection->select_db($db);
+ $return[$db] = $connection->result("SELECT COUNT(*) FROM information_schema.TABLES");
+ }
+ return $return;
+ }
+
+ function table_status($name = "") {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SELECT TABLE_NAME AS Name, TABLE_TYPE AS Engine FROM information_schema.TABLES" . ($name != "" ? " WHERE TABLE_NAME = " . $connection->quote($name) : ""));
+ while ($row = $result->fetch_assoc()) {
+ if ($name != "") {
+ return $row;
+ }
+ $return[$row["Name"]] = $row;
+ }
+ return $return;
+ }
+
+ function fk_support($table_status) {
+ return true;
+ }
+
+ function fields($table) {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = " . $connection->quote($table));
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["COLUMN_NAME"]] = array(
+ "field" => $row["COLUMN_NAME"],
+ "full_type" => $row["DATA_TYPE"],
+ "type" => $row["DATA_TYPE"],
+ "length" => $row["CHARACTER_MAXIMUM_LENGTH"], //! NUMERIC_, DATETIME_?
+ "default" => $row["COLUMN_DEFAULT"],
+ "null" => ($row["IS_NULLABLE"] == "YES"),
+ "collation" => $row["COLLATION_NAME"],
+ "privileges" => array("insert" => 1, "select" => 1, "update" => 1),
+ //! primary - is_identity in sys.columns
+ );
+ }
+ return $return;
+ }
+
+ function indexes($table, $connection2 = null) {
+ global $connection;
+ if (!is_object($connection2)) {
+ $connection2 = $connection;
+ }
+ $return = array();
+ // sp_statistics doesn't return information about primary key
+ $result = $connection2->query("SELECT indexes.name, key_ordinal, is_unique, is_primary_key, columns.name AS column_name
+FROM sys.indexes
+INNER JOIN sys.index_columns ON indexes.object_id = index_columns.object_id AND indexes.index_id = index_columns.index_id
+INNER JOIN sys.columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id
+WHERE OBJECT_NAME(indexes.object_id) = " . $connection2->quote($table));
+ if ($result) {
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["name"]]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
+ $return[$row["name"]]["columns"][$row["key_ordinal"]] = $row["column_name"];
+ }
+ }
+ return $return;
+ }
+
+ function collations() {
+ $return = array();
+ foreach (get_vals("SELECT name FROM fn_helpcollations()") as $collation) {
+ $return[ereg_replace("_.*", "", $collation)][] = $collation;
+ }
+ return $return;
+ }
+
+ function information_schema($db) {
+ return false;
+ }
+
+ function error() {
+ global $connection;
+ return nl_br(h(ereg_replace("^(\\[[^]]*])+", "", $connection->error)));
+ }
+
+ function exact_value($val) {
+ global $connection;
+ return $connection->quote($val);
+ }
+
+ function rename_database($name, $collation) {
+ if ($collation) {
+ queries("ALTER DATABASE " . idf_escape(DB) . " COLLATE " . idf_escape($collation));
+ }
+ return queries("ALTER DATABASE " . idf_escape(DB) . " MODIFY NAME = " . idf_escape($name)); //! false negative "The database name 'test2' has been set."
+ }
+
+ function auto_increment() {
+ return " IDENTITY";
+ }
+
+ function explain($connection, $query) {
+ $connection->query("SET SHOWPLAN_ALL ON");
+ $return = $connection->query($query);
+ $connection->query("SET SHOWPLAN_ALL OFF"); // connection is used also for indexes
+ return $return;
+ }
+
+ function support($feature) {
+ return ereg('^(view|routine|trigger)$', $feature);
+ }
+
+ $driver = "mssql";
+ $types = array();
+ $structured_types = array();
+ foreach (array(
+ lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
+ lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
+ lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
+ lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
+ ) as $key => $val) {
+ $types += $val;
+ $structured_types[$key] = array_keys($val);
+ }
+ $unsigned = array();
+ $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
+ $functions = array("len", "lower", "round", "upper");
+ $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
+ $edit_functions = array(
+ array(
+ "date|time" => "getdate",
+ ), array(
+ "int|decimal|real|float|money|datetime" => "+/-",
+ "char|text" => "+",
+ )
+ );
+}
View
713 adminer/drivers/mysql.inc.php
@@ -0,0 +1,713 @@
+<?php
+$possible_drivers[] = "MySQLi";
+$possible_drivers[] = "MySQL";
+$possible_drivers[] = "PDO_MySQL";
+if (extension_loaded("mysqli") || extension_loaded("mysql") || extension_loaded("pdo_mysql")) {
+ $drivers = array("server" => "MySQL") + $drivers;
+}
+
+if (!defined("DRIVER")) {
+ define("DRIVER", "server"); // server - backwards compatibility
+ // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
+ if (extension_loaded("mysqli")) {
+ class Min_DB extends MySQLi {
+ var $extension = "MySQLi";
+
+ function Min_DB() {
+ parent::init();
+ }
+
+ function connect($server, $username, $password) {
+ list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
+ return @$this->real_connect(
+ ($server != "" ? $host : ini_get("mysqli.default_host")),
+ ("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
+ ("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
+ null,
+ (is_numeric($port) ? $port : ini_get("mysqli.default_port")),
+ (!is_numeric($port) ? $port : null)
+ );
+ }
+
+ function result($query, $field = 0) {
+ $result = $this->query($query);
+ if (!$result) {
+ return false;
+ }
+ $row = $result->fetch_array();
+ return $row[$field];
+ }
+
+ function quote($string) {
+ return "'" . $this->escape_string($string) . "'";
+ }
+ }
+
+ } elseif (extension_loaded("mysql")) {
+ class Min_DB {
+ var
+ $extension = "MySQL", ///< @var string extension name
+ $server_info, ///< @var string server version
+ $affected_rows, ///< @var int number of affected rows
+ $error, ///< @var string last error message
+ $_link, $_result ///< @access private
+ ;
+
+ /** Connect to server
+ * @param string
+ * @param string
+ * @param string
+ * @return bool
+ */
+ function connect($server, $username, $password) {
+ $this->_link = @mysql_connect(
+ ($server != "" ? $server : ini_get("mysql.default_host")),
+ ("$server$username" != "" ? $username : ini_get("mysql.default_user")),
+ ("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
+ true,
+ 131072 // CLIENT_MULTI_RESULTS for CALL
+ );
+ if ($this->_link) {
+ $this->server_info = mysql_get_server_info($this->_link);
+ } else {
+ $this->error = mysql_error();
+ }
+ return (bool) $this->_link;
+ }
+
+ /** Quote string to use in SQL
+ * @param string
+ * @return string escaped string enclosed in '
+ */
+ function quote($string) {
+ return "'" . mysql_real_escape_string($string, $this->_link) . "'";
+ }
+
+ /** Select database
+ * @param string
+ * @return bool
+ */
+ function select_db($database) {
+ return mysql_select_db($database, $this->_link);
+ }
+
+ /** Send query
+ * @param string
+ * @param bool
+ * @return mixed bool or Min_Result
+ */
+ function query($query, $unbuffered = false) {
+ $result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
+ if (!$result) {
+ $this->error = mysql_error($this->_link);
+ return false;
+ }
+ if ($result === true) {
+ $this->affected_rows = mysql_affected_rows($this->_link);
+ $this->info = mysql_info($this->_link);
+ return true;
+ }
+ return new Min_Result($result);
+ }
+
+ /** Send query with more resultsets
+ * @param string
+ * @return bool
+ */
+ function multi_query($query) {
+ return $this->_result = $this->query($query);
+ }
+
+ /** Get current resultset
+ * @return Min_Result
+ */
+ function store_result() {
+ return $this->_result;
+ }
+
+ /** Fetch next resultset
+ * @return bool
+ */
+ function next_result() {
+ // MySQL extension doesn't support multiple results
+ return false;
+ }
+
+ /** Get single field from result
+ * @param string
+ * @param int
+ * @return string
+ */
+ function result($query, $field = 0) {
+ $result = $this->query($query);
+ if (!$result) {
+ return false;
+ }
+ return mysql_result($result->_result, 0, $field);
+ }
+ }
+
+ class Min_Result {
+ var
+ $num_rows, ///< @var int number of rows in the result
+ $_result ///< @access private
+ ;
+
+ /** Constructor
+ * @param resource
+ */
+ function Min_Result($result) {
+ $this->_result = $result;
+ $this->num_rows = mysql_num_rows($result);
+ }
+
+ /** Fetch next row as associative array
+ * @return array
+ */
+ function fetch_assoc() {
+ return mysql_fetch_assoc($this->_result);
+ }
+
+ /** Fetch next row as numbered array
+ * @return array
+ */
+ function fetch_row() {
+ return mysql_fetch_row($this->_result);
+ }
+
+ /** Fetch next field
+ * @return object properties: name, type, orgtable, orgname, charsetnr
+ */
+ function fetch_field() {
+ $return = mysql_fetch_field($this->_result);
+ $return->orgtable = $return->table;
+ $return->orgname = $return->name;
+ $return->charsetnr = ($return->blob ? 63 : 0);
+ return $return;
+ }
+
+ /** Free result set
+ */
+ function __destruct() {
+ mysql_free_result($this->_result); //! not called in PHP 4 which is a problem with mysql.trace_mode
+ }
+ }
+
+ } elseif (extension_loaded("pdo_mysql")) {
+ class Min_DB extends Min_PDO {
+ var $extension = "PDO_MySQL";
+
+ function connect($server, $username, $password) {
+ $this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
+ return true;
+ }
+
+ function select_db($database) {
+ // database selection is separated from the connection so dbname in DSN can't be used
+ return $this->query("USE " . idf_escape($database));
+ }
+
+ function query($query, $unbuffered = false) {
+ $this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
+ return parent::query($query, $unbuffered);
+ }
+ }
+
+ }
+
+ /** Escape database identifier
+ * @param string
+ * @return string
+ */
+ function idf_escape($idf) {
+ return "`" . str_replace("`", "``", $idf) . "`";
+ }
+
+ /** Connect to the database
+ * @return mixed Min_DB or string for error
+ */
+ function connect() {
+ global $adminer;
+ $connection = new Min_DB;
+ $credentials = $adminer->credentials();
+ if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
+ $connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
+ $connection->query("SET NAMES utf8");
+ return $connection;
+ }
+ return $connection->error;
+ }
+
+ /** Get cached list of databases
+ * @param bool
+ * @return array
+ */
+ function get_databases($flush = true) {
+ // SHOW DATABASES can take a very long time so it is cached
+ $return = &get_session("databases");
+ if (!isset($return)) {
+ if ($flush) {
+ restart_session();
+ ob_flush();
+ flush();
+ }
+ $return = get_vals("SHOW DATABASES");
+ }
+ return $return;
+ }
+
+ /** Formulate SQL query with limit
+ * @param string everything after SELECT
+ * @param int
+ * @param int
+ * @return string
+ */
+ function limit($query, $limit, $offset = 0) {
+ return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
+ }
+
+ /** Formulate SQL modification query with limit 1
+ * @param string everything after UPDATE or DELETE
+ * @return string
+ */
+ function limit1($query) {
+ return limit($query, 1);
+ }
+
+ /** Get database collation
+ * @param string
+ * @param array result of collations()
+ * @return string
+ */
+ function db_collation($db, $collations) {
+ global $connection;
+ $return = null;
+ $create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
+ if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
+ $return = $match[1];
+ } elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
+ // default collation
+ $return = $collations[$match[1]][0];
+ }
+ return $return;
+ }
+
+ /** Get supported engines
+ * @return array
+ */
+ function engines() {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SHOW ENGINES");
+ while ($row = $result->fetch_assoc()) {
+ if (ereg("YES|DEFAULT", $row["Support"])) {
+ $return[] = $row["Engine"];
+ }
+ }
+ return $return;
+ }
+
+ /** Get logged user
+ * @return string
+ */
+ function logged_user() {
+ global $connection;
+ return $connection->result("SELECT USER()");
+ }
+
+ /** Get tables list
+ * @return array
+ */
+ function tables_list() {
+ global $connection;
+ return get_key_vals("SHOW" . ($connection->server_info >= 5 ? " FULL" : "") . " TABLES");
+ }
+
+ /** Count tables in all databases
+ * @param array
+ * @return array array($db => $tables)
+ */
+ function count_tables($databases) {
+ $return = array();
+ foreach ($databases as $db) {
+ $return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db)));
+ }
+ return $return;
+ }
+
+ /** Get table status
+ * @param string
+ * @return array
+ */
+ function table_status($name = "") {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
+ while ($row = $result->fetch_assoc()) {
+ if ($row["Engine"] == "InnoDB") {
+ // ignore internal comment, unnecessary since MySQL 5.1.21
+ $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
+ }
+ if (!isset($row["Rows"])) {
+ $row["Engine"] = "VIEW";
+ $row["Comment"] = "";
+ }
+ if ($name != "") {
+ return $row;
+ }
+ $return[$row["Name"]] = $row;
+ }
+ return $return;
+ }
+
+ /** Check if table supports foreign keys
+ * @param array result of table_status
+ * @return bool
+ */
+ function fk_support($table_status) {
+ return ($table_status["Engine"] == "InnoDB");
+ }
+
+ /** Get information about fields
+ * @param string
+ * @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
+ */
+ function fields($table) {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
+ if ($result) {
+ while ($row = $result->fetch_assoc()) {
+ preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
+ $return[$row["Field"]] = array(
+ "field" => $row["Field"],
+ "full_type" => $row["Type"],
+ "type" => $match[1],
+ "length" => $match[2],
+ "unsigned" => ltrim($match[3] . $match[4]),
+ "default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
+ "null" => ($row["Null"] == "YES"),
+ "auto_increment" => ($row["Extra"] == "auto_increment"),
+ "on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
+ "collation" => $row["Collation"],
+ "privileges" => array_flip(explode(",", $row["Privileges"])),
+ "comment" => $row["Comment"],
+ "primary" => ($row["Key"] == "PRI"),
+ );
+ }
+ }
+ return $return;
+ }
+
+ /** Get table indexes
+ * @param string
+ * @param string Min_DB to use
+ * @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
+ */
+ function indexes($table, $connection2 = null) {
+ global $connection;
+ if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
+ $connection2 = $connection;
+ }
+ $return = array();
+ $result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
+ if ($result) {
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
+ $return[$row["Key_name"]]["columns"][] = $row["Column_name"];
+ $return[$row["Key_name"]]["lengths"][] = $row["Sub_part"];
+ }
+ }
+ return $return;
+ }
+
+ /** Get foreign keys in table
+ * @param string
+ * @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
+ */
+ function foreign_keys($table) {
+ global $connection, $on_actions;
+ static $pattern = '`(?:[^`]|``)+`';
+ $return = array();
+ $create_table = $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
+ if ($create_table) {
+ preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
+ foreach ($matches as $match) {
+ preg_match_all("~$pattern~", $match[2], $source);
+ preg_match_all("~$pattern~", $match[5], $target);
+ $return[idf_unescape($match[1])] = array(
+ "db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
+ "table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
+ "source" => array_map('idf_unescape', $source[0]),
+ "target" => array_map('idf_unescape', $target[0]),
+ "on_delete" => $match[6],
+ "on_update" => $match[7],
+ );
+ }
+ }
+ return $return;
+ }
+
+ /** Get view SELECT
+ * @param string
+ * @return array array("select" => )
+ */
+ function view($name) {
+ global $connection;
+ return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result("SHOW CREATE VIEW " . idf_escape($name), 1)));
+ }
+
+ /** Get sorted grouped list of collations
+ * @return array
+ */
+ function collations() {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SHOW COLLATION");
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["Charset"]][] = $row["Collation"];
+ }
+ ksort($return);
+ foreach ($return as $key => $val) {
+ sort($return[$key]);
+ }
+ return $return;
+ }
+
+ /** Find out if database is information_schema
+ * @param string
+ * @return bool
+ */
+ function information_schema($db) {
+ global $connection;
+ return ($connection->server_info >= 5 && $db == "information_schema");
+ }
+
+ /** Get escaped error message
+ * @return string
+ */
+ function error() {
+ global $connection;
+ return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
+ }
+
+ /** Return expression for binary comparison
+ * @param string
+ * @return string
+ */
+ function exact_value($val) {
+ global $connection;
+ return "BINARY " . $connection->quote($val);
+ }
+
+ /** Rename database from DB
+ * @param string new name
+ * @return string
+ * @return bool
+ */
+ function rename_database($name, $collation) {
+ global $connection;
+ $return = false;
+ if (queries("CREATE DATABASE " . idf_escape($name) . ($collation ? " COLLATE " . $connection->quote($collation) : ""))) {
+ //! move triggers
+ $return = true; // table list may by empty
+ foreach (tables_list() as $table) {
+ if (!queries("RENAME TABLE " . idf_escape($table) . " TO " . idf_escape($name) . "." . idf_escape($table))) {
+ $return = false;
+ break;
+ }
+ }
+ if ($return) {
+ queries("DROP DATABASE " . idf_escape(DB));
+ //! saved to history of removed database
+ }
+ }
+ return $return;
+ }
+
+ /** Generate modifier for auto increment column
+ * @return string
+ */
+ function auto_increment() {
+ $auto_increment_index = " PRIMARY KEY";
+ // don't overwrite primary key by auto_increment
+ if ($_GET["create"] != "" && $_POST["auto_increment_col"]) {
+ foreach (indexes($_GET["create"]) as $index) {
+ if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
+ $auto_increment_index = "";
+ break;
+ }
+ if ($index["type"] == "PRIMARY") {
+ $auto_increment_index = " UNIQUE";
+ }
+ }
+ }
+ return " AUTO_INCREMENT$auto_increment_index";
+ }
+
+ /** Run commands to create or alter table
+ * @param string "" to create
+ * @param string new name
+ * @param array of array($orig, $process_field, $after)
+ * @param array of strings
+ * @param string
+ * @param string
+ * @param string
+ * @param int
+ * @param string
+ * @return bool
+ */
+ function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
+ global $connection;
+ $alter = array();
+ foreach ($fields as $field) {
+ $alter[] = ($field[1]
+ ? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode("", $field[1]) . ($table != "" ? " $field[2]" : "")
+ : "DROP " . idf_escape($field[0])
+ );
+ }
+ $alter = array_merge($alter, $foreign);
+ $status = "COMMENT=" . $connection->quote($comment)
+ . ($engine ? " ENGINE=" . $connection->quote($engine) : "")
+ . ($collation ? " COLLATE " . $connection->quote($collation) : "")
+ . ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
+ . $partitioning
+ ;
+ if ($table == "") {
+ return queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n) $status");
+ }
+ if ($table != $name) {
+ $alter[] = "RENAME TO " . idf_escape($name);
+ }
+ $alter[] = $status;
+ return queries("ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
+ }
+
+ /** Run commands to alter indexes
+ * @param string escaped table name
+ * @param array of array("index type", "(columns definition)") or array("index type", "escaped name", "DROP")
+ * @return bool
+ */
+ function alter_indexes($table, $alter) {
+ foreach ($alter as $key => $val) {
+ $alter[$key] = ($val[2] ? "\nDROP INDEX " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
+ }
+ return queries("ALTER TABLE " . idf_escape($table) . implode(",", $alter));
+ }
+
+ /** Run commands to truncate tables
+ * @param array
+ * @return bool
+ */
+ function truncate_tables($tables) {
+ foreach ($tables as $table) {
+ if (!queries("TRUNCATE TABLE " . idf_escape($table))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Drop views
+ * @param array
+ * @return bool
+ */
+ function drop_views($views) {
+ return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
+ }
+
+ /** Drop tables
+ * @param array
+ * @return bool
+ */
+ function drop_tables($tables) {
+ return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
+ }
+
+ /** Get information about trigger
+ * @param string trigger name
+ * @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
+ */
+ function trigger($name) {
+ global $connection;
+ $result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($name));
+ return $result->fetch_assoc();
+ }
+
+ /** Get defined triggers
+ * @param string
+ * @return array array($name => array($timing, $event))
+ */
+ function triggers($table) {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
+ }
+ return $return;
+ }
+
+ /** Explain select
+ * @param Min_DB
+ * @param string
+ * @return Min_Result
+ */
+ function explain($connection, $query) {
+ return $connection->query("EXPLAIN $query");
+ }
+
+ /** Get SQL command to create table
+ * @param string
+ * @return string
+ */
+ function create_sql($table) {
+ global $connection;
+ return $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
+ }
+
+ /** Check whether a feature is supported
+ * @param string
+ * @return bool
+ */
+ function support($feature) {
+ global $connection;
+ $features = array(
+ "view" => ($connection->server_info >= 5),
+ "routine" => ($connection->server_info >= 5),
+ "trigger" => ($connection->server_info >= 5),
+ "event" => ($connection->server_info >= 5.1),
+ "partitioning" => ($connection->server_info >= 5.1),
+ );
+ return (isset($features[$feature]) ? $features[$feature] : true);
+ }
+
+ $driver = "sql"; ///< @var string JUSH identifier
+ $types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
+ $structured_types = array(); ///< @var array ($description => array($type, ...), ...)
+ foreach (array(
+ lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
+ lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
+ lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
+ lang('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
+ lang('Lists') => array("enum" => 65535, "set" => 64),
+ ) as $key => $val) {
+ $types += $val;
+ $structured_types[$key] = array_keys($val);
+ }
+ $unsigned = array("unsigned", "zerofill", "unsigned zerofill"); ///< @var array number variants
+ $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL"); ///< @var array operators used in select
+ $functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "upper"); ///< @var array functions used in select
+ $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
+ $edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
+ array(
+ "char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength
+ "date|time" => "now",
+ ), array(
+ "int|float|double|decimal" => "+/-",
+ "date" => "+ interval/- interval",
+ "time" => "addtime/subtime",
+ "char|text" => "concat",
+ )
+ );
+}
View
443 adminer/drivers/pgsql.inc.php
@@ -0,0 +1,443 @@
+<?php
+$possible_drivers[] = "PgSQL";
+$possible_drivers[] = "PDO_PgSQL";
+if (extension_loaded("pgsql") || extension_loaded("pdo_pgsql")) {
+ $drivers["pgsql"] = "PostgreSQL";
+}
+
+if (isset($_GET["pgsql"])) {
+ define("DRIVER", "pgsql");
+ if (extension_loaded("pgsql")) {
+ class Min_DB {
+ var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error;
+
+ function _error($errno, $error) {
+ if (ini_bool("html_errors")) {
+ $error = html_entity_decode(strip_tags($error));
+ }
+ $error = ereg_replace('^[^:]*: ', '', $error);
+ $this->error = $error;
+ }
+
+ function connect($server, $username, $password) {
+ set_error_handler(array($this, '_error'));
+ $this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
+ $this->_link = @pg_connect($this->_string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), PGSQL_CONNECT_FORCE_NEW);
+ if (!$this->_link && DB != "") {
+ // try to connect directly with database for performance
+ $this->_database = false;
+ $this->_link = @pg_connect($this->_string, PGSQL_CONNECT_FORCE_NEW);
+ }
+ restore_error_handler();
+ if ($this->_link) {
+ $version = pg_version($this->_link);
+ $this->server_info = $version["server"];
+ pg_set_client_encoding($this->_link, "UTF8");
+ }
+ return (bool) $this->_link;
+ }
+
+ function quote($string) {
+ return "'" . pg_escape_string($this->_link, $string) . "'"; //! bytea
+ }
+
+ function select_db($database) {
+ if ($database == DB) {
+ return $this->_database;
+ }
+ $link = @pg_connect($this->_connection . " dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
+ if ($link) {
+ $this->_link = $link;
+ }
+ return $link;
+ }
+
+ function query($query, $unbuffered = false) {
+ $result = @pg_query($this->_link, $query);
+ if (!$result) {
+ $this->error = pg_last_error($this->_link);
+ return false;
+ } elseif (!pg_num_fields($result)) {
+ $this->affected_rows = pg_affected_rows($result);
+ return true;
+ }
+ return new Min_Result($result);
+ }
+
+ function multi_query($query) {
+ return $this->_result = $this->query($query);
+ }
+
+ function store_result() {
+ return $this->_result;
+ }
+
+ function next_result() {
+ // PgSQL extension doesn't support multiple results
+ return false;
+ }
+
+ function result($query, $field = 0) {
+ $result = $this->query($query);
+ if (!$result) {
+ return false;
+ }
+ return pg_fetch_result($result->_result, 0, $field);
+ }
+ }
+
+ class Min_Result {
+ var $_result, $_offset = 0, $num_rows;
+
+ function Min_Result($result) {
+ $this->_result = $result;
+ $this->num_rows = pg_num_rows($result);
+ }
+
+ function fetch_assoc() {
+ return pg_fetch_assoc($this->_result);
+ }
+
+ function fetch_row() {
+ return pg_fetch_row($this->_result);
+ }
+
+ function fetch_field() {
+ $column = $this->_offset++;
+ $row = new stdClass;
+ $row->orgtable = pg_field_table($this->_result, $column);
+ $row->name = pg_field_name($this->_result, $column);
+ $row->orgname = $row->name;
+ $row->type = pg_field_type($this->_result, $column);
+ $row->charsetnr = ($row->type == "bytea" ? 63 : 0);
+ return $row;
+ }
+
+ function __destruct() {
+ pg_free_result($this->_result);
+ }
+ }
+
+ } elseif (extension_loaded("pdo_pgsql")) {
+ class Min_DB extends Min_PDO {
+ var $extension = "PDO_PgSQL";
+
+ function connect($server, $username, $password) {
+ $string = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' options='-c client_encoding=utf8'";
+ $this->dsn($string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), $username, $password);
+ //! connect without DB in case of an error
+ return true;
+ }
+
+ function select_db($database) {
+ return (DB == $database);
+ }
+ }
+
+ }
+
+ function idf_escape($idf) {
+ return '"' . str_replace('"', '""', $idf) . '"';
+ }
+
+ function connect() {
+ global $adminer;
+ $connection = new Min_DB;
+ $credentials = $adminer->credentials();
+ if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
+ return $connection;
+ }
+ return $connection->error;
+ }
+
+ function get_databases() {
+ return get_vals("SELECT datname FROM pg_database");
+ }
+
+