]> git.joonet.de Git - adminer.git/commitdiff
SQLite: Allow editing foreign keys
authorJakub Vrana <jakub@vrana.cz>
Fri, 9 Aug 2013 22:16:15 +0000 (15:16 -0700)
committerJakub Vrana <jakub@vrana.cz>
Fri, 9 Aug 2013 22:16:15 +0000 (15:16 -0700)
adminer/create.inc.php
adminer/drivers/sqlite.inc.php
adminer/foreign.inc.php
adminer/include/editing.inc.php
adminer/table.inc.php
changes.txt

index fcbfabcea2582d08019f9627f287487065079336..c0e636a9080ac64730ced94197ac2e0b9aabfb07 100644 (file)
@@ -58,7 +58,12 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
                                        }
                                }
                                if ($foreign_key !== null) {
-                                       $foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . table($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")" . (preg_match("~^($on_actions)\$~", $field["on_delete"]) ? " ON DELETE $field[on_delete]" : "");
+                                       $foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . format_foreign_key(array(
+                                               'table' => $foreign_keys[$field["type"]],
+                                               'source' => array($field["field"]),
+                                               'target' => array($type_field["field"]),
+                                               'on_delete' => $field["on_delete"],
+                                       ));
                                }
                                $after = " AFTER " . idf_escape($field["field"]);
                        } elseif ($field["orig"] != "") {
index dbfc14c70437217481332fae8120e812403bd9df..8d7c48cddbc8cd849956952a7f4c7bda5ca29e45 100644 (file)
@@ -482,15 +482,21 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
                return true;
        }
 
