Revision: 1397
http://adminer.svn.sourceforge.net/adminer/?rev=1397&view=rev
Author: jakubvrana
Date: 2010-04-07 23:59:59 +0000 (Wed, 07 Apr 2010)
Log Message:
-----------
Update PostgreSQL
Modified Paths:
--------------
branches/sqlite/adminer/create.inc.php
branches/sqlite/adminer/drivers/mssql.inc.php
branches/sqlite/adminer/drivers/mysql.inc.php
branches/sqlite/adminer/drivers/pgsql.inc.php
branches/sqlite/adminer/drivers/sqlite.inc.php
branches/sqlite/adminer/foreign.inc.php
branches/sqlite/adminer/include/functions.inc.php
branches/sqlite/adminer/sql.inc.php
branches/sqlite/adminer/trigger.inc.php
branches/sqlite/compile.php
branches/sqlite/todo.txt
Modified: branches/sqlite/adminer/create.inc.php
===================================================================
--- branches/sqlite/adminer/create.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/create.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -161,7 +161,7 @@
<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); ?>
Modified: branches/sqlite/adminer/drivers/mssql.inc.php
===================================================================
--- branches/sqlite/adminer/drivers/mssql.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/drivers/mssql.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -1,7 +1,8 @@
<?php
/**
-* @author Jakub Černohubý
-* @author Vladimír Šťástka
+* @author Jakub Cernohuby
+* @author Vladimir Stastka
+* @author Jakub Vrana
*/
$possible_drivers[] = "SQLSRV";
@@ -393,15 +394,15 @@
}
function support($feature) {
- return in_array($feature, array("view", "routine", "trigger"));
+ 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, "float" => 53, "real" => 12, "bit" => 1, "money" => 20, "smallmoney" => 10),
- lang('Date and time') => array("date" => 10, "datetime" => 19, "datetime2" => 19, "datetimeoffset" => 10, "time" => 8, "smalldatetime" => 19),
+ 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) {
Modified: branches/sqlite/adminer/drivers/mysql.inc.php
===================================================================
--- branches/sqlite/adminer/drivers/mysql.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/drivers/mysql.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -438,8 +438,8 @@
preg_match_all("~`($pattern)`~", $match[2], $source);
preg_match_all("~`($pattern)`~", $match[5], $target);
$return[$match[1]] = array(
- "db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
- "table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
+ "db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
+ "table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
"source" => array_map('idf_unescape', $source[1]),
"target" => array_map('idf_unescape', $target[1]),
"on_delete" => $match[6],
@@ -571,12 +571,12 @@
/** Get information about trigger
* @param string trigger name
- * @return array array("Timing" => , "Event" => , "Trigger" => , "Statement" => )
+ * @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
*/
function trigger($name) {
global $connection;
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($name));
- $row = $result->fetch_assoc();
+ return $result->fetch_assoc();
}
/** Get defined triggers
Modified: branches/sqlite/adminer/drivers/pgsql.inc.php
===================================================================
--- branches/sqlite/adminer/drivers/pgsql.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/drivers/pgsql.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -102,8 +102,7 @@
}
function fetch_field() {
- static $column = -1;
- $column++;
+ $column = $this->_offset++;
$row = new stdClass;
$row->orgtable = pg_field_table($this->_result, $column);
$row->name = pg_field_name($this->_result, $column);
@@ -180,7 +179,7 @@
function tables_list() {
global $connection;
- return get_key_vals("SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public'");
+ return get_key_vals("SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name");
}
function count_tables($databases) {
@@ -218,32 +217,50 @@
"on_update" => "", //!
"collation" => $row["collation_name"],
"privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable
- "primary" => ($row["is_identity"] == "YES"), //!
+ "primary" => ($row["is_identity"] == "YES"), //! possible false negative
);
}
}
return $return;
}
- function indexes($table, $connection2 = null) { //!
+ function indexes($table, $connection2 = null) {
global $connection;
- if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
+ if (!is_object($connection2)) {
$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["Seq_in_index"]] = $row["Column_name"];
- $return[$row["Key_name"]]["lengths"][$row["Seq_in_index"]] = $row["Sub_part"];
+ $table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relname = " . $connection2->quote($table));
+ $columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = 16418 AND attnum > 0", $connection2);
+ $result = $connection2->query("SELECT relname, indisunique, indisprimary, indkey FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid");
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["relname"]]["type"] = ($row["indisprimary"] == "t" ? "PRIMARY" : ($row["indisunique"] == "t" ? "UNIQUE" : "INDEX"));
+ $return[$row["relname"]]["columns"] = array();
+ foreach (explode(" ", $row["indkey"]) as $indkey) {
+ $return[$row["relname"]]["columns"][] = $columns[$indkey];
}
+ $return[$row["relname"]]["lengths"] = array();
}
return $return;
}
- function foreign_keys($table) { //!
+ function foreign_keys($table) {
+ global $connection;
$return = array();
+ $result = $connection->query("SELECT tc.constraint_name, kcu.column_name, rc.update_rule AS on_update, rc.delete_rule AS on_delete, ccu.table_name AS table, ccu.column_name AS ref
+FROM information_schema.table_constraints tc
+LEFT JOIN information_schema.key_column_usage kcu USING (constraint_catalog, constraint_schema, constraint_name)
+LEFT JOIN information_schema.referential_constraints rc USING (constraint_catalog, constraint_schema, constraint_name)
+LEFT JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_catalog = ccu.constraint_catalog AND rc.unique_constraint_schema = ccu.constraint_schema AND rc.unique_constraint_name = ccu.constraint_name
+WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->quote($table)); //! there can be more unique_constraint_name
+ while ($row = $result->fetch_assoc()) {
+ $foreign_key = &$return[$row["constraint_name"]];
+ if (!$foreign_key) {
+ $foreign_key = $row;
+ }
+ $foreign_key["source"][] = $row["column_name"];
+ $foreign_key["target"][] = $row["ref"];
+ }
return $return;
}
@@ -252,7 +269,8 @@
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result("SHOW CREATE VIEW " . idf_escape($name), 1)));
}
- function collations() { //!
+ function collations() {
+ //! supported in CREATE DATABASE
return array();
}
@@ -262,20 +280,69 @@
function error() {
global $connection;
- return h($connection->error);
+ $return = $connection->error;
+ if (preg_match('~^(.*\\n)?([^\\n]*)\\n( *)\\^(\\n.*)?$~s', $return, $match)) {
+ $return = h($match[1]) . str_replace("\x17", "<b>", h(substr_replace($match[2], "\x17", strlen($match[3]), 0))) . "</b>" . h($match[4]);
+ } else {
+ $return = h($return);
+ }
+ return str_replace("\n", "<br>", $return);
}
function exact_value($val) {
global $connection;
- return "BINARY " . $connection->quote($val);
+ return $connection->quote($val);
}
+ function rename_database($name, $collation) {
+ //! current database cannot be renamed
+ return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
+ }
+
function auto_increment($type) {
return (ereg("^bigint", $type) ? "BIG" : "") . "SERIAL";
}
+ function alter_table($table, $alter) {
+ //! separate rename table, rename column, CHANGE to several ALTER
+ return queries("ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
+ }
+
+ function alter_indexes($table, $alter) {
+ $create = array();
+ $drop = array();
+ foreach ($alter as $val) {
+ if ($val[0] == "DROP") {
+ $drop[] = $val[1]; //! UNIQUE and PRIMARY must use ALTER TABLE tab DROP CONSTRAINT
+ } elseif ($val[0] != "INDEX") {
+ $create[] = "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "") . $val[1];
+ } elseif (!queries("CREATE INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table) . " $val[1]")) {
+ return false;
+ }
+ }
+ return ((!$create || queries("ALTER TABLE " . idf_escape($table) . implode(",", $create)))
+ && (!$drop || queries("DROP INDEX " . implode(", ", $drop)))
+ );
+ }
+
+ function trigger($name) {
+ global $connection;
+ $result = $connection->query('SELECT trigger_name AS "Trigger", condition_timing AS "Timing", event_manipulation AS "Event", action_statement AS "Statement" FROM information_schema.triggers WHERE event_object_table = ' . $connection->quote($_GET["trigger"]) . ' AND trigger_name = ' . $connection->quote($name));
+ return $result->fetch_assoc();
+ }
+
+ function triggers($table) {
+ global $connection;
+ $return = array();
+ $result = $connection->query("SELECT * FROM information_schema.triggers WHERE event_object_table = " . $connection->quote($table));
+ while ($row = $result->fetch_assoc()) {
+ $return[$row["trigger_name"]] = array($row["condition_timing"], $row["event_manipulation"]);
+ }
+ return $return;
+ }
+
function support($feature) {
- return in_array($feature, array("view", "routine", "trigger"));
+ return ereg('^(view|routine|trigger)$', $feature);
}
$driver = "pgsql";
@@ -283,9 +350,9 @@
$types = array();
$structured_types = array();
foreach (array( //! lengths //! arrays
- lang('Numbers') => array("bigint" => 0, "bigserial" => 0, "boolean" => 0, "double precision" => 0, "integer" => 0, "money" => 0, "numeric" => 0, "real" => 0, "smallint" => 0, "serial" => 0),
- lang('Date and time') => array("date" => 0, "interval" => 0, "time" => 0, "timestamp" => 0),
- lang('Strings') => array("character varying" => 0, "character" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
+ lang('Numbers') => array("smallint" => 0, "integer" => 0, "bigint" => 0, "boolean" => 0, "numeric" => 0, "real" => 0, "double precision" => 0, "money" => 0),
+ lang('Date and time') => array("date" => 0, "time" => 0, "timestamp" => 0, "interval" => 0),
+ lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
lang('Network') => array("cidr" => 0, "inet" => 0, "macaddr" => 0, "txid_snapshot" => 0),
lang('Plane') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
Modified: branches/sqlite/adminer/drivers/sqlite.inc.php
===================================================================
--- branches/sqlite/adminer/drivers/sqlite.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/drivers/sqlite.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -51,7 +51,7 @@
}
class Min_Result {
- var $_result, $num_rows;
+ var $_result, $_offset = 0, $num_rows;
function __construct($result) {
$this->_result = $result;
@@ -67,10 +67,8 @@
}
function fetch_field() {
- static $column = -1;
- $column++;
return (object) array(
- "name" => $this->fieldName($column),
+ "name" => $this->fieldName($this->_offset++),
//! type, orgtable, charsetnr
);
}
@@ -80,7 +78,7 @@
} else {
class Min_SQLite extends SQLite3 {
- var $extension = "SQLite3";
+ var $_offset = 0, $extension = "SQLite3";
function __construct() {
$version = $this->version();
@@ -118,7 +116,7 @@
}
class Min_Result {
- var $_result, $num_rows;
+ var $_result, $_offset = 0, $num_rows;
function __construct($result) {
$this->_result = $result;
@@ -134,8 +132,7 @@
}
function fetch_field() {
- static $column = -1;
- $column++;
+ $column = $this->_offset++;
return (object) array(
"name" => $this->_result->columnName($column),
"type" => $this->_result->columnType($column),
@@ -374,7 +371,7 @@
function alter_indexes($table, $alter) {
foreach ($alter as $val) {
- if (!queries(($val[0] == "DROP" ? "DROP INDEX" : "CREATE" . ($val[0] != "INDEX" ? " UNIQUE" : "") . " INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table)) . " $val[1]")) { //! primary
+ if (!queries(($val[0] == "DROP" ? "DROP INDEX" : "CREATE" . ($val[0] != "INDEX" ? " UNIQUE" : "") . " INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table)) . " $val[1]")) { //! primary key must be created in CREATE TABLE
return false;
}
}
@@ -404,7 +401,7 @@
}
function support($feature) {
- return ($feature == "view" || $feature == "trigger");
+ return ereg('^(view|trigger)$', $feature);
}
$driver = "sqlite";
Modified: branches/sqlite/adminer/foreign.inc.php
===================================================================
--- branches/sqlite/adminer/foreign.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/foreign.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -2,7 +2,7 @@
$TABLE = $_GET["foreign"];
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
if ($_POST["drop"]) {
- query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP FOREIGN KEY " . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
+ query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP " . ($driver == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
} else {
$source = array_filter($_POST["source"], 'strlen');
ksort($source); // enforce input order
Modified: branches/sqlite/adminer/include/functions.inc.php
===================================================================
--- branches/sqlite/adminer/include/functions.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/include/functions.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -126,12 +126,16 @@
/** Get keys from first column and values from second
* @param string
+* @param Min_DB
* @return array
*/
-function get_key_vals($query) {
+function get_key_vals($query, $connection2 = null) {
global $connection;
+ if (!$connection2) {
+ $connection2 = $connection;
+ }
$return = array();
- $result = $connection->query($query);
+ $result = $connection2->query($query);
while ($row = $result->fetch_row()) {
$return[$row[0]] = $row[1];
}
Modified: branches/sqlite/adminer/sql.inc.php
===================================================================
--- branches/sqlite/adminer/sql.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/sql.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -29,7 +29,7 @@
$history[] = $query;
}
$space = "(\\s|/\\*.*\\*/|(#|-- )[^\n]*\n|--\n)";
- $alter_database = "(CREATE|DROP)$space+(DATABASE|SCHEMA)\\b~isU";
+ $alter_database = "(CREATE|DROP|ALTER)$space+(DATABASE|SCHEMA)\\b~isU";
if (!ini_get("session.use_cookies")) {
session_write_close();
}
Modified: branches/sqlite/adminer/trigger.inc.php
===================================================================
--- branches/sqlite/adminer/trigger.inc.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/adminer/trigger.inc.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -6,8 +6,8 @@
$dropped = false;
if ($_POST && !$error && in_array($_POST["Timing"], $trigger_time) && in_array($_POST["Event"], $trigger_event)) {
$dropped = drop_create(
- "DROP TRIGGER " . idf_escape($_GET["name"]),
- "CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]",
+ "DROP TRIGGER " . idf_escape($_GET["name"]) . ($driver == "pgsql" ? " ON " . idf_escape($TABLE) : ""),
+ "CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]", //! FOR EACH STATEMENT
ME . "table=" . urlencode($TABLE),
lang('Trigger has been dropped.'),
lang('Trigger has been altered.'),
Modified: branches/sqlite/compile.php
===================================================================
--- branches/sqlite/compile.php 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/compile.php 2010-04-07 23:59:59 UTC (rev 1397)
@@ -165,8 +165,8 @@
unset($_COOKIE["adminer_lang"]);
$_SESSION["lang"] = $_SERVER["argv"][1]; // Adminer functions read language from session
+include dirname(__FILE__) . "/adminer/include/lang.inc.php";
if (isset($_SESSION["lang"])) {
- include dirname(__FILE__) . "/adminer/include/lang.inc.php";
if (isset($_SERVER["argv"][2]) || !isset($langs[$_SESSION["lang"]])) {
echo "Usage: php compile.php [lang]\nPurpose: Compile adminer[-lang].php and editor[-lang].php.\n";
exit(1);
Modified: branches/sqlite/todo.txt
===================================================================
--- branches/sqlite/todo.txt 2010-04-07 19:27:36 UTC (rev 1396)
+++ branches/sqlite/todo.txt 2010-04-07 23:59:59 UTC (rev 1397)
@@ -14,7 +14,7 @@
Shift-click in checkboxes to select range
? LIKE %% operator
? Column and table names auto-completition in SQL textarea
-? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB
+? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, aliasing of $connection->query, $connection->result and $connection->quote can save ~ 3 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB
? Branch binary_compile: LZW compression of translations can save 30 KB, LZW compression of all texts can save 11 KB, remove of base64_decode() + using chars 127-255 in minification can save 1 KB
? AJAX editing - select page has all data to display edit form
Translations - database(s) have been dropped
@@ -32,3 +32,12 @@
DROP DATABASE by file operations
CSV import
Export
+
+PostgreSQL:
+Users - SELECT * FROM pg_user
+Table schema
+boolean (bit in MS SQL)
+Export - http://www.postgresql.org/docs/8.4/static/functions-info.html
+Table status - http://www.postgresql.org/docs/8.4/static/functions-admin.html
+Comments - http://www.postgresql.org/docs/8.4/static/sql-comment.html
+Column rights - http://www.postgresql.org/docs/8.4/static/functions-info.html
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|