diff --git a/adminer/create.inc.php b/adminer/create.inc.php index 0a0569b0..5bc501de 100644 --- a/adminer/create.inc.php +++ b/adminer/create.inc.php @@ -25,27 +25,26 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"] $orig_field = reset($orig_fields); $after = "FIRST"; foreach ($_POST["fields"] as $key => $field) { - $type_field = (isset($types[$field["type"]]) ? $field : $referencable_primary[$foreign_keys[$field["type"]]]); + $foreign_key = $foreign_keys[$field["type"]]; + $type_field = (isset($foreign_key) ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type if ($field["field"] != "") { - if ($type_field) { - if (!$field["has_default"]) { - $field["default"] = null; - } - $default = eregi_replace(" *on update CURRENT_TIMESTAMP", "", $field["default"]); - if ($default != $field["default"]) { // preg_replace $count is available since PHP 5.1.0 - $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); - if ($process_field != process_field($orig_field, $orig_field)) { - $fields[] = array($field["orig"], $process_field, $after); - } - if (!isset($types[$field["type"]])) { - $foreign[] = ($TABLE != "" ? "ADD " : " ") . "FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")"; - } + if (!$field["has_default"]) { + $field["default"] = null; + } + $default = eregi_replace(" *on update CURRENT_TIMESTAMP", "", $field["default"]); + if ($default != $field["default"]) { // preg_replace $count is available since PHP 5.1.0 + $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); + if ($process_field != process_field($orig_field, $orig_field)) { + $fields[] = array($field["orig"], $process_field, $after); + } + if (isset($foreign_key)) { + $foreign[] = ($TABLE != "" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_key) . " (" . idf_escape($type_field["field"]) . ")"; } $after = "AFTER " . idf_escape($field["field"]); } elseif ($field["orig"] != "") { diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index baa57cf5..51cd4e0a 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -201,8 +201,8 @@ if (isset($_GET["pgsql"])) { function table_status($name = "") { global $connection; $return = array(); - $result = $connection->query("SELECT relname AS \"Name\", CASE relkind WHEN 'r' THEN '' ELSE 'view' END AS \"Engine\", pg_relation_size(oid) AS \"Data_length\", pg_total_relation_size(oid) - pg_relation_size(oid) AS \"Index_length\", pg_catalog.obj_description(oid, 'pg_class') AS \"Comment\" -FROM pg_catalog.pg_class + $result = $connection->query("SELECT relname AS \"Name\", CASE relkind WHEN 'r' THEN '' ELSE 'view' END AS \"Engine\", pg_relation_size(oid) AS \"Data_length\", pg_total_relation_size(oid) - pg_relation_size(oid) AS \"Index_length\", obj_description(oid, 'pg_class') AS \"Comment\" +FROM pg_class WHERE relkind IN ('r','v') AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema())" . ($name != "" ? " AND relname = " . $connection->quote($name) : "") @@ -220,24 +220,25 @@ AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema( function fields($table) { global $connection; $return = array(); - $table_oid = $connection->result("SELECT oid FROM pg_class WHERE relname = " . $connection->quote($table)); - $result = $connection->query("SELECT *, col_description($table_oid, ordinal_position) AS comment FROM information_schema.columns WHERE table_name = " . $connection->quote($table) . " ORDER BY ordinal_position"); + $result = $connection->query("SELECT a.attname AS field, format_type(a.atttypid, a.atttypmod) AS full_type, d.adsrc AS default, a.attnotnull, col_description(c.oid, a.attnum) AS comment +FROM pg_class c +JOIN pg_namespace n ON c.relnamespace = n.oid +JOIN pg_attribute a ON c.oid = a.attrelid +LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum +WHERE c.relname = " . $connection->quote($table) . " +AND n.nspname = current_schema() +AND a.attnum > 0 +ORDER BY a.attnum"); if ($result) { while ($row = $result->fetch_assoc()) { - $length = $row["character_maximum_length"]; - $return[$row["column_name"]] = array( - "field" => $row["column_name"], - "full_type" => $row["data_type"] . ($length ? "($length)" : ""), - "type" => $row["data_type"], - "length" => $length, - "default" => $row["column_default"], - "null" => ($row["is_nullable"] == "YES"), - "auto_increment" => eregi("^nextval\\(", $row["column_default"]), - "collation" => $row["collation_name"], - "privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable - "primary" => false, //! - "comment" => $row["comment"], - ); + //! collation, primary + ereg('(.*)(\\((.*)\\))?', $row["full_type"], $match); + list(, $row["type"], , $row["length"]) = $match; + $row["full_type"] = $row["type"] . ($row["length"] ? "($row[length])" : ""); + $row["null"] = ($row["attnotnull"] == "f"); + $row["auto_increment"] = eregi("^nextval\\(", $row["default"]); + $row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1); + $return[$row["field"]] = $row; } } return $return; @@ -478,7 +479,18 @@ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->qu } function set_schema($schema) { - global $connection; + global $connection, $types, $structured_types; + foreach (get_vals("SELECT typname +FROM pg_type +WHERE typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = " . $connection->quote($schema) . ") +AND typtype IN ('b','d','e') +AND typelem = 0" + ) as $type) { //! get types from current_schemas('t') + if (!isset($types[$type])) { + $types[$type] = 0; + $structured_types[lang('User types')][] = $type; + } + } return $connection->query("SET search_path TO " . idf_escape($schema)); } @@ -504,7 +516,7 @@ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->qu lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0), lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0), lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0), - ) as $key => $val) { + ) as $key => $val) { //! can be retrieved from pg_type $types += $val; $structured_types[$key] = array_keys($val); } diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index c22aeaab..aa8ff07a 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -131,9 +131,10 @@ function process_length($length) { * @return string */ function process_type($field, $collate = "COLLATE") { - global $connection, $unsigned; - return " $field[type]" - . ($field["length"] != "" && !ereg('^date|time$', $field["type"]) ? "(" . process_length($field["length"]) . ")" : "") + global $types, $connection, $unsigned; + $type = $field["type"]; + return " " . (isset($types[$type]) ? $type : idf_escape($type)) + . ($field["length"] != "" ? "(" . process_length($field["length"]) . ")" : "") . (ereg('int|float|double|decimal', $field["type"]) && in_array($field["unsigned"], $unsigned) ? " $field[unsigned]" : "") . (ereg('char|text|enum|set', $field["type"]) && $field["collation"] ? " $collate " . $connection->quote($field["collation"]) : "") ; diff --git a/adminer/lang/cs.inc.php b/adminer/lang/cs.inc.php index 5a534de7..70131b78 100644 --- a/adminer/lang/cs.inc.php +++ b/adminer/lang/cs.inc.php @@ -250,5 +250,6 @@ $translations = array( 'Sequence has been created.' => 'Sekvence byla vytvořena.', 'Sequence has been altered.' => 'Sekvence byla změněna.', 'Alter sequence' => 'Pozměnit sekvenci', + 'User types' => 'Uživatelské typy', 'Search data in tables' => 'Vyhledat data v tabulkách', ); diff --git a/changes.txt b/changes.txt index af3676ac..7c619dab 100644 --- a/changes.txt +++ b/changes.txt @@ -3,10 +3,12 @@ Drivers for MS SQL, SQLite, PostgreSQL, Oracle Allow concurrent logins on the same server Allow permanent login without customization In-place editation in select +Foreign key options in Table creation Show number of tables in server overview Operator LIKE %% Remember export parameters in cookie Allow semicolon as CSV separator +Schema and sequences support (PostgreSQL) Autofocus username in login form Disable spellchecking in SQL textareas Display auto_increment value of inserted item diff --git a/todo.txt b/todo.txt index 4143150e..b6de6554 100644 --- a/todo.txt +++ b/todo.txt @@ -32,6 +32,7 @@ Delimiter in export and SQL command Backward keys in Editor PostgreSQL: +user types Users - SELECT * FROM pg_user ORDER BY COUNT(*) Export - http://www.postgresql.org/docs/8.4/static/functions-info.html