-       function recreate_table($table, $name, $alter, $originals, $foreign, $indexes = array()) {
+       function recreate_table($table, $name, $fields, $originals, $foreign, $indexes = array()) {
                queries("BEGIN");
                if ($table != "") {
+                       if (!$fields) {
+                               foreach (fields($table) as $key => $field) {
+                                       $fields[] = process_field($field, $field);
+                                       $originals[$key] = idf_escape($key);
+                               }
+                       }
                        $primary_key = false;
-                       foreach ($alter as $key => $field) {
+                       foreach ($fields as $key => $field) {
                                if ($field[6]) {
                                        $primary_key = true;
                                }
-                               $alter[$key] = "  " . implode($field);
+                               $fields[$key] = "  " . implode($field);
                        }
                        $drop_indexes = array();
                        foreach ($indexes as $key => $val) {
@@ -520,23 +526,20 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
                                        $foreign[] = "  PRIMARY KEY $val[2]";
                                }
                        }
-                       foreach (foreign_keys($table) as $foreign_key) {
-                               $columns = array();
-                               foreach ($foreign_key["source"] as $column) {
+                       foreach (foreign_keys($table) as $key_name => $foreign_key) {
+                               foreach ($foreign_key["source"] as $key => $column) {
                                        if (!$originals[$column]) {
                                                continue 2;
                                        }
-                                       $columns[] = $originals[$column];
+                                       $foreign_key["source"][$key] = idf_unescape($originals[$column]);
+                               }
+                               if (!isset($foreign[" $key_name"])) {
+                                       $foreign[] = " " . format_foreign_key($foreign_key);
                                }
-                               $foreign[] = "  FOREIGN KEY (" . implode(", ", $columns) . ") REFERENCES "
-                                       . table($foreign_key["table"])
-                                       . " (" . implode(", ", array_map('idf_escape', $foreign_key["target"]))
-                                       . ") ON DELETE $foreign_key[on_delete] ON UPDATE $foreign_key[on_update]"
-                               ;
                        }
                }
-               $alter = array_merge($alter, $foreign);
-               if (!queries("CREATE TABLE " . table($table != "" ? "adminer_$name" : $name) . " (\n" . implode(",\n", $alter) . "\n)")) {
+               $fields = array_merge($fields, array_filter($foreign));
+               if (!queries("CREATE TABLE " . table($table != "" ? "adminer_$name" : $name) . " (\n" . implode(",\n", $fields) . "\n)")) {
                        // implicit ROLLBACK to not overwrite $connection->error
                        return false;
                }
@@ -577,13 +580,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
        function alter_indexes($table, $alter) {
                foreach ($alter as $primary) {
                        if ($primary[0] == "PRIMARY") {
-                               $fields = array();
-                               $originals = array();
-                               foreach (fields($table) as $name => $field) {
-                                       $fields[] = process_field($field, $field);
-                                       $originals[$name] = idf_escape($name);
-                               }
-                               return recreate_table($table, $table, $fields, $originals, array(), $alter);
+                               return recreate_table($table, $table, array(), array(), array(), $alter);
                        }
                }
                foreach (array_reverse($alter) as $val) {
index 9f7e05f29dabf9b79ff9a41f06916ea1158b8db1..bad28c2bed045795e77a617a7cc657dedd41fbd8 100644 (file)
@@ -4,25 +4,28 @@ $name = $_GET["name"];
 $row = $_POST;
 
 if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
-       $alter = "ALTER TABLE " . table($TABLE);
-       $drop = "\nDROP " . ($jush == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name);
-       if ($_POST["drop"]) {
-               query_redirect($alter . $drop, ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
+       $message = ($_POST["drop"] ? lang('Foreign key has been dropped.') : ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.')));
+       $location = ME . "table=" . urlencode($TABLE);
+       
+       $row["source"] = array_filter($row["source"], 'strlen');
+       ksort($row["source"]); // enforce input order
+       $target = array();
+       foreach ($row["source"] as $key => $val) {
+               $target[$key] = $row["target"][$key];
+       }
+       $row["target"] = $target;
+       
+       if ($jush == "sqlite") {
+               queries_redirect($location, $message, recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($_POST["drop"] ? "" : " " . format_foreign_key($row)))));
        } else {
-               $source = array_filter($row["source"], 'strlen');
-               ksort($source); // enforce input order
-               $target = array();
-               foreach ($source as $key => $val) {
-                       $target[$key] = $row["target"][$key];
+               $alter = "ALTER TABLE " . table($TABLE);
+               $drop = "\nDROP " . ($jush == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name);
+               if ($_POST["drop"]) {
+                       query_redirect($alter . $drop, $location, $message);
+               } else {
+                       query_redirect($alter . ($name != "" ? "$drop," : "") . "\nADD" . format_foreign_key($row), $location, $message);
+                       $error = lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.') . "<br>$error"; //! no partitioning
                }
-
-               query_redirect($alter
-                       . ($name != "" ? "$drop," : "")
-                       . "\nADD FOREIGN KEY (" . implode(", ", array_map('idf_escape', $source)) . ") REFERENCES " . table($row["table"]) . " (" . implode(", ", array_map('idf_escape', $target)) . ")" //! reuse $name - check in older MySQL versions
-                       . (preg_match("~^($on_actions)\$~", $row["on_delete"]) ? " ON DELETE $row[on_delete]" : "")
-                       . (preg_match("~^($on_actions)\$~", $row["on_update"]) ? " ON UPDATE $row[on_update]" : "")
-               , ME . "table=" . urlencode($TABLE), ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.')));
-               $error = lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.') . "<br>$error"; //! no partitioning
        }
 }
 
index 42389be4f7d80f960835d10631eb65fb298b07c3..4f4f615fa8bcd3ba70fa89b076718a15f3d5e9a6 100644 (file)
@@ -436,6 +436,19 @@ function remove_definer($query) {
        return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\\1)', logged_user()) . '`~', '\\1', $query); //! proper escaping of user
 }
 
+/** Format foreign key to use in SQL query
+* @param array ("table" => string, "source" => array, "target" => array, "on_delete" => one of $on_actions, "on_update" => one of $on_actions)
+* @return 
+*/
+function format_foreign_key($foreign_key) {
+       global $on_actions;
+       return " FOREIGN KEY (" . implode(", ", array_map('idf_escape', $foreign_key["source"])) . ") REFERENCES " . table($foreign_key["table"])
+               . " (" . implode(", ", array_map('idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions
+               . (preg_match("~^($on_actions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "")
+               . (preg_match("~^($on_actions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "")
+       ;
+}
+
 /** Add a file to TAR
 * @param string
 * @param TmpFile
index 84a20a82d22a2d5c5ebc4886039e3f339da401c7..a84a371879e7f66e62a2999659c95b7cd0d5c48c 100644 (file)
@@ -53,7 +53,7 @@ if ($fields) {
                        $foreign_keys = foreign_keys($TABLE);
                        if ($foreign_keys) {
                                echo "<table cellspacing='0'>\n";
-                               echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . ($jush != "sqlite" ? "<td>&nbsp;" : "") . "</thead>\n";
+                               echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td>&nbsp;</thead>\n";
                                foreach ($foreign_keys as $name => $foreign_key) {
                                        echo "<tr title='" . h($name) . "'>";
                                        echo "<th><i>" . implode("</i>, <i>", array_map('h', $foreign_key["source"])) . "</i>";
@@ -64,13 +64,11 @@ if ($fields) {
                                        echo "(<i>" . implode("</i>, <i>", array_map('h', $foreign_key["target"])) . "</i>)";
                                        echo "<td>" . nbsp($foreign_key["on_delete"]) . "\n";
                                        echo "<td>" . nbsp($foreign_key["on_update"]) . "\n";
-                                       echo ($jush == "sqlite" ? "" : '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>');
+                                       echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
                                }
                                echo "</table>\n";
                        }
-                       if ($jush != "sqlite") {
-                               echo '<p class="links"><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n";
-                       }
+                       echo '<p class="links"><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n";
                }
                
                if (support("trigger")) {
index c5e0981f96298712f28f3b5332272abcbffcb481..f9f691b9e07d69bd6addf9499be6bc791f32ee8c 100644 (file)
@@ -15,6 +15,7 @@ Don't append newlines to uploaded files, bug since Adminer 3.7.0
 Don't display SQL edit form on Ctrl+click on the select query, introduced in Adminer 3.6.4
 Use MD5 for editing long keys only in supported drivers, bug since Adminer 3.6.4
 SQLite: Allow editing primary key
+SQLite: Allow editing foreign keys
 PostgreSQL: Fix handling of nextval() default values
 PostgreSQL: Support creating array columns