mirror of
https://github.com/vrana/adminer.git
synced 2025-09-03 03:13:00 +02:00
Compare commits
132 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
dcf11d8fc9 | ||
|
0de6a057d3 | ||
|
18b62aba38 | ||
|
10ff74552d | ||
|
f5c7ab54f7 | ||
|
cc110c448c | ||
|
6f766f8c52 | ||
|
9a60d158f1 | ||
|
6dec0d63b0 | ||
|
c9a52cd28c | ||
|
9424b7431e | ||
|
35b2b969be | ||
|
165f1b241c | ||
|
4d75f822e9 | ||
|
5e9c185596 | ||
|
cfd69dfd8c | ||
|
1fc5acb389 | ||
|
8ca0e36970 | ||
|
9e8de24e3d | ||
|
4cb09852e3 | ||
|
e115dccdae | ||
|
1ba410cad1 | ||
|
0764a20a19 | ||
|
b2c4574325 | ||
|
466eceff40 | ||
|
27c5f6d21b | ||
|
2744538c8c | ||
|
41456c9eb7 | ||
|
9745c12769 | ||
|
f24f72ac51 | ||
|
2b52a9b653 | ||
|
9ba4b86916 | ||
|
1cc3fdf915 | ||
|
b960c41d63 | ||
|
3ec750ef7e | ||
|
737b631dda | ||
|
8fc450946c | ||
|
e282d6eb89 | ||
|
86ffeb2a1e | ||
|
31530ba03e | ||
|
146d3539d8 | ||
|
04068a631e | ||
|
4698686232 | ||
|
57b6afc8cb | ||
|
e589c80f42 | ||
|
acfebf1788 | ||
|
246c3c489b | ||
|
92b95606c1 | ||
|
ac8318f387 | ||
|
d1c2679acd | ||
|
caf6e495dc | ||
|
ec5ad85470 | ||
|
307fabaf22 | ||
|
1862b84612 | ||
|
e76be9f890 | ||
|
1cfc8451ef | ||
|
62a9cf3e3f | ||
|
e707c7a5f4 | ||
|
c92b127b56 | ||
|
cf52c4c0a8 | ||
|
5f7fb62803 | ||
|
9b0acfa7c9 | ||
|
45d61803c4 | ||
|
48160f2cd7 | ||
|
61f2b370df | ||
|
e13910b5c5 | ||
|
de86789bfc | ||
|
ebcf4feeb2 | ||
|
d881f51deb | ||
|
b9c39e77fc | ||
|
c734deca84 | ||
|
1466051402 | ||
|
36e55a3f55 | ||
|
155668906d | ||
|
70ce02a798 | ||
|
de3220acc7 | ||
|
1030e84904 | ||
|
f4ca974623 | ||
|
af627e7116 | ||
|
0c5bba47da | ||
|
e340a2973e | ||
|
be2afb49c5 | ||
|
c8fa515ed5 | ||
|
3dad86d279 | ||
|
d9c1ac00f3 | ||
|
2a4d2cfb39 | ||
|
67a64c8d72 | ||
|
d59d6c4075 | ||
|
dbec3a1b92 | ||
|
a93f0003ae | ||
|
29a31c6b9c | ||
|
a04823f4c4 | ||
|
82c544514d | ||
|
7185d7854f | ||
|
d845d4b358 | ||
|
92ce506243 | ||
|
6d6998c3d3 | ||
|
45799f4605 | ||
|
b999f123c8 | ||
|
7642b00877 | ||
|
45be56e4e1 | ||
|
e1b92f73aa | ||
|
63850ebf19 | ||
|
49fd96f8b9 | ||
|
fcae403f60 | ||
|
7dc152b732 | ||
|
29f7b2df96 | ||
|
3466ab730b | ||
|
9235cb8350 | ||
|
020285772b | ||
|
8238838285 | ||
|
a165d4ed81 | ||
|
f5b42eae55 | ||
|
460a24ea2d | ||
|
4646298015 | ||
|
cde6b9008c | ||
|
8783f4d3ac | ||
|
3d2395fc59 | ||
|
3a73815ba4 | ||
|
d0a2de53ef | ||
|
982233d7e5 | ||
|
cedfe97f40 | ||
|
9beb72edc2 | ||
|
9555c96d6a | ||
|
a3d0bbba8f | ||
|
a9bcde334f | ||
|
a735b795b2 | ||
|
008cd33058 | ||
|
036ce4f1c5 | ||
|
5867b0724f | ||
|
71f2578af6 | ||
|
c809216a56 |
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -8,8 +8,11 @@ assignees: ''
|
||||
---
|
||||
|
||||
**Adminer version:** please use latest published or Git
|
||||
**Compiled:** single file / single language / source codes / custom compilation
|
||||
**Driver:** e.g. MySQLi
|
||||
**Database version:** e.g. 10.2.12-MariaDB
|
||||
**Plugins used:**
|
||||
|
||||
_Please provide reproducible steps including a SQL dump (with no personal information) if applicable.
|
||||
Also please include a screenshot._
|
||||
Also please include a screenshot.
|
||||
Report issues with Adminer Docker image at https://github.com/TimWolla/docker-adminer._
|
||||
|
17
.github/workflows/ci.yml
vendored
Normal file
17
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: php-actions/composer@v6
|
||||
- uses: php-actions/phpcs@v1
|
||||
with:
|
||||
path: adminer/
|
||||
standard: phpcs.xml
|
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,3 +1,47 @@
|
||||
## Adminer dev
|
||||
- Allow specifying operator in search anywhere
|
||||
- Do not order descending in GROUP BY select
|
||||
- Allow exporting SQL in SQL command (bug #1092)
|
||||
- Add section links in database overview
|
||||
- Warn about exceeded max_file_uploads in import
|
||||
- Display @ after username without server in existing logins
|
||||
- Display data length and index length for materialized views
|
||||
- Link routines from syntax highlighting
|
||||
- MySQL 5.0-: Do not load partitioning info in alter table (bug #1099)
|
||||
- MariaDB: Parse COLLATE in routine definition (bug #1104)
|
||||
- PostgreSQL: Show structure of inherited tables
|
||||
- PostgreSQL: Display index expressions
|
||||
- PostgreSQL: Add SQL operator to select
|
||||
- PostgreSQL: Hide only partitions, not all inherited tables from menu
|
||||
- PostgreSQL: Allow comparing json columns (bug #1107)
|
||||
- PostgreSQL: Shorten values in hstore columns
|
||||
- PostgreSQL: Quote edit value with interval operator
|
||||
- PostgreSQL 11-: Avoid duplicate oid in table status (bug #1089)
|
||||
- Elasticsearch: Support dropping aliases
|
||||
- Plugins: Methods afterConnect(), processList() and killProcess()
|
||||
- New plugin: Display row numbers in select (bug #1106)
|
||||
- New plugin: Specify query timeout
|
||||
|
||||
## Adminer 5.3.0 (released 2025-05-04)
|
||||
- Align numeric functions right
|
||||
- Autocomplete: Support table aliases
|
||||
- Fix type error in Create function (bug #1053, regression from 5.1.1)
|
||||
- Add border to column actions (bug #1072)
|
||||
- Align money values right (bug #1071)
|
||||
- MySQL: Avoid warning on selecting tables with fulltext indexes (bug #1036)
|
||||
- MySQL, PostgreSQL: Support index algorithms (bug #1030)
|
||||
- MySQL: Fix connecting to localhost:3306 (bug #1057, regression from 5.1.1)
|
||||
- PostgreSQL, CockroachDB: Creating partitioned tables (bug #1031)
|
||||
- PostgreSQL: Move partitioned tables from table list to parent table
|
||||
- PostgreSQL: Support partial indices (bug #1048)
|
||||
- PostgreSQL: Support calling functions returning table (bug #1040)
|
||||
- PostgreSQL: Add NOT ILIKE operator (bug #1066)
|
||||
- Editor: Fix bit and enum search (bug #1062)
|
||||
- Designs: adminer.css with 'prefers-color-scheme: dark' doesn't disable dark mode
|
||||
- Plugins: Method bodyClass() to add <body class>
|
||||
- Plugins: Allow setting dark mode in css()
|
||||
- Hindi translation
|
||||
|
||||
## Adminer 5.2.1 (released 2025-04-11)
|
||||
- Fix search anywhere (bug #1004, regression from 5.1.1)
|
||||
- Fix import without primary key (bug #1017, regression from 5.1.1)
|
||||
@@ -46,8 +90,8 @@
|
||||
- CSS: Allow more custom styles with dark mode (bug #925)
|
||||
- CSS: Increase maximum width of string edit (bug #930)
|
||||
- CSS: Increase space after SQL result (bug #937)
|
||||
- Plugins: autoload plugins from adminer-plugins/
|
||||
- Plugins: configure plugins with adminer-plugins.php
|
||||
- Plugins: Autoload plugins from adminer-plugins/
|
||||
- Plugins: Configure plugins with adminer-plugins.php
|
||||
- Plugins: Display loaded plugins in server overview
|
||||
- New plugin: AI prompt in SQL command generating the queries with Google Gemini
|
||||
- New plugin: Verify new versions from GitHub
|
||||
|
@@ -8,7 +8,7 @@ $routine = routine($_GET["call"], (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDU
|
||||
$in = array();
|
||||
$out = array();
|
||||
foreach ($routine["fields"] as $i => $field) {
|
||||
if (substr($field["inout"], -3) == "OUT") {
|
||||
if (substr($field["inout"], -3) == "OUT" && JUSH == 'sql') {
|
||||
$out[$i] = "@" . idf_escape($field["field"]) . " AS " . idf_escape($field["field"]);
|
||||
}
|
||||
if (!$field["inout"] || substr($field["inout"], 0, 2) == "IN") {
|
||||
@@ -29,7 +29,11 @@ if (!$error && $_POST) {
|
||||
connection()->query("SET @" . idf_escape($field["field"]) . " = $val");
|
||||
}
|
||||
}
|
||||
$call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val);
|
||||
if (isset($out[$key])) {
|
||||
$call[] = "@" . idf_escape($field["field"]);
|
||||
} elseif (in_array($key, $in)) {
|
||||
$call[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
|
||||
|
@@ -2,10 +2,8 @@
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["create"];
|
||||
$partition_by = array();
|
||||
foreach (array('HASH', 'LINEAR HASH', 'KEY', 'LINEAR KEY', 'RANGE', 'LIST') as $key) {
|
||||
$partition_by[$key] = $key;
|
||||
}
|
||||
$partition_by = driver()->partitionBy;
|
||||
$partitions_info = ($partition_by ? driver()->partitionsInfo($TABLE) : array());
|
||||
|
||||
$referencable_primary = referencable_primary($TABLE);
|
||||
$foreign_keys = array();
|
||||
@@ -80,40 +78,26 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
}
|
||||
}
|
||||
|
||||
$partitioning = "";
|
||||
if (support("partitioning")) {
|
||||
if (isset($partition_by[$row["partition_by"]])) {
|
||||
$params = array();
|
||||
foreach ($row as $key => $val) {
|
||||
if (preg_match('~^partition~', $key)) {
|
||||
$params[$key] = $val;
|
||||
}
|
||||
$partitioning = array();
|
||||
if (in_array($row["partition_by"], $partition_by)) {
|
||||
foreach ($row as $key => $val) {
|
||||
if (preg_match('~^partition~', $key)) {
|
||||
$partitioning[$key] = $val;
|
||||
}
|
||||
foreach ($params["partition_names"] as $key => $name) {
|
||||
if ($name == "") {
|
||||
unset($params["partition_names"][$key]);
|
||||
unset($params["partition_values"][$key]);
|
||||
}
|
||||
}
|
||||
if ($params != get_partitions_info($TABLE)) {
|
||||
$partitions = array();
|
||||
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
|
||||
foreach ($params["partition_names"] as $key => $name) {
|
||||
$value = $params["partition_values"][$key];
|
||||
$partitions[] = "\n PARTITION " . idf_escape($name) . " VALUES " . ($params["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
|
||||
}
|
||||
}
|
||||
// $params["partition"] can be expression, not only column
|
||||
$partitioning .= "\nPARTITION BY $params[partition_by]($params[partition])";
|
||||
if ($partitions) {
|
||||
$partitioning .= " (" . implode(",", $partitions) . "\n)";
|
||||
} elseif ($params["partitions"]) {
|
||||
$partitioning .= " PARTITIONS " . (+$params["partitions"]);
|
||||
}
|
||||
}
|
||||
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
|
||||
$partitioning .= "\nREMOVE PARTITIONING";
|
||||
}
|
||||
foreach ($partitioning["partition_names"] as $key => $name) {
|
||||
if ($name == "") {
|
||||
unset($partitioning["partition_names"][$key]);
|
||||
unset($partitioning["partition_values"][$key]);
|
||||
}
|
||||
}
|
||||
$partitioning["partition_names"] = array_values($partitioning["partition_names"]);
|
||||
$partitioning["partition_values"] = array_values($partitioning["partition_values"]);
|
||||
if ($partitioning == $partitions_info) {
|
||||
$partitioning = array();
|
||||
}
|
||||
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
|
||||
$partitioning = null;
|
||||
}
|
||||
|
||||
$message = lang('Table has been altered.');
|
||||
@@ -159,8 +143,8 @@ if (!$_POST) {
|
||||
$row["fields"][] = $field;
|
||||
}
|
||||
|
||||
if (support("partitioning")) {
|
||||
$row += get_partitions_info($TABLE);
|
||||
if ($partition_by) {
|
||||
$row += $partitions_info;
|
||||
$row["partition_names"][] = "";
|
||||
$row["partition_values"][] = "";
|
||||
}
|
||||
@@ -221,10 +205,10 @@ if (support("columns")) {
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?>
|
||||
<?php } ?>
|
||||
<?php
|
||||
if (support("partitioning")) {
|
||||
if ($partition_by && (JUSH == 'sql' || $TABLE == "")) {
|
||||
$partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]);
|
||||
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
|
||||
echo "<p>" . html_select("partition_by", array("" => "") + $partition_by, $row["partition_by"]) . on_help("event.target.value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;");
|
||||
echo "<p>" . html_select("partition_by", array_merge(array(""), $partition_by), $row["partition_by"]) . on_help("event.target.value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;");
|
||||
echo "(<input name='partition' value='" . h($row["partition"]) . "'>)\n";
|
||||
echo lang('Partitions') . ": <input type='number' name='partitions' class='size" . ($partition_table || !$row["partition_by"] ? " hidden" : "") . "' value='" . h($row["partitions"]) . "'>\n";
|
||||
echo "<table id='partition-table'" . ($partition_table ? "" : " class='hidden'") . ">\n";
|
||||
|
@@ -64,12 +64,13 @@ if (adminer()->homepage()) {
|
||||
echo "<form action='' method='post'>\n";
|
||||
if (support("table")) {
|
||||
echo "<fieldset><legend>" . lang('Search data in tables') . " <span id='selected2'></span></legend><div>";
|
||||
echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'>";
|
||||
echo html_select("op", adminer()->operators(), idx($_POST, "op", JUSH == "elastic" ? "should" : "LIKE %%"));
|
||||
echo " <input type='search' name='query' value='" . h($_POST["query"]) . "'>";
|
||||
echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", "");
|
||||
echo " <input type='submit' name='search' value='" . lang('Search') . "'>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
if ($_POST["search"] && $_POST["query"] != "") {
|
||||
$_GET["where"][0]["op"] = driver()->convertOperator("LIKE %%");
|
||||
$_GET["where"][0]["op"] = $_POST["op"];
|
||||
search_tables();
|
||||
}
|
||||
}
|
||||
@@ -95,8 +96,9 @@ if (adminer()->homepage()) {
|
||||
$id = h("Table-" . $name);
|
||||
echo '<tr><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array("$name", $tables_views, true), "", "", "", $id); // "$name" to check numeric table names
|
||||
echo '<th>' . (support("table") || support("indexes") ? "<a href='" . h(ME) . "table=" . urlencode($name) . "' title='" . lang('Show structure') . "' id='$id'>" . h($name) . '</a>' : h($name));
|
||||
if ($view) {
|
||||
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '" title="' . lang('Alter view') . '">' . (preg_match('~materialized~i', $type) ? lang('Materialized view') : lang('View')) . '</a>';
|
||||
if ($view && !preg_match('~materialized~i', $type)) {
|
||||
$title = lang('View');
|
||||
echo '<td colspan="6">' . (support("view") ? "<a href='" . h(ME) . "view=" . urlencode($name) . "' title='" . lang('Alter view') . "'>$title</a>" : $title);
|
||||
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '" title="' . lang('Select data') . '">?</a>';
|
||||
} else {
|
||||
foreach (
|
||||
@@ -131,6 +133,7 @@ if (adminer()->homepage()) {
|
||||
echo "\n";
|
||||
|
||||
echo "</table>\n";
|
||||
echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
|
||||
echo "</div>\n";
|
||||
if (!information_schema(DB)) {
|
||||
echo "<div class='footer'><div>\n";
|
||||
@@ -147,18 +150,23 @@ if (adminer()->homepage()) {
|
||||
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help(JUSH == "sqlite" ? "'DELETE'" : "'TRUNCATE" . (JUSH == "pgsql" ? "'" : " TABLE'")) . confirm()
|
||||
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n";
|
||||
$databases = (support("scheme") ? adminer()->schemas() : adminer()->databases());
|
||||
echo "</div></fieldset>\n";
|
||||
$script = "";
|
||||
if (count($databases) != 1 && JUSH != "sqlite") {
|
||||
echo "<fieldset><legend>" . lang('Move to other database') . " <span id='selected3'></span></legend><div>";
|
||||
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
|
||||
echo "<p><label>" . lang('Move to other database') . ": ";
|
||||
echo ($databases ? html_select("target", $databases, $db) : '<input name="target" value="' . h($db) . '" autocapitalize="off">');
|
||||
echo "</label> <input type='submit' name='move' value='" . lang('Move') . "'>";
|
||||
echo (support("copy") ? " <input type='submit' name='copy' value='" . lang('Copy') . "'> " . checkbox("overwrite", 1, $_POST["overwrite"], lang('overwrite')) : "");
|
||||
echo "\n";
|
||||
echo "</div></fieldset>\n";
|
||||
$script = " selectCount('selected3', formChecked(this, /^(tables|views)\[/));";
|
||||
}
|
||||
echo "<input type='hidden' name='all' value=''>"; // used by trCheck()
|
||||
echo script("qsl('input').onclick = function () { selectCount('selected', formChecked(this, /^(tables|views)\[/));" . (support("table") ? " selectCount('selected2', formChecked(this, /^tables\[/) || $tables);" : "") . " }");
|
||||
echo script("qsl('input').onclick = function () { selectCount('selected', formChecked(this, /^(tables|views)\[/));"
|
||||
. (support("table") ? " selectCount('selected2', formChecked(this, /^tables\[/) || $tables);" : "")
|
||||
. "$script }"
|
||||
);
|
||||
echo input_token();
|
||||
echo "</div></fieldset>\n";
|
||||
echo "</div></div>\n";
|
||||
}
|
||||
echo "</form>\n";
|
||||
@@ -239,9 +247,5 @@ if (adminer()->homepage()) {
|
||||
}
|
||||
echo '<p class="links"><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n";
|
||||
}
|
||||
|
||||
if ($tables_list) {
|
||||
echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
($server . $username . $password != "" ? $password : ini_get("mysqli.default_pw")),
|
||||
null,
|
||||
(is_numeric($port) ? intval($port) : ini_get("mysqli.default_port")),
|
||||
(is_numeric($port) ? $port : null),
|
||||
(is_numeric($port) ? null : $port),
|
||||
($ssl ? ($ssl['verify'] !== false ? 2048 : 64) : 0) // 2048 - MYSQLI_CLIENT_SSL, 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
|
||||
);
|
||||
$this->options(MYSQLI_OPT_LOCAL_INFILE, false);
|
||||
@@ -258,6 +258,9 @@ if (!defined('Adminer\DRIVER')) {
|
||||
$this->types[lang('Numbers')]["vector"] = 16383;
|
||||
$this->insertFunctions['vector'] = 'string_to_vector';
|
||||
}
|
||||
if (min_version(5.1, '', $connection)) {
|
||||
$this->partitionBy = array("HASH", "LINEAR HASH", "KEY", "LINEAR KEY", "RANGE", "LIST");
|
||||
}
|
||||
if (min_version(5.7, 10.2, $connection)) {
|
||||
$this->generated = array("STORED", "VIRTUAL");
|
||||
}
|
||||
@@ -335,6 +338,17 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
}
|
||||
|
||||
function partitionsInfo(string $table): array {
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
|
||||
$result = $this->conn->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
$return = array();
|
||||
list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row();
|
||||
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
|
||||
$return["partition_names"] = array_keys($partitions);
|
||||
$return["partition_values"] = array_values($partitions);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function hasCStyleEscapes(): bool {
|
||||
static $c_style;
|
||||
if ($c_style === null) {
|
||||
@@ -353,6 +367,10 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexAlgorithms(array $tableStatus): array {
|
||||
return (preg_match('~^(MEMORY|NDB)$~', $tableStatus["Engine"]) ? array("HASH", "BTREE") : array());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -544,6 +562,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
$return[$name]["columns"][] = $row["Column_name"];
|
||||
$return[$name]["lengths"][] = ($row["Index_type"] == "SPATIAL" ? null : $row["Sub_part"]);
|
||||
$return[$name]["descs"][] = null;
|
||||
$return[$name]["algorithm"] = $row["Index_type"];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -677,9 +696,10 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @param list<array{string, list<string>, string}> $fields of [$orig, $process_field, $after]
|
||||
* @param string[] $foreign
|
||||
* @param numeric-string $auto_increment
|
||||
* @param ?Partitions $partitioning null means remove partitioning
|
||||
* @return Result|bool
|
||||
*/
|
||||
function alter_table(string $table, string $name, array $fields, array $foreign, ?string $comment, string $engine, string $collation, string $auto_increment, string $partitioning) {
|
||||
function alter_table(string $table, string $name, array $fields, array $foreign, ?string $comment, string $engine, string $collation, string $auto_increment, ?array $partitioning) {
|
||||
$alter = array();
|
||||
foreach ($fields as $field) {
|
||||
if ($field[1]) {
|
||||
@@ -700,8 +720,28 @@ if (!defined('Adminer\DRIVER')) {
|
||||
. ($collation ? " COLLATE " . q($collation) : "")
|
||||
. ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
|
||||
;
|
||||
|
||||
if ($partitioning) {
|
||||
$partitions = array();
|
||||
if ($partitioning["partition_by"] == 'RANGE' || $partitioning["partition_by"] == 'LIST') {
|
||||
foreach ($partitioning["partition_names"] as $key => $val) {
|
||||
$value = $partitioning["partition_values"][$key];
|
||||
$partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($partitioning["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
|
||||
}
|
||||
}
|
||||
// $partitioning["partition"] can be expression, not only column
|
||||
$status .= "\nPARTITION BY $partitioning[partition_by]($partitioning[partition])";
|
||||
if ($partitions) {
|
||||
$status .= " (" . implode(",", $partitions) . "\n)";
|
||||
} elseif ($partitioning["partitions"]) {
|
||||
$status .= " PARTITIONS " . (+$partitioning["partitions"]);
|
||||
}
|
||||
} elseif ($partitioning === null) {
|
||||
$status .= "\nREMOVE PARTITIONING";
|
||||
}
|
||||
|
||||
if ($table == "") {
|
||||
return queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)$status$partitioning");
|
||||
return queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)$status");
|
||||
}
|
||||
if ($table != $name) {
|
||||
$alter[] = "RENAME TO " . table($name);
|
||||
@@ -709,12 +749,12 @@ if (!defined('Adminer\DRIVER')) {
|
||||
if ($status) {
|
||||
$alter[] = ltrim($status);
|
||||
}
|
||||
return ($alter || $partitioning ? queries("ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter) . $partitioning) : true);
|
||||
return ($alter ? queries("ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter)) : true);
|
||||
}
|
||||
|
||||
/** Run commands to alter indexes
|
||||
* @param string $table escaped table name
|
||||
* @param list<array{string, string, 'DROP'|list<string>}> $alter of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
|
||||
* @param list<array{string, string, 'DROP'|list<string>, 3?: string, 4?: string}> $alter of ["index type", "name", ["column definition", ...], "algorithm", "condition"] or ["index type", "name", "DROP"]
|
||||
* @return Result|bool
|
||||
*/
|
||||
function alter_indexes(string $table, $alter) {
|
||||
@@ -856,7 +896,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
|
||||
$enum = driver()->enumLength;
|
||||
$type_pattern = "((" . implode("|", array_merge(array_keys(driver()->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum)++)\\))?"
|
||||
. "\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
|
||||
. "\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?(?:\\s*COLLATE\\s*['\"]?([^'\"\\s,]+)['\"]?)?"; //! store COLLATE
|
||||
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : driver()->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
|
||||
$create = get_val("SHOW CREATE $type " . idf_escape($name), 2);
|
||||
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
|
||||
@@ -888,7 +928,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return list<string[]> ["SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ]
|
||||
*/
|
||||
function routines(): array {
|
||||
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
|
||||
return get_rows("SELECT SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
|
||||
}
|
||||
|
||||
/** Get list of available routine languages
|
||||
@@ -1012,18 +1052,26 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
|
||||
/** Check whether a feature is supported
|
||||
* @param literal-string $feature "check|comment|copy|database|descidx|drop_col|dump|event|indexes|kill|materializedview|partitioning|privileges|procedure|processlist|routine|scheme|sequence|status|table|trigger|type|variables|view|view_trigger"
|
||||
* @param literal-string $feature check|comment|columns|copy|database|descidx|drop_col|dump|event|indexes|kill|materializedview
|
||||
* |move_col|privileges|procedure|processlist|routine|scheme|sequence|sql|status|table|trigger|type|variables|view|view_trigger
|
||||
*/
|
||||
function support(string $feature): bool {
|
||||
return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning")) . (min_version('8.0.16', '10.2.1') ? "" : "|check") . "~", $feature);
|
||||
return preg_match(
|
||||
'~^(comment|columns|copy|database|drop_col|dump|indexes|kill|privileges|move_col|procedure|processlist|routine|sql|status|table|trigger|variables|view'
|
||||
. (min_version(5.1) ? '|event' : '')
|
||||
. (min_version(8) ? '|descidx' : '')
|
||||
. (min_version('8.0.16', '10.2.1') ? '|check' : '')
|
||||
. ')$~',
|
||||
$feature
|
||||
);
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
* @param numeric-string $val
|
||||
* @param numeric-string $id
|
||||
* @return Result|bool
|
||||
*/
|
||||
function kill_process(string $val) {
|
||||
return queries("KILL " . number($val));
|
||||
function kill_process(string $id) {
|
||||
return queries("KILL " . number($id));
|
||||
}
|
||||
|
||||
/** Return query to get connection ID */
|
||||
|
@@ -60,6 +60,10 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function timeout(int $ms): bool {
|
||||
return oci_set_call_timeout($this->link, $ms);
|
||||
}
|
||||
}
|
||||
|
||||
class Result {
|
||||
@@ -391,7 +395,6 @@ ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row
|
||||
$queries = array();
|
||||
foreach ($alter as $val) {
|
||||
if ($val[0] != "INDEX") {
|
||||
//! descending UNIQUE indexes results in syntax error
|
||||
$val[2] = preg_replace('~ DESC$~', '', $val[2]);
|
||||
$create = ($val[2] == "DROP"
|
||||
? "\nDROP CONSTRAINT " . idf_escape($val[1])
|
||||
|
@@ -127,8 +127,9 @@ if (isset($_GET["pgsql"])) {
|
||||
$return = new \stdClass;
|
||||
$return->orgtable = pg_field_table($this->result, $column);
|
||||
$return->name = pg_field_name($this->result, $column);
|
||||
$return->type = pg_field_type($this->result, $column); //! map to MySQL numbers
|
||||
$return->charsetnr = ($return->type == "bytea" ? 63 : 0); // 63 - binary
|
||||
$type = pg_field_type($this->result, $column);
|
||||
$return->type = (preg_match(number_type(), $type) ? 0 : 15);
|
||||
$return->charsetnr = ($type == "bytea" ? 63 : 0); // 63 - binary
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -203,10 +204,12 @@ if (isset($_GET["pgsql"])) {
|
||||
static $extensions = array("PgSQL", "PDO_PgSQL");
|
||||
static $jush = "pgsql";
|
||||
|
||||
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
|
||||
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT ILIKE", "NOT IN", "IS NOT NULL", "SQL"); //! SQL - same-site CSRF
|
||||
public $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
|
||||
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
|
||||
public string $nsOid = "(SELECT oid FROM pg_namespace WHERE nspname = current_schema())";
|
||||
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
$connection = parent::connect($server, $username, $password);
|
||||
if (is_string($connection)) {
|
||||
@@ -252,6 +255,10 @@ if (isset($_GET["pgsql"])) {
|
||||
if (min_version(12, 0, $connection)) {
|
||||
$this->generated = array("STORED");
|
||||
}
|
||||
$this->partitionBy = array("RANGE", "LIST");
|
||||
if (!$connection->flavor) {
|
||||
$this->partitionBy[] = "HASH";
|
||||
}
|
||||
}
|
||||
|
||||
function enumLength(array $field) {
|
||||
@@ -324,6 +331,39 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
function inheritsFrom(string $table): array {
|
||||
return get_vals("SELECT relname FROM pg_class JOIN pg_inherits ON inhparent = oid WHERE inhrelid = " . $this->tableOid($table) . " ORDER BY 1");
|
||||
}
|
||||
|
||||
function inheritedTables(string $table): array {
|
||||
return get_vals("SELECT relname FROM pg_inherits JOIN pg_class ON inhrelid = oid WHERE inhparent = " . $this->tableOid($table) . " ORDER BY 1");
|
||||
}
|
||||
|
||||
function partitionsInfo(string $table): array {
|
||||
$row = (min_version(10) ? connection()->query("SELECT * FROM pg_partitioned_table WHERE partrelid = " . $this->tableOid($table))->fetch_assoc() : null);
|
||||
if ($row) {
|
||||
$attrs = get_vals("SELECT attname FROM pg_attribute WHERE attrelid = $row[partrelid] AND attnum IN (" . str_replace(" ", ", ", $row["partattrs"]) . ")"); //! ordering
|
||||
$by = array('h' => 'HASH', 'l' => 'LIST', 'r' => 'RANGE');
|
||||
return array(
|
||||
"partition_by" => $by[$row["partstrat"]],
|
||||
"partition" => implode(", ", array_map('Adminer\idf_escape', $attrs)),
|
||||
);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
function tableOid(string $table): string {
|
||||
return "(SELECT oid FROM pg_class WHERE relnamespace = $this->nsOid AND relname = " . q($table) . " AND relkind IN ('r', 'm', 'v', 'f', 'p'))";
|
||||
}
|
||||
|
||||
function indexAlgorithms(array $tableStatus): array {
|
||||
static $return = array();
|
||||
if (!$return) {
|
||||
$return = get_vals("SELECT amname FROM pg_am" . (min_version(9.6) ? " WHERE amtype = 'i'" : "") . " ORDER BY amname = 'btree' DESC, amname");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function supportsIndex(array $table_status): bool {
|
||||
// returns true for "materialized view"
|
||||
return $table_status["Engine"] != "view";
|
||||
@@ -406,18 +446,19 @@ ORDER BY 1";
|
||||
$return = array();
|
||||
foreach (
|
||||
get_rows("SELECT
|
||||
c.relname AS \"Name\",
|
||||
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\"" . ($has_size ? ",
|
||||
relname AS \"Name\",
|
||||
CASE relkind WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' ELSE 'table' END AS \"Engine\"" . ($has_size ? ",
|
||||
pg_table_size(c.oid) AS \"Data_length\",
|
||||
pg_indexes_size(c.oid) AS \"Index_length\"" : "") . ",
|
||||
obj_description(c.oid, 'pg_class') AS \"Comment\",
|
||||
" . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
|
||||
c.reltuples as \"Rows\",
|
||||
n.nspname
|
||||
" . (min_version(12) ? "''" : "CASE WHEN relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
|
||||
reltuples AS \"Rows\",
|
||||
" . (min_version(10) ? "relispartition::int AS partition," : "") . "
|
||||
current_schema() AS nspname
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON(n.nspname = current_schema() AND n.oid = c.relnamespace)
|
||||
WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
|
||||
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")) as $row //! Index_length, Auto_increment
|
||||
AND relnamespace = " . driver()->nsOid . "
|
||||
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")) as $row //! Auto_increment
|
||||
) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
@@ -444,15 +485,12 @@ WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
|
||||
format_type(a.atttypid, a.atttypmod) AS full_type,
|
||||
pg_get_expr(d.adbin, d.adrelid) AS default,
|
||||
a.attnotnull::int,
|
||||
col_description(c.oid, a.attnum) AS comment" . (min_version(10) ? ",
|
||||
col_description(a.attrelid, a.attnum) AS comment" . (min_version(10) ? ",
|
||||
a.attidentity" . (min_version(12) ? ",
|
||||
a.attgenerated" : "") : "") . "
|
||||
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 = " . q($table) . "
|
||||
AND n.nspname = current_schema()
|
||||
FROM pg_attribute a
|
||||
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
||||
WHERE a.attrelid = " . driver()->tableOid($table) . "
|
||||
AND NOT a.attisdropped
|
||||
AND a.attnum > 0
|
||||
ORDER BY a.attnum") as $row
|
||||
@@ -488,25 +526,28 @@ ORDER BY a.attnum") as $row
|
||||
function indexes($table, $connection2 = null) {
|
||||
$connection2 = connection($connection2);
|
||||
$return = array();
|
||||
$table_oid = get_val("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($table), 0, $connection2);
|
||||
$table_oid = driver()->tableOid($table);
|
||||
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
|
||||
foreach (
|
||||
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial
|
||||
FROM pg_index i, pg_class ci
|
||||
WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid
|
||||
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, amname, pg_get_expr(indpred, indrelid, true) AS partial, pg_get_expr(indexprs, indrelid) AS indexpr
|
||||
FROM pg_index
|
||||
JOIN pg_class ON indexrelid = oid
|
||||
JOIN pg_am ON pg_am.oid = pg_class.relam
|
||||
WHERE indrelid = $table_oid
|
||||
ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row
|
||||
) {
|
||||
$relname = $row["relname"];
|
||||
$return[$relname]["type"] = ($row["indispartial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
|
||||
$return[$relname]["type"] = ($row["partial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
|
||||
$return[$relname]["columns"] = array();
|
||||
$return[$relname]["descs"] = array();
|
||||
if ($row["indkey"]) {
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = (intval($indoption) & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
}
|
||||
$return[$relname]["algorithm"] = $row["amname"];
|
||||
$return[$relname]["partial"] = $row["partial"];
|
||||
$indexpr = preg_split('~(?<=\)), (?=\()~', $row["indexpr"]); //! '), (' used in expression
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = ($indkey ? $columns[$indkey] : array_shift($indexpr));
|
||||
}
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = (intval($indoption) & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
}
|
||||
$return[$relname]["lengths"] = array();
|
||||
}
|
||||
@@ -518,7 +559,7 @@ ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row
|
||||
foreach (
|
||||
get_rows("SELECT conname, condeferrable::int AS deferrable, pg_get_constraintdef(oid) AS definition
|
||||
FROM pg_constraint
|
||||
WHERE conrelid = (SELECT pc.oid FROM pg_class AS pc INNER JOIN pg_namespace AS pn ON (pn.oid = pc.relnamespace) WHERE pc.relname = " . q($table) . " AND pn.nspname = current_schema())
|
||||
WHERE conrelid = " . driver()->tableOid($table) . "
|
||||
AND contype = 'f'::char
|
||||
ORDER BY conkey, conname") as $row
|
||||
) {
|
||||
@@ -538,7 +579,7 @@ ORDER BY conkey, conname") as $row
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
return array("select" => trim(get_val("SELECT pg_get_viewdef(" . get_val("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
|
||||
return array("select" => trim(get_val("SELECT pg_get_viewdef(" . driver()->tableOid($name) . ")")));
|
||||
}
|
||||
|
||||
function collations() {
|
||||
@@ -621,7 +662,31 @@ ORDER BY conkey, conname") as $row
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
if ($table == "") {
|
||||
array_unshift($queries, "CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)");
|
||||
$status = "";
|
||||
if ($partitioning) {
|
||||
$cockroach = (connection()->flavor == 'cockroach');
|
||||
$status = " PARTITION BY $partitioning[partition_by]($partitioning[partition])";
|
||||
if ($partitioning["partition_by"] == 'HASH') {
|
||||
$partitions = +$partitioning["partitions"];
|
||||
for ($i=0; $i < $partitions; $i++) {
|
||||
$queries[] = "CREATE TABLE " . idf_escape($name . "_$i") . " PARTITION OF " . idf_escape($name) . " FOR VALUES WITH (MODULUS $partitions, REMAINDER $i)";
|
||||
}
|
||||
} else {
|
||||
$prev = "MINVALUE";
|
||||
foreach ($partitioning["partition_names"] as $i => $val) {
|
||||
$value = $partitioning["partition_values"][$i];
|
||||
$partition = " VALUES " . ($partitioning["partition_by"] == 'LIST' ? "IN ($value)" : "FROM ($prev) TO ($value)");
|
||||
if ($cockroach) {
|
||||
$status .= ($i ? "," : " (") . "\n PARTITION " . (preg_match('~^DEFAULT$~i', $val) ? $val : idf_escape($val)) . "$partition";
|
||||
} else {
|
||||
$queries[] = "CREATE TABLE " . idf_escape($name . "_$val") . " PARTITION OF " . idf_escape($name) . " FOR$partition";
|
||||
}
|
||||
$prev = $value;
|
||||
}
|
||||
$status .= ($cockroach ? "\n)" : "");
|
||||
}
|
||||
}
|
||||
array_unshift($queries, "CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)$status");
|
||||
} elseif ($alter) {
|
||||
array_unshift($queries, "ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter));
|
||||
}
|
||||
@@ -648,7 +713,7 @@ ORDER BY conkey, conname") as $row
|
||||
$queries = array();
|
||||
foreach ($alter as $val) {
|
||||
if ($val[0] != "INDEX") {
|
||||
//! descending UNIQUE indexes results in syntax error
|
||||
//! descending UNIQUE indexes result in syntax error
|
||||
$create[] = ($val[2] == "DROP"
|
||||
? "\nDROP CONSTRAINT " . idf_escape($val[1])
|
||||
: "\nADD" . ($val[1] != "" ? " CONSTRAINT " . idf_escape($val[1]) : "") . " $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "") . "(" . implode(", ", $val[2]) . ")"
|
||||
@@ -656,7 +721,12 @@ ORDER BY conkey, conname") as $row
|
||||
} elseif ($val[2] == "DROP") {
|
||||
$drop[] = idf_escape($val[1]);
|
||||
} else {
|
||||
$queries[] = "CREATE INDEX " . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table) . " (" . implode(", ", $val[2]) . ")";
|
||||
$queries[] = "CREATE INDEX " . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_"))
|
||||
. " ON " . table($table)
|
||||
. ($val[3] ? " USING $val[3]" : "")
|
||||
. " (" . implode(", ", $val[2]) . ")"
|
||||
. ($val[4] ? " WHERE $val[4]" : "")
|
||||
;
|
||||
}
|
||||
}
|
||||
if ($create) {
|
||||
@@ -798,7 +868,7 @@ ORDER BY SPECIFIC_NAME');
|
||||
return get_key_vals(
|
||||
"SELECT oid, typname
|
||||
FROM pg_type
|
||||
WHERE typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema())
|
||||
WHERE typnamespace = " . driver()->nsOid . "
|
||||
AND typtype IN ('b','d','e')
|
||||
AND typelem = 0"
|
||||
);
|
||||
@@ -899,8 +969,16 @@ AND typelem = 0"
|
||||
foreach (driver()->checkConstraints($table) as $conname => $consrc) {
|
||||
$return_parts[] = "CONSTRAINT " . idf_escape($conname) . " CHECK $consrc";
|
||||
}
|
||||
$return .= implode(",\n ", $return_parts) . "\n)";
|
||||
|
||||
$return .= implode(",\n ", $return_parts) . "\n) WITH (oids = " . ($status['Oid'] ? 'true' : 'false') . ");";
|
||||
$partition = driver()->partitionsInfo($status['Name']);
|
||||
if ($partition) {
|
||||
$return .= "\nPARTITION BY $partition[partition_by]($partition[partition])";
|
||||
}
|
||||
//! parse pg_class.relpartbound to create PARTITION OF
|
||||
//! don't insert partitioned data twice
|
||||
|
||||
$return .= "\nWITH (oids = " . ($status['Oid'] ? 'true' : 'false') . ");";
|
||||
|
||||
// comments for table & fields
|
||||
if ($status['Comment']) {
|
||||
@@ -955,9 +1033,11 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|' . (min_version(11) ? 'procedure|' : '') . 'routine|sequence|trigger|type|variables|drop_col'
|
||||
return preg_match('~^(check|columns|comment|database|drop_col|dump|descidx|indexes|kill|partial_indexes|routine|scheme|sequence|sql|table|trigger|type|variables|view'
|
||||
. (min_version(9.3) ? '|materializedview' : '')
|
||||
. (min_version(11) ? '|procedure' : '')
|
||||
. (connection()->flavor == 'cockroach' ? '' : '|processlist') // https://github.com/cockroachdb/cockroach/issues/24745
|
||||
. '|kill|dump)$~', $feature)
|
||||
. ')$~', $feature)
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -85,6 +85,10 @@ class Adminer {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/** Called after connecting and selecting a database */
|
||||
function afterConnect(): void {
|
||||
}
|
||||
|
||||
/** Headers to send before HTML output */
|
||||
function headers(): void {
|
||||
}
|
||||
@@ -108,15 +112,24 @@ class Adminer {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Print extra classes in <body class>; must start with a space */
|
||||
function bodyClass(): void {
|
||||
echo " adminer";
|
||||
}
|
||||
|
||||
/** Get URLs of the CSS files
|
||||
* @return list<string>
|
||||
* @return string[] key is URL, value is either 'light' (supports only light color scheme), 'dark' or '' (both)
|
||||
*/
|
||||
function css(): array {
|
||||
$return = array();
|
||||
foreach (array("", "-dark") as $mode) {
|
||||
$filename = "adminer$mode.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = "$filename?v=" . crc32(file_get_contents($filename));
|
||||
$file = file_get_contents($filename);
|
||||
$return["$filename?v=" . crc32($file)] = ($mode
|
||||
? "dark"
|
||||
: (preg_match('~prefers-color-scheme:\s*dark~', $file) ? '' : 'light')
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
@@ -179,6 +192,7 @@ class Adminer {
|
||||
* @param ?string $set new item options, NULL for no new item
|
||||
*/
|
||||
function selectLinks(array $tableStatus, ?string $set = ""): void {
|
||||
$name = $tableStatus["Name"];
|
||||
echo '<p class="links">';
|
||||
$links = array("select" => lang('Select data'));
|
||||
if (support("table") || support("indexes")) {
|
||||
@@ -187,16 +201,15 @@ class Adminer {
|
||||
$is_view = false;
|
||||
if (support("table")) {
|
||||
$is_view = is_view($tableStatus);
|
||||
if ($is_view) {
|
||||
$links["view"] = lang('Alter view');
|
||||
} else {
|
||||
if (!$is_view) {
|
||||
$links["create"] = lang('Alter table');
|
||||
} elseif (support("view")) {
|
||||
$links["view"] = lang('Alter view');
|
||||
}
|
||||
}
|
||||
if ($set !== null) {
|
||||
$links["edit"] = lang('New item');
|
||||
}
|
||||
$name = $tableStatus["Name"];
|
||||
foreach ($links as $key => $val) {
|
||||
echo " <a href='" . h(ME) . "$key=" . urlencode($name) . ($key == "edit" ? $set : "") . "'" . bold(isset($_GET[$key])) . ">$val</a>";
|
||||
}
|
||||
@@ -343,9 +356,15 @@ class Adminer {
|
||||
|
||||
/** Print list of indexes on table in tabular format
|
||||
* @param Index[] $indexes
|
||||
* @param TableStatus $tableStatus
|
||||
*/
|
||||
function tableIndexesPrint(array $indexes): void {
|
||||
function tableIndexesPrint(array $indexes, array $tableStatus): void {
|
||||
$partial = false;
|
||||
foreach ($indexes as $name => $index) {
|
||||
$partial |= !!$index["partial"];
|
||||
}
|
||||
echo "<table>\n";
|
||||
$default_algorithm = first(driver()->indexAlgorithms($tableStatus));
|
||||
foreach ($indexes as $name => $index) {
|
||||
ksort($index["columns"]); // enforce correct columns order
|
||||
$print = array();
|
||||
@@ -355,7 +374,14 @@ class Adminer {
|
||||
. ($index["descs"][$key] ? " DESC" : "")
|
||||
;
|
||||
}
|
||||
echo "<tr title='" . h($name) . "'><th>$index[type]<td>" . implode(", ", $print) . "\n";
|
||||
|
||||
echo "<tr title='" . h($name) . "'>";
|
||||
echo "<th>$index[type]" . ($default_algorithm && $index['algorithm'] != $default_algorithm ? " ($index[algorithm])" : "");
|
||||
echo "<td>" . implode(", ", $print);
|
||||
if ($partial) {
|
||||
echo "<td>" . ($index['partial'] ? "<code class='jush-" . JUSH . "'>WHERE " . h($index['partial']) : "");
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
@@ -395,7 +421,7 @@ class Adminer {
|
||||
foreach ($indexes as $i => $index) {
|
||||
if ($index["type"] == "FULLTEXT") {
|
||||
echo "<div>(<i>" . implode("</i>, <i>", array_map('Adminer\h', $index["columns"])) . "</i>) AGAINST";
|
||||
echo " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>";
|
||||
echo " <input type='search' name='fulltext[$i]' value='" . h(idx($_GET["fulltext"], $i)) . "'>";
|
||||
echo script("qsl('input').oninput = selectFieldChange;", "");
|
||||
echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL");
|
||||
echo "</div>\n";
|
||||
@@ -533,7 +559,7 @@ class Adminer {
|
||||
function selectSearchProcess(array $fields, array $indexes): array {
|
||||
$return = array();
|
||||
foreach ($indexes as $i => $index) {
|
||||
if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") {
|
||||
if ($index["type"] == "FULLTEXT" && idx($_GET["fulltext"], $i) != "") {
|
||||
$return[] = "MATCH (" . implode(", ", array_map('Adminer\idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
|
||||
}
|
||||
}
|
||||
@@ -728,7 +754,7 @@ class Adminer {
|
||||
} elseif (preg_match('~^([+-]|\|\|)$~', $function)) {
|
||||
$return = idf_escape($name) . " $function $return";
|
||||
} elseif (preg_match('~^[+-] interval$~', $function)) {
|
||||
$return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $return);
|
||||
$return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) && JUSH != "pgsql" ? $value : $return);
|
||||
} elseif (preg_match('~^(addtime|subtime|concat)$~', $function)) {
|
||||
$return = "$function(" . idf_escape($name) . ", $return)";
|
||||
} elseif (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) {
|
||||
@@ -940,6 +966,12 @@ class Adminer {
|
||||
echo (support("scheme") ? "<a href='" . h(ME) . "scheme='>" . ($_GET["ns"] != "" ? lang('Alter schema') : lang('Create schema')) . "</a>\n" : "");
|
||||
echo ($_GET["ns"] !== "" ? '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n" : "");
|
||||
echo (support("privileges") ? "<a href='" . h(ME) . "privileges='>" . lang('Privileges') . "</a>\n" : "");
|
||||
if ($_GET["ns"] !== "") {
|
||||
echo (support("routine") ? "<a href='#routines'>" . lang('Routines') . "</a>\n" : "");
|
||||
echo (support("sequence") ? "<a href='#sequences'>" . lang('Sequences') . "</a>\n" : "");
|
||||
echo (support("type") ? "<a href='#user-types'>" . lang('User types') . "</a>\n" : "");
|
||||
echo (support("event") ? "<a href='#events'>" . lang('Events') . "</a>\n" : "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -962,7 +994,7 @@ class Adminer {
|
||||
if ($password !== null) {
|
||||
$dbs = $_SESSION["db"][$vendor][$server][$username];
|
||||
foreach (($dbs ? array_keys($dbs) : array("")) as $db) {
|
||||
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($name) " . h($username . ($server != "" ? "@" . adminer()->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($name) " . h("$username@" . ($server != "" ? adminer()->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1020,7 +1052,15 @@ class Adminer {
|
||||
foreach ($tables as $table => $type) {
|
||||
$links[] = preg_quote($table, '/');
|
||||
}
|
||||
echo "var jushLinks = { " . JUSH . ": [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
|
||||
echo "var jushLinks = { " . JUSH . ":";
|
||||
json_row(js_escape(ME) . (support("table") ? "table" : "select") . '=$&', '/\b(' . implode('|', $links) . ')\b/g', false);
|
||||
if (support('routine')) {
|
||||
foreach (routines() as $row) {
|
||||
json_row(js_escape(ME) . 'function=' . urlencode($row["SPECIFIC_NAME"]) . '&name=$&', '/\b' . preg_quote($row["ROUTINE_NAME"], '/') . '(?=["`]?\()/g', false);
|
||||
}
|
||||
}
|
||||
json_row('');
|
||||
echo "};\n";
|
||||
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
|
||||
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
|
||||
}
|
||||
@@ -1078,7 +1118,7 @@ class Adminer {
|
||||
foreach ($tables as $table => $status) {
|
||||
$table = "$table"; // do not highlight "0" as active everywhere
|
||||
$name = adminer()->tableName($status);
|
||||
if ($name != "") {
|
||||
if ($name != "" && !$status["partition"]) {
|
||||
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"'
|
||||
. bold($_GET["select"] == $table || $_GET["edit"] == $table, "select")
|
||||
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> "
|
||||
@@ -1093,4 +1133,19 @@ class Adminer {
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
|
||||
/** Get process list
|
||||
* @return list<string[]> [$row]
|
||||
*/
|
||||
function processList(): array {
|
||||
return process_list();
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
* @param numeric-string $id
|
||||
* @return Result|bool
|
||||
*/
|
||||
function killProcess(string $id) {
|
||||
return kill_process($id);
|
||||
}
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
|
||||
|
||||
define('Adminer\JUSH', Driver::$jush);
|
||||
define('Adminer\SERVER', $_GET[DRIVER]); // read from pgsql=localhost, '' means default server, null means no server
|
||||
define('Adminer\DB', $_GET["db"]); // for the sake of speed and size
|
||||
define('Adminer\DB', "$_GET[db]"); // for the sake of speed and size
|
||||
define(
|
||||
'Adminer\ME',
|
||||
preg_replace('~\?.*~', '', relative_uri()) . '?'
|
||||
@@ -108,3 +108,5 @@ include "../adminer/include/xxtea.inc.php";
|
||||
include "../adminer/include/auth.inc.php";
|
||||
include "./include/editing.inc.php";
|
||||
include "./include/connect.inc.php";
|
||||
|
||||
adminer()->afterConnect();
|
||||
|
@@ -27,17 +27,13 @@ function page_header(string $title, string $error = "", $breadcrumb = array(), s
|
||||
<title><?php echo $title_page; ?></title>
|
||||
<link rel="stylesheet" href="../adminer/static/default.css">
|
||||
<?php
|
||||
|
||||
$css = adminer()->css();
|
||||
$has_light = false;
|
||||
$has_dark = false;
|
||||
foreach ($css as $filename) {
|
||||
if (strpos($filename, "adminer.css") !== false) {
|
||||
$has_light = true;
|
||||
}
|
||||
if (strpos($filename, "adminer-dark.css") !== false) {
|
||||
$has_dark = true;
|
||||
}
|
||||
if (is_int(key($css))) { // legacy return value
|
||||
$css = array_fill_keys($css, 'light');
|
||||
}
|
||||
$has_light = in_array('light', $css) || in_array('', $css);
|
||||
$has_dark = in_array('dark', $css) || in_array('', $css);
|
||||
$dark = ($has_light
|
||||
? ($has_dark ? null : false) // both styles - autoswitching, only adminer.css - light
|
||||
: ($has_dark ?: null) // only adminer-dark.css - dark, neither - autoswitching
|
||||
@@ -47,6 +43,7 @@ function page_header(string $title, string $error = "", $breadcrumb = array(), s
|
||||
echo "<link rel='stylesheet'" . ($dark ? "" : $media) . " href='../adminer/static/dark.css'>\n";
|
||||
}
|
||||
echo "<meta name='color-scheme' content='" . ($dark === null ? "light dark" : ($dark ? "dark" : "light")) . "'>\n";
|
||||
|
||||
// this is matched by compile.php
|
||||
echo script_src("../adminer/static/functions.js");
|
||||
echo script_src("static/editing.js");
|
||||
@@ -54,10 +51,16 @@ function page_header(string $title, string $error = "", $breadcrumb = array(), s
|
||||
echo "<link rel='icon' href='data:image/gif;base64,R0lGODlhEAAQAJEAAAQCBPz+/PwCBAROZCH5BAEAAAAALAAAAAAQABAAAAI2hI+pGO1rmghihiUdvUBnZ3XBQA7f05mOak1RWXrNq5nQWHMKvuoJ37BhVEEfYxQzHjWQ5qIAADs='>\n";
|
||||
echo "<link rel='apple-touch-icon' href='../adminer/static/logo.png'>\n";
|
||||
}
|
||||
foreach ($css as $val) {
|
||||
echo "<link rel='stylesheet'" . (preg_match('~-dark\.~', $val) && !$dark ? $media : "") . " href='" . h($val) . "'>\n";
|
||||
foreach ($css as $url => $mode) {
|
||||
$attrs = ($mode == 'dark' && !$dark
|
||||
? $media
|
||||
: ($mode == 'light' && $has_dark ? " media='(prefers-color-scheme: light)'" : "")
|
||||
);
|
||||
echo "<link rel='stylesheet'$attrs href='" . h($url) . "'>\n";
|
||||
}
|
||||
echo "\n<body class='" . lang('ltr') . " nojs'>\n";
|
||||
echo "\n<body class='" . lang('ltr') . " nojs";
|
||||
adminer()->bodyClass();
|
||||
echo "'>\n";
|
||||
$filename = get_temp_dir() . "/adminer.version";
|
||||
if (!$_COOKIE["adminer_version"] && function_exists('openssl_verify') && file_exists($filename) && filemtime($filename) + 86400 > time()) { // 86400 - 1 day in seconds
|
||||
$version = unserialize(file_get_contents($filename));
|
||||
|
@@ -7,7 +7,7 @@ function add_driver(string $id, string $name): void {
|
||||
}
|
||||
|
||||
/** Get driver name */
|
||||
function get_driver(string $id): string {
|
||||
function get_driver(string $id): ?string {
|
||||
return SqlDriver::$drivers[$id];
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ abstract class SqlDriver {
|
||||
/** @var list<string> */ public $functions = array(); // functions used in select
|
||||
/** @var list<string> */ public $grouping = array(); // grouping functions used in select
|
||||
/** @var string */ public $onActions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; // used in foreign_keys()
|
||||
/** @var list<string> */ public $partitionBy = array(); // supported partitioning types
|
||||
/** @var string */ public $inout = "IN|OUT|INOUT"; // used in routines
|
||||
/** @var string */ public $enumLength = "'(?:''|[^'\\\\]|\\\\.)*'"; // regular expression for parsing enum lengths
|
||||
/** @var list<string> */ public $generated = array(); // allowed types of generated columns
|
||||
@@ -188,11 +189,6 @@ abstract class SqlDriver {
|
||||
return $idf;
|
||||
}
|
||||
|
||||
/** Convert operator so it can be used in search */
|
||||
function convertOperator(string $operator): string {
|
||||
return $operator;
|
||||
}
|
||||
|
||||
/** Convert value returned by database to actual value
|
||||
* @param Field $field
|
||||
*/
|
||||
@@ -217,6 +213,27 @@ abstract class SqlDriver {
|
||||
function tableHelp(string $name, bool $is_view = false) {
|
||||
}
|
||||
|
||||
/** Get tables this table inherits from
|
||||
* @return list<string>
|
||||
*/
|
||||
function inheritsFrom(string $table): array {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Get inherited tables
|
||||
* @return list<string>
|
||||
*/
|
||||
function inheritedTables(string $table): array {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Get partitions info
|
||||
* @return Partitions
|
||||
*/
|
||||
function partitionsInfo(string $table): array {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Check if C-style escapes are supported */
|
||||
function hasCStyleEscapes(): bool {
|
||||
return false;
|
||||
@@ -236,6 +253,14 @@ abstract class SqlDriver {
|
||||
return !is_view($table_status);
|
||||
}
|
||||
|
||||
/** Return list of supported index algorithms, first one is default
|
||||
* @param TableStatus $tableStatus
|
||||
* @return list<string>
|
||||
*/
|
||||
function indexAlgorithms(array $tableStatus): array {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Get defined check constraints
|
||||
* @return string[] [$name => $clause]
|
||||
*/
|
||||
@@ -254,14 +279,16 @@ AND CHECK_CLAUSE NOT LIKE '% IS NOT NULL'", $this->conn); // ignore default IS N
|
||||
*/
|
||||
function allFields(): array {
|
||||
$return = array();
|
||||
foreach (
|
||||
get_rows("SELECT TABLE_NAME AS tab, COLUMN_NAME AS field, IS_NULLABLE AS nullable, DATA_TYPE AS type, CHARACTER_MAXIMUM_LENGTH AS length" . (JUSH == 'sql' ? ", COLUMN_KEY = 'PRI' AS `primary`" : "") . "
|
||||
if (DB != "") {
|
||||
foreach (
|
||||
get_rows("SELECT TABLE_NAME AS tab, COLUMN_NAME AS field, IS_NULLABLE AS nullable, DATA_TYPE AS type, CHARACTER_MAXIMUM_LENGTH AS length" . (JUSH == 'sql' ? ", COLUMN_KEY = 'PRI' AS `primary`" : "") . "
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = " . q($_GET["ns"] != "" ? $_GET["ns"] : DB) . "
|
||||
ORDER BY TABLE_NAME, ORDINAL_POSITION", $this->conn) as $row
|
||||
) {
|
||||
$row["null"] = ($row["nullable"] == "YES");
|
||||
$return[$row["tab"]][] = $row;
|
||||
) {
|
||||
$row["null"] = ($row["nullable"] == "YES");
|
||||
$return[$row["tab"]][] = $row;
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
@@ -150,13 +150,13 @@ function select_input(string $attrs, array $options, ?string $value = "", string
|
||||
* @param string $key or "" to close the object
|
||||
* @param string|int $val
|
||||
*/
|
||||
function json_row(string $key, $val = null): void {
|
||||
function json_row(string $key, $val = null, bool $escape = true): void {
|
||||
static $first = true;
|
||||
if ($first) {
|
||||
echo "{";
|
||||
}
|
||||
if ($key != "") {
|
||||
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
|
||||
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? ($escape ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : $val) : 'null');
|
||||
$first = false;
|
||||
} else {
|
||||
echo "\n}\n";
|
||||
@@ -201,20 +201,6 @@ function edit_type(string $key, array $field, array $collations, array $foreign_
|
||||
);
|
||||
}
|
||||
|
||||
/** Get partition info
|
||||
* @return array{partition_by:string, partition:string, partitions:string, partition_names:list<string>, partition_values:list<string>}
|
||||
*/
|
||||
function get_partitions_info(string $table): array {
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
|
||||
$result = connection()->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
$return = array();
|
||||
list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row();
|
||||
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
|
||||
$return["partition_names"] = array_keys($partitions);
|
||||
$return["partition_values"] = array_values($partitions);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Filter length value including enums */
|
||||
function process_length(?string $length): string {
|
||||
$enum_length = driver()->enumLength;
|
||||
|
@@ -264,9 +264,10 @@ function where(array $where, array $fields = array()): string {
|
||||
$field_type = $field["type"];
|
||||
$return[] = $column
|
||||
. (JUSH == "sql" && $field_type == "json" ? " = CAST(" . q($val) . " AS JSON)"
|
||||
: (JUSH == "pgsql" && preg_match('~^json~', $field_type) ? "::jsonb = " . q($val) . "::jsonb"
|
||||
: (JUSH == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
|
||||
: (JUSH == "mssql" && strpos($field_type, "datetime") === false ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text but it does not work with datetime
|
||||
: " = " . unconvert_field($field, q($val)))))
|
||||
: " = " . unconvert_field($field, q($val))))))
|
||||
; //! enum and set
|
||||
if (JUSH == "sql" && preg_match('~char|text~', $field_type) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
|
||||
$return[] = "$column = " . q($val) . " COLLATE " . charset(connection()) . "_bin";
|
||||
@@ -291,7 +292,7 @@ function where_check(string $val, array $fields = array()): string {
|
||||
* @param int $i condition order
|
||||
* @param string $column column identifier
|
||||
*/
|
||||
function where_link(int $i, string $column, string $value, string $operator = "="): string {
|
||||
function where_link(int $i, string $column, ?string $value, string $operator = "="): string {
|
||||
return "&where%5B$i%5D%5Bcol%5D=" . urlencode($column) . "&where%5B$i%5D%5Bop%5D=" . urlencode(($value !== null ? $operator : "IS NULL")) . "&where%5B$i%5D%5Bval%5D=" . urlencode($value);
|
||||
}
|
||||
|
||||
@@ -337,11 +338,11 @@ function get_settings(string $cookie): array {
|
||||
}
|
||||
|
||||
/** Get setting stored in a cookie
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
function get_setting(string $key, string $cookie = "adminer_settings") {
|
||||
$settings = get_settings($cookie);
|
||||
return $settings[$key];
|
||||
function get_setting(string $key, string $cookie = "adminer_settings", $default = null) {
|
||||
return idx(get_settings($cookie), $key, $default);
|
||||
}
|
||||
|
||||
/** Store settings to a cookie
|
||||
@@ -685,7 +686,7 @@ function file_open_lock(string $filename) {
|
||||
if (!$fp) {
|
||||
return;
|
||||
}
|
||||
chmod($filename, 0660);
|
||||
@chmod($filename, 0660); // @ - may not be permitted
|
||||
if (!flock($fp, LOCK_EX)) {
|
||||
fclose($fp);
|
||||
return;
|
||||
@@ -808,7 +809,7 @@ function is_url(?string $string): bool {
|
||||
* @param Field $field
|
||||
*/
|
||||
function is_shortable(array $field): bool {
|
||||
return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea~', $field["type"]);
|
||||
return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea|hstore~', $field["type"]);
|
||||
}
|
||||
|
||||
/** Get query to compute number of found rows
|
||||
|
@@ -66,6 +66,7 @@ function langs(): array {
|
||||
'fr' => 'Français', // Francis Gagné, Aurélien Royer
|
||||
'gl' => 'Galego', // Eduardo Penabad Ramos
|
||||
'he' => 'עברית', // Binyamin Yawitz - https://stuff-group.com/
|
||||
'hi' => 'हिन्दी', // Joshi yogesh
|
||||
'hu' => 'Magyar', // Borsos Szilárd (Borsosfi) - http://www.borsosfi.hu, info@borsosfi.hu
|
||||
'id' => 'Bahasa Indonesia', // Ivan Lanin - http://ivan.lanin.org
|
||||
'it' => 'Italiano', // Alessandro Fiorotto, Paolo Asperti
|
||||
|
@@ -67,7 +67,7 @@ class Plugins {
|
||||
function __call(string $name, array $params) {
|
||||
$args = array();
|
||||
foreach ($params as $key => $val) {
|
||||
// some plugins accept params by reference - we don't need to propage it outside, just to the other plugins
|
||||
// some plugins accept params by reference - we don't need to propagate it outside, just to the other plugins
|
||||
$args[] = &$params[$key];
|
||||
}
|
||||
$return = null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
const VERSION = "5.2.1";
|
||||
const VERSION = "5.3.1-dev";
|
||||
|
@@ -4,6 +4,7 @@ namespace Adminer;
|
||||
$TABLE = $_GET["indexes"];
|
||||
$index_types = array("PRIMARY", "UNIQUE", "INDEX");
|
||||
$table_status = table_status1($TABLE, true);
|
||||
$index_algorithms = driver()->indexAlgorithms($table_status);
|
||||
if (preg_match('~MyISAM|M?aria' . (min_version(5.6, '10.0.5') ? '|InnoDB' : '') . '~i', $table_status["Engine"])) {
|
||||
$index_types[] = "FULLTEXT";
|
||||
}
|
||||
@@ -11,6 +12,7 @@ if (preg_match('~MyISAM|M?aria' . (min_version(5.7, '10.2.2') ? '|InnoDB' : '')
|
||||
$index_types[] = "SPATIAL";
|
||||
}
|
||||
$indexes = indexes($TABLE);
|
||||
$fields = fields($TABLE);
|
||||
$primary = array();
|
||||
if (JUSH == "mongo") { // doesn't support primary key
|
||||
$primary = $indexes["_id_"];
|
||||
@@ -29,13 +31,15 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
$columns = array();
|
||||
$lengths = array();
|
||||
$descs = array();
|
||||
$index_condition = (support("partial_indexes") ? $index["partial"] : "");
|
||||
$index_algorithm = (in_array($index["algorithm"], $index_algorithms) ? $index["algorithm"] : "");
|
||||
$set = array();
|
||||
ksort($index["columns"]);
|
||||
foreach ($index["columns"] as $key => $column) {
|
||||
if ($column != "") {
|
||||
$length = idx($index["lengths"], $key);
|
||||
$desc = idx($index["descs"], $key);
|
||||
$set[] = idf_escape($column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
|
||||
$set[] = ($fields[$column] ? idf_escape($column) : $column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
|
||||
$columns[] = $column;
|
||||
$lengths[] = ($length ?: null);
|
||||
$descs[] = $desc;
|
||||
@@ -52,6 +56,8 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
&& array_values($existing["columns"]) === $columns
|
||||
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
|
||||
&& array_values($existing["descs"]) === $descs
|
||||
&& $existing["partial"] == $index_condition
|
||||
&& (!$index_algorithms || $existing["algorithm"] == $index_algorithm)
|
||||
) {
|
||||
// skip existing index
|
||||
unset($indexes[$name]);
|
||||
@@ -59,7 +65,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
}
|
||||
}
|
||||
if ($columns) {
|
||||
$alter[] = array($index["type"], $name, $set);
|
||||
$alter[] = array($index["type"], $name, $set, $index_algorithm, $index_condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +82,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
|
||||
page_header(lang('Indexes'), $error, array("table" => $TABLE), h($TABLE));
|
||||
|
||||
$fields = array_keys(fields($TABLE));
|
||||
$fields_keys = array_keys($fields);
|
||||
if ($_POST["add"]) {
|
||||
foreach ($row["indexes"] as $key => $index) {
|
||||
if ($index["columns"][count($index["columns"])] != "") {
|
||||
@@ -105,20 +111,35 @@ $show_options = ($_POST ? $_POST["options"] : get_setting("index_options"));
|
||||
<table class="nowrap">
|
||||
<thead><tr>
|
||||
<th id="label-type"><?php echo lang('Index Type'); ?>
|
||||
<?php
|
||||
$idxopts = " class='idxopts" . ($show_options ? "" : " hidden") . "'";
|
||||
if ($index_algorithms) {
|
||||
echo "<th id='label-algorithm'$idxopts>" . lang('Algorithm') . doc_link(array(
|
||||
'sql' => 'create-index.html#create-index-storage-engine-index-types',
|
||||
'mariadb' => 'storage-engine-index-types/',
|
||||
'pgsql' => 'indexes-types.html',
|
||||
));
|
||||
}
|
||||
?>
|
||||
<th><input type="submit" class="wayoff"><?php
|
||||
echo lang('Columns') . ($lengths ? "<span class='idxopts" . ($show_options ? "" : " hidden") . "'> (" . lang('length') . ")</span>" : "");
|
||||
echo lang('Columns') . ($lengths ? "<span$idxopts> (" . lang('length') . ")</span>" : "");
|
||||
if ($lengths || support("descidx")) {
|
||||
echo checkbox("options", 1, $show_options, lang('Options'), "indexOptionsShow(this.checked)", "jsonly") . "\n";
|
||||
}
|
||||
?>
|
||||
<th id="label-name"><?php echo lang('Name'); ?>
|
||||
<?php
|
||||
if (support("partial_indexes")) {
|
||||
echo "<th id='label-condition'$idxopts>" . lang('Condition');
|
||||
}
|
||||
?>
|
||||
<th><noscript><?php echo icon("plus", "add[0]", "+", lang('Add next')); ?></noscript>
|
||||
</thead>
|
||||
<?php
|
||||
if ($primary) {
|
||||
echo "<tr><td>PRIMARY<td>";
|
||||
foreach ($primary["columns"] as $key => $column) {
|
||||
echo select_input(" disabled", $fields, $column);
|
||||
echo select_input(" disabled", $fields_keys, $column);
|
||||
echo "<label><input disabled type='checkbox'>" . lang('descending') . "</label> ";
|
||||
}
|
||||
echo "<td><td>\n";
|
||||
@@ -128,17 +149,21 @@ foreach ($row["indexes"] as $index) {
|
||||
if (!$_POST["drop_col"] || $j != key($_POST["drop_col"])) {
|
||||
echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow.call(this);" : ""), "label-type");
|
||||
|
||||
if ($index_algorithms) {
|
||||
echo "<td$idxopts>" . html_select("indexes[$j][algorithm]", array_merge(array(""), $index_algorithms), $index['algorithm'], "label-algorithm");
|
||||
}
|
||||
|
||||
echo "<td>";
|
||||
ksort($index["columns"]);
|
||||
$i = 1;
|
||||
foreach ($index["columns"] as $key => $column) {
|
||||
echo "<span>" . select_input(
|
||||
" name='indexes[$j][columns][$i]' title='" . lang('Column') . "'",
|
||||
($fields ? array_combine($fields, $fields) : $fields),
|
||||
($fields && ($column == "" || $fields[$column]) ? array_combine($fields_keys, $fields_keys) : array()),
|
||||
$column,
|
||||
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape(JUSH == "sql" ? "" : $_GET["indexes"] . "_") . "')"
|
||||
);
|
||||
echo "<span class='idxopts" . ($show_options ? "" : " hidden") . "'>";
|
||||
echo "<span$idxopts>";
|
||||
echo ($lengths ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h(idx($index["lengths"], $key)) . "' title='" . lang('Length') . "'>" : "");
|
||||
echo (support("descidx") ? checkbox("indexes[$j][descs][$i]", 1, idx($index["descs"], $key), lang('descending')) : "");
|
||||
echo "</span> </span>";
|
||||
@@ -146,6 +171,9 @@ foreach ($row["indexes"] as $index) {
|
||||
}
|
||||
|
||||
echo "<td><input name='indexes[$j][name]' value='" . h($index["name"]) . "' autocapitalize='off' aria-labelledby='label-name'>\n";
|
||||
if (support("partial_indexes")) {
|
||||
echo "<td$idxopts><input name='indexes[$j][partial]' value='" . h($index["partial"]) . "' autocapitalize='off' aria-labelledby='label-condition'>\n";
|
||||
}
|
||||
echo "<td>" . icon("cross", "drop_col[$j]", "x", lang('Remove')) . script("qsl('button').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");
|
||||
}
|
||||
$j++;
|
||||
|
@@ -259,6 +259,56 @@ Lang::$translations = array(
|
||||
'Permanent link' => 'স্থায়ী লিংক',
|
||||
'Edit all' => 'সবগুলো সম্পাদনা করুন',
|
||||
'HH:MM:SS' => 'HH:MM:SS',
|
||||
'Check has been dropped.' => 'চেক ড্রপ করা হয়েছে।',
|
||||
'Check has been altered.' => 'চেক পরিবর্তন করা হয়েছে।',
|
||||
'Check has been created.' => 'চেক তৈরি করা হয়েছে।',
|
||||
'Alter check' => 'চেক পরিবর্তন করুন',
|
||||
'Create check' => 'চেক তৈরি করুন',
|
||||
'Drop %s?' => '%s ড্রপ করবেন?',
|
||||
'Tables have been optimized.' => 'টেবিলগুলি অপ্টিমাইজ করা হয়েছে।',
|
||||
'Materialized view' => 'মেটেরিয়ালাইজড ভিউ',
|
||||
'Vacuum' => 'ভ্যাকুয়াম',
|
||||
'Selected' => 'নির্বাচিত',
|
||||
'overwrite' => 'ওভাররাইট',
|
||||
'DB' => 'ডিবি',
|
||||
'Algorithm' => 'অ্যালগরিদম',
|
||||
'Columns' => 'কলাম',
|
||||
'Ctrl+click on a value to modify it.' => 'একটি মান পরিবর্তন করতে Ctrl+ক্লিক করুন।',
|
||||
'File must be in UTF-8 encoding.' => 'ফাইলটি UTF-8 এনকোডিংয়ে হতে হবে।',
|
||||
'Modify' => 'পরিবর্তন করুন',
|
||||
'Load more data' => 'আরও ডেটা লোড করুন',
|
||||
'Loading' => 'লোড হচ্ছে',
|
||||
'ATTACH queries are not supported.' => 'ATTACH কোয়েরি সমর্থিত নয়।',
|
||||
'Warnings' => 'সতর্কতা',
|
||||
'%d / ' => array('%d / '),
|
||||
'Limit rows' => 'সারি সীমিত করুন',
|
||||
'Inherits from' => 'থেকে উত্তরাধিকারসূত্রে প্রাপ্ত',
|
||||
'Checks' => 'চেকস',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer পাসওয়ার্ড ছাড়া ডাটাবেস অ্যাক্সেস সমর্থন করে না, <a href="https://www.adminer.org/en/password/"%s>আরও তথ্য</a>।',
|
||||
'Default value' => 'ডিফল্ট মান',
|
||||
'Full table scan' => 'সম্পূর্ণ টেবিল স্ক্যান',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('অনেকগুলি ব্যর্থ লগইন প্রচেষ্টা, %d মিনিট পরে আবার চেষ্টা করুন।'),
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Adminer ব্যবহার করার জন্য ধন্যবাদ, <a href="https://www.adminer.org/en/donation/">দান করার</a> কথা বিবেচনা করুন।',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'মাস্টার পাসওয়ার্ডের মেয়াদ শেষ হয়েছে। এটিকে স্থায়ী করতে <a href="https://www.adminer.org/en/extension/"%s>ইমপ্লিমেন্ট</a> %s মেথড।',
|
||||
'The action will be performed after successful login with the same credentials.' => 'একই ক্রেডেনশিয়ালস দিয়ে সফলভাবে লগইন করার পরে এই কর্মটি সম্পাদন করা হবে।',
|
||||
'Connecting to privileged ports is not allowed.' => 'প্রিভিলেজড পোর্টে সংযোগ করা অনুমোদিত নয়।',
|
||||
'There is a space in the input password which might be the cause.' => 'ইনপুট পাসওয়ার্ডে একটি স্পেস রয়েছে যা এর কারণ হতে পারে।',
|
||||
'If you did not send this request from Adminer then close this page.' => 'আপনি যদি Adminer থেকে এই অনুরোধ না করে থাকেন তবে এই পৃষ্ঠাটি বন্ধ করুন।',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'আপনি FTP এর মাধ্যমে একটি বড় SQL ফাইল আপলোড করতে পারেন এবং সার্ভার থেকে এটি ইম্পোর্ট করতে পারেন।',
|
||||
'Size' => 'আকার',
|
||||
'Compute' => 'কম্পিউট',
|
||||
'Loaded plugins' => 'লোড করা প্লাগইনগুলি',
|
||||
'screenshot' => 'স্ক্রিনশট',
|
||||
'You are offline.' => 'আপনি অফলাইনে আছেন।',
|
||||
'You have no privileges to update this table.' => 'এই টেবিল আপডেট করার জন্য আপনার কোন অনুমতি নেই।',
|
||||
'Saving' => 'সংরক্ষণ করা হচ্ছে',
|
||||
'Unknown error.' => 'অজানা ত্রুটি।',
|
||||
'%s must <a%s>return an array</a>.' => '%s অবশ্যই <a%s>একটি অ্যারে রিটার্ন করতে হবে</a>।',
|
||||
'<a%s>Configure</a> %s in %s.' => '<a%s>কনফিগার করুন</a> %s এ %s।',
|
||||
'Disable %s or enable %s or %s extensions.' => '%s নিষ্ক্রিয় করুন অথবা %s বা %s এক্সটেনশন সক্রিয় করুন।',
|
||||
'Database does not support password.' => 'ডাটাবেস পাসওয়ার্ড সমর্থন করে না।',
|
||||
'yes' => 'হ্যাঁ',
|
||||
'no' => 'না',
|
||||
);
|
||||
|
||||
// run `php ../../lang.php bn` to update this file
|
||||
|
@@ -27,7 +27,7 @@ Lang::$translations = array(
|
||||
'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Zakažte %s nebo povolte rozšíření %s nebo %s.',
|
||||
'Session support must be enabled.' => 'Session proměnné musí být povolené.',
|
||||
'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
|
||||
'Session expired, please login again.' => 'Session vypršela, přihlaste se prosím znovu.',
|
||||
'The action will be performed after successful login with the same credentials.' => 'Akce bude provedena po úspěšném přihlášení se stejnými přihlašovacími údaji.',
|
||||
'%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP rozšíření %s',
|
||||
'Refresh' => 'Obnovit',
|
||||
@@ -76,6 +76,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Soubor %s na webovém serveru',
|
||||
'Run file' => 'Spustit soubor',
|
||||
'File does not exist.' => 'Soubor neexistuje.',
|
||||
'Increase %s.' => 'Zvyšte %s.',
|
||||
'File uploads are disabled.' => 'Nahrávání souborů není povoleno.',
|
||||
'Unable to upload a file.' => 'Nepodařilo se nahrát soubor.',
|
||||
'Maximum allowed file size is %sB.' => 'Maximální povolená velikost souboru je %sB.',
|
||||
@@ -194,6 +195,8 @@ Lang::$translations = array(
|
||||
'Partitions' => 'Oddíly',
|
||||
'Partition name' => 'Název oddílu',
|
||||
'Values' => 'Hodnoty',
|
||||
'Inherits from' => 'Zděděná z',
|
||||
'Inherited by' => 'Zděděné',
|
||||
|
||||
'View' => 'Pohled',
|
||||
'Materialized view' => 'Materializovaný pohled',
|
||||
@@ -209,6 +212,8 @@ Lang::$translations = array(
|
||||
'Add next' => 'Přidat další',
|
||||
'Index Type' => 'Typ indexu',
|
||||
'length' => 'délka',
|
||||
'Algorithm' => 'Algoritmus',
|
||||
'Condition' => 'Podmínka',
|
||||
|
||||
'Foreign keys' => 'Cizí klíče',
|
||||
'Foreign key' => 'Cizí klíč',
|
||||
|
314
adminer/lang/hi.inc.php
Normal file
314
adminer/lang/hi.inc.php
Normal file
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
Lang::$translations = array(
|
||||
'Login' => 'लॉगिन',
|
||||
'Logout successful.' => 'सफलतापूर्वक लॉगआउट हो गया।',
|
||||
'Invalid credentials.' => 'गलत पासवर्ड।',
|
||||
'Server' => 'सर्वर',
|
||||
'Username' => 'उपयोगकर्ता नाम',
|
||||
'Password' => 'पासवर्ड',
|
||||
'Select database' => 'डेटाबेस चुनें',
|
||||
'Invalid database.' => 'अमान्य डेटाबेस।',
|
||||
'Table has been dropped.' => 'टेबल हटा दिया गया है।',
|
||||
'Table has been altered.' => 'टेबल बदल दिया गया है।',
|
||||
'Table has been created.' => 'टेबल बनाया गया है।',
|
||||
'Alter table' => 'टेबल बदलें',
|
||||
'Create table' => 'टेबल बनाएं',
|
||||
'Table name' => 'टेबल का नाम',
|
||||
'engine' => 'इंजन',
|
||||
'collation' => 'कॉलेशन',
|
||||
'Column name' => 'कॉलम का नाम',
|
||||
'Type' => 'प्रकार',
|
||||
'Length' => 'लंबाई',
|
||||
'Auto Increment' => 'ऑटो इंक्रीमेंट',
|
||||
'Options' => 'विकल्प',
|
||||
'Save' => 'सहेजें',
|
||||
'Drop' => 'हटाएं',
|
||||
'Database has been dropped.' => 'डेटाबेस हटा दिया गया है।',
|
||||
'Database has been created.' => 'डेटाबेस बनाया गया है।',
|
||||
'Database has been renamed.' => 'डेटाबेस का नाम बदल दिया गया है।',
|
||||
'Database has been altered.' => 'डेटाबेस बदल दिया गया है।',
|
||||
'Alter database' => 'डेटाबेस बदलें',
|
||||
'Create database' => 'डेटाबेस बनाएं',
|
||||
'SQL command' => 'SQL कमांड',
|
||||
'Logout' => 'लॉगआउट',
|
||||
'Use' => 'उपयोग करें',
|
||||
'No tables.' => 'कोई टेबल नहीं।',
|
||||
'select' => 'चुनें',
|
||||
'Item has been deleted.' => 'आइटम हटा दिया गया है।',
|
||||
'Item has been updated.' => 'आइटम अपडेट किया गया है।',
|
||||
'Item%s has been inserted.' => 'आइटम%s डाला गया है।',
|
||||
'Edit' => 'संपादित करें',
|
||||
'Insert' => 'डालें',
|
||||
'Save and insert next' => 'सहेजें और अगला डालें',
|
||||
'Delete' => 'हटाएं',
|
||||
'Database' => 'डेटाबेस',
|
||||
'Routines' => 'रूटीन्स',
|
||||
'Indexes have been altered.' => 'इंडेक्स बदल दिए गए हैं।',
|
||||
'Indexes' => 'इंडेक्स',
|
||||
'Alter indexes' => 'इंडेक्स बदलें',
|
||||
'Add next' => 'अगला जोड़ें',
|
||||
'Language' => 'भाषा',
|
||||
'Select' => 'चुनें',
|
||||
'New item' => 'नया आइटम',
|
||||
'Search' => 'खोजें',
|
||||
'Sort' => 'क्रमबद्ध करें',
|
||||
'descending' => 'अवरोही',
|
||||
'Limit' => 'सीमा',
|
||||
'No rows.' => 'कोई पंक्ति नहीं।',
|
||||
'Action' => 'कार्रवाई',
|
||||
'edit' => 'संपादित करें',
|
||||
'Page' => 'पृष्ठ',
|
||||
'Query executed OK, %d row(s) affected.' => array('क्वेरी सफलतापूर्वक निष्पादित, %d पंक्ति प्रभावित।', 'क्वेरी सफलतापूर्वक निष्पादित, %d पंक्तियां प्रभावित।'),
|
||||
'Error in query' => 'क्वेरी में त्रुटि',
|
||||
'Execute' => 'निष्पादित करें',
|
||||
'Table' => 'टेबल',
|
||||
'Foreign keys' => 'फॉरेन की',
|
||||
'Triggers' => 'ट्रिगर्स',
|
||||
'View' => 'व्यू',
|
||||
'Unable to select the table' => 'टेबल चुनने में असमर्थ',
|
||||
'Invalid CSRF token. Send the form again.' => 'अमान्य CSRF टोकन। फॉर्म फिर से भेजें।',
|
||||
'Comment' => 'टिप्पणी',
|
||||
'Default values' => 'डिफ़ॉल्ट मान',
|
||||
'%d byte(s)' => array('%d बाइट', '%d बाइट्स'),
|
||||
'No commands to execute.' => 'निष्पादित करने के लिए कोई कमांड नहीं।',
|
||||
'Unable to upload a file.' => 'फाइल अपलोड करने में असमर्थ।',
|
||||
'File upload' => 'फाइल अपलोड',
|
||||
'File uploads are disabled.' => 'फाइल अपलोड अक्षम हैं।',
|
||||
'Routine has been called, %d row(s) affected.' => array('रूटीन कॉल किया गया, %d पंक्ति प्रभावित।', 'रूटीन कॉल किया गया, %d पंक्तियां प्रभावित।'),
|
||||
'Call' => 'कॉल',
|
||||
'No extension' => 'कोई एक्सटेंशन नहीं',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'कोई समर्थित PHP एक्सटेंशन (%s) उपलब्ध नहीं है।',
|
||||
'Session support must be enabled.' => 'सेशन सपोर्ट सक्षम होना चाहिए।',
|
||||
'Session expired, please login again.' => 'सेशन समाप्त, कृपया फिर से लॉगिन करें।',
|
||||
'Text length' => 'टेक्स्ट लंबाई',
|
||||
'Foreign key has been dropped.' => 'फॉरेन की हटा दी गई है।',
|
||||
'Foreign key has been altered.' => 'फॉरेन की बदल दी गई है।',
|
||||
'Foreign key has been created.' => 'फॉरेन की बनाई गई है।',
|
||||
'Foreign key' => 'फॉरेन की',
|
||||
'Target table' => 'लक्ष्य टेबल',
|
||||
'Change' => 'बदलें',
|
||||
'Source' => 'स्रोत',
|
||||
'Target' => 'लक्ष्य',
|
||||
'Add column' => 'कॉलम जोड़ें',
|
||||
'Alter' => 'बदलें',
|
||||
'Add foreign key' => 'फॉरेन की जोड़ें',
|
||||
'ON DELETE' => 'ऑन डिलीट',
|
||||
'ON UPDATE' => 'ऑन अपडेट',
|
||||
'Index Type' => 'इंडेक्स प्रकार',
|
||||
'length' => 'लंबाई',
|
||||
'View has been dropped.' => 'व्यू हटा दिया गया है।',
|
||||
'View has been altered.' => 'व्यू बदल दिया गया है।',
|
||||
'View has been created.' => 'व्यू बनाया गया है।',
|
||||
'Alter view' => 'व्यू बदलें',
|
||||
'Create view' => 'व्यू बनाएं',
|
||||
'Name' => 'नाम',
|
||||
'Process list' => 'प्रक्रिया सूची',
|
||||
'%d process(es) have been killed.' => array('%d प्रक्रिया समाप्त की गई है।', '%d प्रक्रियाएं समाप्त की गई हैं।'),
|
||||
'Kill' => 'समाप्त करें',
|
||||
'Parameter name' => 'पैरामीटर नाम',
|
||||
'Database schema' => 'डेटाबेस स्कीमा',
|
||||
'Create procedure' => 'प्रक्रिया बनाएं',
|
||||
'Create function' => 'फंक्शन बनाएं',
|
||||
'Routine has been dropped.' => 'रूटीन हटा दिया गया है।',
|
||||
'Routine has been altered.' => 'रूटीन बदल दिया गया है।',
|
||||
'Routine has been created.' => 'रूटीन बनाया गया है।',
|
||||
'Alter function' => 'फंक्शन बदलें',
|
||||
'Alter procedure' => 'प्रक्रिया बदलें',
|
||||
'Return type' => 'वापसी प्रकार',
|
||||
'Add trigger' => 'ट्रिगर जोड़ें',
|
||||
'Trigger has been dropped.' => 'ट्रिगर हटा दिया गया है।',
|
||||
'Trigger has been altered.' => 'ट्रिगर बदल दिया गया है।',
|
||||
'Trigger has been created.' => 'ट्रिगर बनाया गया है।',
|
||||
'Alter trigger' => 'ट्रिगर बदलें',
|
||||
'Create trigger' => 'ट्रिगर बनाएं',
|
||||
'Time' => 'समय',
|
||||
'Event' => 'घटना',
|
||||
'%s version: %s through PHP extension %s' => 'संस्करण %s: %s, PHP एक्सटेंशन %s के माध्यम से',
|
||||
'%d row(s)' => array('%d पंक्ति', '%d पंक्तियां'),
|
||||
'Remove' => 'हटाएं',
|
||||
'Are you sure?' => 'क्या आप सुनिश्चित हैं?',
|
||||
'Privileges' => 'विशेषाधिकार',
|
||||
'Create user' => 'उपयोगकर्ता बनाएं',
|
||||
'User has been dropped.' => 'उपयोगकर्ता हटा दिया गया है।',
|
||||
'User has been altered.' => 'उपयोगकर्ता बदल दिया गया है।',
|
||||
'User has been created.' => 'उपयोगकर्ता बनाया गया है।',
|
||||
'Hashed' => 'हैश्ड',
|
||||
'Column' => 'कॉलम',
|
||||
'Routine' => 'रूटीन',
|
||||
'Grant' => 'अनुदान',
|
||||
'Revoke' => 'रद्द करें',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'बहुत बड़ा POST डेटा। डेटा कम करें या %s कॉन्फ़िगरेशन निर्देश बढ़ाएं।',
|
||||
'Logged as: %s' => '%s के रूप में लॉगिन',
|
||||
'Move up' => 'ऊपर ले जाएं',
|
||||
'Move down' => 'नीचे ले जाएं',
|
||||
'Functions' => 'फंक्शन्स',
|
||||
'Aggregation' => 'एग्रीगेशन',
|
||||
'Export' => 'निर्यात',
|
||||
'Output' => 'आउटपुट',
|
||||
'open' => 'खोलें',
|
||||
'save' => 'सहेजें',
|
||||
'Format' => 'प्रारूप',
|
||||
'Tables' => 'टेबल्स',
|
||||
'Data' => 'डेटा',
|
||||
'Event has been dropped.' => 'घटना हटा दी गई है।',
|
||||
'Event has been altered.' => 'घटना बदल दी गई है।',
|
||||
'Event has been created.' => 'घटना बनाई गई है।',
|
||||
'Alter event' => 'घटना बदलें',
|
||||
'Create event' => 'घटना बनाएं',
|
||||
'At given time' => 'निर्धारित समय पर',
|
||||
'Every' => 'हर',
|
||||
'Events' => 'घटनाएं',
|
||||
'Schedule' => 'अनुसूची',
|
||||
'Start' => 'शुरू',
|
||||
'End' => 'समाप्त',
|
||||
'Status' => 'स्थिति',
|
||||
'On completion preserve' => 'पूरा होने पर संरक्षित करें',
|
||||
'Tables and views' => 'टेबल्स और व्यूज',
|
||||
'Data Length' => 'डेटा लंबाई',
|
||||
'Index Length' => 'इंडेक्स लंबाई',
|
||||
'Data Free' => 'डेटा मुक्त',
|
||||
'Collation' => 'कॉलेशन',
|
||||
'Analyze' => 'विश्लेषण',
|
||||
'Optimize' => 'अनुकूलित',
|
||||
'Check' => 'जांच',
|
||||
'Repair' => 'मरम्मत',
|
||||
'Truncate' => 'ट्रंकेट',
|
||||
'Tables have been truncated.' => 'टेबल्स ट्रंकेट कर दिए गए हैं।',
|
||||
'Rows' => 'पंक्तियां',
|
||||
',' => ',',
|
||||
'0123456789' => '०१२३४५६७८९',
|
||||
'Tables have been moved.' => 'टेबल्स स्थानांतरित कर दिए गए हैं।',
|
||||
'Move to other database' => 'अन्य डेटाबेस में स्थानांतरित करें',
|
||||
'Move' => 'स्थानांतरित करें',
|
||||
'Engine' => 'इंजन',
|
||||
'Save and continue edit' => 'सहेजें और संपादन जारी रखें',
|
||||
'original' => 'मूल',
|
||||
'Tables have been dropped.' => 'टेबल्स हटा दिए गए हैं।',
|
||||
'%d item(s) have been affected.' => '%d आइटम प्रभावित हुए हैं।',
|
||||
'Whole result' => 'पूरा परिणाम',
|
||||
'Clone' => 'क्लोन',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s.' => 'अनुमत फील्ड्स की अधिकतम संख्या पार हो गई। कृपया %s बढ़ाएं।',
|
||||
'Partition by' => 'द्वारा विभाजन',
|
||||
'Partitions' => 'पार्टीशन्स',
|
||||
'Partition name' => 'पार्टीशन नाम',
|
||||
'Values' => 'मान',
|
||||
'%d row(s) have been imported.' => array('%d पंक्ति आयात की गई है।', '%d पंक्तियां आयात की गई हैं।'),
|
||||
'anywhere' => 'कहीं भी',
|
||||
'Import' => 'आयात',
|
||||
'Stop on error' => 'त्रुटि पर रुकें',
|
||||
'%.3f s' => '%.3f सेकंड',
|
||||
'$1-$3-$5' => '$1-$3-$5',
|
||||
'[yyyy]-mm-dd' => '[yyyy]-mm-dd',
|
||||
'History' => 'इतिहास',
|
||||
'Variables' => 'चर',
|
||||
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'स्रोत और लक्ष्य कॉलम्स का डेटा प्रकार समान होना चाहिए, लक्ष्य कॉलम्स पर एक इंडेक्स होना चाहिए और संदर्भित डेटा मौजूद होना चाहिए।',
|
||||
'Relations' => 'संबंध',
|
||||
'Run file' => 'फाइल चलाएं',
|
||||
'Clear' => 'साफ़ करें',
|
||||
'Maximum allowed file size is %sB.' => 'अधिकतम अनुमत फाइल आकार %sB है।',
|
||||
'Numbers' => 'संख्याएं',
|
||||
'Date and time' => 'तिथि और समय',
|
||||
'Strings' => 'स्ट्रिंग्स',
|
||||
'Binary' => 'बाइनरी',
|
||||
'Lists' => 'सूचियां',
|
||||
'Editor' => 'संपादक',
|
||||
'Webserver file %s' => 'वेबसर्वर फाइल %s',
|
||||
'File does not exist.' => 'फाइल मौजूद नहीं है।',
|
||||
'%d in total' => 'कुल %d',
|
||||
'Permanent login' => 'स्थायी लॉगिन',
|
||||
'Databases have been dropped.' => 'डेटाबेस हटा दिए गए हैं।',
|
||||
'Search data in tables' => 'टेबल्स में डेटा खोजें',
|
||||
'Schema' => 'स्कीमा',
|
||||
'Alter schema' => 'स्कीमा बदलें',
|
||||
'Create schema' => 'स्कीमा बनाएं',
|
||||
'Schema has been dropped.' => 'स्कीमा हटा दी गई है।',
|
||||
'Schema has been created.' => 'स्कीमा बनाई गई है।',
|
||||
'Schema has been altered.' => 'स्कीमा बदल दी गई है।',
|
||||
'Sequences' => 'अनुक्रम',
|
||||
'Create sequence' => 'अनुक्रम बनाएं',
|
||||
'Alter sequence' => 'अनुक्रम बदलें',
|
||||
'Sequence has been dropped.' => 'अनुक्रम हटा दिया गया है।',
|
||||
'Sequence has been created.' => 'अनुक्रम बनाया गया है।',
|
||||
'Sequence has been altered.' => 'अनुक्रम बदल दिया गया है।',
|
||||
'User types' => 'उपयोगकर्ता प्रकार',
|
||||
'Create type' => 'प्रकार बनाएं',
|
||||
'Alter type' => 'प्रकार बदलें',
|
||||
'Type has been dropped.' => 'प्रकार हटा दिया गया है।',
|
||||
'Type has been created.' => 'प्रकार बनाया गया है।',
|
||||
'Use edit link to modify this value.' => 'इस मान को संशोधित करने के लिए संपादन लिंक का उपयोग करें।',
|
||||
'last' => 'अंतिम',
|
||||
'From server' => 'सर्वर से',
|
||||
'System' => 'सिस्टम',
|
||||
'Select data' => 'डेटा चुनें',
|
||||
'Show structure' => 'संरचना दिखाएं',
|
||||
'empty' => 'खाली',
|
||||
'Network' => 'नेटवर्क',
|
||||
'Geometry' => 'ज्यामिति',
|
||||
'File exists.' => 'फाइल मौजूद है।',
|
||||
'%d query(s) executed OK.' => array('%d क्वेरी सफलतापूर्वक निष्पादित।', '%d क्वेरीज़ सफलतापूर्वक निष्पादित।'),
|
||||
'Show only errors' => 'केवल त्रुटियां दिखाएं',
|
||||
'Refresh' => 'ताज़ा करें',
|
||||
'Invalid schema.' => 'अमान्य स्कीमा।',
|
||||
'Please use one of the extensions %s.' => 'कृपया %s एक्सटेंशन्स में से एक का उपयोग करें।',
|
||||
'now' => 'अब',
|
||||
'ltr' => 'ltr',
|
||||
'Tables have been copied.' => 'टेबल्स कॉपी कर दिए गए हैं।',
|
||||
'Copy' => 'कॉपी',
|
||||
'Permanent link' => 'स्थायी लिंक',
|
||||
'Edit all' => 'सभी संपादित करें',
|
||||
'HH:MM:SS' => 'HH:MM:SS',
|
||||
'Check has been dropped.' => 'चेक हटा दिया गया है।',
|
||||
'Check has been altered.' => 'चेक को बदल दिया गया है।',
|
||||
'Check has been created.' => 'चेक बनाया गया है।',
|
||||
'Alter check' => 'चेक बदलें',
|
||||
'Create check' => 'चेक बनाएँ',
|
||||
'Drop %s?' => '%s हटाएँ?',
|
||||
'Tables have been optimized.' => 'टेबल्स को ऑप्टिमाइज़ कर दिया गया है।',
|
||||
'Materialized view' => 'मटेरियलाइज़्ड व्यू',
|
||||
'Vacuum' => 'वैक्यूम',
|
||||
'Selected' => 'चयनित',
|
||||
'overwrite' => 'ओवरराइट',
|
||||
'DB' => 'डेटाबेस',
|
||||
'Algorithm' => 'एल्गोरिदम',
|
||||
'Columns' => 'कॉलम',
|
||||
'Ctrl+click on a value to modify it.' => 'किसी मान को संशोधित करने के लिए Ctrl+क्लिक करें।',
|
||||
'File must be in UTF-8 encoding.' => 'फ़ाइल UTF-8 एन्कोडिंग में होनी चाहिए।',
|
||||
'Modify' => 'संशोधित करें',
|
||||
'Load more data' => 'और डेटा लोड करें',
|
||||
'Loading' => 'लोड हो रहा है',
|
||||
'ATTACH queries are not supported.' => 'संलग्न क्वेरीज़ समर्थित नहीं हैं।',
|
||||
'Warnings' => 'चेतावनियाँ',
|
||||
'%d / ' => '%d / ',
|
||||
'Limit rows' => 'पंक्तियाँ सीमित करें',
|
||||
'Inherits from' => 'इनहेरिट करता है',
|
||||
'Checks' => 'चेक्स',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'एडमिनर बिना पासवर्ड के डेटाबेस एक्सेस करने का समर्थन नहीं करता, <a href="https://www.adminer.org/en/password/"%s>अधिक जानकारी</a>।',
|
||||
'Default value' => 'डिफ़ॉल्ट मान',
|
||||
'Full table scan' => 'पूरी टेबल स्कैन',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => 'बहुत अधिक असफल लॉगिन प्रयास, %d मिनट बाद पुनः प्रयास करें।',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'एडमिनर उपयोग करने के लिए धन्यवाद, <a href="https://www.adminer.org/en/donation/">दान</a> करने पर विचार करें।',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'मास्टर पासवर्ड समाप्त हो गया। इसे स्थायी बनाने के लिए %s मेथड <a href="https://www.adminer.org/en/extension/"%s>इम्प्लीमेंट</a> करें।',
|
||||
'The action will be performed after successful login with the same credentials.' => 'यह क्रिया उसी क्रेडेंशियल्स से सफल लॉगिन के बाद की जाएगी।',
|
||||
'Connecting to privileged ports is not allowed.' => 'प्रिविलेज्ड पोर्ट्स से कनेक्ट करने की अनुमति नहीं है।',
|
||||
'There is a space in the input password which might be the cause.' => 'इनपुट पासवर्ड में एक स्पेस है जो कारण हो सकता है।',
|
||||
'If you did not send this request from Adminer then close this page.' => 'अगर आपने यह अनुरोध एडमिनर से नहीं भेजा है तो इस पेज को बंद करें।',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'आप एक बड़ी SQL फ़ाइल FTP के माध्यम से अपलोड कर सकते हैं और सर्वर से इम्पोर्ट कर सकते हैं।',
|
||||
'Size' => 'आकार',
|
||||
'Compute' => 'कम्प्यूट',
|
||||
'Loaded plugins' => 'लोडेड प्लगइन्स',
|
||||
'screenshot' => 'स्क्रीनशॉट',
|
||||
'You are offline.' => 'आप ऑफ़लाइन हैं।',
|
||||
'You have no privileges to update this table.' => 'आपके पास इस टेबल को अपडेट करने की अनुमति नहीं है।',
|
||||
'Saving' => 'सेव हो रहा है',
|
||||
'Unknown error.' => 'अज्ञात त्रुटि।',
|
||||
'%s must <a%s>return an array</a>.' => '%s को <a%s>एक ऐरे रिटर्न</a> करना चाहिए।',
|
||||
'<a%s>Configure</a> %s in %s.' => '<a%s>कॉन्फ़िगर</a> %s में %s।',
|
||||
'Disable %s or enable %s or %s extensions.' => '%s को डिसेबल करें या %s या %s एक्सटेंशन्स को एनेबल करें।',
|
||||
'Database does not support password.' => 'डेटाबेस पासवर्ड का समर्थन नहीं करता।',
|
||||
'yes' => 'हाँ',
|
||||
'no' => 'नहीं',
|
||||
);
|
||||
|
||||
// run `php ../../lang.php hi` to update this file
|
@@ -5,8 +5,8 @@ Lang::$translations = array(
|
||||
'Login' => 'ログイン',
|
||||
'Logout successful.' => 'ログアウトしました。',
|
||||
'Invalid credentials.' => '不正なログインです。',
|
||||
'Server' => 'サーバ',
|
||||
'Username' => 'ユーザ名',
|
||||
'Server' => 'サーバー',
|
||||
'Username' => 'ユーザー名',
|
||||
'Password' => 'パスワード',
|
||||
'Loaded plugins' => '読込済プラグイン',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Adminerのご利用ありがとうございました。(寄付は<a href="https://www.adminer.org/en/donation/">こちら</a>)',
|
||||
@@ -20,14 +20,14 @@ Lang::$translations = array(
|
||||
'Select database' => 'データベースを選択してください',
|
||||
'Invalid database.' => '不正なデータベースです。',
|
||||
'Table has been dropped.' => 'テーブルを削除しました。',
|
||||
'Table has been altered.' => 'テーブルを変更しました。',
|
||||
'Table has been altered.' => 'テーブルの設定を変更しました。',
|
||||
'Table has been created.' => 'テーブルを作成しました。',
|
||||
'Alter table' => 'テーブルを変更',
|
||||
'Alter table' => 'テーブルの設定を変更',
|
||||
'Create table' => 'テーブルを作成',
|
||||
'Table name' => 'テーブル名',
|
||||
'engine' => 'エンジン',
|
||||
'collation' => '照合順序',
|
||||
'Column name' => '列名',
|
||||
'collation' => 'コレーション',
|
||||
'Column name' => 'カラム名',
|
||||
'Type' => '型',
|
||||
'Length' => '長さ',
|
||||
'Auto Increment' => '連番',
|
||||
@@ -38,16 +38,16 @@ Lang::$translations = array(
|
||||
'Database has been dropped.' => 'データベースを削除しました。',
|
||||
'Database has been created.' => 'データベースを作成しました。',
|
||||
'Database has been renamed.' => 'データベースの名前を変えました。',
|
||||
'Database has been altered.' => 'データベースを変更しました。',
|
||||
'Alter database' => 'データベースを変更',
|
||||
'Database has been altered.' => 'データベースの設定を変更しました。',
|
||||
'Alter database' => 'データベースの設定を変更',
|
||||
'Create database' => 'データベースを作成',
|
||||
'SQL command' => 'SQLコマンド',
|
||||
'Logout' => 'ログアウト',
|
||||
'Use' => '使用',
|
||||
'No tables.' => 'テーブルがありません。',
|
||||
'select' => '選択',
|
||||
'Item has been deleted.' => '項目を削除しました。',
|
||||
'Item has been updated.' => '項目を更新しました。',
|
||||
'Item has been deleted.' => 'レコードを削除しました。',
|
||||
'Item has been updated.' => 'レコードを更新しました。',
|
||||
'Edit' => '編集',
|
||||
'Insert' => '挿入',
|
||||
'Save and insert next' => '保存/追加',
|
||||
@@ -56,18 +56,18 @@ Lang::$translations = array(
|
||||
'Database' => 'データベース',
|
||||
'DB' => 'DB',
|
||||
'Routines' => 'ルーチン',
|
||||
'Indexes have been altered.' => '索引を変更しました。',
|
||||
'Indexes' => '索引',
|
||||
'Alter indexes' => '索引の変更',
|
||||
'Indexes have been altered.' => 'インデックスを変更しました。',
|
||||
'Indexes' => 'インデックス',
|
||||
'Alter indexes' => 'インデックスを変更',
|
||||
'Add next' => '追加',
|
||||
'Language' => '言語',
|
||||
'Select' => '選択',
|
||||
'New item' => '項目の作成',
|
||||
'New item' => '新規レコードを挿入',
|
||||
'Search' => '検索',
|
||||
'Sort' => 'ソート',
|
||||
'descending' => '降順',
|
||||
'Limit' => '制約',
|
||||
'Limit rows' => '行数の制約',
|
||||
'Limit rows' => '表示行数を制限',
|
||||
'No rows.' => '行がありません。',
|
||||
'Action' => '動作',
|
||||
'edit' => '編集',
|
||||
@@ -82,17 +82,17 @@ Lang::$translations = array(
|
||||
'Foreign keys' => '外部キー',
|
||||
'Triggers' => 'トリガー',
|
||||
'View' => 'ビュー',
|
||||
'Materialized view' => 'マテビュー',
|
||||
'Full table scan' => 'テーブルの全スキャン',
|
||||
'Materialized view' => 'マテリアライズドビュー',
|
||||
'Full table scan' => 'テーブルを全スキャン',
|
||||
'Unable to select the table' => 'テーブルを選択できません',
|
||||
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークン。再送信してください。',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Adminerからのリクエストを送信しない場合はこのページを閉じてください。',
|
||||
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークンです。フォームを再送信してください。',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Adminerからのリクエストでない場合はこのページを閉じてください。',
|
||||
'Comment' => 'コメント',
|
||||
'Default values' => '規定値',
|
||||
'Default values' => '既定値',
|
||||
'%d byte(s)' => '%d バイト',
|
||||
'No commands to execute.' => '実行するコマンドがありません。',
|
||||
'Unable to upload a file.' => 'ファイルをアップロードできません。',
|
||||
'File upload' => 'ファイルをアップロード',
|
||||
'File upload' => 'アップロード',
|
||||
'File uploads are disabled.' => 'ファイルのアップロードが無効です。',
|
||||
'Routine has been called, %d row(s) affected.' => 'ルーチンを呼びました。%d 行を変更しました。',
|
||||
'Call' => '呼出し',
|
||||
@@ -103,7 +103,7 @@ Lang::$translations = array(
|
||||
'Session support must be enabled.' => 'セッションを有効にしてください。',
|
||||
'Session expired, please login again.' => 'セッションの期限切れ。ログインし直してください。',
|
||||
'The action will be performed after successful login with the same credentials.' => '同じアカウントで正しくログインすると作業を実行します。',
|
||||
'Text length' => '文字列の長さ',
|
||||
'Text length' => '文字数を丸める',
|
||||
'Foreign key has been dropped.' => '外部キーを削除しました。',
|
||||
'Foreign key has been altered.' => '外部キーを変更しました。',
|
||||
'Foreign key has been created.' => '外部キーを作成しました。',
|
||||
@@ -112,12 +112,12 @@ Lang::$translations = array(
|
||||
'Change' => '変更',
|
||||
'Source' => 'ソース',
|
||||
'Target' => 'ターゲット',
|
||||
'Add column' => '列を追加',
|
||||
'Add column' => 'カラムを追加',
|
||||
'Alter' => '変更',
|
||||
'Add foreign key' => '外部キーを追加',
|
||||
'ON DELETE' => 'ON DELETE',
|
||||
'ON UPDATE' => 'ON UPDATE',
|
||||
'Index Type' => '索引の型',
|
||||
'Index Type' => 'インデックスの型',
|
||||
'length' => '長さ',
|
||||
'View has been dropped.' => 'ビューを削除しました。',
|
||||
'View has been altered.' => 'ビューを変更しました。',
|
||||
@@ -126,25 +126,25 @@ Lang::$translations = array(
|
||||
'Create view' => 'ビューを作成',
|
||||
'Name' => '名称',
|
||||
'Process list' => 'プロセス一覧',
|
||||
'%d process(es) have been killed.' => '%d プロセスを強制終了しました。',
|
||||
'Kill' => '強制終了',
|
||||
'Parameter name' => '参数名',
|
||||
'Database schema' => '構造',
|
||||
'Create procedure' => 'プロシージャの作成',
|
||||
'Create function' => '関数の作成',
|
||||
'Routine has been dropped.' => 'ルーチンを作成しました。',
|
||||
'%d process(es) have been killed.' => '%d プロセスを終了しました。',
|
||||
'Kill' => 'プロセスを終了',
|
||||
'Parameter name' => 'パラメータ名',
|
||||
'Database schema' => 'スキーマ',
|
||||
'Create procedure' => 'プロシージャを作成',
|
||||
'Create function' => '関数を作成',
|
||||
'Routine has been dropped.' => 'ルーチンを削除しました。',
|
||||
'Routine has been altered.' => 'ルーチンを変更しました。',
|
||||
'Routine has been created.' => 'ルーチンを作成しました。',
|
||||
'Alter function' => '関数の変更',
|
||||
'Alter procedure' => 'プロシージャの変更',
|
||||
'Alter function' => '関数を変更',
|
||||
'Alter procedure' => 'プロシージャを変更',
|
||||
'Return type' => '戻り値の型',
|
||||
'Add trigger' => 'トリガーの追加',
|
||||
'Add trigger' => 'トリガーを追加',
|
||||
'Trigger has been dropped.' => 'トリガーを削除しました。',
|
||||
'Trigger has been altered.' => 'トリガーを変更しました。',
|
||||
'Trigger has been created.' => 'トリガーを追加しました。',
|
||||
'Alter trigger' => 'トリガーの変更',
|
||||
'Create trigger' => 'トリガーの作成',
|
||||
'Time' => '時間',
|
||||
'Alter trigger' => 'トリガーを変更',
|
||||
'Create trigger' => 'トリガーを作成',
|
||||
'Time' => 'タイミング',
|
||||
'Event' => 'イベント',
|
||||
'%s version: %s through PHP extension %s' => '%sバージョン:%s、 PHP拡張機能 %s',
|
||||
'%d / ' => '%d / ',
|
||||
@@ -157,11 +157,11 @@ Lang::$translations = array(
|
||||
'User has been altered.' => 'ユーザを変更しました。',
|
||||
'User has been created.' => 'ユーザを作成しました。',
|
||||
'Hashed' => 'Hashed',
|
||||
'Column' => '列',
|
||||
'Columns' => '列',
|
||||
'Column' => 'カラム',
|
||||
'Columns' => 'カラム',
|
||||
'Routine' => 'ルーチン',
|
||||
'Grant' => '権限の付与',
|
||||
'Revoke' => '権限の取消し',
|
||||
'Grant' => '権限を付与',
|
||||
'Revoke' => '権限を取り消す',
|
||||
'Logged as: %s' => 'ログ:%s',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POSTデータが大きすぎます。データサイズを小さくするか %s 設定を大きくしてください。',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => '大きなSQLファイルは、FTP経由でアップロードしてサーバからインポートしてください。',
|
||||
@@ -172,16 +172,16 @@ Lang::$translations = array(
|
||||
'Tables' => 'テーブル',
|
||||
'Data' => 'データ',
|
||||
'Output' => '出力',
|
||||
'open' => '開く',
|
||||
'open' => 'ブラウザに表示',
|
||||
'save' => '保存',
|
||||
'Format' => '形式',
|
||||
'Functions' => '関数',
|
||||
'Aggregation' => '集合',
|
||||
'Aggregation' => '集約関数',
|
||||
'Event has been dropped.' => 'イベントを削除しました。',
|
||||
'Event has been altered.' => 'イベントを変更しました。',
|
||||
'Event has been created.' => 'イベントを作成しました。',
|
||||
'Alter event' => '変更',
|
||||
'Create event' => '作成',
|
||||
'Alter event' => 'イベントを変更',
|
||||
'Create event' => 'イベントを作成',
|
||||
'Start' => '開始',
|
||||
'End' => '終了',
|
||||
'Every' => '毎回',
|
||||
@@ -194,24 +194,24 @@ Lang::$translations = array(
|
||||
'Tables have been moved.' => 'テーブルを移動しました。',
|
||||
'Tables and views' => 'テーブルとビュー',
|
||||
'Engine' => 'エンジン',
|
||||
'Collation' => '照合順序',
|
||||
'Collation' => 'コレーション',
|
||||
'Data Length' => 'データ長',
|
||||
'Index Length' => '索引長',
|
||||
'Index Length' => 'インデックス長',
|
||||
'Data Free' => '空き',
|
||||
'Rows' => '行数',
|
||||
',' => ',',
|
||||
'0123456789' => '0123456789',
|
||||
'Analyze' => '分析',
|
||||
'Optimize' => '最適化',
|
||||
'Vacuum' => '不要領域の回収',
|
||||
'Check' => 'チェック',
|
||||
'Vacuum' => '不要領域を回収(Vacuum)',
|
||||
'Check' => '検査',
|
||||
'Repair' => '修復',
|
||||
'Truncate' => '空にする',
|
||||
'Move to other database' => '別のデータベースへ移動',
|
||||
'Move to other database' => '他のデータベースへ移動',
|
||||
'Move' => '移動',
|
||||
'Save and continue edit' => '保存して継続',
|
||||
'original' => '元',
|
||||
'%d item(s) have been affected.' => '%d 個を更新しました。',
|
||||
'%d item(s) have been affected.' => '%d レコードを更新しました。',
|
||||
'Whole result' => '全結果',
|
||||
'Tables have been dropped.' => 'テーブルを削除しました。',
|
||||
'Tables have been optimized.' => 'テーブルを最適化しました。',
|
||||
@@ -223,7 +223,7 @@ Lang::$translations = array(
|
||||
'Values' => '値',
|
||||
'%d row(s) have been imported.' => '%d 行をインポートしました。',
|
||||
'File must be in UTF-8 encoding.' => 'ファイルをUTF-8で保存してください。',
|
||||
'Show structure' => '構造',
|
||||
'Show structure' => 'スキーマ',
|
||||
'anywhere' => '任意',
|
||||
'Import' => 'インポート',
|
||||
'Stop on error' => 'エラーの場合は停止',
|
||||
@@ -233,9 +233,9 @@ Lang::$translations = array(
|
||||
'[yyyy]-mm-dd' => '[yyyy]/mm/dd',
|
||||
'History' => '履歴',
|
||||
'Variables' => '変数',
|
||||
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'ソースとターゲットの列は同じデータ型でなければなりません。ターゲット列に索引があり、データが存在しなければなりません。',
|
||||
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'ソースとターゲットのカラムは同じデータ型でなければなりません。ターゲットカラムにインデックスがあり、データが存在しなければなりません。',
|
||||
'Relations' => '関係',
|
||||
'Run file' => 'ファイルを実行',
|
||||
'Run file' => '実行',
|
||||
'Clear' => '消去',
|
||||
'Maximum allowed file size is %sB.' => '最大ファイルサイズは %sB です。',
|
||||
'Numbers' => '数字',
|
||||
@@ -244,7 +244,7 @@ Lang::$translations = array(
|
||||
'Binary' => 'バイナリ',
|
||||
'Lists' => 'リスト',
|
||||
'Editor' => 'エディタ',
|
||||
'Webserver file %s' => 'Webサーバファイル %s',
|
||||
'Webserver file %s' => 'ファイル名 %s',
|
||||
'File does not exist.' => 'ファイルは存在しません。',
|
||||
'%d in total' => '合計 %d',
|
||||
'Permanent login' => '永続的にログイン',
|
||||
@@ -268,15 +268,15 @@ Lang::$translations = array(
|
||||
'Type has been dropped.' => 'ユーザー定義型を削除しました。',
|
||||
'Type has been created.' => 'ユーザー定義型を追加しました。',
|
||||
'Ctrl+click on a value to modify it.' => 'Ctrl+クリックで値を修正します。',
|
||||
'Use edit link to modify this value.' => 'この値を修正するとリンクを編集します。',
|
||||
'Use edit link to modify this value.' => 'この値を修正するにはリンクを使用してください。',
|
||||
'last' => '最終',
|
||||
'From server' => 'サーバーから実行',
|
||||
'From server' => 'サーバー上のファイル',
|
||||
'System' => 'データベース種類',
|
||||
'empty' => '空',
|
||||
'Network' => 'ネットワーク型',
|
||||
'Geometry' => 'ジオメトリ型',
|
||||
'File exists.' => 'ファイルが既に存在します。',
|
||||
'Item%s has been inserted.' => '%s項目を挿入しました。',
|
||||
'Item%s has been inserted.' => '%sレコードを挿入しました。',
|
||||
'now' => '現在の日時',
|
||||
'%d query(s) executed OK.' => '%d クエリーを実行しました。',
|
||||
'Show only errors' => 'エラーのみ表示',
|
||||
@@ -287,29 +287,30 @@ Lang::$translations = array(
|
||||
'Tables have been copied.' => 'テーブルをコピーしました。',
|
||||
'Copy' => 'コピー',
|
||||
'overwrite' => '上書き',
|
||||
'Permanent link' => 'パーマネントリンク',
|
||||
'Edit all' => 'すべて編集',
|
||||
'Permanent link' => '固定リンク',
|
||||
'Edit all' => '一括編集',
|
||||
'Selected' => '選択中',
|
||||
'Modify' => '編集',
|
||||
'Load more data' => 'さらにデータを表示',
|
||||
'Compute' => '再計算',
|
||||
'Saving' => '保存しています...',
|
||||
'Checks' => 'CHECK制約',
|
||||
'Create check' => 'CHECK制約を追加',
|
||||
'Alter check' => 'CHECK制約を編集',
|
||||
'Check has been created.' => 'CHECK制約を追加しました。',
|
||||
'Check has been altered.' => 'CHECK制約を編集しました。',
|
||||
'Check has been dropped.' => 'CHECK制約を削除しました。',
|
||||
|
||||
'screenshot' => 'スクリーンショット',
|
||||
'Algorithm' => 'アルゴリズム',
|
||||
'Condition' => '条件',
|
||||
'Inherits from' => '継承元',
|
||||
'HH:MM:SS' => '時:分:秒',
|
||||
'Selected' => '選択済',
|
||||
'Modify' => '修正',
|
||||
'Load more data' => '続きを読み込み',
|
||||
'Loading' => '読み込み中',
|
||||
'Size' => 'サイズ',
|
||||
'Compute' => '算出',
|
||||
'Saving' => '保存中',
|
||||
'yes' => 'はい',
|
||||
'no' => 'いいえ',
|
||||
'Default value' => '既定値',
|
||||
|
||||
// Table check constraints
|
||||
'Checks' => 'チェック',
|
||||
'Create check' => 'チェックを作成',
|
||||
'Alter check' => 'チェックを変更',
|
||||
'Check has been created.' => 'チェックを作成しました。',
|
||||
'Check has been altered.' => 'チェックを変更しました。',
|
||||
'Check has been dropped.' => 'チェックを削除しました。',
|
||||
|
||||
'screenshot' => 'スクリーンショット',
|
||||
);
|
||||
|
||||
// run `php ../../lang.php ja` to update this file
|
||||
|
@@ -13,9 +13,6 @@ Lang::$translations = array(
|
||||
'Logged as: %s' => 'Zalogowany jako: %s',
|
||||
'Logout successful.' => 'Wylogowano pomyślnie.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ <a href="https://www.adminer.org/pl/donation/">dotację</a>.',
|
||||
'Loaded plugins' => 'Wczytane wtyczki',
|
||||
'%s must <a%s>return an array</a>.' => '%s musi <a%s>zwrócić tablicę</a>.',
|
||||
'<a%s>Configure</a> %s in %s.' => '<a%s>Skonfiguruj</a> %s w %s.',
|
||||
'Invalid credentials.' => 'Nieprawidłowe dane logowania.',
|
||||
'There is a space in the input password which might be the cause.' => 'W haśle wejściowym znajduje się spacja, która może być przyczyną.',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nie obsługuje dostępu do bazy danych bez hasła, <a href="https://www.adminer.org/pl/password/"%s>więcej informacji</a>.',
|
||||
@@ -79,6 +76,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Plik %s na serwerze',
|
||||
'Run file' => 'Uruchom z pliku',
|
||||
'File does not exist.' => 'Plik nie istnieje.',
|
||||
'Increase %s.' => 'Zwiększ %s.',
|
||||
'File uploads are disabled.' => 'Wgrywanie plików jest wyłączone.',
|
||||
'Unable to upload a file.' => 'Wgranie pliku było niemożliwe.',
|
||||
'Maximum allowed file size is %sB.' => 'Maksymalna wielkość pliku to %sB.',
|
||||
@@ -90,6 +88,7 @@ Lang::$translations = array(
|
||||
'Output' => 'Rezultat',
|
||||
'open' => 'otwórz',
|
||||
'save' => 'zapisz',
|
||||
'Saving' => 'Zapisywanie',
|
||||
'Format' => 'Format',
|
||||
'Data' => 'Dane',
|
||||
|
||||
@@ -197,6 +196,8 @@ Lang::$translations = array(
|
||||
'Partitions' => 'Partycje',
|
||||
'Partition name' => 'Nazwa partycji',
|
||||
'Values' => 'Wartości',
|
||||
'Inherits from' => 'Dziedziczy po',
|
||||
'Inherited by' => 'Odziedziczone przez',
|
||||
|
||||
'View' => 'Perspektywa',
|
||||
'Materialized view' => 'Zmaterializowana perspektywa',
|
||||
@@ -212,6 +213,8 @@ Lang::$translations = array(
|
||||
'Add next' => 'Dodaj następny',
|
||||
'Index Type' => 'Typ indeksu',
|
||||
'length' => 'długość',
|
||||
'Algorithm' => 'Algorytm',
|
||||
'Condition' => 'Warunek',
|
||||
|
||||
'Foreign keys' => 'Klucze obce',
|
||||
'Foreign key' => 'Klucz obcy',
|
||||
@@ -288,7 +291,6 @@ Lang::$translations = array(
|
||||
'Edit' => 'Edytuj',
|
||||
'Insert' => 'Dodaj',
|
||||
'Save' => 'Zapisz zmiany',
|
||||
'Saving' => 'Zapisywanie',
|
||||
'Save and continue edit' => 'Zapisz i kontynuuj edycję',
|
||||
'Save and insert next' => 'Zapisz i dodaj następny',
|
||||
'Selected' => 'Zaznaczone',
|
||||
@@ -352,6 +354,11 @@ Lang::$translations = array(
|
||||
'Check has been created.' => 'Kontrola została utworzona.',
|
||||
'Check has been altered.' => 'Kontrola została zmieniona.',
|
||||
'Check has been dropped.' => 'Kontrola została usunięta.',
|
||||
|
||||
'Loaded plugins' => 'Wczytane wtyczki',
|
||||
'%s must <a%s>return an array</a>.' => '%s musi <a%s>zwrócić tablicę</a>.',
|
||||
'<a%s>Configure</a> %s in %s.' => '<a%s>Skonfiguruj</a> %s w %s.',
|
||||
'screenshot' => 'zrzut ekranu',
|
||||
);
|
||||
|
||||
// run `php ../../lang.php pl` to update this file
|
||||
|
@@ -77,6 +77,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Xx %s',
|
||||
'Run file' => 'Xx',
|
||||
'File does not exist.' => 'Xx.',
|
||||
'Increase %s.' => 'Xx %s.',
|
||||
'File uploads are disabled.' => 'Xx.',
|
||||
'Unable to upload a file.' => 'Xx.',
|
||||
'Maximum allowed file size is %sB.' => 'Xx %sB.',
|
||||
@@ -196,6 +197,8 @@ Lang::$translations = array(
|
||||
'Partitions' => 'Xx',
|
||||
'Partition name' => 'Xx',
|
||||
'Values' => 'Xx',
|
||||
'Inherits from' => 'Xx',
|
||||
'Inherited by' => 'Xx',
|
||||
|
||||
'View' => 'Xx',
|
||||
'Materialized view' => 'Xx',
|
||||
@@ -211,6 +214,8 @@ Lang::$translations = array(
|
||||
'Add next' => 'Xx',
|
||||
'Index Type' => 'Xx',
|
||||
'length' => 'xx',
|
||||
'Algorithm' => 'Xx',
|
||||
'Condition' => 'Xx',
|
||||
|
||||
'Foreign keys' => 'Xx',
|
||||
'Foreign key' => 'Xx',
|
||||
|
@@ -56,13 +56,13 @@ echo ($collations ? "<datalist id='collations'>" . optionlist($collations) . "</
|
||||
edit_fields($row["fields"], $collations, $routine);
|
||||
if (isset($_GET["function"])) {
|
||||
echo "<tr><td>" . lang('Return type');
|
||||
edit_type("returns", $row["returns"], $collations, array(), (JUSH == "pgsql" ? array("void", "trigger") : array()));
|
||||
edit_type("returns", (array) $row["returns"], $collations, array(), (JUSH == "pgsql" ? array("void", "trigger") : array()));
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
<?php echo script("editFields();"); ?>
|
||||
</div>
|
||||
<p><?php textarea("definition", $row["definition"]); ?>
|
||||
<p><?php textarea("definition", $row["definition"], 20); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($PROCEDURE != "") { ?>
|
||||
|
@@ -5,7 +5,7 @@ if (support("kill")) {
|
||||
if ($_POST && !$error) {
|
||||
$killed = 0;
|
||||
foreach ((array) $_POST["kill"] as $val) {
|
||||
if (kill_process($val)) {
|
||||
if (adminer()->killProcess($val)) {
|
||||
$killed++;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ page_header(lang('Process list'), $error);
|
||||
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
|
||||
// HTML valid because there is always at least one process
|
||||
$i = -1;
|
||||
foreach (process_list() as $i => $row) {
|
||||
foreach (adminer()->processList() as $i => $row) {
|
||||
if (!$i) {
|
||||
echo "<thead><tr lang='en'>" . (support("kill") ? "<th>" : "");
|
||||
foreach ($row as $key => $val) {
|
||||
|
@@ -7,7 +7,7 @@ if ($_GET["script"] == "db") {
|
||||
$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
|
||||
foreach (table_status() as $name => $table_status) {
|
||||
json_row("Comment-$name", h($table_status["Comment"]));
|
||||
if (!is_view($table_status)) {
|
||||
if (!is_view($table_status) || preg_match('~materialized~i', $table_status["Engine"])) {
|
||||
foreach (array("Engine", "Collation") as $key) {
|
||||
json_row("$key-$name", h($table_status[$key]));
|
||||
}
|
||||
|
@@ -354,7 +354,7 @@ if (!$columns && support("table")) {
|
||||
echo "<th id='th[" . h(bracket_escape($key)) . "]'>" . script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});", "");
|
||||
$fun = apply_sql_function($val["fun"], $name); //! columns looking like functions
|
||||
$sortable = isset($field["privileges"]["order"]) || $fun;
|
||||
echo ($sortable ? '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && $is_group && $group[0] == $column) ? $desc : '')) . '">' . "$fun</a>" : $fun); // $order[0] == $key - COUNT(*)
|
||||
echo ($sortable ? "<a href='" . h($href . ($order[0] == $column || $order[0] == $key ? $desc : '')) . "'>$fun</a>" : $fun); // $order[0] == $key - COUNT(*)
|
||||
echo "<span class='column hidden'>";
|
||||
if ($sortable) {
|
||||
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
|
||||
@@ -389,10 +389,12 @@ if (!$columns && support("table")) {
|
||||
$unique_array = unique_array($rows[$n], $indexes);
|
||||
if (!$unique_array) {
|
||||
$unique_array = array();
|
||||
reset($select);
|
||||
foreach ($rows[$n] as $key => $val) {
|
||||
if (!preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~', $key)) { //! columns looking like functions
|
||||
if (!preg_match('~^(COUNT|AVG|GROUP_CONCAT|MAX|MIN|SUM)\(~', current($select))) {
|
||||
$unique_array[$key] = $val;
|
||||
}
|
||||
next($select);
|
||||
}
|
||||
}
|
||||
$unique_idf = "";
|
||||
@@ -410,8 +412,10 @@ if (!$columns && support("table")) {
|
||||
. ($is_group || information_schema(DB) ? "" : " <a href='" . h(ME . "edit=" . urlencode($TABLE) . $unique_idf) . "' class='edit'>" . lang('edit') . "</a>")
|
||||
);
|
||||
|
||||
reset($select);
|
||||
foreach ($row as $key => $val) {
|
||||
if (isset($names[$key])) {
|
||||
$column = current($select);
|
||||
$field = (array) $fields[$key];
|
||||
$val = driver()->value($val, $field);
|
||||
if ($val != "" && (!isset($email_fields[$key]) || $email_fields[$key] != "")) {
|
||||
@@ -439,7 +443,7 @@ if (!$columns && support("table")) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($key == "COUNT(*)") { //! columns looking like functions
|
||||
if ($column == "COUNT(*)") {
|
||||
$link = ME . "select=" . urlencode($TABLE);
|
||||
$i = 0;
|
||||
foreach ((array) $_GET["where"] as $v) {
|
||||
@@ -456,8 +460,10 @@ if (!$columns && support("table")) {
|
||||
$id = h("val[$unique_idf][" . bracket_escape($key) . "]");
|
||||
$posted = idx(idx($_POST["val"], $unique_idf), bracket_escape($key));
|
||||
$editable = !is_array($row[$key]) && is_utf8($html) && $rows[$n][$key] == $row[$key] && !$functions[$key] && !$field["generated"];
|
||||
$text = preg_match('~text|json|lob~', $field["type"]);
|
||||
echo "<td id='$id'" . (preg_match(number_type(), $field["type"]) && ($val === null || is_numeric(strip_tags($html))) ? " class='number'" : "");
|
||||
$type = (preg_match('~^(AVG|MIN|MAX)\((.+)\)~', $column, $match) ? $fields[idf_unescape($match[2])]["type"] : $field["type"]);
|
||||
$text = preg_match('~text|json|lob~', $type);
|
||||
$is_number = preg_match(number_type(), $type) || preg_match('~^(CHAR_LENGTH|ROUND|FLOOR|CEIL|TIME_TO_SEC|COUNT|SUM)\(~', $column);
|
||||
echo "<td id='$id'" . ($is_number && ($val === null || is_numeric(strip_tags($html)) || $type == "money") ? " class='number'" : "");
|
||||
if (($_GET["modify"] && $editable && $val !== null) || $posted !== null) {
|
||||
$h_value = h($posted !== null ? $posted : $row[$key]);
|
||||
echo ">" . ($text ? "<textarea name='$id' cols='30' rows='" . (substr_count($row[$key], "\n") + 1) . "'>$h_value</textarea>" : "<input name='$id' value='$h_value' size='$lengths[$key]'>");
|
||||
@@ -469,6 +475,7 @@ if (!$columns && support("table")) {
|
||||
;
|
||||
}
|
||||
}
|
||||
next($select);
|
||||
}
|
||||
|
||||
if ($backward_keys) {
|
||||
|
@@ -4,9 +4,13 @@ namespace Adminer;
|
||||
if (!$error && $_POST["export"]) {
|
||||
save_settings(array("output" => $_POST["output"], "format" => $_POST["format"]), "adminer_import");
|
||||
dump_headers("sql");
|
||||
adminer()->dumpTable("", "");
|
||||
adminer()->dumpData("", "table", $_POST["query"]);
|
||||
adminer()->dumpFooter();
|
||||
if ($_POST["format"] == "sql") {
|
||||
echo "$_POST[query]\n";
|
||||
} else {
|
||||
adminer()->dumpTable("", "");
|
||||
adminer()->dumpData("", "table", $_POST["query"]);
|
||||
adminer()->dumpFooter();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -65,11 +69,9 @@ if (!$error && $_POST) {
|
||||
}
|
||||
$commands = 0;
|
||||
$errors = array();
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|' . $line_comment . '|$' . (JUSH == "pgsql" ? '|\$[^$]*\$' : '');
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|' . $line_comment . '|$' . (JUSH == "pgsql" ? '|\$([a-zA-Z]\w*)?\$' : '');
|
||||
$total_start = microtime(true);
|
||||
$adminer_export = get_settings("adminer_import"); // this doesn't offer SQL export so we match the import/export style at select
|
||||
$dump_format = adminer()->dumpFormat();
|
||||
unset($dump_format["sql"]);
|
||||
|
||||
while ($query != "") {
|
||||
if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) {
|
||||
@@ -174,7 +176,7 @@ if (!$error && $_POST) {
|
||||
$id = "export-$commands";
|
||||
echo ", <a href='#$id'>" . lang('Export') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "") . "<span id='$id' class='hidden'>: "
|
||||
. html_select("output", adminer()->dumpOutput(), $adminer_export["output"]) . " "
|
||||
. html_select("format", $dump_format, $adminer_export["format"])
|
||||
. html_select("format", adminer()->dumpFormat(), $adminer_export["format"])
|
||||
. input_hidden("query", $q)
|
||||
. "<input type='submit' name='export' value='" . lang('Export') . "'>" . input_token() . "</span>\n"
|
||||
. "</form>\n"
|
||||
@@ -250,8 +252,11 @@ if (!isset($_GET["import"])) {
|
||||
} else {
|
||||
echo "<fieldset><legend>" . lang('File upload') . "</legend><div>";
|
||||
$gz = (extension_loaded("zlib") ? "[.gz]" : "");
|
||||
$max_file_uploads = "max_file_uploads";
|
||||
$max_file_uploads_value = ini_get($max_file_uploads);
|
||||
echo (ini_bool("file_uploads")
|
||||
? "SQL$gz (< " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n$execute" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
|
||||
? "SQL$gz (< " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
|
||||
. script("qsl('input').onchange = partialArg(fileChange, $max_file_uploads_value, '" . lang('Increase %s.', "$max_file_uploads = $max_file_uploads_value") . "')") . $execute
|
||||
: lang('File uploads are disabled.')
|
||||
);
|
||||
echo "</div></fieldset>\n";
|
||||
|
@@ -4,17 +4,16 @@ html {
|
||||
--bg: #002240;
|
||||
--fg: #829bb0;
|
||||
--dim: #154269;
|
||||
--lit: #011d35;
|
||||
}
|
||||
|
||||
a { color: #618CB3; }
|
||||
a:visited { color: #618CB3; }
|
||||
a, a:visited { color: #618cb3; }
|
||||
a:link:hover, a:visited:hover { color: #9bc0e1; }
|
||||
h1 { border-color: #5e94c1; color: #ffddbf; }
|
||||
h2 { border-color: #a3bdd3; color: #000; background: #3c678d; }
|
||||
table, td, th { border-color: #0e416d; }
|
||||
table, td, th, .js .column { border-color: #0e416d; }
|
||||
th { background: #11385a; }
|
||||
thead td, thead th { color: #a8b05f; background: #011d35; }
|
||||
thead th a { color: #a8b05f; }
|
||||
thead td, thead th, thead th a { color: #a8b05f; }
|
||||
fieldset { border-color: #16548a; }
|
||||
code { background: #11385a; }
|
||||
tbody tr:hover td, tbody tr:hover th { background: #133553; }
|
||||
@@ -22,7 +21,6 @@ pre.jush { background: #11385a; }
|
||||
input.default { box-shadow: 1px 1px 1px #888; }
|
||||
input.required, input.maxlength { box-shadow: 1px 1px 1px red; }
|
||||
.version { color: #888; }
|
||||
.js .column { background: #011d35; }
|
||||
.error { color: red; background: #efdada; border: 1px solid #e76f6f; }
|
||||
.error b { background: #efeaea; }
|
||||
.message { color: #0b860b; background: #efe; border: 1px solid #7fbd7f; }
|
||||
@@ -45,3 +43,4 @@ input.required, input.maxlength { box-shadow: 1px 1px 1px red; }
|
||||
#schema div.table a { color: #3c7bb3; }
|
||||
#menu .active { color: #398c8d; }
|
||||
#edit-fields tbody tr:hover td, #edit-fields tbody tr:hover th { background: #3b6f9d; }
|
||||
:target { color: #a8b05f; }
|
||||
|
@@ -4,6 +4,7 @@ html {
|
||||
--bg: #fff;
|
||||
--fg: #000;
|
||||
--dim: #eee;
|
||||
--lit: #ddf;
|
||||
}
|
||||
|
||||
body { color: var(--fg); background: var(--bg); font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; min-width: fit-content; }
|
||||
@@ -13,17 +14,17 @@ a:link:hover, a:visited:hover { color: red; text-decoration: underline; }
|
||||
a.text:hover { text-decoration: none; }
|
||||
a.jush-help:hover { color: inherit; }
|
||||
h1 { font-size: 150%; margin: 0; padding: .8em .667em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: var(--dim); }
|
||||
h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom: 1px solid var(--fg); font-weight: normal; background: #ddf; }
|
||||
h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom: 1px solid var(--fg); font-weight: normal; background: var(--lit); }
|
||||
h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; }
|
||||
form { margin: 0; }
|
||||
td table { width: 100%; margin: 0; }
|
||||
table { margin: 1em 20px 0 0; font-size: 90%; border-spacing: 0; border-width: 1px 0 0 1px; }
|
||||
table, td, th { border-color: #999; border-style: solid; }
|
||||
table, td, th, .js .column { border-color: #999; border-style: solid; }
|
||||
td, th { border-width: 0 1px 1px 0; padding: .2em .3em; margin: 0; }
|
||||
th { background: var(--dim); text-align: left; }
|
||||
thead { position: sticky; top: 0; }
|
||||
thead th { text-align: center; padding: .2em .5em; }
|
||||
thead td, thead th { background: #ddf; }
|
||||
thead td, thead th { background: var(--lit); }
|
||||
fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: .8em .5em 0 0; border: 1px solid #999; border-radius: 5px; }
|
||||
p { margin: .8em 20px 0 0; }
|
||||
img { vertical-align: middle; border: 0; }
|
||||
@@ -44,7 +45,7 @@ input.wayoff { left: -1000px; position: absolute; }
|
||||
.block { display: block; }
|
||||
.version { color: #777; font-size: 62%; }
|
||||
.js .hidden, .nojs .jsonly { display: none; }
|
||||
.js .column { position: absolute; background: #ddf; padding: .27em 1ex .3em 0; margin-top: -.27em; }
|
||||
.js .column { position: absolute; background: var(--lit); padding: .27em 1ex .33em 0; margin-top: -.37em; border-width: 1px 1px 1px 0; border-radius: 0 8px 8px 0; }
|
||||
.nowrap td, .nowrap th, td.nowrap, p.nowrap { white-space: pre; }
|
||||
.wrap td { white-space: normal; }
|
||||
.error { color: red; background: #fee; }
|
||||
@@ -57,7 +58,7 @@ input.wayoff { left: -1000px; position: absolute; }
|
||||
.enum { color: #007F7F; }
|
||||
.binary { color: red; }
|
||||
.odds tbody tr:nth-child(2n) { background: #F5F5F5; }
|
||||
.js .checkable .checked td, .js .checkable .checked th { background: #ddf; }
|
||||
.js .checkable .checked td, .js .checkable .checked th { background: var(--lit); }
|
||||
.time { color: silver; font-size: 70%; }
|
||||
.function, .number, .datetime { text-align: right; }
|
||||
.type { width: 15ex; }
|
||||
@@ -67,7 +68,7 @@ input.wayoff { left: -1000px; position: absolute; }
|
||||
.sqlarea { width: 98%; }
|
||||
.sql-footer { margin-bottom: 2.5em; }
|
||||
.explain table { white-space: pre; }
|
||||
.icon { width: 18px; height: 18px; background: navy center no-repeat; border: 0; vertical-align: middle; }
|
||||
.icon { width: 18px; height: 18px; background: navy center no-repeat; border: 0; padding: 0; vertical-align: middle; }
|
||||
.icon span { display: none; }
|
||||
.icon:hover { background-color: red; }
|
||||
.size { width: 7ex; }
|
||||
@@ -96,6 +97,7 @@ input.wayoff { left: -1000px; position: absolute; }
|
||||
#schema .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; }
|
||||
#schema .references { position: absolute; }
|
||||
#help { position: absolute; border: 1px solid #999; background: var(--dim); padding: 5px; font-family: monospace; z-index: 1; }
|
||||
:target { background: var(--lit); }
|
||||
|
||||
/* inlined here and not in compile.php because otherwise the development version flickers a little bit when loading the images */
|
||||
.icon-up { background-image: url(data:image/gif;base64,R0lGODlhEgASAIEAMe7u7gAAgJmZmQAAACH5BAEAAAEALAAAAAASABIAAQIghI+py+0PTQhRTgrvfRP0nmEVOIoReZphxbauAMfyHBcAOw==); }
|
||||
|
@@ -665,6 +665,17 @@ function sqlSubmit(form, root) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if PHP can handle the uploaded files
|
||||
* @param number
|
||||
* @param string
|
||||
* @param Event
|
||||
*/
|
||||
function fileChange(event, maxFileUploads, message) {
|
||||
if (event.target.files.length > maxFileUploads) {
|
||||
alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Handle changing trigger time or event
|
||||
|
@@ -26,11 +26,25 @@ if ($fields) {
|
||||
adminer()->tableStructurePrint($fields, $table_status);
|
||||
}
|
||||
|
||||
function tables_links($tables) {
|
||||
echo "<ul>\n";
|
||||
foreach ($tables as $table) {
|
||||
echo "<li><a href='" . h(ME . "table=" . urlencode($table)) . "'>" . h($table) . "</a>";
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
|
||||
$inherits = driver()->inheritsFrom($TABLE);
|
||||
if ($inherits) {
|
||||
echo "<h3>" . lang('Inherits from') . "</h3>\n";
|
||||
tables_links($inherits);
|
||||
}
|
||||
|
||||
if (support("indexes") && driver()->supportsIndex($table_status)) {
|
||||
echo "<h3 id='indexes'>" . lang('Indexes') . "</h3>\n";
|
||||
$indexes = indexes($TABLE);
|
||||
if ($indexes) {
|
||||
adminer()->tableIndexesPrint($indexes);
|
||||
adminer()->tableIndexesPrint($indexes, $table_status);
|
||||
}
|
||||
echo '<p class="links"><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n";
|
||||
}
|
||||
@@ -95,3 +109,13 @@ if (support(is_view($table_status) ? "view_trigger" : "trigger")) {
|
||||
}
|
||||
echo '<p class="links"><a href="' . h(ME) . 'trigger=' . urlencode($TABLE) . '">' . lang('Add trigger') . "</a>\n";
|
||||
}
|
||||
|
||||
$inherited = driver()->inheritedTables($TABLE);
|
||||
if ($inherited) {
|
||||
echo "<h3 id='partitions'>" . lang('Inherited by') . "</h3>\n";
|
||||
$partition = driver()->partitionsInfo($TABLE);
|
||||
if ($partition) {
|
||||
echo "<p><code class='jush-" . JUSH . "'>BY " . h("$partition[partition_by]($partition[partition])") . "</code>\n";
|
||||
}
|
||||
tables_links($inherited);
|
||||
}
|
||||
|
@@ -165,7 +165,7 @@ function put_file_lang($match) {
|
||||
case "' . $lang . '": $compressed = "' . add_quo_slashes(lzw_compress(implode("\n", $translation_ids))) . '"; break;';
|
||||
}
|
||||
$translations_version = crc32($return);
|
||||
return 'Lang::$translations = $_SESSION["translations"];
|
||||
return 'Lang::$translations = (array) $_SESSION["translations"];
|
||||
if ($_SESSION["translations_version"] != LANG . ' . $translations_version . ') {
|
||||
Lang::$translations = array();
|
||||
$_SESSION["translations_version"] = LANG . ' . $translations_version . ';
|
||||
|
2
designs/lavender-light/README.md
Normal file
2
designs/lavender-light/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Screenshot
|
||||

|
283
designs/lavender-light/adminer.css
Normal file
283
designs/lavender-light/adminer.css
Normal file
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* lavender-light theme for Adminer
|
||||
* by Alex Yu
|
||||
*
|
||||
* Color palette from:
|
||||
* https://color.adobe.com/Lavender-v2-color-theme-294b8aa6-1935-401f-a763-13b98ec68b90/
|
||||
*
|
||||
* - white
|
||||
* - ghostwhite (f8f8ff)
|
||||
* - lavender (f0f0ff)
|
||||
* - darkslateblue (483d8b)
|
||||
* - aliceblue (f0f8ff)
|
||||
* - gray (313b43), (21282e)
|
||||
* - blue (001dff), (002799)
|
||||
*/
|
||||
|
||||
body {
|
||||
display: grid;
|
||||
column-gap: 1rem;
|
||||
row-gap: 20px;
|
||||
|
||||
width: 100%;
|
||||
height: auto;
|
||||
|
||||
grid-template-areas:
|
||||
"menu content";
|
||||
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: 21rem 1fr;
|
||||
|
||||
align-items: stretch;
|
||||
justify-items: start;
|
||||
|
||||
font: 0.96rem/1.2rem sans-serif !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #001dff;
|
||||
text-underline-offset: 1px;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(.4,0,.2,1);
|
||||
transition-duration: .15s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic tags
|
||||
*/
|
||||
|
||||
a:visited {
|
||||
color: #002799;
|
||||
}
|
||||
|
||||
a:link:hover, a:visited:hover {
|
||||
color: #7388c9;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0 0 20px 0px;
|
||||
line-height: 1.68rem;
|
||||
border-bottom: 1px solid #20165a; /* darkslateblue; */
|
||||
background: #3c3085;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#h1 {
|
||||
font-size: 1.2rem;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#h1 img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tables
|
||||
*/
|
||||
|
||||
table {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
|
||||
#table .column {
|
||||
display: none;
|
||||
}
|
||||
|
||||
td, th {
|
||||
font-size: 1.05em;
|
||||
border-right: 1px solid silver;
|
||||
border-bottom: 1px solid silver;
|
||||
padding: .3em .6em;
|
||||
background: none;
|
||||
}
|
||||
|
||||
thead th, thead td {
|
||||
background: #313b43;
|
||||
color: white;
|
||||
border-right: 1px solid #21282e;
|
||||
border-bottom: 1px solid #21282e;
|
||||
padding: .5em .5em;
|
||||
}
|
||||
|
||||
thead th a, thead td a,
|
||||
thead th a:visited, thead td a:visited,
|
||||
thead th a:hover, thead td a:hover {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
th span.column a.text {
|
||||
color: #2980b9;
|
||||
}
|
||||
|
||||
.js span.column {
|
||||
background: white;
|
||||
}
|
||||
|
||||
|
||||
table#table thead .checked td,
|
||||
table#table thead .checked th {
|
||||
background: #313b43;
|
||||
}
|
||||
|
||||
.pages {
|
||||
border: none;
|
||||
box-shadow: -1px -1px 4px silver;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common sections
|
||||
*/
|
||||
|
||||
#breadcrumb {
|
||||
position: static;
|
||||
top: initial;
|
||||
left: initial;
|
||||
margin: 0;
|
||||
padding: 0.6rem 0 0.4rem 0;
|
||||
color: #596167;
|
||||
background: none;
|
||||
}
|
||||
|
||||
#breadcrumb a {
|
||||
color: #002799;
|
||||
}
|
||||
|
||||
#content {
|
||||
grid-area: content;
|
||||
margin: 0;
|
||||
padding: 0 20px 0 0;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
#logout {
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
padding: 0.3rem 0.7rem;
|
||||
}
|
||||
|
||||
#menu {
|
||||
grid-area: menu;
|
||||
position: initial;
|
||||
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem;
|
||||
width: 18rem;
|
||||
|
||||
background: ghostwhite;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#menu h1 {
|
||||
padding: 0 0 1rem 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
#menu #dbs {
|
||||
padding: 3rem 0 1.5rem;
|
||||
}
|
||||
|
||||
#menu p, #logins, #tables {
|
||||
padding: .8em 0em 1.2rem;
|
||||
}
|
||||
|
||||
#menu #tables a[href*="&select="] {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHISURBVDjLpVPNK0RRFP+9D98syMwUspHkm9I0YkFZWBFKkZ0s7a3Ewh+ilChK7FgoZCJFKYlYKB8zk2+Z5t0P577He29kQU7dd+6575zf+d1zztWklPiPmOozt/U4SThjXIoyIQS4AJjSXO0lGGlvcXAm6Vzsz4xUhm0AIeX4QLig+C+ZpxbOG1wGhGYHr1zMUmZGWRgs0ha3PE1nX/8mWmdgWTzLB+DUYbhm9FfZ35IEyrhXA3VXJfPbsV8B9LQUIeUHYJ8ASobag1jcucNgW8g9W4reYSDi2YnnZDoDiwCokDANct6NwTB0LEdj0HRA/wxa2SN25JNBEdWluUhZ366gqmAaGvrCAXKOozccTGPgt8+vn8GYSGcgyTYp3dpBnBg42nbQPRBTo5bTvqYkmxL6AQhNTWQGBXY3B7BxlEBXozcW64dxRKoKUZBju+P06gl5WaaviMJBM3TNDlbypemIZgHYOnlwASsCmW7nHADGnBoQ3c76YmweJ9BR5zFYjsbRHwm4tmJg6PhWA7pCXXk+bu7fURHKweXtq/sWaksz7SC/CCGFrwtyZ3r+rCnFRZ7qr1qc6mLZj4f9OEyPL8lVpbX/PucPv5QPKHB1TdEAAAAASUVORK5CYII=) no-repeat scroll right bottom;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
margin-right: 4px;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
padding-left: 18px;
|
||||
border-left: 1px solid transparent;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
#menu #tables a.active {
|
||||
border-left: 1px solid #20165a;
|
||||
}
|
||||
|
||||
#menu .links {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
padding: 1rem 0 0 1.6rem;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#menu #tables li {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#menu #tables li a+a {
|
||||
padding-left: 0.3rem;
|
||||
}
|
||||
|
||||
#lang {
|
||||
position: absolute;
|
||||
top: 4rem;
|
||||
z-index: 100;
|
||||
padding: 0 0 0 1.5rem;
|
||||
}
|
||||
|
||||
#logins a, #tables a, #tables span {
|
||||
background: initial;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elements
|
||||
*/
|
||||
|
||||
sup {
|
||||
padding: 3px 7px;
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border-radius: 2em;
|
||||
}
|
||||
|
||||
code.jush-sql {
|
||||
display: block;
|
||||
padding: .4em .7em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.jush-bac, .jush-php_bac, .jush-bra, .jush-mssql_bra, .jush-sqlite_quo {
|
||||
color: #dc33f9;
|
||||
}
|
||||
|
||||
pre, textarea {
|
||||
padding: 1.5rem;
|
||||
font: 100% / 1.25 monospace;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
background: #f2f2ff;
|
||||
}
|
||||
|
||||
pre.sqlarea {
|
||||
padding: 1rem !important;
|
||||
border: 2px solid #a9a9a9 !important;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
a.jush-custom:link, a.jush-custom:visited {
|
||||
color: midnightblue;
|
||||
}
|
||||
|
||||
select, input {
|
||||
padding: 2px;
|
||||
}
|
2
designs/win98/README.md
Normal file
2
designs/win98/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Screenshot
|
||||

|
298
designs/win98/adminer.css
Normal file
298
designs/win98/adminer.css
Normal file
@@ -0,0 +1,298 @@
|
||||
/* inspired by https://github.com/jdan/98.css */
|
||||
|
||||
:root {
|
||||
--text-color: #222222;
|
||||
--button-face: #dfdfdf;
|
||||
--window-frame: #0a0a0a;
|
||||
--dialog-blue-light: #1084d0;
|
||||
--link-blue: #0000ff;
|
||||
}
|
||||
|
||||
body {
|
||||
background: teal;
|
||||
color: var(--text-color);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
button, input[type=reset], input[type=submit] {
|
||||
background: silver;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px white, inset -2px -2px grey, inset 2px 2px var(--button-face);
|
||||
box-sizing: border-box;
|
||||
color: transparent;
|
||||
font-size: 12px;
|
||||
min-height: 23px;
|
||||
min-width: 75px;
|
||||
padding: 0 12px;
|
||||
text-shadow: 0 0 var(--text-color);
|
||||
}
|
||||
|
||||
button.default, input[type=reset].default, input[type=submit].default {
|
||||
box-shadow: inset -2px -2px var(--window-frame), inset 1px 1px var(--window-frame), inset 2px 2px white, inset -3px -3px grey, inset 3px 3px var(--button-face);
|
||||
}
|
||||
|
||||
button:not(:disabled):active, input[type=reset]:not(:disabled):active, input[type=submit]:not(:disabled):active {
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px var(--window-frame), inset -2px -2px var(--button-face), inset 2px 2px grey;
|
||||
text-shadow: 1px 1px var(--text-color);
|
||||
}
|
||||
|
||||
button.default:not(:disabled):active, input[type=reset].default:not(:disabled):active, input[type=submit].default:not(:disabled):active {
|
||||
box-shadow: inset 2px 2px var(--window-frame), inset -1px -1px var(--window-frame), inset -2px -2px white, inset 3px 3px grey, inset -3px -3px var(--button-face);
|
||||
}
|
||||
|
||||
button:focus, input[type=reset]:focus, input[type=submit]:focus {
|
||||
outline: 1px dotted black;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner, input[type=reset]::-moz-focus-inner, input[type=submit]::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:disabled, :disabled + label, input[readonly], input[readonly] + label, input[type=submit]:disabled, input[type=reset]:disabled, input[type=submit]:disabled {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
:disabled + label, button:disabled, input[type=reset]:disabled, input[type=submit]:disabled {
|
||||
text-shadow: 1px 1px 0 white;
|
||||
}
|
||||
|
||||
#content, #menu, .footer, #breadcrumb {
|
||||
background: silver;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px var(--button-face), inset -2px -2px grey, inset 2px 2px white;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#content h2 {
|
||||
align-items: center;
|
||||
background: linear-gradient(90deg, navy, var(--dialog-blue-light));
|
||||
color: white;
|
||||
display: flex;
|
||||
font-size: 120%;
|
||||
font-weight: normal;
|
||||
justify-content: space-between;
|
||||
letter-spacing: 0;
|
||||
margin: -13px -13px 16px -13px;
|
||||
padding: 3px 2px 3px 3px;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' fill='gray' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h5v5H0V2h2v1h1V2H0' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h4v4H0V1h1v2h2V1H0'/%3E%3C/svg%3E") 2;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
padding-block-start: 8px;
|
||||
}
|
||||
|
||||
legend {
|
||||
background: silver;
|
||||
}
|
||||
|
||||
input[type=email], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text], input:not([type]) {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input[type=email], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text], select, input:not([type]) {
|
||||
background-color: white;
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px grey, inset -2px -2px var(--button-face), inset 2px 2px var(--window-frame);
|
||||
box-sizing: border-box;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
select, textarea {
|
||||
border: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: white;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px grey, inset -2px -2px var(--button-face), inset 2px 2px var(--window-frame);
|
||||
box-sizing: border-box;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
input[type=email], input[type=password], input[type=search], input[type=tel], input[type=text], input[type=number], select {
|
||||
min-height: 21px;
|
||||
}
|
||||
|
||||
input[type=search]::-ms-clear, input[type=search]::-ms-reveal {
|
||||
display: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration, input[type=search]::-webkit-search-results-button, input[type=search]::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=email]:disabled, input[type=email]:read-only, input[type=number]:disabled, input[type=number]:read-only, input[type=password]:disabled, input[type=password]:read-only, input[type=search]:disabled, input[type=search]:read-only, input[type=tel]:disabled, input[type=tel]:read-only, input[type=text]:disabled, input[type=text]:read-only, textarea:disabled {
|
||||
background-color: silver;
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0v16h1V1h14V0z' fill='%23DFDFDF'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1v14h1V2h12V1H2z' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H0v-1h15V0h1v17z' fill='%23000'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1h-1v14H1v1h14V1z' fill='gray'/%3E%3Cpath fill='silver' d='M2 2h12v13H2z'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 6H4v1h1v1h1v1h1v1h1V9h1V8h1V7h1V6z' fill='%23000'/%3E%3C/svg%3E");
|
||||
background-position: top 2px right 2px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0;
|
||||
padding-right: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type=email]:focus, input[type=number]:focus, input[type=password]:focus, input[type=search]:focus, input[type=tel]:focus, input[type=text]:focus, select:focus, textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
background-color: navy;
|
||||
color: white;
|
||||
}
|
||||
|
||||
select:focus option {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
select:active {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h16v17H0V0zm1 16h14V1H1v15z' fill='gray'/%3E%3Cpath fill='silver' d='M1 1h14v15H1z'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 7H5v1h1v1h1v1h1v1h1v-1h1V9h1V8h1V7z' fill='%23000'/%3E%3C/svg%3E")
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-blue);
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted var(--link-blue);
|
||||
}
|
||||
|
||||
pre {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' fill='gray' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h5v5H0V2h2v1h1V2H0' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h4v4H0V1h1v2h2V1H0'/%3E%3C/svg%3E") 2;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
margin: 0;
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
table > thead > tr > * {
|
||||
background: silver;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px white, inset -2px -2px grey, inset 2px 2px var(--button-face);
|
||||
}
|
||||
|
||||
table.interactive > tbody > tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#fieldset-sort > div:not(:last-of-type), #fieldset-search > div:not(:last-of-type), #fieldset-select > div:not(:last-of-type) {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
#fieldset-partition p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#logins a, #tables a, #tables span {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.jush-autocomplete, .jush-autocomplete:active {
|
||||
background: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.logout {
|
||||
box-shadow: none;
|
||||
margin-top: .8em;
|
||||
}
|
||||
|
||||
#breadcrumb {
|
||||
height: auto;
|
||||
margin: 0;
|
||||
padding: 2px 16px;
|
||||
top: calc(1.5em - 14px);
|
||||
}
|
||||
|
||||
code {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#menu {
|
||||
margin: 0;
|
||||
top: 3em;
|
||||
width: 18em;
|
||||
}
|
||||
|
||||
#menu h1 {
|
||||
background: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#menu h1 a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
#menu .links a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lang {
|
||||
top: -2.8em;
|
||||
}
|
||||
|
||||
#lang label {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.footer > div {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.js .column {
|
||||
background: silver;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px var(--button-face), inset -2px -2px grey, inset 2px 2px white;
|
||||
margin-top: -.4em;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
.js .logout {
|
||||
box-shadow: none;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#lang label {
|
||||
color: initial;
|
||||
}
|
||||
}
|
@@ -252,7 +252,8 @@ This extracts them for translation and applies translations if available.
|
||||
Translations are updated via [lang.php](/lang.php), which also checks for style consistency, such as matching punctuation.
|
||||
Plurals are stored as arrays, with selection logic handled in [lang.inc.php](/adminer/include/lang.inc.php).
|
||||
|
||||
Plugins extending [`Adminer\Plugin`](/adminer/include/plugin.inc.php) can use `$this->lang()` and store translations in `static $translations = array('en' => array('' => 'Plugin description'))`.
|
||||
Plugins extending [`Adminer\Plugin`](/adminer/include/plugin.inc.php) can use `$this->lang()` and store translations in `$translations = array('en' => array('' => 'Plugin description'))`.
|
||||
|
||||
The website translations are managed at https://www.adminer.org/en/translations/.
|
||||
|
||||
## Compilation
|
||||
|
@@ -59,6 +59,9 @@ class Adminer {
|
||||
return 5;
|
||||
}
|
||||
|
||||
function afterConnect() {
|
||||
}
|
||||
|
||||
function headers() {
|
||||
}
|
||||
|
||||
@@ -70,12 +73,20 @@ class Adminer {
|
||||
return true;
|
||||
}
|
||||
|
||||
function bodyClass(): void {
|
||||
echo " editor";
|
||||
}
|
||||
|
||||
function css() {
|
||||
$return = array();
|
||||
foreach (array("", "-dark") as $mode) {
|
||||
$filename = "adminer$mode.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = "$filename?v=" . crc32(file_get_contents($filename));
|
||||
$file = file_get_contents($filename);
|
||||
$return["$filename?v=" . crc32($file)] = ($mode
|
||||
? "dark"
|
||||
: (preg_match('~prefers-color-scheme:\s*dark~', $file) ? '' : 'light')
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
@@ -256,10 +267,11 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
if (preg_match("~enum~", $field["type"]) || like_bool($field)) { //! set - uses 1 << $i and FIND_IN_SET()
|
||||
$key = $keys[$name];
|
||||
$i--;
|
||||
echo "<div>" . h($desc) . input_hidden("where[$i][col]", $name) . ":";
|
||||
echo "<div>" . h($desc) . ":" . input_hidden("where[$i][col]", $name);
|
||||
$val = idx($where[$key], "val");
|
||||
echo (like_bool($field)
|
||||
? " <select name='where[$i][val]'>" . optionlist(array("" => "", lang('no'), lang('yes')), $where[$key]["val"], true) . "</select>"
|
||||
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $where[$key]["val"], ($field["null"] ? 0 : null))
|
||||
? "<select name='where[$i][val]'>" . optionlist(array("" => "", lang('no'), lang('yes')), $val, true) . "</select>"
|
||||
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $val, ($field["null"] ? 0 : null))
|
||||
);
|
||||
echo "</div>\n";
|
||||
unset($columns[$name]);
|
||||
@@ -357,14 +369,14 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
if ($col != "" || is_numeric($val) || !preg_match(number_type(), $field["type"])) {
|
||||
$name = idf_escape($name);
|
||||
if ($col != "" && $field["type"] == "enum") {
|
||||
$conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('intval', $val)) . ")";
|
||||
$conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('Adminer\q', $val)) . ")";
|
||||
} else {
|
||||
$text_type = preg_match('~char|text|enum|set~', $field["type"]);
|
||||
$value = adminer()->processInput($field, (!$op && $text_type && preg_match('~^[^%]+$~', $val) ? "%$val%" : $val));
|
||||
$conds[] = driver()->convertSearch($name, $where, $field) . ($value == "NULL" ? " IS" . ($op == ">=" ? " NOT" : "") . " $value"
|
||||
: (in_array($op, adminer()->operators()) || $op == "=" ? " $op $value"
|
||||
: ($text_type ? " LIKE $value"
|
||||
: " IN (" . str_replace(",", "', '", $value) . ")"
|
||||
: " IN (" . ($value[0] == "'" ? str_replace(",", "', '", $value) : $value) . ")"
|
||||
)));
|
||||
if ($key < 0 && $val == "0") {
|
||||
$conds[] = "$name IS NULL";
|
||||
@@ -492,7 +504,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
if (preg_match('~date|timestamp~', $field["type"]) && preg_match('(^' . str_replace('\$1', '(?P<p1>\d*)', preg_replace('~(\\\\\\$([2-6]))~', '(?P<p\2>\d{1,2})', preg_quote(lang('$1-$3-$5')))) . '(.*))', $value, $match)) {
|
||||
$return = ($match["p1"] != "" ? $match["p1"] : ($match["p2"] != "" ? ($match["p2"] < 70 ? 20 : 19) . $match["p2"] : gmdate("Y"))) . "-$match[p3]$match[p4]-$match[p5]$match[p6]" . end($match);
|
||||
}
|
||||
$return = ($field["type"] == "bit" && preg_match('~^[0-9]+$~', $value) ? $return : q($return));
|
||||
$return = q($return);
|
||||
if ($value == "" && like_bool($field)) {
|
||||
$return = "'0'";
|
||||
} elseif ($value == "" && ($field["null"] || !preg_match('~char|text~', $field["type"]))) {
|
||||
|
@@ -1,6 +1,10 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
function doc_link(array $paths, string $text = ""): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
/** Encode e-mail header in UTF-8 */
|
||||
function email_header(string $header): string {
|
||||
// iconv_mime_encode requires iconv, imap_8bit requires IMAP extension
|
||||
|
2
externals/PhpShrink
vendored
2
externals/PhpShrink
vendored
Submodule externals/PhpShrink updated: 10781d1fbf...b3d92cdf76
2
externals/jush
vendored
2
externals/jush
vendored
Submodule externals/jush updated: 5fa4d1f97e...1775a0dafa
12
lang.php
12
lang.php
@@ -12,15 +12,7 @@ if (isset($_SESSION["lang"])) {
|
||||
}
|
||||
|
||||
$messages_all = array();
|
||||
foreach (
|
||||
array_merge(
|
||||
glob(__DIR__ . "/adminer/*.php"),
|
||||
glob(__DIR__ . "/adminer/include/*.php"),
|
||||
glob(__DIR__ . "/adminer/drivers/*.php"),
|
||||
glob(__DIR__ . "/editor/*.php"),
|
||||
glob(__DIR__ . "/editor/include/*.php")
|
||||
) as $include
|
||||
) {
|
||||
foreach (glob(__DIR__ . "/{adminer,adminer/include,adminer/drivers,editor,editor/include}/*.php", GLOB_BRACE) as $include) {
|
||||
$file = file_get_contents($include);
|
||||
if (preg_match_all("~[^>]lang\\(('(?:[^\\\\']+|\\\\.)*')([),])~", $file, $matches)) { // lang() always uses apostrophes
|
||||
$messages_all += array_combine($matches[1], $matches[2]);
|
||||
@@ -53,7 +45,7 @@ function update_translations($lang, $messages, $filename, $pattern, $tabs = "\t"
|
||||
$start = $match[2][1];
|
||||
preg_match_all("~^(\\s*(?:// [^'].*\\s+)?)(?:// )?(('(?:[^\\\\']+|\\\\.)*') => (.*[^,\n])),?~m", $match[2][0], $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
|
||||
$s = "";
|
||||
$fullstop = ($lang == "bn" ? '।' : (preg_match('~^(ja|zh)~', $lang) ? '。' : ($lang == 'he' ? '[^.]' : '\.')));
|
||||
$fullstop = ($lang == 'bn' || $lang == 'hi' ? '।' : (preg_match('~^(ja|zh)~', $lang) ? '。' : ($lang == 'he' ? '[^.]' : '\.')));
|
||||
foreach ($matches as $match) {
|
||||
list(, list($indent), list($line, $offset), list($en), list($translation)) = $match;
|
||||
if (isset($messages[$en])) {
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<exclude-pattern>/(adminer|editor)[-.]</exclude-pattern>
|
||||
|
||||
<rule ref="PSR12">
|
||||
<exclude name="Generic.Whitespace.DisallowTabIndent"/><!-- Replaced by: Generic.Whitespace.DisallowSpaceIndent -->
|
||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/><!-- Replaced by: Generic.WhiteSpace.DisallowSpaceIndent -->
|
||||
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
|
||||
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
|
||||
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine"/><!-- Replaced by: Generic.Classes.OpeningBraceSameLine -->
|
||||
@@ -58,6 +58,7 @@
|
||||
<property name="lineLimit" value="250"/>
|
||||
</properties>
|
||||
<exclude-pattern>adminer/lang/</exclude-pattern>
|
||||
<exclude-pattern>plugins/foreign-system.php</exclude-pattern>
|
||||
</rule>
|
||||
|
||||
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
||||
@@ -86,7 +87,7 @@
|
||||
<rule ref="Generic.PHP.ForbiddenFunctions"/>
|
||||
<rule ref="Generic.Strings.UnnecessaryHeredoc"/>
|
||||
<rule ref="Generic.VersionControl.GitMergeConflict"/>
|
||||
<rule ref="Generic.Whitespace.DisallowSpaceIndent"/>
|
||||
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
|
||||
<rule ref="Generic.WhiteSpace.LanguageConstructSpacing"/>
|
||||
|
||||
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
|
||||
|
@@ -61,12 +61,13 @@ parameters:
|
||||
max: 80499
|
||||
|
||||
typeAliases:
|
||||
TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, nspname?:string}"
|
||||
TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, partition?:numeric-string, nspname?:string}"
|
||||
Field: "array{field?:string, full_type:string, type:string, length:numeric-string, unsigned:string, default?:string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update?:string, on_delete?:string, default_constraint?: string}"
|
||||
FieldType: "array{type:string, length:numeric-string, unsigned:string, collation:string}" # subset of RoutineField and Field
|
||||
RoutineField: "array{field:string, type:string, length:numeric-string, unsigned:string, null:bool, full_type:string, collation:string, inout?:string}"
|
||||
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>}"
|
||||
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>, algorithm?:string, partial?:string}"
|
||||
ForeignKey: "array{db?:string, ns?:string, table:string, source:list<string>, target:list<?string>, on_delete:string, on_update?:string, definition?:string, deferrable?:string}"
|
||||
Trigger: "array{Trigger?:string, Timing?:string, Event?:string, Of?:string, Type?:string, Statement?:string}"
|
||||
Routine: "array{name?:string, fields:list<RoutineField>, comment:string, returns?:FieldType, definition:string, language?:string}"
|
||||
Partitions: "array{partition_by?:string, partition?:string, partitions?:numeric-string, partition_names?:list<string>, partition_values?:list<string>}"
|
||||
BackwardKey: "array{name:string, keys:string[][]}"
|
||||
|
@@ -11,15 +11,26 @@ class AdminerBackwardKeys extends Adminer\Plugin {
|
||||
|
||||
function backwardKeys($table, $tableName) {
|
||||
$return = array();
|
||||
// we couldn't use the same query in MySQL and PostgreSQL because unique_constraint_name is not table-specific in MySQL and referenced_table_name is not available in PostgreSQL
|
||||
foreach (
|
||||
Adminer\get_rows($q = "SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = " . Adminer\q(Adminer\DB) . "
|
||||
AND REFERENCED_TABLE_SCHEMA = " . Adminer\q(Adminer\DB) . "
|
||||
AND REFERENCED_TABLE_NAME = " . Adminer\q($table) . "
|
||||
ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
Adminer\get_rows("SELECT s.table_name table_name, s.constraint_name constraint_name, s.column_name column_name, " . (Adminer\JUSH == "sql" ? "referenced_column_name" : "t.column_name") . " referenced_column_name
|
||||
FROM information_schema.key_column_usage s" . (Adminer\JUSH == "sql" ? "
|
||||
WHERE table_schema = " . Adminer\q(Adminer\DB) . "
|
||||
AND referenced_table_schema = " . Adminer\q(Adminer\DB) . "
|
||||
AND referenced_table_name" : "
|
||||
JOIN information_schema.referential_constraints r USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
JOIN information_schema.key_column_usage t ON r.unique_constraint_catalog = t.constraint_catalog
|
||||
AND r.unique_constraint_schema = t.constraint_schema
|
||||
AND r.unique_constraint_name = t.constraint_name
|
||||
AND r.constraint_catalog = t.constraint_catalog
|
||||
AND r.constraint_schema = t.constraint_schema
|
||||
AND r.unique_constraint_name = t.constraint_name
|
||||
AND s.position_in_unique_constraint = t.ordinal_position
|
||||
WHERE t.table_catalog = " . Adminer\q(Adminer\DB) . " AND t.table_schema = " . Adminer\q("$_GET[ns]") . "
|
||||
AND t.table_name") . " = " . Adminer\q($table) . "
|
||||
ORDER BY s.ordinal_position", null, "") as $row
|
||||
) {
|
||||
$return[$row["TABLE_NAME"]]["keys"][$row["CONSTRAINT_NAME"]][$row["COLUMN_NAME"]] = $row["REFERENCED_COLUMN_NAME"];
|
||||
$return[$row["table_name"]]["keys"][$row["constraint_name"]][$row["column_name"]] = $row["referenced_column_name"];
|
||||
}
|
||||
foreach ($return as $key => $val) {
|
||||
$name = Adminer\adminer()->tableName(Adminer\table_status1($key, true));
|
||||
@@ -40,9 +51,12 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
$link = Adminer\ME . 'select=' . urlencode($table);
|
||||
$i = 0;
|
||||
foreach ($cols as $column => $val) {
|
||||
if (!isset($row[$val])) {
|
||||
continue 2;
|
||||
}
|
||||
$link .= Adminer\where_link($i++, $column, $row[$val]);
|
||||
}
|
||||
echo "<a href='" . Adminer\h($link) . "'>" . Adminer\h($backwardKey["name"]) . "</a>";
|
||||
echo "<a href='" . Adminer\h($link) . "'>" . Adminer\h(preg_replace('(^' . preg_quote($_GET["select"]) . (substr($_GET["select"], -1) == 's' ? '?' : '') . '_)', '_', $backwardKey["name"])) . "</a>";
|
||||
$link = Adminer\ME . 'edit=' . urlencode($table);
|
||||
foreach ($cols as $column => $val) {
|
||||
$link .= "&set" . urlencode("[" . Adminer\bracket_escape($column) . "]") . "=" . urlencode($row[$val]);
|
||||
|
@@ -28,6 +28,8 @@ const saved = document.cookie.match(/adminer_dark=(\d)/);
|
||||
if (saved) {
|
||||
adminerDark = +saved[1];
|
||||
adminerDarkSet();
|
||||
} else {
|
||||
adminerDark = +matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
@@ -35,7 +37,7 @@ if (saved) {
|
||||
|
||||
function navigation($missing) {
|
||||
echo "<big style='position: fixed; bottom: .5em; right: .5em; cursor: pointer;'>☀</big>"
|
||||
. Adminer\script("if (adminerDark != null) adminerDarkSet(); qsl('big').onclick = adminerDarkSwitch;") . "\n"
|
||||
. Adminer\script("adminerDarkSet(); qsl('big').onclick = adminerDarkSwitch;") . "\n"
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ class AdminerDesigns extends Adminer\Plugin {
|
||||
function css() {
|
||||
$return = array();
|
||||
if (array_key_exists($_SESSION["design"], $this->designs)) {
|
||||
$return[] = $_SESSION["design"];
|
||||
$return[$_SESSION["design"]] = (preg_match('~-dark~', $_SESSION["design"]) ? "dark" : "light");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
Using drivers: https://www.adminer.org/plugins/#use
|
||||
|
||||
Developing drivers: https://www.adminer.org/en/drivers/
|
||||
|
||||
The type declarations must be compatible both with source codes and the compiled version (where PHP5-incompatible types are stripped). It means:
|
||||
|
@@ -287,10 +287,6 @@ if (isset($_GET["elastic"])) {
|
||||
|
||||
return !!$this->conn->affected_rows;
|
||||
}
|
||||
|
||||
function convertOperator($operator): string {
|
||||
return $operator == "LIKE %%" ? "should" : $operator;
|
||||
}
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
@@ -412,6 +408,11 @@ if (isset($_GET["elastic"])) {
|
||||
return $table_status["Engine"] == "view";
|
||||
}
|
||||
|
||||
function view(string $name): array {
|
||||
$return = connection()->rootQuery("_alias/" . urlencode($name) . "");
|
||||
return array("select" => implode("\n", array_keys($return)));
|
||||
}
|
||||
|
||||
function error() {
|
||||
return h(connection()->error);
|
||||
}
|
||||
@@ -533,15 +534,18 @@ if (isset($_GET["elastic"])) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Drop types
|
||||
* @param list<string> $tables
|
||||
*/
|
||||
function drop_views(array $tables): bool {
|
||||
$return = connection()->rootQuery('_aliases', array('actions' => array_map(function ($table) {
|
||||
return array('remove' => array('index' => '*', 'alias' => $table));
|
||||
}, $tables)), 'POST');
|
||||
return $return && !$return['errors'];
|
||||
}
|
||||
|
||||
function drop_tables(array $tables): bool {
|
||||
$return = true;
|
||||
foreach ($tables as $table) { //! convert to bulk api
|
||||
$return = $return && connection()->rootQuery(urlencode($table), null, 'DELETE');
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
/** Link system tables (in "mysql" and "information_schema" databases) by foreign keys
|
||||
/** Link system tables (in "mysql", "information_schema" and "pg_catalog" schemas) by foreign keys
|
||||
* @link https://www.adminer.org/plugins/#use
|
||||
* @author Jakub Vrana, https://www.vrana.cz/
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
@@ -29,7 +29,8 @@ class AdminerForeignSystem extends Adminer\Plugin {
|
||||
"time_zone_transition_type" => array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id"))),
|
||||
);
|
||||
return $return[$table];
|
||||
} elseif (Adminer\DB == "information_schema") {
|
||||
|
||||
} elseif (Adminer\DB == "information_schema" || $_GET["ns"] == "information_schema") {
|
||||
$schemata = $this->schemata("TABLE");
|
||||
$tables = $this->tables("TABLE");
|
||||
$columns = array("table" => "COLUMNS", "source" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME"), "target" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME"));
|
||||
@@ -85,10 +86,88 @@ class AdminerForeignSystem extends Adminer\Plugin {
|
||||
"VIEWS" => array($schemata, $this->character_sets("CHARACTER_SET_CLIENT"), $this->collations("COLLATION_CONNECTION")),
|
||||
"VIEW_TABLE_USAGE" => array($schemata, $this->schemata("VIEW"), $tables, array("table" => "VIEWS", "source" => array("VIEW_CATALOG", "VIEW_SCHEMA", "VIEW_NAME"), "target" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME"))),
|
||||
);
|
||||
return $return[$table];
|
||||
if ($_GET["ns"] == "information_schema") {
|
||||
$return = $this->lowerCase($return);
|
||||
}
|
||||
return $return[strtoupper($table)];
|
||||
|
||||
} elseif (Adminer\DRIVER == "pgsql" && $_GET["ns"] == "pg_catalog") {
|
||||
$mapping = array(
|
||||
'pg_aggregate' => array('aggfnoid.proc', 'aggtransfn.proc', 'aggfinalfn.proc', 'aggcombinefn.proc', 'aggserialfn.proc', 'aggdeserialfn.proc', 'aggmtransfn.proc', 'aggminvtransfn.proc', 'aggmfinalfn.proc', 'aggsortop.operator', 'aggtranstype.type', 'aggmtranstype.type'),
|
||||
'pg_am' => array('amhandler.proc'),
|
||||
'pg_amop' => array('amopfamily.opfamily', 'amoplefttype.type', 'amoprighttype.type', 'amopopr.operator', 'amopmethod.am', 'amopsortfamily.opfamily'),
|
||||
'pg_amproc' => array('amprocfamily.opfamily', 'amproclefttype.type', 'amprocrighttype.type', 'amproc.proc'),
|
||||
'pg_attrdef' => array('adrelid.class', 'adnum.attribute.attnum'),
|
||||
'pg_attribute' => array('attrelid.class', 'atttypid.type', 'attcollation.collation'),
|
||||
'pg_auth_members' => array('roleid.authid', 'member.authid', 'grantor.authid'),
|
||||
'pg_cast' => array('castsource.type', 'casttarget.type', 'castfunc.proc'),
|
||||
'pg_class' => array('relnamespace.namespace', 'reltype.type', 'reloftype.type', 'relowner.authid', 'relam.am', 'reltablespace.tablespace', 'reltoastrelid.class', 'relrewrite.class'),
|
||||
'pg_collation' => array('collnamespace.namespace', 'collowner.authid'),
|
||||
'pg_constraint' => array('connamespace.namespace', 'conrelid.class', 'contypid.type', 'conindid.class', 'conparentid.constraint', 'confrelid.class', 'conkey.attribute.attnum', 'confkey.attribute.attnum', 'conpfeqop.operator', 'conppeqop.operator', 'conffeqop.operator', 'confdelsetcols.attribute.attnum', 'conexclop.operator'),
|
||||
'pg_conversion' => array('connamespace.namespace', 'conowner.authid', 'conproc.proc'),
|
||||
'pg_database' => array('datdba.authid', 'dattablespace.tablespace'),
|
||||
'pg_db_role_setting' => array('setdatabase.database', 'setrole.authid'),
|
||||
'pg_default_acl' => array('defaclrole.authid', 'defaclnamespace.namespace'),
|
||||
'pg_depend' => array('classid.class', 'refclassid.class'),
|
||||
'pg_description' => array('classoid.class'),
|
||||
'pg_enum' => array('enumtypid.type'),
|
||||
'pg_event_trigger' => array('evtowner.authid', 'evtfoid.proc'),
|
||||
'pg_extension' => array('extowner.authid', 'extnamespace.namespace', 'extconfig.class'),
|
||||
'pg_foreign_data_wrapper' => array('fdwowner.authid', 'fdwhandler.proc', 'fdwvalidator.proc'),
|
||||
'pg_foreign_server' => array('srvowner.authid', 'srvfdw.foreign_data_wrapper'),
|
||||
'pg_foreign_table' => array('ftrelid.class', 'ftserver.foreign_server'),
|
||||
'pg_index' => array('indexrelid.class', 'indrelid.class', 'indkey.attribute.attnum', 'indcollation.collation', 'indclass.opclass'),
|
||||
'pg_inherits' => array('inhrelid.class', 'inhparent.class'),
|
||||
'pg_init_privs' => array('classoid.class'),
|
||||
'pg_language' => array('lanowner.authid', 'lanplcallfoid.proc', 'laninline.proc', 'lanvalidator.proc'),
|
||||
'pg_largeobject' => array('loid.largeobject_metadata'),
|
||||
'pg_largeobject_metadata' => array('lomowner.authid'),
|
||||
'pg_namespace' => array('nspowner.authid'),
|
||||
'pg_opclass' => array('opcmethod.am', 'opcnamespace.namespace', 'opcowner.authid', 'opcfamily.opfamily', 'opcintype.type', 'opckeytype.type'),
|
||||
'pg_operator' => array('oprnamespace.namespace', 'oprowner.authid', 'oprleft.type', 'oprright.type', 'oprresult.type', 'oprcom.operator', 'oprnegate.operator', 'oprcode.proc', 'oprrest.proc', 'oprjoin.proc'),
|
||||
'pg_opfamily' => array('opfmethod.am', 'opfnamespace.namespace', 'opfowner.authid'),
|
||||
'pg_partitioned_table' => array('partrelid.class', 'partdefid.class', 'partattrs.attribute.attnum', 'partclass.opclass', 'partcollation.collation'),
|
||||
'pg_policy' => array('polrelid.class', 'polroles.authid'),
|
||||
'pg_proc' => array('pronamespace.namespace', 'proowner.authid', 'prolang.language', 'provariadic.type', 'prosupport.proc', 'prorettype.type', 'proargtypes.type', 'proallargtypes.type', 'protrftypes.type'),
|
||||
'pg_publication' => array('pubowner.authid'),
|
||||
'pg_publication_namespace' => array('pnpubid.publication', 'pnnspid.namespace'),
|
||||
'pg_publication_rel' => array('prpubid.publication', 'prrelid.class', 'prattrs.attribute.attnum'),
|
||||
'pg_range' => array('rngtypid.type', 'rngsubtype.type', 'rngmultitypid.type', 'rngcollation.collation', 'rngsubopc.opclass', 'rngcanonical.proc', 'rngsubdiff.proc'),
|
||||
'pg_rewrite' => array('ev_class.class'),
|
||||
'pg_seclabel' => array('classoid.class'),
|
||||
'pg_sequence' => array('seqrelid.class', 'seqtypid.type'),
|
||||
'pg_shdepend' => array('dbid.database', 'classid.class', 'refclassid.class'),
|
||||
'pg_shdescription' => array('classoid.class'),
|
||||
'pg_shseclabel' => array('classoid.class'),
|
||||
'pg_statistic' => array('starelid.class', 'staattnum.attribute.attnum', 'staop.operator', 'stacoll.collation'),
|
||||
'pg_statistic_ext' => array('stxrelid.class', 'stxnamespace.namespace', 'stxowner.authid', 'stxkeys.attribute.attnum'),
|
||||
'pg_statistic_ext_data' => array('stxoid.statistic_ext'),
|
||||
'pg_subscription' => array('subdbid.database', 'subowner.authid'),
|
||||
'pg_subscription_rel' => array('srsubid.subscription', 'srrelid.class'),
|
||||
'pg_tablespace' => array('spcowner.authid'),
|
||||
'pg_transform' => array('trftype.type', 'trflang.language', 'trffromsql.proc', 'trftosql.proc'),
|
||||
'pg_trigger' => array('tgrelid.class', 'tgparentid.trigger', 'tgfoid.proc', 'tgconstrrelid.class', 'tgconstrindid.class', 'tgconstraint.constraint', 'tgattr.attribute.attnum'),
|
||||
'pg_ts_config' => array('cfgnamespace.namespace', 'cfgowner.authid', 'cfgparser.ts_parser'),
|
||||
'pg_ts_config_map' => array('mapcfg.ts_config', 'mapdict.ts_dict'),
|
||||
'pg_ts_dict' => array('dictnamespace.namespace', 'dictowner.authid', 'dicttemplate.ts_template'),
|
||||
'pg_ts_parser' => array('prsnamespace.namespace', 'prsstart.proc', 'prstoken.proc', 'prsend.proc', 'prsheadline.proc', 'prslextype.proc'),
|
||||
'pg_ts_template' => array('tmplnamespace.namespace', 'tmplinit.proc', 'tmpllexize.proc'),
|
||||
'pg_type' => array('typnamespace.namespace', 'typowner.authid', 'typrelid.class', 'typsubscript.proc', 'typelem.type', 'typarray.type', 'typinput.proc', 'typoutput.proc', 'typreceive.proc', 'typsend.proc', 'typmodin.proc', 'typmodout.proc', 'typanalyze.proc', 'typbasetype.type', 'typcollation.collation'),
|
||||
'pg_user_mapping' => array('umuser.authid', 'umserver.foreign_server'),
|
||||
);
|
||||
$return = array();
|
||||
foreach ((array) $mapping[$table] as $val) {
|
||||
list($source, $target, $column) = explode(".", "$val.oid");
|
||||
$return[] = array("table" => "pg_$target", "source" => array($source), "target" => array($column));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
private function lowerCase($value) {
|
||||
return (is_array($value) ? array_map(array($this, 'lowerCase'), $value) : strtolower($value));
|
||||
}
|
||||
|
||||
private function schemata($catalog, $schema = null) {
|
||||
return array("table" => "SCHEMATA", "source" => array($catalog . "_CATALOG", ($schema ?: $catalog) . "_SCHEMA"), "target" => array("CATALOG_NAME", "SCHEMA_NAME"));
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
class AdminerCodemirror extends Adminer\Plugin {
|
||||
class AdminerHighlightCodemirror extends Adminer\Plugin {
|
||||
private $root;
|
||||
private $minified;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
class AdminerMonaco extends Adminer\Plugin {
|
||||
class AdminerHighlightMonaco extends Adminer\Plugin {
|
||||
private $root;
|
||||
|
||||
function __construct($root = "https://cdn.jsdelivr.net/npm/monaco-editor@0.52/min/vs") {
|
@@ -7,7 +7,7 @@
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
class AdminerPrism extends Adminer\Plugin {
|
||||
class AdminerHighlightPrism extends Adminer\Plugin {
|
||||
private $editorRoot;
|
||||
private $minified;
|
||||
private $theme;
|
@@ -12,7 +12,7 @@ class AdminerLoginOtp extends Adminer\Plugin {
|
||||
/**
|
||||
* @param string $secret decoded secret, e.g. base64_decode("SECRET")
|
||||
*/
|
||||
function __construct(string $secret) {
|
||||
function __construct($secret) {
|
||||
$this->secret = $secret;
|
||||
if ($_POST["auth"]) {
|
||||
$_SESSION["otp"] = (string) $_POST["auth"]["otp"];
|
||||
|
@@ -12,7 +12,7 @@ class AdminerLoginPasswordLess extends Adminer\Plugin {
|
||||
/** Set allowed password
|
||||
* @param string $password_hash result of password_hash()
|
||||
*/
|
||||
function __construct(string $password_hash) {
|
||||
function __construct($password_hash) {
|
||||
$this->password_hash = $password_hash;
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ class AdminerLoginTable extends Adminer\Plugin {
|
||||
protected $database;
|
||||
|
||||
/** Set database of login table */
|
||||
function __construct(string $database) {
|
||||
function __construct($database) {
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
|
@@ -21,12 +21,12 @@ class AdminerMenuLinks extends Adminer\Plugin {
|
||||
'' => $this->lang('Both'),
|
||||
'auto' => $this->lang('Auto (select on select page, structure otherwise)'),
|
||||
);
|
||||
$menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu;
|
||||
$menu = Adminer\get_setting("menu", "adminer_config", $this->menu);
|
||||
return array($this->lang('Menu table links') => Adminer\html_radios('config[menu]', $options, $menu, "<br>"));
|
||||
}
|
||||
|
||||
function tablesPrint(array $tables) {
|
||||
$menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu;
|
||||
$menu = Adminer\get_setting("menu", "adminer_config", $this->menu);
|
||||
$titles = array(
|
||||
'select' => $this->lang('Select data'),
|
||||
'table' => $this->lang('Show structure'),
|
||||
@@ -36,7 +36,7 @@ class AdminerMenuLinks extends Adminer\Plugin {
|
||||
foreach ($tables as $table => $status) {
|
||||
$table = "$table"; // do not highlight "0" as active everywhere
|
||||
$name = Adminer\adminer()->tableName($status);
|
||||
if ($name != "") {
|
||||
if ($name != "" && !$status["partition"]) {
|
||||
echo '<li>';
|
||||
if (!$menu) {
|
||||
echo '<a href="' . Adminer\h(Adminer\ME) . 'select=' . urlencode($table) . '"'
|
||||
|
@@ -26,7 +26,7 @@ class AdminerPrettyJsonColumn extends Adminer\Plugin {
|
||||
if ($function === '') {
|
||||
$json = $this->testJson($value);
|
||||
if ($json !== $value) {
|
||||
$value = json_encode($json);
|
||||
return Adminer\q(json_encode($json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
plugins/row-numbers.php
Normal file
24
plugins/row-numbers.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/** Display row numbers in select
|
||||
* @link https://www.adminer.org/plugins/#use
|
||||
* @author Jakub Vrana, https://www.vrana.cz/
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
class AdminerRowNumbers extends Adminer\Plugin {
|
||||
|
||||
function backwardKeys($table, $tableName) {
|
||||
return array(1);
|
||||
}
|
||||
|
||||
function backwardKeysPrint($backwardKeys, $row) {
|
||||
static $n = $_GET["page"] * Adminer\adminer()->selectLimitProcess();
|
||||
$n++;
|
||||
echo "$n.\n";
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array('' => 'Zobrazí čísla řádek ve výpisu'),
|
||||
);
|
||||
}
|
@@ -18,7 +18,7 @@ class AdminerSelectEmail extends Adminer\Plugin {
|
||||
echo $this->lang('Subject') . ": <input name='email_subject' value='" . Adminer\h($_POST["email_subject"]) . "'>\n";
|
||||
echo "<p><textarea name='email_message' rows='15' cols='75'>" . Adminer\h($_POST["email_message"] . ($_POST["email_append"] ? '{$' . "$_POST[email_addition]}" : "")) . "</textarea>\n";
|
||||
echo "<p>" . Adminer\script("qsl('p').onkeydown = partialArg(bodyKeydown, 'email_append');", "") . Adminer\html_select("email_addition", $columns, $_POST["email_addition"])
|
||||
. " <input type='submit' name='email_append' value='" . $this->lang('Insert') . "'>\n"; //! JavaScript
|
||||
. " <input type='submit' name='email_append' value='" . Adminer\lang('Insert') . "'>\n"; //! JavaScript
|
||||
echo "<p>" . $this->lang('Attachments') . ": <input type='file' name='email_files[]'>" . Adminer\script("qsl('input').onchange = emailFileChange;");
|
||||
echo "<p>" . (count($emailFields) == 1 ? Adminer\input_hidden("email_field", key($emailFields)) : Adminer\html_select("email_field", $emailFields));
|
||||
echo "<input type='submit' name='email' value='" . $this->lang('Send') . "'>" . Adminer\confirm();
|
||||
@@ -101,50 +101,361 @@ class AdminerSelectEmail extends Adminer\Plugin {
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'ar' => array('E-mail' => 'البريد الإلكتروني', 'From' => 'من', 'Subject' => 'الموضوع', 'Send' => 'إرسال', '%d e-mail(s) have been sent.' => 'تم إرسال %d رسالة.', 'Attachments' => 'ملفات مرفقة'),
|
||||
'bg' => array('E-mail' => 'E-mail', 'From' => 'От', 'Subject' => 'Тема', 'Attachments' => 'Прикачени', 'Send' => 'Изпращане', '%d e-mail(s) have been sent.' => array('%d писмо беше изпратено.', '%d писма бяха изпратени.')),
|
||||
'bn' => array('E-mail' => 'ই-মেইল', 'From' => 'থেকে', 'Subject' => 'বিষয়', 'Send' => 'পাঠান', '%d e-mail(s) have been sent.' => array('%d ইমেইল(গুলি) পাঠানো হয়েছে।', '%d ইমেইল(গুলি) পাঠানো হয়েছে।'), 'Attachments' => 'সংযুক্তিগুলো'),
|
||||
'bs' => array('E-mail' => 'El. pošta', 'From' => 'Od', 'Subject' => 'Naslov', 'Attachments' => 'Prilozi', 'Send' => 'Pošalji', '%d e-mail(s) have been sent.' => array('%d poruka el. pošte je poslata.', '%d poruke el. pošte su poslate.', '%d poruka el. pošte je poslato.')),
|
||||
'ca' => array('E-mail' => 'Correu electrònic', 'From' => 'De', 'Subject' => 'Assumpte', 'Send' => 'Envia', '%d e-mail(s) have been sent.' => array('S\'ha enviat %d correu electrònic.', 'S\'han enviat %d correus electrònics.'), 'Attachments' => 'Adjuncions'),
|
||||
'cs' => array('' => 'Umožňuje posílat e-maily na adresy v tabulce', 'E-mail' => 'E-mail', 'From' => 'Odesílatel', 'Subject' => 'Předmět', 'Attachments' => 'Přílohy', 'Send' => 'Odeslat', '%d e-mail(s) have been sent.' => array('Byl odeslán %d e-mail.', 'Byly odeslány %d e-maily.', 'Bylo odesláno %d e-mailů.')),
|
||||
'da' => array('E-mail' => 'E-mail', 'From' => 'Fra', 'Subject' => 'Titel', 'Attachments' => 'Vedhæft', 'Send' => 'Send', '%d e-mail(s) have been sent.' => array('%d email sendt.', '%d emails sendt.')),
|
||||
'de' => array('E-mail' => 'E-Mail', 'From' => 'Von', 'Subject' => 'Betreff', 'Send' => 'Abschicken', '%d e-mail(s) have been sent.' => array('%d E-Mail abgeschickt.', '%d E-Mails abgeschickt.'), 'Attachments' => 'Anhänge'),
|
||||
'el' => array('E-mail' => 'E-mail', 'From' => 'Από', 'Subject' => 'Θέμα', 'Attachments' => 'Συνημμένα', 'Send' => 'Αποστολή', '%d e-mail(s) have been sent.' => array('%d e-mail απεστάλη.', '%d e-mail απεστάλησαν.')),
|
||||
'en' => array('%d e-mail(s) have been sent.' => array('%d e-mail has been sent.', '%d e-mails have been sent.')),
|
||||
'es' => array('E-mail' => 'Email', 'From' => 'De', 'Subject' => 'Asunto', 'Send' => 'Enviar', '%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'), 'Attachments' => 'Adjuntos'),
|
||||
'et' => array('E-mail' => 'E-post', 'From' => 'Kellelt', 'Subject' => 'Pealkiri', 'Send' => 'Saada', '%d e-mail(s) have been sent.' => 'Saadetud kirju: %d.', 'Attachments' => 'Manused'),
|
||||
'fa' => array('E-mail' => 'پست الکترونیک', 'From' => 'فرستنده', 'Subject' => 'موضوع', 'Attachments' => 'پیوست ها', 'Send' => 'ارسال', '%d e-mail(s) have been sent.' => array('%d ایمیل ارسال شد.', '%d ایمیل ارسال شد.')),
|
||||
'fi' => array('E-mail' => 'S-posti', 'From' => 'Lähettäjä', 'Subject' => 'Aihe', 'Attachments' => 'Liitteet', 'Send' => 'Lähetä', '%d e-mail(s) have been sent.' => array('% sähköpostiviestiä lähetetty.', '% sähköpostiviestiä lähetetty.')),
|
||||
'fr' => array('E-mail' => 'Courriel', 'From' => 'De', 'Subject' => 'Sujet', 'Send' => 'Envoyer', '%d e-mail(s) have been sent.' => array('%d message a été envoyé.', '%d messages ont été envoyés.'), 'Attachments' => 'Pièces jointes'),
|
||||
'gl' => array('E-mail' => 'Email', 'From' => 'De', 'Subject' => 'Asunto', 'Send' => 'Enviar', '%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'), 'Attachments' => 'Adxuntos'),
|
||||
'he' => array('E-mail' => 'דוא"ל', 'From' => 'מ:', 'Subject' => 'נושא', 'Send' => 'שלח', '%d e-mail(s) have been sent.' => '%d הודעות דוא"ל נשלחו', 'Attachments' => 'קבצים מצורפים'),
|
||||
'hu' => array('E-mail' => 'E-mail', 'From' => 'Feladó', 'Subject' => 'Tárgy', 'Send' => 'Küldés', '%d e-mail(s) have been sent.' => array('%d e-mail elküldve.', '%d e-mail elküldve.', '%d e-mail elküldve.'), 'Attachments' => 'Csatolmány'),
|
||||
'id' => array('E-mail' => 'Surel', 'From' => 'Dari', 'Subject' => 'Judul', 'Attachments' => 'Lampiran', 'Send' => 'Kirim', '%d e-mail(s) have been sent.' => '%d surel berhasil dikirim.'),
|
||||
'it' => array('E-mail' => 'E-mail', 'From' => 'Da', 'Subject' => 'Oggetto', 'Send' => 'Invia', '%d e-mail(s) have been sent.' => array('%d e-mail inviata.', '%d e-mail inviate.'), 'Attachments' => 'Allegati'),
|
||||
'ja' => array('' => 'テーブルに含まれるアドレスにメールを送信', 'E-mail' => 'メール', 'From' => '差出人', 'Subject' => '題名', 'Send' => '送信', '%d e-mail(s) have been sent.' => '%d メールを送信しました。', 'Attachments' => '添付ファイル'),
|
||||
'ka' => array('E-mail' => 'ელ. ფოსტა', 'From' => 'ავტორი:', 'Subject' => 'თემა', 'Send' => 'გაგზავნა', '%d e-mail(s) have been sent.' => 'გაიგზავნა %d წერილი.', 'Attachments' => 'მიმაგრებული ფაილები'),
|
||||
'ko' => array('%d e-mail(s) have been sent.' => '%d개 메일을 보냈습니다.', 'Attachments' => '첨부 파일', 'E-mail' => '메일', 'From' => '보낸 사람', 'Send' => '보내기', 'Subject' => '제목'),
|
||||
'lt' => array('E-mail' => 'El. paštas', 'From' => 'Nuo', 'Subject' => 'Antraštė', 'Attachments' => 'Priedai', 'Send' => 'Siųsti', '%d e-mail(s) have been sent.' => array('Išsiųstas %d laiškas.', 'Išsiųsti %d laiškai.', 'Išsiųsta %d laiškų.')),
|
||||
'lv' => array('E-mail' => 'Epasts', 'From' => 'No', 'Subject' => 'Tēma', 'Send' => 'Sūtīt', '%d e-mail(s) have been sent.' => array('Nosūtīts %d epasts.', 'Nosūtīti %d epasti.', 'Nosūtīti %d epasti.'), 'Attachments' => 'Pielikumi'),
|
||||
'ms' => array('E-mail' => 'Emel', 'From' => 'Dari', 'Subject' => 'Subjek', 'Attachments' => 'Lampiran', 'Send' => 'Hantar', '%d e-mail(s) have been sent.' => '%d emel telah dihantar.'),
|
||||
'nl' => array('E-mail' => 'E-mail', 'From' => 'Van', 'Subject' => 'Onderwerp', 'Send' => 'Verzenden', '%d e-mail(s) have been sent.' => array('%d e-mail verzonden.', '%d e-mails verzonden.'), 'Attachments' => 'Bijlagen'),
|
||||
'no' => array('E-mail' => 'E-post', 'From' => 'Fra', 'Subject' => 'Tittel', 'Attachments' => 'Vedlegg', 'Send' => 'Send', '%d e-mail(s) have been sent.' => array('%d epost sendt.', '%d eposter sendt.')),
|
||||
'pl' => array('E-mail' => 'E-mail', 'From' => 'Nadawca', 'Subject' => 'Temat', 'Attachments' => 'Załączniki', 'Send' => 'Wyślij', '%d e-mail(s) have been sent.' => array('Wysłano %d e-mail.', 'Wysłano %d e-maile.', 'Wysłano %d e-maili.')),
|
||||
'pt-br' => array('E-mail' => 'E-mail', 'From' => 'De', 'Subject' => 'Assunto', 'Send' => 'Enviar', '%d e-mail(s) have been sent.' => array('%d email foi enviado.', '%d emails foram enviados.'), 'Attachments' => 'Anexos'),
|
||||
'pt' => array('E-mail' => 'E-mail', 'From' => 'De', 'Subject' => 'Assunto', 'Send' => 'Enviar', '%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'), 'Attachments' => 'Anexos'),
|
||||
'ro' => array('E-mail' => 'Poșta electronică', 'From' => 'De la', 'Subject' => 'Pentru', 'Send' => 'Trimite', '%d e-mail(s) have been sent.' => array('A fost trimis %d mail.', 'Au fost trimise %d mail-uri.'), 'Attachments' => 'Fișiere atașate'),
|
||||
'ru' => array('E-mail' => 'Эл. почта', 'From' => 'От', 'Subject' => 'Тема', 'Send' => 'Послать', '%d e-mail(s) have been sent.' => array('Было отправлено %d письмо.', 'Было отправлено %d письма.', 'Было отправлено %d писем.'), 'Attachments' => 'Прикреплённые файлы'),
|
||||
'sk' => array('E-mail' => 'E-mail', 'From' => 'Odosielateľ', 'Subject' => 'Predmet', 'Send' => 'Odoslať', '%d e-mail(s) have been sent.' => array('Bol odoslaný %d e-mail.', 'Boli odoslané %d e-maily.', 'Bolo odoslaných %d e-mailov.'), 'Attachments' => 'Prílohy'),
|
||||
'sl' => array('E-mail' => 'E-mail', 'From' => 'Od', 'Subject' => 'Zadeva', 'Attachments' => 'Priponke', 'Send' => 'Pošlji', '%d e-mail(s) have been sent.' => array('Poslan je %d e-mail.', 'Poslana sta %d e-maila.', 'Poslani so %d e-maili.', 'Poslanih je %d e-mailov.')),
|
||||
'sr' => array('E-mail' => 'Ел. пошта', 'From' => 'Од', 'Subject' => 'Наслов', 'Attachments' => 'Прилози', 'Send' => 'Пошаљи', '%d e-mail(s) have been sent.' => array('%d порука ел. поште је послата.', '%d поруке ел. поште су послате.', '%d порука ел. поште је послато.')),
|
||||
'sv' => array('E-mail' => 'Email', 'From' => 'Från', 'Subject' => 'Ämne', 'Attachments' => 'Bilagor', 'Send' => 'Skicka', '%d e-mail(s) have been sent.' => array('%d email har blivit skickat.', '%d email har blivit skickade.')),
|
||||
'ta' => array('E-mail' => 'மின்னஞ்சல்', 'From' => 'அனுப்புனர்', 'Subject' => 'பொருள்', 'Send' => 'அனுப்பு', '%d e-mail(s) have been sent.' => array('%d மின்னஞ்சல் அனுப்பபட்டது.', '%d மின்னஞ்சல்கள் அனுப்பப்பட்டன.'), 'Attachments' => 'இணைப்புகள்'),
|
||||
'th' => array('E-mail' => 'อีเมล์', 'From' => 'จาก', 'Subject' => 'หัวข้อ', 'Send' => 'ส่ง', '%d e-mail(s) have been sent.' => 'มี %d อีเมล์ ถูกส่งออกแล้ว.', 'Attachments' => 'ไฟล์แนบ'),
|
||||
'tr' => array('E-mail' => 'E-posta', 'From' => 'Gönderen', 'Subject' => 'Konu', 'Attachments' => 'Ekler', 'Send' => 'Gönder', '%d e-mail(s) have been sent.' => array('%d e-posta gönderildi.', '%d adet e-posta gönderildi.')),
|
||||
'uk' => array('E-mail' => 'E-mail', 'From' => 'Від', 'Subject' => 'Заголовок', 'Attachments' => 'Додатки', 'Send' => 'Надіслати', '%d e-mail(s) have been sent.' => array('Було надіслано %d повідомлення.', 'Було надіслано %d повідомлення.', 'Було надіслано %d повідомлень.')),
|
||||
'uz' => array('E-mail' => 'E-pochta', 'From' => 'Kimdan', 'Subject' => 'Mavzu', 'Attachments' => 'Ilovalar', 'Send' => 'Yuborish', '%d e-mail(s) have been sent.' => array('%d e-pochta yuborildi.', '%d e-pochtalar yuborildi.')),
|
||||
'vi' => array('E-mail' => 'Địa chỉ email', 'From' => 'Người gửi', 'Subject' => 'Chủ đề', 'Attachments' => 'Đính kèm', 'Send' => 'Gửi', '%d e-mail(s) have been sent.' => '%d thư đã gửi.'),
|
||||
'zh-tw' => array('E-mail' => '電子郵件', 'From' => '來自', 'Subject' => '主旨', 'Attachments' => '附件', 'Send' => '寄出', '%d e-mail(s) have been sent.' => '已寄出 %d 封郵件。'),
|
||||
'zh' => array('E-mail' => '电子邮件', 'From' => '来自', 'Subject' => '主题', 'Attachments' => '附件', 'Send' => '发送', '%d e-mail(s) have been sent.' => '%d 封邮件已发送。'),
|
||||
'ar' => array(
|
||||
'E-mail' => 'البريد الإلكتروني',
|
||||
'From' => 'من',
|
||||
'Subject' => 'الموضوع',
|
||||
'Send' => 'إرسال',
|
||||
'%d e-mail(s) have been sent.' => 'تم إرسال %d رسالة.',
|
||||
'Attachments' => 'ملفات مرفقة',
|
||||
),
|
||||
'bg' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'От',
|
||||
'Subject' => 'Тема',
|
||||
'Attachments' => 'Прикачени',
|
||||
'Send' => 'Изпращане',
|
||||
'%d e-mail(s) have been sent.' => array('%d писмо беше изпратено.', '%d писма бяха изпратени.'),
|
||||
),
|
||||
'bn' => array(
|
||||
'E-mail' => 'ই-মেইল',
|
||||
'From' => 'থেকে',
|
||||
'Subject' => 'বিষয়',
|
||||
'Send' => 'পাঠান',
|
||||
'%d e-mail(s) have been sent.' => array('%d ইমেইল(গুলি) পাঠানো হয়েছে।', '%d ইমেইল(গুলি) পাঠানো হয়েছে।'),
|
||||
'Attachments' => 'সংযুক্তিগুলো',
|
||||
),
|
||||
'bs' => array(
|
||||
'E-mail' => 'El. pošta',
|
||||
'From' => 'Od',
|
||||
'Subject' => 'Naslov',
|
||||
'Attachments' => 'Prilozi',
|
||||
'Send' => 'Pošalji',
|
||||
'%d e-mail(s) have been sent.' => array('%d poruka el. pošte je poslata.', '%d poruke el. pošte su poslate.', '%d poruka el. pošte je poslato.'),
|
||||
),
|
||||
'ca' => array(
|
||||
'E-mail' => 'Correu electrònic',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Assumpte',
|
||||
'Send' => 'Envia',
|
||||
'%d e-mail(s) have been sent.' => array('S\'ha enviat %d correu electrònic.', 'S\'han enviat %d correus electrònics.'),
|
||||
'Attachments' => 'Adjuncions',
|
||||
),
|
||||
'cs' => array(
|
||||
'' => 'Umožňuje posílat e-maily na adresy v tabulce',
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Odesílatel',
|
||||
'Subject' => 'Předmět',
|
||||
'Attachments' => 'Přílohy',
|
||||
'Send' => 'Odeslat',
|
||||
'%d e-mail(s) have been sent.' => array('Byl odeslán %d e-mail.', 'Byly odeslány %d e-maily.', 'Bylo odesláno %d e-mailů.'),
|
||||
),
|
||||
'da' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Fra',
|
||||
'Subject' => 'Titel',
|
||||
'Attachments' => 'Vedhæft',
|
||||
'Send' => 'Send',
|
||||
'%d e-mail(s) have been sent.' => array('%d email sendt.', '%d emails sendt.'),
|
||||
),
|
||||
'de' => array(
|
||||
'E-mail' => 'E-Mail',
|
||||
'From' => 'Von',
|
||||
'Subject' => 'Betreff',
|
||||
'Send' => 'Abschicken',
|
||||
'%d e-mail(s) have been sent.' => array('%d E-Mail abgeschickt.', '%d E-Mails abgeschickt.'),
|
||||
'Attachments' => 'Anhänge',
|
||||
),
|
||||
'el' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Από',
|
||||
'Subject' => 'Θέμα',
|
||||
'Attachments' => 'Συνημμένα',
|
||||
'Send' => 'Αποστολή',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-mail απεστάλη.', '%d e-mail απεστάλησαν.'),
|
||||
),
|
||||
'en' => array(
|
||||
'%d e-mail(s) have been sent.' => array('%d e-mail has been sent.', '%d e-mails have been sent.'),
|
||||
),
|
||||
'es' => array(
|
||||
'E-mail' => 'Email',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Asunto',
|
||||
'Send' => 'Enviar',
|
||||
'%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'),
|
||||
'Attachments' => 'Adjuntos',
|
||||
),
|
||||
'et' => array(
|
||||
'E-mail' => 'E-post',
|
||||
'From' => 'Kellelt',
|
||||
'Subject' => 'Pealkiri',
|
||||
'Send' => 'Saada',
|
||||
'%d e-mail(s) have been sent.' => 'Saadetud kirju: %d.',
|
||||
'Attachments' => 'Manused',
|
||||
),
|
||||
'fa' => array(
|
||||
'E-mail' => 'پست الکترونیک',
|
||||
'From' => 'فرستنده',
|
||||
'Subject' => 'موضوع',
|
||||
'Attachments' => 'پیوست ها',
|
||||
'Send' => 'ارسال',
|
||||
'%d e-mail(s) have been sent.' => array('%d ایمیل ارسال شد.', '%d ایمیل ارسال شد.'),
|
||||
),
|
||||
'fi' => array(
|
||||
'E-mail' => 'S-posti',
|
||||
'From' => 'Lähettäjä',
|
||||
'Subject' => 'Aihe',
|
||||
'Attachments' => 'Liitteet',
|
||||
'Send' => 'Lähetä',
|
||||
'%d e-mail(s) have been sent.' => array('% sähköpostiviestiä lähetetty.', '% sähköpostiviestiä lähetetty.'),
|
||||
),
|
||||
'fr' => array(
|
||||
'E-mail' => 'Courriel',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Sujet',
|
||||
'Send' => 'Envoyer',
|
||||
'%d e-mail(s) have been sent.' => array('%d message a été envoyé.', '%d messages ont été envoyés.'),
|
||||
'Attachments' => 'Pièces jointes',
|
||||
),
|
||||
'gl' => array(
|
||||
'E-mail' => 'Email',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Asunto',
|
||||
'Send' => 'Enviar',
|
||||
'%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'),
|
||||
'Attachments' => 'Adxuntos',
|
||||
),
|
||||
'he' => array(
|
||||
'E-mail' => 'דוא"ל',
|
||||
'From' => 'מ:',
|
||||
'Subject' => 'נושא',
|
||||
'Send' => 'שלח',
|
||||
'%d e-mail(s) have been sent.' => '%d הודעות דוא"ל נשלחו',
|
||||
'Attachments' => 'קבצים מצורפים',
|
||||
),
|
||||
'hu' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Feladó',
|
||||
'Subject' => 'Tárgy',
|
||||
'Send' => 'Küldés',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-mail elküldve.', '%d e-mail elküldve.', '%d e-mail elküldve.'),
|
||||
'Attachments' => 'Csatolmány',
|
||||
),
|
||||
'id' => array(
|
||||
'E-mail' => 'Surel',
|
||||
'From' => 'Dari',
|
||||
'Subject' => 'Judul',
|
||||
'Attachments' => 'Lampiran',
|
||||
'Send' => 'Kirim',
|
||||
'%d e-mail(s) have been sent.' => '%d surel berhasil dikirim.',
|
||||
),
|
||||
'it' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Da',
|
||||
'Subject' => 'Oggetto',
|
||||
'Send' => 'Invia',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-mail inviata.', '%d e-mail inviate.'),
|
||||
'Attachments' => 'Allegati',
|
||||
),
|
||||
'ja' => array(
|
||||
'' => 'テーブルに含まれるアドレスにメールを送信',
|
||||
'E-mail' => 'メール',
|
||||
'From' => '差出人',
|
||||
'Subject' => '題名',
|
||||
'Send' => '送信',
|
||||
'%d e-mail(s) have been sent.' => '%d メールを送信しました。',
|
||||
'Attachments' => '添付ファイル',
|
||||
),
|
||||
'ka' => array(
|
||||
'E-mail' => 'ელ. ფოსტა',
|
||||
'From' => 'ავტორი:',
|
||||
'Subject' => 'თემა',
|
||||
'Send' => 'გაგზავნა',
|
||||
'%d e-mail(s) have been sent.' => 'გაიგზავნა %d წერილი.',
|
||||
'Attachments' => 'მიმაგრებული ფაილები',
|
||||
),
|
||||
'ko' => array(
|
||||
'%d e-mail(s) have been sent.' => '%d개 메일을 보냈습니다.',
|
||||
'Attachments' => '첨부 파일',
|
||||
'E-mail' => '메일',
|
||||
'From' => '보낸 사람',
|
||||
'Send' => '보내기',
|
||||
'Subject' => '제목',
|
||||
),
|
||||
'lt' => array(
|
||||
'E-mail' => 'El. paštas',
|
||||
'From' => 'Nuo',
|
||||
'Subject' => 'Antraštė',
|
||||
'Attachments' => 'Priedai',
|
||||
'Send' => 'Siųsti',
|
||||
'%d e-mail(s) have been sent.' => array('Išsiųstas %d laiškas.', 'Išsiųsti %d laiškai.', 'Išsiųsta %d laiškų.'),
|
||||
),
|
||||
'lv' => array(
|
||||
'E-mail' => 'Epasts',
|
||||
'From' => 'No',
|
||||
'Subject' => 'Tēma',
|
||||
'Send' => 'Sūtīt',
|
||||
'%d e-mail(s) have been sent.' => array('Nosūtīts %d epasts.', 'Nosūtīti %d epasti.', 'Nosūtīti %d epasti.'),
|
||||
'Attachments' => 'Pielikumi',
|
||||
),
|
||||
'ms' => array(
|
||||
'E-mail' => 'Emel',
|
||||
'From' => 'Dari',
|
||||
'Subject' => 'Subjek',
|
||||
'Attachments' => 'Lampiran',
|
||||
'Send' => 'Hantar',
|
||||
'%d e-mail(s) have been sent.' => '%d emel telah dihantar.',
|
||||
),
|
||||
'nl' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Van',
|
||||
'Subject' => 'Onderwerp',
|
||||
'Send' => 'Verzenden',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-mail verzonden.', '%d e-mails verzonden.'),
|
||||
'Attachments' => 'Bijlagen',
|
||||
),
|
||||
'no' => array(
|
||||
'E-mail' => 'E-post',
|
||||
'From' => 'Fra',
|
||||
'Subject' => 'Tittel',
|
||||
'Attachments' => 'Vedlegg',
|
||||
'Send' => 'Send',
|
||||
'%d e-mail(s) have been sent.' => array('%d epost sendt.', '%d eposter sendt.'),
|
||||
),
|
||||
'pl' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Nadawca',
|
||||
'Subject' => 'Temat',
|
||||
'Attachments' => 'Załączniki',
|
||||
'Send' => 'Wyślij',
|
||||
'%d e-mail(s) have been sent.' => array('Wysłano %d e-mail.', 'Wysłano %d e-maile.', 'Wysłano %d e-maili.'),
|
||||
),
|
||||
'pt-br' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Assunto',
|
||||
'Send' => 'Enviar',
|
||||
'%d e-mail(s) have been sent.' => array('%d email foi enviado.', '%d emails foram enviados.'),
|
||||
'Attachments' => 'Anexos',
|
||||
),
|
||||
'pt' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'De',
|
||||
'Subject' => 'Assunto',
|
||||
'Send' => 'Enviar',
|
||||
'%d e-mail(s) have been sent.' => array('%d email enviado.', '%d emails enviados.'),
|
||||
'Attachments' => 'Anexos',
|
||||
),
|
||||
'ro' => array(
|
||||
'E-mail' => 'Poșta electronică',
|
||||
'From' => 'De la',
|
||||
'Subject' => 'Pentru',
|
||||
'Send' => 'Trimite',
|
||||
'%d e-mail(s) have been sent.' => array('A fost trimis %d mail.', 'Au fost trimise %d mail-uri.'),
|
||||
'Attachments' => 'Fișiere atașate',
|
||||
),
|
||||
'ru' => array(
|
||||
'E-mail' => 'Эл. почта',
|
||||
'From' => 'От',
|
||||
'Subject' => 'Тема',
|
||||
'Send' => 'Послать',
|
||||
'%d e-mail(s) have been sent.' => array('Было отправлено %d письмо.', 'Было отправлено %d письма.', 'Было отправлено %d писем.'),
|
||||
'Attachments' => 'Прикреплённые файлы',
|
||||
),
|
||||
'sk' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Odosielateľ',
|
||||
'Subject' => 'Predmet',
|
||||
'Send' => 'Odoslať',
|
||||
'%d e-mail(s) have been sent.' => array('Bol odoslaný %d e-mail.', 'Boli odoslané %d e-maily.', 'Bolo odoslaných %d e-mailov.'),
|
||||
'Attachments' => 'Prílohy',
|
||||
),
|
||||
'sl' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Od',
|
||||
'Subject' => 'Zadeva',
|
||||
'Attachments' => 'Priponke',
|
||||
'Send' => 'Pošlji',
|
||||
'%d e-mail(s) have been sent.' => array('Poslan je %d e-mail.', 'Poslana sta %d e-maila.', 'Poslani so %d e-maili.', 'Poslanih je %d e-mailov.'),
|
||||
),
|
||||
'sr' => array(
|
||||
'E-mail' => 'Ел. пошта',
|
||||
'From' => 'Од',
|
||||
'Subject' => 'Наслов',
|
||||
'Attachments' => 'Прилози',
|
||||
'Send' => 'Пошаљи',
|
||||
'%d e-mail(s) have been sent.' => array('%d порука ел. поште је послата.', '%d поруке ел. поште су послате.', '%d порука ел. поште је послато.'),
|
||||
),
|
||||
'sv' => array(
|
||||
'E-mail' => 'Email',
|
||||
'From' => 'Från',
|
||||
'Subject' => 'Ämne',
|
||||
'Attachments' => 'Bilagor',
|
||||
'Send' => 'Skicka',
|
||||
'%d e-mail(s) have been sent.' => array('%d email har blivit skickat.', '%d email har blivit skickade.'),
|
||||
),
|
||||
'ta' => array(
|
||||
'E-mail' => 'மின்னஞ்சல்',
|
||||
'From' => 'அனுப்புனர்',
|
||||
'Subject' => 'பொருள்',
|
||||
'Send' => 'அனுப்பு',
|
||||
'%d e-mail(s) have been sent.' => array('%d மின்னஞ்சல் அனுப்பபட்டது.', '%d மின்னஞ்சல்கள் அனுப்பப்பட்டன.'),
|
||||
'Attachments' => 'இணைப்புகள்',
|
||||
),
|
||||
'th' => array(
|
||||
'E-mail' => 'อีเมล์',
|
||||
'From' => 'จาก',
|
||||
'Subject' => 'หัวข้อ',
|
||||
'Send' => 'ส่ง',
|
||||
'%d e-mail(s) have been sent.' => 'มี %d อีเมล์ ถูกส่งออกแล้ว.',
|
||||
'Attachments' => 'ไฟล์แนบ',
|
||||
),
|
||||
'tr' => array(
|
||||
'E-mail' => 'E-posta',
|
||||
'From' => 'Gönderen',
|
||||
'Subject' => 'Konu',
|
||||
'Attachments' => 'Ekler',
|
||||
'Send' => 'Gönder',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-posta gönderildi.', '%d adet e-posta gönderildi.'),
|
||||
),
|
||||
'uk' => array(
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Від',
|
||||
'Subject' => 'Заголовок',
|
||||
'Attachments' => 'Додатки',
|
||||
'Send' => 'Надіслати',
|
||||
'%d e-mail(s) have been sent.' => array('Було надіслано %d повідомлення.', 'Було надіслано %d повідомлення.', 'Було надіслано %d повідомлень.'),
|
||||
),
|
||||
'uz' => array(
|
||||
'E-mail' => 'E-pochta',
|
||||
'From' => 'Kimdan',
|
||||
'Subject' => 'Mavzu',
|
||||
'Attachments' => 'Ilovalar',
|
||||
'Send' => 'Yuborish',
|
||||
'%d e-mail(s) have been sent.' => array('%d e-pochta yuborildi.', '%d e-pochtalar yuborildi.'),
|
||||
),
|
||||
'vi' => array(
|
||||
'E-mail' => 'Địa chỉ email',
|
||||
'From' => 'Người gửi',
|
||||
'Subject' => 'Chủ đề',
|
||||
'Attachments' => 'Đính kèm',
|
||||
'Send' => 'Gửi',
|
||||
'%d e-mail(s) have been sent.' => '%d thư đã gửi.',
|
||||
),
|
||||
'zh-tw' => array(
|
||||
'E-mail' => '電子郵件',
|
||||
'From' => '來自',
|
||||
'Subject' => '主旨',
|
||||
'Attachments' => '附件',
|
||||
'Send' => '寄出',
|
||||
'%d e-mail(s) have been sent.' => '已寄出 %d 封郵件。',
|
||||
),
|
||||
'zh' => array(
|
||||
'E-mail' => '电子邮件',
|
||||
'From' => '来自',
|
||||
'Subject' => '主题',
|
||||
'Attachments' => '附件',
|
||||
'Send' => '发送',
|
||||
'%d e-mail(s) have been sent.' => '%d 封邮件已发送。'),
|
||||
);
|
||||
}
|
||||
|
@@ -41,8 +41,8 @@ class AdminerSqlGemini extends Adminer\Plugin {
|
||||
echo "-- " . $response->error->message;
|
||||
} else {
|
||||
$text = $response->candidates[0]->content->parts[0]->text;
|
||||
$text = preg_replace('~(\n|^)```sql\n(.+)\n```(\n|$)~sU', "*/\n\n\\2\n\n/*", "/*\n$text*/\n");
|
||||
echo preg_replace('~/\*\s*\*/\n*~', '', $text);
|
||||
$text2 = preg_replace('~(\n|^)```sql\n(.+)\n```(\n|$)~sU', "*/\n\n\\2\n\n/*", "/*\n$text\n*/", -1, $count);
|
||||
echo ($count ? preg_replace('~/\*\s*\*/\n*~', '', $text2) : $text);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class AdminerSqlLog extends Adminer\Plugin {
|
||||
|
||||
private function log($query) {
|
||||
if ($this->filename == "") {
|
||||
$this->filename = Adminer\adminer()->database() . ".sql"; // no database goes to ".sql" to avoid collisions
|
||||
$this->filename = Adminer\adminer()->database() . ($_GET["ns"] != "" ? ".$_GET[ns]" : "") . ".sql"; // no database goes to ".sql" to avoid collisions
|
||||
}
|
||||
$fp = fopen($this->filename, "a");
|
||||
flock($fp, LOCK_EX);
|
||||
|
@@ -8,14 +8,11 @@
|
||||
*/
|
||||
class AdminerTableIndexesStructure extends Adminer\Plugin {
|
||||
|
||||
/** Print table structure in tabular format
|
||||
* @param Index[] $indexes data about all indexes on a table
|
||||
*/
|
||||
function tableIndexesPrint($indexes): bool {
|
||||
function tableIndexesPrint($indexes, $tableStatus): bool {
|
||||
echo "<table>\n";
|
||||
echo "<thead><tr><th>" . Adminer\lang('Name') . "<th>" . Adminer\lang('Type') . "<th>" . Adminer\lang('Columns') . "</thead>\n";
|
||||
echo "<thead><tr><th>" . Adminer\lang('Name') . "<th>" . Adminer\lang('Type') . "<th>" . Adminer\lang('Algorithm') . "<th>" . Adminer\lang('Columns') . "</thead>\n";
|
||||
foreach ($indexes as $name => $index) {
|
||||
echo "<tr><th>" . Adminer\h($name) . "<td>" . $index['type'];
|
||||
echo "<tr><th>" . Adminer\h($name) . "<td>$index[type]<td>$index[algorithm]";
|
||||
ksort($index["columns"]); // enforce correct columns order
|
||||
$print = array();
|
||||
foreach ($index["columns"] as $key => $val) {
|
||||
|
@@ -64,15 +64,26 @@ sessionStorage && document.addEventListener('DOMContentLoaded', () => {
|
||||
sessionStorage.setItem('adminer_tables_filter_db', db);
|
||||
});
|
||||
</script>
|
||||
<p class="jsonly"><input id="filter-field" autocomplete="off" type="search"><?php echo Adminer\script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
|
||||
<p class="jsonly"><?php echo $this->lang('Filter'); ?>: <input id="filter-field" autocomplete="off" type="search"><?php echo Adminer\script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array('' => 'Filtruje názvy v seznamu tabulek'),
|
||||
'de' => array('' => 'Filtern Sie Namen in der Tabellenliste'),
|
||||
'pl' => array('' => 'Filtruj nazwy na liście tabel'),
|
||||
'ro' => array('' => 'Nume de filtre în lista de tabele'),
|
||||
'ja' => array('' => 'テーブル一覧をテーブル名でフィルタリング'),
|
||||
'cs' => array(
|
||||
'' => 'Filtruje názvy v seznamu tabulek',
|
||||
'Filter' => 'Filtr',
|
||||
),
|
||||
'de' => array(
|
||||
'' => 'Filtern Sie Namen in der Tabellenliste',
|
||||
),
|
||||
'pl' => array(
|
||||
'' => 'Filtruj nazwy na liście tabel',
|
||||
),
|
||||
'ro' => array(
|
||||
'' => 'Nume de filtre în lista de tabele',
|
||||
),
|
||||
'ja' => array(
|
||||
'' => 'テーブル一覧をテーブル名でフィルタリング',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
48
plugins/timeout.php
Normal file
48
plugins/timeout.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/** Specify timeout for running every query
|
||||
* @link https://www.adminer.org/plugins/#use
|
||||
* @author Jakub Vrana, https://www.vrana.cz/
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
class AdminerTimeout extends Adminer\Plugin {
|
||||
private $seconds;
|
||||
|
||||
/**
|
||||
* @param int $seconds
|
||||
*/
|
||||
function __construct($seconds = 5) {
|
||||
$this->seconds = $seconds;
|
||||
}
|
||||
|
||||
function afterConnect() {
|
||||
$seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds);
|
||||
if ($seconds != '') {
|
||||
$ms = $seconds * 1000;
|
||||
$conn = Adminer\connection();
|
||||
switch (Adminer\JUSH) {
|
||||
case 'sql': $conn->query("SET max_execution_time = $ms"); break;
|
||||
case 'pgsql': $conn->query("SET statement_timeout = $ms"); break;
|
||||
case 'mssql': $conn->query("SET LOCK_TIMEOUT $ms"); break;
|
||||
default:
|
||||
if (method_exists(connection(), 'timeout')) {
|
||||
$conn->timeout($ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function config() {
|
||||
$seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds);
|
||||
return array($this->lang('Queries timeout') => '<input type="number" name="config[timeout]" min="0" value="' . Adminer\h($seconds) . '" class="size"> ' . $this->lang('seconds'));
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array(
|
||||
'' => 'Nastaví timeout pro spouštění každého dotazu',
|
||||
'Queries timeout' => 'Timeout dotazů',
|
||||
'seconds' => 'sekund',
|
||||
),
|
||||
);
|
||||
}
|
@@ -375,6 +375,41 @@
|
||||
<tr><td>verifyTextPresent</td><td>No tables.</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
<thead><tr><td rowspan="1" colspan="3" data-tags="">Partitioning</td></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&username=ODBC&db=adminer_test&ns=public&create=</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=name</td><td>range</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Partition by</td><td></td></tr>
|
||||
<tr><td>select</td><td>name=partition_by</td><td>label=RANGE</td></tr>
|
||||
<tr><td>type</td><td>name=partition</td><td>id</td></tr>
|
||||
<tr><td>type</td><td>name=partition_names[]</td><td>old</td></tr>
|
||||
<tr><td>type</td><td>name=partition_values[]</td><td>10</td></tr>
|
||||
<tr><td>type</td><td>xpath=//table[@id='partition-table']/tr/td/input</td><td>new</td></tr>
|
||||
<tr><td>type</td><td>xpath=//table[@id='partition-table']/tr/td[2]/input</td><td>MAXVALUE</td></tr>
|
||||
<tr><td>click</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION BY RANGE(id)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION "old" VALUES FROM (MINVALUE) TO (10)</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Create table</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=name</td><td>list</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Partition by</td><td></td></tr>
|
||||
<tr><td>select</td><td>name=partition_by</td><td>label=LIST</td></tr>
|
||||
<tr><td>type</td><td>name=partition</td><td>id</td></tr>
|
||||
<tr><td>type</td><td>name=partition_names[]</td><td>odd</td></tr>
|
||||
<tr><td>type</td><td>name=partition_values[]</td><td>1,3,5</td></tr>
|
||||
<tr><td>click</td><td>xpath=//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION BY LIST(id)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION "odd" VALUES IN (1,3,5)</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=public</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@name='tables[]' and @value='list']</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@name='tables[]' and @value='range']</td><td></td></tr>
|
||||
<tr><td>chooseOkOnNextConfirmation</td><td>Are you sure?</td><td></td></tr>
|
||||
<tr><td>click</td><td>name=drop</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>No tables.</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
<thead><tr><td rowspan="1" colspan="3">Variables</td></tr></thead>
|
||||
<tbody>
|
||||
|
@@ -31,6 +31,9 @@
|
||||
<tr><td>type</td><td>fields[1.1][field]</td><td>name</td></tr>
|
||||
<tr><td>select</td><td>fields[1.1][type]</td><td>label=character varying</td></tr>
|
||||
<tr><td>type</td><td>fields[1.1][length]</td><td>50</td></tr>
|
||||
<tr><td>type</td><td>fields[1.11][field]</td><td>surname</td></tr>
|
||||
<tr><td>select</td><td>fields[1.11][type]</td><td>label=character varying</td></tr>
|
||||
<tr><td>type</td><td>fields[1.11][length]</td><td>50</td></tr>
|
||||
<tr><td>uncheck</td><td>name=comments</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>name=comments</td><td></td></tr>
|
||||
<tr><td>type</td><td>fields[1.1][comment]</td><td>Interpret</td></tr>
|
||||
@@ -50,8 +53,16 @@
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>multiple primary keys for table "interprets" are not allowed</td><td></td></tr>
|
||||
<tr><td>select</td><td>indexes[2][type]</td><td>label=INDEX</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='options']</td><td></td></tr>
|
||||
<tr><td>select</td><td>indexes[3][type]</td><td>label=INDEX</td></tr>
|
||||
<tr><td>select</td><td>indexes[3][columns][1]</td><td>label=surname</td></tr>
|
||||
<tr><td>select</td><td>indexes[3][algorithm]</td><td>label=hash</td></tr>
|
||||
<tr><td>type</td><td>indexes[3][partial]</td><td>surname IS NOT NULL</td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>Indexes have been altered.</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>INDEX (hash)</td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>surname</td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>WHERE surname IS NOT NULL</td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
@@ -384,6 +395,54 @@
|
||||
<tr><td>verifyTextPresent</td><td>No tables.</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
<thead><tr><td rowspan="1" colspan="3" data-tags="">Partitioning</td></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>open</td><td>/adminer/?pgsql=&username=ODBC&db=adminer_test&ns=public&create=</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=name</td><td>range</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Partition by</td><td></td></tr>
|
||||
<tr><td>select</td><td>name=partition_by</td><td>label=RANGE</td></tr>
|
||||
<tr><td>type</td><td>name=partition</td><td>id</td></tr>
|
||||
<tr><td>type</td><td>name=partition_names[]</td><td>old</td></tr>
|
||||
<tr><td>type</td><td>name=partition_values[]</td><td>10</td></tr>
|
||||
<tr><td>type</td><td>xpath=//table[@id='partition-table']/tr/td/input</td><td>new</td></tr>
|
||||
<tr><td>type</td><td>xpath=//table[@id='partition-table']/tr/td[2]/input</td><td>MAXVALUE</td></tr>
|
||||
<tr><td>click</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION BY RANGE(id)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>"range_old" PARTITION OF "range" FOR VALUES FROM (MINVALUE) TO (10)</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Create table</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=name</td><td>list</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Partition by</td><td></td></tr>
|
||||
<tr><td>select</td><td>name=partition_by</td><td>label=LIST</td></tr>
|
||||
<tr><td>type</td><td>name=partition</td><td>id</td></tr>
|
||||
<tr><td>type</td><td>name=partition_names[]</td><td>odd</td></tr>
|
||||
<tr><td>type</td><td>name=partition_values[]</td><td>1,3,5</td></tr>
|
||||
<tr><td>click</td><td>xpath=//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION BY LIST(id)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>"list_odd" PARTITION OF "list" FOR VALUES IN (1,3,5)</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Create table</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=name</td><td>hash</td></tr>
|
||||
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Partition by</td><td></td></tr>
|
||||
<tr><td>select</td><td>name=partition_by</td><td>label=HASH</td></tr>
|
||||
<tr><td>type</td><td>name=partition</td><td>id</td></tr>
|
||||
<tr><td>type</td><td>name=partitions</td><td>4</td></tr>
|
||||
<tr><td>click</td><td>xpath=//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>PARTITION BY HASH(id)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>"hash_0" PARTITION OF "hash" FOR VALUES WITH (MODULUS 4, REMAINDER 0)</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=hash_0</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>Inherits from</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=public</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@name='tables[]' and @value='hash']</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@name='tables[]' and @value='list']</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@name='tables[]' and @value='range']</td><td></td></tr>
|
||||
<tr><td>chooseOkOnNextConfirmation</td><td>Are you sure?</td><td></td></tr>
|
||||
<tr><td>click</td><td>name=drop</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>No tables.</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
<thead><tr><td rowspan="1" colspan="3">Variables</td></tr></thead>
|
||||
<tbody>
|
||||
|
Reference in New Issue
Block a user