|
| 1 | +<?php |
| 2 | +defined( 'ABSPATH' ) or die( 'Access forbidden!' ); |
| 3 | + |
| 4 | +$TABLE = $_GET["create"]; |
| 5 | +$partition_by = array(); |
| 6 | +foreach (array('HASH', 'LINEAR HASH', 'KEY', 'LINEAR KEY', 'RANGE', 'LIST') as $key) { |
| 7 | + $partition_by[$key] = $key; |
| 8 | +} |
| 9 | + |
| 10 | +$referencable_primary = referencable_primary($TABLE); |
| 11 | +$foreign_keys = array(); |
| 12 | +foreach ($referencable_primary as $table_name => $field) { |
| 13 | + $foreign_keys[str_replace("`", "``", $table_name) . "`" . str_replace("`", "``", $field["field"])] = $table_name; // not idf_escape() - used in JS |
| 14 | +} |
| 15 | + |
| 16 | +$orig_fields = array(); |
| 17 | +$table_status = array(); |
| 18 | +if ($TABLE != "") { |
| 19 | + $orig_fields = fields($TABLE); |
| 20 | + $table_status = table_status($TABLE); |
| 21 | + if (!$table_status) { |
| 22 | + $error = lang('No tables.'); |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +$row = $_POST; |
| 27 | +$row["fields"] = (array) $row["fields"]; |
| 28 | +if ($row["auto_increment_col"]) { |
| 29 | + $row["fields"][$row["auto_increment_col"]]["auto_increment"] = true; |
| 30 | +} |
| 31 | + |
| 32 | +if ($_POST) { |
| 33 | + set_adminer_settings(array("comments" => $_POST["comments"], "defaults" => $_POST["defaults"])); |
| 34 | +} |
| 35 | + |
| 36 | +if ($_POST && !process_fields($row["fields"]) && !$error) { |
| 37 | + if ($_POST["drop"]) { |
| 38 | + queries_redirect(substr(ME, 0, -1), lang('Table has been dropped.'), drop_tables(array($TABLE))); |
| 39 | + } else { |
| 40 | + $fields = array(); |
| 41 | + $all_fields = array(); |
| 42 | + $use_all_fields = false; |
| 43 | + $foreign = array(); |
| 44 | + $orig_field = reset($orig_fields); |
| 45 | + $after = " FIRST"; |
| 46 | + |
| 47 | + foreach ($row["fields"] as $key => $field) { |
| 48 | + $foreign_key = $foreign_keys[$field["type"]]; |
| 49 | + $type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type |
| 50 | + if ($field["field"] != "") { |
| 51 | + if (!$field["has_default"]) { |
| 52 | + $field["default"] = null; |
| 53 | + } |
| 54 | + if ($key == $row["auto_increment_col"]) { |
| 55 | + $field["auto_increment"] = true; |
| 56 | + } |
| 57 | + $process_field = process_field($field, $type_field); |
| 58 | + $all_fields[] = array($field["orig"], $process_field, $after); |
| 59 | + if ($process_field != process_field($orig_field, $orig_field)) { |
| 60 | + $fields[] = array($field["orig"], $process_field, $after); |
| 61 | + if ($field["orig"] != "" || $after) { |
| 62 | + $use_all_fields = true; |
| 63 | + } |
| 64 | + } |
| 65 | + if ($foreign_key !== null) { |
| 66 | + $foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . format_foreign_key(array( |
| 67 | + 'table' => $foreign_keys[$field["type"]], |
| 68 | + 'source' => array($field["field"]), |
| 69 | + 'target' => array($type_field["field"]), |
| 70 | + 'on_delete' => $field["on_delete"], |
| 71 | + )); |
| 72 | + } |
| 73 | + $after = " AFTER " . idf_escape($field["field"]); |
| 74 | + } elseif ($field["orig"] != "") { |
| 75 | + $use_all_fields = true; |
| 76 | + $fields[] = array($field["orig"]); |
| 77 | + } |
| 78 | + if ($field["orig"] != "") { |
| 79 | + $orig_field = next($orig_fields); |
| 80 | + if (!$orig_field) { |
| 81 | + $after = ""; |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + $partitioning = ""; |
| 87 | + if ($partition_by[$row["partition_by"]]) { |
| 88 | + $partitions = array(); |
| 89 | + if ($row["partition_by"] == 'RANGE' || $row["partition_by"] == 'LIST') { |
| 90 | + foreach (array_filter($row["partition_names"]) as $key => $val) { |
| 91 | + $value = $row["partition_values"][$key]; |
| 92 | + $partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($row["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection |
| 93 | + } |
| 94 | + } |
| 95 | + $partitioning .= "\nPARTITION BY $row[partition_by]($row[partition])" . ($partitions // $row["partition"] can be expression, not only column |
| 96 | + ? " (" . implode(",", $partitions) . "\n)" |
| 97 | + : ($row["partitions"] ? " PARTITIONS " . (+$row["partitions"]) : "") |
| 98 | + ); |
| 99 | + } elseif (support("partitioning") && preg_match("~partitioned~", $table_status["Create_options"])) { |
| 100 | + $partitioning .= "\nREMOVE PARTITIONING"; |
| 101 | + } |
| 102 | + |
| 103 | + $message = lang('Table has been altered.'); |
| 104 | + if ($TABLE == "") { |
| 105 | + cookie("adminer_engine", $row["Engine"]); |
| 106 | + $message = lang('Table has been created.'); |
| 107 | + } |
| 108 | + $name = trim($row["name"]); |
| 109 | + |
| 110 | + queries_redirect(ME . (support("table") ? "table=" : "select=") . urlencode($name), $message, alter_table( |
| 111 | + $TABLE, |
| 112 | + $name, |
| 113 | + ($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields), |
| 114 | + $foreign, |
| 115 | + ($row["Comment"] != $table_status["Comment"] ? $row["Comment"] : null), |
| 116 | + ($row["Engine"] && $row["Engine"] != $table_status["Engine"] ? $row["Engine"] : ""), |
| 117 | + ($row["Collation"] && $row["Collation"] != $table_status["Collation"] ? $row["Collation"] : ""), |
| 118 | + ($row["Auto_increment"] != "" ? number($row["Auto_increment"]) : ""), |
| 119 | + $partitioning |
| 120 | + )); |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +page_header(($TABLE != "" ? lang('Alter table') : lang('Create table')), $error, array("table" => $TABLE), h($TABLE)); |
| 125 | + |
| 126 | +if (!$_POST) { |
| 127 | + $row = array( |
| 128 | + "Engine" => $_COOKIE["adminer_engine"], |
| 129 | + "fields" => array(array("field" => "", "type" => (isset($types["int"]) ? "int" : (isset($types["integer"]) ? "integer" : "")), "on_update" => "")), |
| 130 | + "partition_names" => array(""), |
| 131 | + ); |
| 132 | + |
| 133 | + if ($TABLE != "") { |
| 134 | + $row = $table_status; |
| 135 | + $row["name"] = $TABLE; |
| 136 | + $row["fields"] = array(); |
| 137 | + if (!$_GET["auto_increment"]) { // don't prefill by original Auto_increment for the sake of performance and not reusing deleted ids |
| 138 | + $row["Auto_increment"] = ""; |
| 139 | + } |
| 140 | + foreach ($orig_fields as $field) { |
| 141 | + $field["has_default"] = isset($field["default"]); |
| 142 | + $row["fields"][] = $field; |
| 143 | + } |
| 144 | + |
| 145 | + if (support("partitioning")) { |
| 146 | + $from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($TABLE); |
| 147 | + $result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); |
| 148 | + list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row(); |
| 149 | + $partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION"); |
| 150 | + $partitions[""] = ""; |
| 151 | + $row["partition_names"] = array_keys($partitions); |
| 152 | + $row["partition_values"] = array_values($partitions); |
| 153 | + } |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +$collations = collations(); |
| 158 | +$engines = engines(); |
| 159 | +// case of engine may differ |
| 160 | +foreach ($engines as $engine) { |
| 161 | + if (!strcasecmp($engine, $row["Engine"])) { |
| 162 | + $row["Engine"] = $engine; |
| 163 | + break; |
| 164 | + } |
| 165 | +} |
| 166 | +?> |
| 167 | + |
| 168 | +<form action="" method="post" id="form"> |
| 169 | +<p> |
| 170 | +<?php if (support("columns") || $TABLE == "") { ?> |
| 171 | +<?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off"> |
| 172 | +<?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?> |
| 173 | +<?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?> |
| 174 | + <?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?> |
| 175 | + <input type="submit" value="<?php echo lang('Save'); ?>"> |
| 176 | +<?php } ?> |
| 177 | + |
| 178 | +<?php if (support("columns")) { ?> |
| 179 | +<div class="scrollable"> |
| 180 | +<table cellspacing="0" id="edit-fields" class="nowrap"> |
| 181 | +<?php |
| 182 | +edit_fields($row["fields"], $collations, "TABLE", $foreign_keys); |
| 183 | +?> |
| 184 | +</table> |
| 185 | +</div> |
| 186 | +<p> |
| 187 | +<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>"> |
| 188 | +<?php echo checkbox("defaults", 1, ($_POST ? $_POST["defaults"] : adminer_setting("defaults")), lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?> |
| 189 | +<?php echo (support("comment") |
| 190 | + ? checkbox("comments", 1, ($_POST ? $_POST["comments"] : adminer_setting("comments")), lang('Comment'), "editingCommentsClick(this, true);", "jsonly") |
| 191 | + . ' <input name="Comment" value="' . h($row["Comment"]) . '" data-maxlength="' . (min_version(5.5) ? 2048 : 60) . '">' |
| 192 | + : '') |
| 193 | +; ?> |
| 194 | +<p> |
| 195 | +<input type="submit" value="<?php echo lang('Save'); ?>"> |
| 196 | +<?php } ?> |
| 197 | + |
| 198 | +<?php if ($TABLE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?><?php } ?> |
| 199 | +<?php |
| 200 | +if (support("partitioning")) { |
| 201 | + $partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]); |
| 202 | + print_fieldset("partition", lang('Partition by'), $row["partition_by"]); |
| 203 | + ?> |
| 204 | +<p> |
| 205 | +<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?> |
| 206 | +(<input name="partition" value="<?php echo h($row["partition"]); ?>">) |
| 207 | +<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>"> |
| 208 | +<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>> |
| 209 | +<thead><tr><th><?php echo lang('Partition name'); ?><th><?php echo lang('Values'); ?></thead> |
| 210 | +<?php |
| 211 | +foreach ($row["partition_names"] as $key => $val) { |
| 212 | + echo '<tr>'; |
| 213 | + echo '<td><input name="partition_names[]" value="' . h($val) . '" autocapitalize="off">'; |
| 214 | + echo ($key == count($row["partition_names"]) - 1 ? script("qsl('input').oninput = partitionNameChange;") : ''); |
| 215 | + echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">'; |
| 216 | +} |
| 217 | +?> |
| 218 | +</table> |
| 219 | +</div></fieldset> |
| 220 | +<?php |
| 221 | +} |
| 222 | +?> |
| 223 | +<input type="hidden" name="token" value="<?php echo $token; ?>"> |
| 224 | +</form> |
| 225 | +<?php echo script("qs('#form')['defaults'].onclick();" . (support("comment") ? " editingCommentsClick(qs('#form')['comments']);" : "")); ?> |
0 commit comments