diff --git a/adminer/drivers/sqlite.inc.php b/adminer/drivers/sqlite.inc.php index edf06073..71877dcf 100644 --- a/adminer/drivers/sqlite.inc.php +++ b/adminer/drivers/sqlite.inc.php @@ -326,7 +326,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) { $return = array(); $sql = $connection2->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)); if (preg_match('~\bPRIMARY\s+KEY\s*\((([^)"]+|"[^"]*")++)~i', $sql, $match)) { - $return[""] = array("type" => "PRIMARY", "columns" => array(), "descs" => array()); + $return[""] = array("type" => "PRIMARY", "columns" => array(), "lengths" => array(), "descs" => array()); preg_match_all('~((("[^"]*+")+)|(\S+))(\s+(ASC|DESC))?(,\s*|$)~i', $match[1], $matches, PREG_SET_ORDER); foreach ($matches as $match) { $return[""]["columns"][] = idf_unescape($match[2]) . $match[4]; @@ -463,21 +463,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) { } if ($use_all_fields) { if ($table != "") { - queries("BEGIN"); - foreach (foreign_keys($table) as $foreign_key) { - $columns = array(); - foreach ($foreign_key["source"] as $column) { - if (!$originals[$column]) { - continue 2; - } - $columns[] = $originals[$column]; - } - $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]" - ; - } $indexes = array(); foreach (indexes($table) as $key_name => $index) { $columns = array(); @@ -495,34 +480,9 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) { } } } - $alter = array_merge($alter, $foreign); - if (!queries("CREATE TABLE " . table($table != "" ? "adminer_$name" : $name) . " (\n" . implode(",\n", $alter) . "\n)")) { - // implicit ROLLBACK to not overwrite $connection->error + if (!recreate_table($table, $name, $alter, $originals, $foreign, $indexes)) { return false; } - if ($table != "") { - if ($originals && !queries("INSERT INTO " . table("adminer_$name") . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('idf_escape', array_keys($originals))) . " FROM " . table($table))) { - return false; - } - $triggers = array(); - foreach (triggers($table) as $trigger_name => $timing_event) { - $trigger = trigger($trigger_name); - $triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]"; - } - if (!queries("DROP TABLE " . table($table))) { // drop before creating indexes and triggers to allow using old names - return false; - } - queries("ALTER TABLE " . table("adminer_$name") . " RENAME TO " . table($name)); - if (!alter_indexes($name, $indexes)) { - return false; - } - foreach ($triggers as $trigger) { - if (!queries($trigger)) { - return false; - } - } - queries("COMMIT"); - } } else { foreach ($alter as $val) { if (!queries("ALTER TABLE " . table($table) . " $val")) { @@ -539,6 +499,55 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) { return true; } + function recreate_table($table, $name, $alter, $originals, $foreign, $indexes) { + queries("BEGIN"); + if ($table != "") { + foreach (foreign_keys($table) as $foreign_key) { + $columns = array(); + foreach ($foreign_key["source"] as $column) { + if (!$originals[$column]) { + continue 2; + } + $columns[] = $originals[$column]; + } + $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)")) { + // implicit ROLLBACK to not overwrite $connection->error + return false; + } + if ($table != "") { + if ($originals && !queries("INSERT INTO " . table("adminer_$name") . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('idf_escape', array_keys($originals))) . " FROM " . table($table))) { + return false; + } + $triggers = array(); + foreach (triggers($table) as $trigger_name => $timing_event) { + $trigger = trigger($trigger_name); + $triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]"; + } + if (!queries("DROP TABLE " . table($table))) { // drop before creating indexes and triggers to allow using old names + return false; + } + queries("ALTER TABLE " . table("adminer_$name") . " RENAME TO " . table($name)); + if (!alter_indexes($name, $indexes)) { + return false; + } + foreach ($triggers as $trigger) { + if (!queries($trigger)) { + return false; + } + } + queries("COMMIT"); + } + return true; + } + function index_sql($table, $type, $name, $columns) { return "CREATE $type " . ($type != "INDEX" ? "INDEX " : "") . idf_escape($name != "" ? $name : uniqid($table . "_")) @@ -548,6 +557,32 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) { } function alter_indexes($table, $alter) { + foreach ($alter as $primary) { + if ($primary[0] == "PRIMARY") { + $indexes = array(); + foreach (indexes($table) as $key_name => $index) { + $columns = array(); + foreach ($index["columns"] as $key => $column) { + $columns[] = idf_escape($column) . ($index["descs"][$key] ? " DESC" : ""); + } + $indexes[$key_name] = array($index["type"], $key_name, "(" . implode(", ", $columns) . ")"); + } + foreach ($alter as $val) { + if ($val[2] == "DROP") { + unset($indexes[$val[1]]); + } elseif ($val != $primary) { + $indexes[] = $val; + } + } + $alter = array(); + $originals = array(); + foreach (fields($table) as $name => $field) { + $alter[] = " " . implode(process_field($field, $field)); + $originals[$name] = idf_escape($name); + } + return recreate_table($table, $table, $alter, $originals, array(" PRIMARY KEY $primary[2]"), $indexes); + } + } foreach (array_reverse($alter) as $val) { if (!queries($val[2] == "DROP" ? "DROP INDEX " . idf_escape($val[1]) diff --git a/adminer/indexes.inc.php b/adminer/indexes.inc.php index b9006772..98b6b132 100644 --- a/adminer/indexes.inc.php +++ b/adminer/indexes.inc.php @@ -7,10 +7,10 @@ if (preg_match('~MyISAM|M?aria' . ($connection->server_info >= 5.6 ? '|InnoDB' : } $indexes = indexes($TABLE); $primary = array(); -if ($jush == "sqlite") { // doesn't support primary key - $primary = $indexes[""]; +if ($jush == "mongo") { // doesn't support primary key + $primary = $indexes["_id_"]; unset($index_types[0]); - unset($indexes[""]); + unset($indexes["_id_"]); } $row = $_POST; diff --git a/changes.txt b/changes.txt index 449ee1c3..c5e0981f 100644 --- a/changes.txt +++ b/changes.txt @@ -14,6 +14,7 @@ Keep form values after refresh in Firefox 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 PostgreSQL: Fix handling of nextval() default values PostgreSQL: Support creating array columns