SQLite: Allow editing primary key

This commit is contained in:
Jakub Vrana 2013-08-08 15:32:36 -07:00
parent 4e22af6de0
commit 6664b0fb7e
3 changed files with 81 additions and 45 deletions

View file

@ -326,7 +326,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$return = array(); $return = array();
$sql = $connection2->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)); $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)) { 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); preg_match_all('~((("[^"]*+")+)|(\S+))(\s+(ASC|DESC))?(,\s*|$)~i', $match[1], $matches, PREG_SET_ORDER);
foreach ($matches as $match) { foreach ($matches as $match) {
$return[""]["columns"][] = idf_unescape($match[2]) . $match[4]; $return[""]["columns"][] = idf_unescape($match[2]) . $match[4];
@ -463,21 +463,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
} }
if ($use_all_fields) { if ($use_all_fields) {
if ($table != "") { 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(); $indexes = array();
foreach (indexes($table) as $key_name => $index) { foreach (indexes($table) as $key_name => $index) {
$columns = array(); $columns = array();
@ -495,34 +480,9 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
} }
} }
} }
$alter = array_merge($alter, $foreign); if (!recreate_table($table, $name, $alter, $originals, $foreign, $indexes)) {
if (!queries("CREATE TABLE " . table($table != "" ? "adminer_$name" : $name) . " (\n" . implode(",\n", $alter) . "\n)")) {
// implicit ROLLBACK to not overwrite $connection->error
return false; 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 { } else {
foreach ($alter as $val) { foreach ($alter as $val) {
if (!queries("ALTER TABLE " . table($table) . " $val")) { if (!queries("ALTER TABLE " . table($table) . " $val")) {
@ -539,6 +499,55 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return true; 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) { function index_sql($table, $type, $name, $columns) {
return "CREATE $type " . ($type != "INDEX" ? "INDEX " : "") return "CREATE $type " . ($type != "INDEX" ? "INDEX " : "")
. idf_escape($name != "" ? $name : uniqid($table . "_")) . idf_escape($name != "" ? $name : uniqid($table . "_"))
@ -548,6 +557,32 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
} }
function alter_indexes($table, $alter) { 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) { foreach (array_reverse($alter) as $val) {
if (!queries($val[2] == "DROP" if (!queries($val[2] == "DROP"
? "DROP INDEX " . idf_escape($val[1]) ? "DROP INDEX " . idf_escape($val[1])

View file

@ -7,10 +7,10 @@ if (preg_match('~MyISAM|M?aria' . ($connection->server_info >= 5.6 ? '|InnoDB' :
} }
$indexes = indexes($TABLE); $indexes = indexes($TABLE);
$primary = array(); $primary = array();
if ($jush == "sqlite") { // doesn't support primary key if ($jush == "mongo") { // doesn't support primary key
$primary = $indexes[""]; $primary = $indexes["_id_"];
unset($index_types[0]); unset($index_types[0]);
unset($indexes[""]); unset($indexes["_id_"]);
} }
$row = $_POST; $row = $_POST;

View file

@ -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 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 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 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: Fix handling of nextval() default values
PostgreSQL: Support creating array columns PostgreSQL: Support creating array columns