mirror of
https://github.com/vrana/adminer.git
synced 2025-08-30 09:39:51 +02:00
Compare commits
161 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8d7cb5954d | ||
|
47700f2763 | ||
|
a4a8f48a9c | ||
|
770a77ac33 | ||
|
8ceaf36de7 | ||
|
517d2d1c2f | ||
|
af5d519266 | ||
|
c045b20a8e | ||
|
874307a27f | ||
|
c27b91a167 | ||
|
afe03ef720 | ||
|
c0e2ab22d5 | ||
|
7351980beb | ||
|
7b5a20334d | ||
|
6262b120f5 | ||
|
bd27ca0b2b | ||
|
aa7cf70d25 | ||
|
94a4f61db2 | ||
|
dc50bf17ea | ||
|
f05f4b4cbc | ||
|
0541680d73 | ||
|
5a84ff7647 | ||
|
edd7c67797 | ||
|
c6f825a786 | ||
|
f711135574 | ||
|
2b16f51933 | ||
|
d268e0ebb4 | ||
|
5fdaae27dc | ||
|
049536da90 | ||
|
bddce074fa | ||
|
347d9f1f55 | ||
|
a8feb00098 | ||
|
69d7d76dc5 | ||
|
2f0cd4185b | ||
|
37a75f3759 | ||
|
d2add4dd72 | ||
|
f5d47d46a0 | ||
|
e8d9a126be | ||
|
12f0a4bc9a | ||
|
d9df9693e3 | ||
|
873d6d50fd | ||
|
c873ceba17 | ||
|
0bf8861dd1 | ||
|
137ac2396b | ||
|
755d7b47ac | ||
|
dd947fc1ee | ||
|
105999f62e | ||
|
ed5de27dd3 | ||
|
293e031498 | ||
|
a7f097e78c | ||
|
af68e30742 | ||
|
f820fa1c26 | ||
|
f468c095ae | ||
|
c10b614ee1 | ||
|
f5b255230b | ||
|
54568ddef6 | ||
|
3da09dd31a | ||
|
45ac930e06 | ||
|
e801753519 | ||
|
a4e9f7b87b | ||
|
35829eedaf | ||
|
44c2e979f7 | ||
|
2a8b4009b1 | ||
|
6ceebc99df | ||
|
2f49bfb67e | ||
|
e1e085f312 | ||
|
50e7a65e6e | ||
|
52c5392089 | ||
|
5a708df6ca | ||
|
c52ba0308e | ||
|
422668f2d7 | ||
|
f0335f7f8b | ||
|
cc635acd20 | ||
|
63dd38c44d | ||
|
e411c229ab | ||
|
b9d6529442 | ||
|
0426bd4610 | ||
|
c7d283d262 | ||
|
d61678f5cb | ||
|
94088474dd | ||
|
9b25969fb2 | ||
|
996b178406 | ||
|
116827060f | ||
|
af87336116 | ||
|
17939b56c4 | ||
|
d5a17835ff | ||
|
4967a40410 | ||
|
4cdcb44bee | ||
|
160beb726a | ||
|
fb3b23617d | ||
|
dfe3cc1888 | ||
|
c1704d83c1 | ||
|
364a4bce1f | ||
|
d9bca2df37 | ||
|
315ffc9d8b | ||
|
530b3dd1e5 | ||
|
980c22fe8d | ||
|
26d1e51916 | ||
|
6d889b9f99 | ||
|
7e4ee77cc0 | ||
|
742fd7dcb6 | ||
|
d23a0eb77e | ||
|
5eac6a44bd | ||
|
db300bc38b | ||
|
48a680658c | ||
|
70f9ff75fc | ||
|
81340ff7e5 | ||
|
89b097c699 | ||
|
e075f4bd8b | ||
|
e8fa48a257 | ||
|
0ed3c5cb19 | ||
|
2f237dfa04 | ||
|
afdc78a07b | ||
|
3dc87c1811 | ||
|
de7bb79132 | ||
|
f81658ecfe | ||
|
a603de853d | ||
|
2998db57d4 | ||
|
9aaa429528 | ||
|
ba70be12a4 | ||
|
4b47326ffa | ||
|
848cd482e2 | ||
|
15cd83fc39 | ||
|
4de6e47c0a | ||
|
45f24a8f62 | ||
|
cf835515b1 | ||
|
c38b967fc4 | ||
|
efb1eb9d6b | ||
|
ce1031e017 | ||
|
d54be5ac2e | ||
|
76cc7c6614 | ||
|
54dd702763 | ||
|
dfd26d0704 | ||
|
0f8460b5e8 | ||
|
09883aa2f5 | ||
|
e3a2b1b57a | ||
|
a28d95a023 | ||
|
ab025e74a3 | ||
|
8077ef41c1 | ||
|
9d8864a6c7 | ||
|
e107ef52d5 | ||
|
57ec1f924d | ||
|
491b481b7f | ||
|
e327d31a08 | ||
|
708a4e9494 | ||
|
c55ad679ac | ||
|
dccbdfde97 | ||
|
09091c0dac | ||
|
bb22a965b2 | ||
|
4f0da70733 | ||
|
a1235f68ff | ||
|
0138f3b0a5 | ||
|
192ae38d57 | ||
|
620e147b8c | ||
|
644cde4855 | ||
|
c15576bbf8 | ||
|
0d8028ddc5 | ||
|
242f5a1ed8 | ||
|
d12ea17b17 | ||
|
a7365a50b1 | ||
|
b5beffb37c |
@@ -7,7 +7,7 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{php,css,js}]
|
||||
[*.{php,css,js,xml}]
|
||||
indent_style = tab
|
||||
|
||||
[*.json]
|
||||
|
67
.github/workflows/codeql-analysis.yml
vendored
67
.github/workflows/codeql-analysis.yml
vendored
@@ -1,67 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '20 16 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["call"]);
|
||||
namespace Adminer;
|
||||
|
||||
$PROCEDURE = ($_GET["name"] ?: $_GET["call"]);
|
||||
page_header(lang('Call') . ": " . h($PROCEDURE), $error);
|
||||
|
||||
$routine = routine($_GET["call"], (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDURE"));
|
||||
@@ -96,14 +98,17 @@ function pre_tr($s) {
|
||||
}
|
||||
$table = '(\+--[-+]+\+\n)';
|
||||
$row = '(\| .* \|\n)';
|
||||
echo
|
||||
preg_replace_callback("~^$table?$row$table?($row*)$table?~m", function ($match) {
|
||||
echo preg_replace_callback(
|
||||
"~^$table?$row$table?($row*)$table?~m",
|
||||
function ($match) {
|
||||
$first_row = pre_tr($match[2]);
|
||||
return "<table>\n" . ($match[1] ? "<thead>$first_row</thead>\n" : $first_row) . pre_tr($match[4]) . "\n</table>";
|
||||
},
|
||||
preg_replace('~(\n( -|mysql)> )(.+)~', "\\1<code class='jush-sql'>\\3</code>",
|
||||
preg_replace('~(.+)\n---+\n~', "<b>\\1</b>\n",
|
||||
h($routine['comment'])
|
||||
)));
|
||||
preg_replace(
|
||||
'~(\n( -|mysql)> )(.+)~',
|
||||
"\\1<code class='jush-sql'>\\3</code>",
|
||||
preg_replace('~(.+)\n---+\n~', "<b>\\1</b>\n", h($routine['comment']))
|
||||
)
|
||||
);
|
||||
?>
|
||||
</pre>
|
||||
|
@@ -1,12 +1,18 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["check"];
|
||||
$name = $_GET["name"];
|
||||
$row = $_POST;
|
||||
|
||||
if ($row && !$error) {
|
||||
$result = ($name == "" || queries("ALTER TABLE " . table($TABLE) . " DROP CONSTRAINT " . idf_escape($name)));
|
||||
if (!$row["drop"]) {
|
||||
$result = queries("ALTER TABLE " . table($TABLE) . " ADD" . ($row["name"] != "" ? " CONSTRAINT " . idf_escape($row["name"]) . "" : "") . " CHECK ($row[clause])"); //! SQL injection
|
||||
if (JUSH == "sqlite") {
|
||||
$result = recreate_table($TABLE, $TABLE, array(), array(), array(), 0, array(), $name, ($row["drop"] ? "" : $row["clause"]));
|
||||
} else {
|
||||
$result = ($name == "" || queries("ALTER TABLE " . table($TABLE) . " DROP CONSTRAINT " . idf_escape($name)));
|
||||
if (!$row["drop"]) {
|
||||
$result = queries("ALTER TABLE " . table($TABLE) . " ADD" . ($row["name"] != "" ? " CONSTRAINT " . idf_escape($row["name"]) : "") . " CHECK ($row[clause])"); //! SQL injection
|
||||
}
|
||||
}
|
||||
queries_redirect(
|
||||
ME . "table=" . urlencode($TABLE),
|
||||
@@ -18,18 +24,28 @@ if ($row && !$error) {
|
||||
page_header(($name != "" ? lang('Alter check') . ": " . h($name) : lang('Create check')), $error, array("table" => $TABLE));
|
||||
|
||||
if (!$row) {
|
||||
$checks = check_constraints($TABLE);
|
||||
$checks = $driver->checkConstraints($TABLE);
|
||||
$row = array("name" => $name, "clause" => $checks[$name]);
|
||||
}
|
||||
?>
|
||||
|
||||
<form action="" method="post">
|
||||
<p><?php echo lang('Name'); ?>: <input name="name" value="<?php echo h($row["name"]); ?>" data-maxlength="64" autocapitalize="off"><?php echo doc_link(array(
|
||||
'sql' => 'create-table-check-constraints.html',
|
||||
'mariadb' => 'constraint/',
|
||||
)); ?>
|
||||
<p><?php
|
||||
if (JUSH != "sqlite") {
|
||||
echo lang('Name') . ': <input name="name" value="' . h($row["name"]) . '" data-maxlength="64" autocapitalize="off"> ';
|
||||
}
|
||||
echo doc_link(array(
|
||||
'sql' => "create-table-check-constraints.html",
|
||||
'mariadb' => "constraint/",
|
||||
'pgsql' => "ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS",
|
||||
'mssql' => "relational-databases/tables/create-check-constraints",
|
||||
'sqlite' => "lang_createtable.html#check_constraints",
|
||||
), "?");
|
||||
?>
|
||||
<p><?php textarea("clause", $row["clause"]); ?>
|
||||
<p><input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?><?php } ?>
|
||||
<?php if ($name != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["create"];
|
||||
$partition_by = array();
|
||||
foreach (array('HASH', 'LINEAR HASH', 'KEY', 'LINEAR KEY', 'RANGE', 'LIST') as $key) {
|
||||
@@ -46,7 +48,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
$foreign_key = $foreign_keys[$field["type"]];
|
||||
$type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type
|
||||
if ($field["field"] != "") {
|
||||
if (!$field["has_default"]) {
|
||||
if (!$field["generated"]) {
|
||||
$field["default"] = null;
|
||||
}
|
||||
$process_field = process_field($field, $type_field);
|
||||
@@ -58,7 +60,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
}
|
||||
}
|
||||
if ($foreign_key !== null) {
|
||||
$foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . format_foreign_key(array(
|
||||
$foreign[idf_escape($field["field"])] = ($TABLE != "" && JUSH != "sqlite" ? "ADD" : " ") . format_foreign_key(array(
|
||||
'table' => $foreign_keys[$field["type"]],
|
||||
'source' => array($field["field"]),
|
||||
'target' => array($type_field["field"]),
|
||||
@@ -124,7 +126,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
queries_redirect(ME . (support("table") ? "table=" : "select=") . urlencode($name), $message, alter_table(
|
||||
$TABLE,
|
||||
$name,
|
||||
($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
|
||||
(JUSH == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
|
||||
$foreign,
|
||||
($row["Comment"] != $table_status["Comment"] ? $row["Comment"] : null),
|
||||
($row["Engine"] && $row["Engine"] != $table_status["Engine"] ? $row["Engine"] : ""),
|
||||
@@ -138,6 +140,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
page_header(($TABLE != "" ? lang('Alter table') : lang('Create table')), $error, array("table" => $TABLE), h($TABLE));
|
||||
|
||||
if (!$_POST) {
|
||||
$types = $driver->types();
|
||||
$row = array(
|
||||
"Engine" => $_COOKIE["adminer_engine"],
|
||||
"fields" => array(array("field" => "", "type" => (isset($types["int"]) ? "int" : (isset($types["integer"]) ? "integer" : "")), "on_update" => "")),
|
||||
@@ -152,7 +155,7 @@ if (!$_POST) {
|
||||
$row["Auto_increment"] = "";
|
||||
}
|
||||
foreach ($orig_fields as $field) {
|
||||
$field["has_default"] = isset($field["default"]);
|
||||
$field["generated"] = $field["generated"] ?: (isset($field["default"]) ? "DEFAULT" : "");
|
||||
$row["fields"][] = $field;
|
||||
}
|
||||
|
||||
@@ -180,7 +183,7 @@ foreach ($engines as $engine) {
|
||||
<?php if (support("columns") || $TABLE == "") { ?>
|
||||
<?php echo lang('Table name'); ?>: <input name="name"<?php echo ($TABLE == "" && !$_POST ? " autofocus" : ""); ?> data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
|
||||
<?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?>
|
||||
<?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
|
||||
<?php echo ($collations && !preg_match("~sqlite|mssql~", JUSH) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php } ?>
|
||||
|
||||
@@ -188,8 +191,8 @@ foreach ($engines as $engine) {
|
||||
<div class="scrollable">
|
||||
<table id="edit-fields" class="nowrap">
|
||||
<?php
|
||||
edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
|
||||
?>
|
||||
edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
|
||||
?>
|
||||
</table>
|
||||
<?php echo script("editFields();"); ?>
|
||||
</div>
|
||||
@@ -197,21 +200,23 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
|
||||
<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" class="size" value="<?php echo h($row["Auto_increment"]); ?>">
|
||||
<?php echo checkbox("defaults", 1, ($_POST ? $_POST["defaults"] : adminer_setting("defaults")), lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?>
|
||||
<?php
|
||||
$comments = ($_POST ? $_POST["comments"] : adminer_setting("comments"));
|
||||
echo (support("comment")
|
||||
? checkbox("comments", 1, $comments, lang('Comment'), "editingCommentsClick(this, true);", "jsonly")
|
||||
. ' ' . (preg_match('~\n~', $row["Comment"])
|
||||
? "<textarea name='Comment' rows='2' cols='20'" . ($comments ? "" : " class='hidden'") . ">" . h($row["Comment"]) . "</textarea>"
|
||||
: '<input name="Comment" value="' . h($row["Comment"]) . '" data-maxlength="' . (min_version(5.5) ? 2048 : 60) . '"' . ($comments ? "" : " class='hidden'") . '>'
|
||||
)
|
||||
: '')
|
||||
;
|
||||
?>
|
||||
$comments = ($_POST ? $_POST["comments"] : adminer_setting("comments"));
|
||||
echo (support("comment")
|
||||
? checkbox("comments", 1, $comments, lang('Comment'), "editingCommentsClick(this, true);", "jsonly")
|
||||
. ' ' . (preg_match('~\n~', $row["Comment"])
|
||||
? "<textarea name='Comment' rows='2' cols='20'" . ($comments ? "" : " class='hidden'") . ">" . h($row["Comment"]) . "</textarea>"
|
||||
: '<input name="Comment" value="' . h($row["Comment"]) . '" data-maxlength="' . (min_version(5.5) ? 2048 : 60) . '"' . ($comments ? "" : " class='hidden'") . '>'
|
||||
)
|
||||
: '')
|
||||
;
|
||||
?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($TABLE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?><?php } ?>
|
||||
<?php if ($TABLE != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?>
|
||||
<?php } ?>
|
||||
<?php
|
||||
if (support("partitioning")) {
|
||||
$partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]);
|
||||
@@ -224,13 +229,13 @@ if (support("partitioning")) {
|
||||
<table id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
|
||||
<thead><tr><th><?php echo lang('Partition name'); ?><th><?php echo lang('Values'); ?></thead>
|
||||
<?php
|
||||
foreach ($row["partition_names"] as $key => $val) {
|
||||
echo '<tr>';
|
||||
echo '<td><input name="partition_names[]" value="' . h($val) . '" autocapitalize="off">';
|
||||
echo ($key == count($row["partition_names"]) - 1 ? script("qsl('input').oninput = partitionNameChange;") : '');
|
||||
echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">';
|
||||
}
|
||||
?>
|
||||
foreach ($row["partition_names"] as $key => $val) {
|
||||
echo '<tr>';
|
||||
echo '<td><input name="partition_names[]" value="' . h($val) . '" autocapitalize="off">';
|
||||
echo ($key == count($row["partition_names"]) - 1 ? script("qsl('input').oninput = partitionNameChange;") : '');
|
||||
echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">';
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div></fieldset>
|
||||
<?php
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$row = $_POST;
|
||||
|
||||
if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x
|
||||
@@ -44,7 +46,7 @@ if ($_POST) {
|
||||
$name = $row["name"];
|
||||
} elseif (DB != "") {
|
||||
$row["collation"] = db_collation(DB, $collations);
|
||||
} elseif ($jush == "sql") {
|
||||
} elseif (JUSH == "sql") {
|
||||
// propose database name with limited privileges
|
||||
foreach (get_vals("SHOW GRANTS") as $grant) {
|
||||
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~', $grant, $match) && $match[1]) {
|
||||
@@ -64,7 +66,7 @@ echo ($_POST["add_x"] || strpos($name, "\n")
|
||||
) . "\n" . ($collations ? html_select("collation", array("" => "(" . lang('collation') . ")") + $collations, $row["collation"]) . doc_link(array(
|
||||
'sql' => "charset-charsets.html",
|
||||
'mariadb' => "supported-character-sets-and-collations/",
|
||||
'mssql' => "ms187963.aspx",
|
||||
'mssql' => "relational-databases/system-functions/sys-fn-helpcollations-transact-sql",
|
||||
)) : "");
|
||||
?>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$tables_views = array_merge((array) $_POST["tables"], (array) $_POST["views"]);
|
||||
|
||||
if ($tables_views && !$error && !$_POST["search"]) {
|
||||
$result = true;
|
||||
$message = "";
|
||||
if ($jush == "sql" && $_POST["tables"] && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) {
|
||||
if (JUSH == "sql" && $_POST["tables"] && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) {
|
||||
queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once
|
||||
}
|
||||
|
||||
@@ -27,15 +29,21 @@ if ($tables_views && !$error && !$_POST["search"]) {
|
||||
$result = drop_tables($_POST["tables"]);
|
||||
}
|
||||
$message = lang('Tables have been dropped.');
|
||||
} elseif ($jush != "sql") {
|
||||
$result = ($jush == "sqlite"
|
||||
} elseif (JUSH == "sqlite" && $_POST["check"]) {
|
||||
foreach ((array) $_POST["tables"] as $table) {
|
||||
foreach (get_rows("PRAGMA integrity_check(" . q($table) . ")") as $row) {
|
||||
$message .= "<b>" . h($table) . "</b>: " . h($row["integrity_check"]) . "<br>";
|
||||
}
|
||||
}
|
||||
} elseif (JUSH != "sql") {
|
||||
$result = (JUSH == "sqlite"
|
||||
? queries("VACUUM")
|
||||
: apply_queries("VACUUM" . ($_POST["optimize"] ? "" : " ANALYZE"), $_POST["tables"])
|
||||
);
|
||||
$message = lang('Tables have been optimized.');
|
||||
} elseif (!$_POST["tables"]) {
|
||||
$message = lang('No tables.');
|
||||
} elseif ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"])))) {
|
||||
} elseif ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('Adminer\idf_escape', $_POST["tables"])))) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$message .= "<b>" . h($row["Table"]) . "</b>: " . h($row["Msg_text"]) . "<br>";
|
||||
}
|
||||
@@ -91,15 +99,17 @@ if ($adminer->homepage()) {
|
||||
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>';
|
||||
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '" title="' . lang('Select data') . '">?</a>';
|
||||
} else {
|
||||
foreach (array(
|
||||
"Engine" => array(),
|
||||
"Collation" => array(),
|
||||
"Data_length" => array("create", lang('Alter table')),
|
||||
"Index_length" => array("indexes", lang('Alter indexes')),
|
||||
"Data_free" => array("edit", lang('New item')),
|
||||
"Auto_increment" => array("auto_increment=1&create", lang('Alter table')),
|
||||
"Rows" => array("select", lang('Select data')),
|
||||
) as $key => $link) {
|
||||
foreach (
|
||||
array(
|
||||
"Engine" => array(),
|
||||
"Collation" => array(),
|
||||
"Data_length" => array("create", lang('Alter table')),
|
||||
"Index_length" => array("indexes", lang('Alter indexes')),
|
||||
"Data_free" => array("edit", lang('New item')),
|
||||
"Auto_increment" => array("auto_increment=1&create", lang('Alter table')),
|
||||
"Rows" => array("select", lang('Select data')),
|
||||
) as $key => $link
|
||||
) {
|
||||
$id = " id='$key-" . h($name) . "'";
|
||||
echo ($link ? "<td align='right'>" . (support("table") || $key == "Rows" || (support("indexes") && $key != "Data_length")
|
||||
? "<a href='" . h(ME . "$link[0]=") . urlencode($name) . "'$id title='$link[1]'>?</a>"
|
||||
@@ -113,7 +123,7 @@ if ($adminer->homepage()) {
|
||||
}
|
||||
|
||||
echo "<tr><td><th>" . lang('%d in total', count($tables_list));
|
||||
echo "<td>" . h($jush == "sql" ? $connection->result("SELECT @@default_storage_engine") : "");
|
||||
echo "<td>" . h(JUSH == "sql" ? $connection->result("SELECT @@default_storage_engine") : "");
|
||||
echo "<td>" . h(db_collation(DB, collations()));
|
||||
foreach (array("Data_length", "Index_length", "Data_free") as $key) {
|
||||
echo "<td align='right' id='sum-$key'>";
|
||||
@@ -125,18 +135,19 @@ if ($adminer->homepage()) {
|
||||
if (!information_schema(DB)) {
|
||||
echo "<div class='footer'><div>\n";
|
||||
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . on_help("'VACUUM'");
|
||||
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help($jush == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'");
|
||||
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help(JUSH == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'");
|
||||
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
|
||||
. ($jush == "sqlite" ? $vacuum
|
||||
: ($jush == "pgsql" ? $vacuum . $optimize
|
||||
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'") . $optimize
|
||||
. (JUSH == "sqlite" ? $vacuum . "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'PRAGMA integrity_check'")
|
||||
: (JUSH == "pgsql" ? $vacuum . $optimize
|
||||
: (JUSH == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'")
|
||||
. $optimize
|
||||
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'CHECK TABLE'")
|
||||
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . on_help("'REPAIR TABLE'")
|
||||
: "")))
|
||||
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help($jush == "sqlite" ? "'DELETE'" : "'TRUNCATE" . ($jush == "pgsql" ? "'" : " TABLE'")) . confirm()
|
||||
. "<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());
|
||||
if (count($databases) != 1 && $jush != "sqlite") {
|
||||
if (count($databases) != 1 && JUSH != "sqlite") {
|
||||
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
|
||||
echo "<p>" . lang('Move to other database') . ": ";
|
||||
echo ($databases ? html_select("target", $databases, $db) : '<input name="target" value="' . h($db) . '" autocapitalize="off">');
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["download"];
|
||||
$fields = fields($TABLE);
|
||||
header("Content-Type: application/octet-stream");
|
||||
|
@@ -1,229 +1,26 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers["mongo"] = "MongoDB (alpha)";
|
||||
|
||||
if (isset($_GET["mongo"])) {
|
||||
define("DRIVER", "mongo");
|
||||
define('Adminer\DRIVER', "mongo");
|
||||
|
||||
if (class_exists('MongoDB')) {
|
||||
class Min_DB {
|
||||
var $extension = "Mongo", $server_info = MongoClient::VERSION, $error, $last_id, $_link, $_db;
|
||||
|
||||
function connect($uri, $options) {
|
||||
try {
|
||||
$this->_link = new MongoClient($uri, $options);
|
||||
if ($options["password"] != "") {
|
||||
$options["password"] = "";
|
||||
try {
|
||||
new MongoClient($uri, $options);
|
||||
$this->error = lang('Database does not support password.');
|
||||
} catch (Exception $e) {
|
||||
// this is what we want
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
function query($query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
try {
|
||||
$this->_db = $this->_link->selectDB($database);
|
||||
return true;
|
||||
} catch (Exception $ex) {
|
||||
$this->error = $ex->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $num_rows, $_rows = array(), $_offset = 0, $_charset = array();
|
||||
|
||||
function __construct($result) {
|
||||
foreach ($result as $item) {
|
||||
$row = array();
|
||||
foreach ($item as $key => $val) {
|
||||
if (is_a($val, 'MongoBinData')) {
|
||||
$this->_charset[$key] = 63;
|
||||
}
|
||||
$row[$key] =
|
||||
(is_a($val, 'MongoId') ? "ObjectId(\"$val\")" :
|
||||
(is_a($val, 'MongoDate') ? gmdate("Y-m-d H:i:s", $val->sec) . " GMT" :
|
||||
(is_a($val, 'MongoBinData') ? $val->bin : //! allow downloading
|
||||
(is_a($val, 'MongoRegex') ? "$val" :
|
||||
(is_object($val) ? get_class($val) : // MongoMinKey, MongoMaxKey
|
||||
$val
|
||||
)))));
|
||||
}
|
||||
$this->_rows[] = $row;
|
||||
foreach ($row as $key => $val) {
|
||||
if (!isset($this->_rows[0][$key])) {
|
||||
$this->_rows[0][$key] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->num_rows = count($this->_rows);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
$row = current($this->_rows);
|
||||
if (!$row) {
|
||||
return $row;
|
||||
}
|
||||
$return = array();
|
||||
foreach ($this->_rows[0] as $key => $val) {
|
||||
$return[$key] = $row[$key];
|
||||
}
|
||||
next($this->_rows);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
$return = $this->fetch_assoc();
|
||||
if (!$return) {
|
||||
return $return;
|
||||
}
|
||||
return array_values($return);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$keys = array_keys($this->_rows[0]);
|
||||
$name = $keys[$this->_offset++];
|
||||
return (object) array(
|
||||
'name' => $name,
|
||||
'charsetnr' => $this->_charset[$name],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
public $primary = "_id";
|
||||
|
||||
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
|
||||
$select = ($select == array("*")
|
||||
? array()
|
||||
: array_fill_keys($select, true)
|
||||
);
|
||||
$sort = array();
|
||||
foreach ($order as $val) {
|
||||
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
|
||||
$sort[$val] = ($count ? -1 : 1);
|
||||
}
|
||||
return new Min_Result($this->_conn->_db->selectCollection($table)
|
||||
->find(array(), $select)
|
||||
->sort($sort)
|
||||
->limit($limit != "" ? +$limit : 0)
|
||||
->skip($page * $limit)
|
||||
);
|
||||
}
|
||||
|
||||
function insert($table, $set) {
|
||||
try {
|
||||
$return = $this->_conn->_db->selectCollection($table)->insert($set);
|
||||
$this->_conn->errno = $return['code'];
|
||||
$this->_conn->error = $return['err'];
|
||||
$this->_conn->last_id = $set['_id'];
|
||||
return !$return['err'];
|
||||
} catch (Exception $ex) {
|
||||
$this->_conn->error = $ex->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_databases($flush) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$dbs = $connection->_link->listDBs();
|
||||
foreach ($dbs['databases'] as $db) {
|
||||
$return[] = $db['name'];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$return[$db] = count($connection->_link->selectDB($db)->getCollectionNames(true));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
global $connection;
|
||||
return array_fill_keys($connection->_db->getCollectionNames(true), 'table');
|
||||
}
|
||||
|
||||
function drop_databases($databases) {
|
||||
global $connection;
|
||||
foreach ($databases as $db) {
|
||||
$response = $connection->_link->selectDB($db)->drop();
|
||||
if (!$response['ok']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($connection->_db->selectCollection($table)->getIndexInfo() as $index) {
|
||||
$descs = array();
|
||||
foreach ($index["key"] as $column => $type) {
|
||||
$descs[] = ($type == -1 ? '1' : null);
|
||||
}
|
||||
$return[$index["name"]] = array(
|
||||
"type" => ($index["name"] == "_id_" ? "PRIMARY" : ($index["unique"] ? "UNIQUE" : "INDEX")),
|
||||
"columns" => array_keys($index["key"]),
|
||||
"lengths" => array(),
|
||||
"descs" => $descs,
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
return fields_from_edit();
|
||||
}
|
||||
|
||||
function found_rows($table_status, $where) {
|
||||
global $connection;
|
||||
//! don't call count_rows()
|
||||
return $connection->_db->selectCollection($_GET["select"])->count($where);
|
||||
}
|
||||
|
||||
$operators = array("=");
|
||||
|
||||
} elseif (class_exists('MongoDB\Driver\Manager')) {
|
||||
class Min_DB {
|
||||
if (class_exists('MongoDB\Driver\Manager')) {
|
||||
class Db {
|
||||
var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id;
|
||||
/** @var MongoDB\Driver\Manager */
|
||||
var $_link;
|
||||
var $_db, $_db_name;
|
||||
|
||||
function connect($uri, $options) {
|
||||
$class = 'MongoDB\Driver\Manager';
|
||||
$this->_link = new $class($uri, $options);
|
||||
$this->_link = new \MongoDB\Driver\Manager($uri, $options);
|
||||
$this->executeCommand($options["db"], array('ping' => 1));
|
||||
}
|
||||
|
||||
function executeCommand($db, $command) {
|
||||
$class = 'MongoDB\Driver\Command';
|
||||
try {
|
||||
return $this->_link->executeCommand($db, new $class($command));
|
||||
return $this->_link->executeCommand($db, new \MongoDB\Driver\Command($command));
|
||||
} catch (Exception $e) {
|
||||
$this->error = $e->getMessage();
|
||||
return array();
|
||||
@@ -255,7 +52,7 @@ if (isset($_GET["mongo"])) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
class Result {
|
||||
var $num_rows, $_rows = array(), $_offset = 0, $_charset = array();
|
||||
|
||||
function __construct($result) {
|
||||
@@ -313,88 +110,9 @@ if (isset($_GET["mongo"])) {
|
||||
'charsetnr' => $this->_charset[$name],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
public $primary = "_id";
|
||||
|
||||
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
|
||||
global $connection;
|
||||
$select = ($select == array("*")
|
||||
? array()
|
||||
: array_fill_keys($select, 1)
|
||||
);
|
||||
if (count($select) && !isset($select['_id'])) {
|
||||
$select['_id'] = 0;
|
||||
}
|
||||
$where = where_to_query($where);
|
||||
$sort = array();
|
||||
foreach ($order as $val) {
|
||||
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
|
||||
$sort[$val] = ($count ? -1 : 1);
|
||||
}
|
||||
if (isset($_GET['limit']) && is_numeric($_GET['limit']) && $_GET['limit'] > 0) {
|
||||
$limit = $_GET['limit'];
|
||||
}
|
||||
$limit = min(200, max(1, (int) $limit));
|
||||
$skip = $page * $limit;
|
||||
$class = 'MongoDB\Driver\Query';
|
||||
try {
|
||||
return new Min_Result($connection->_link->executeQuery("$connection->_db_name.$table", new $class($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
|
||||
} catch (Exception $e) {
|
||||
$connection->error = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") {
|
||||
global $connection;
|
||||
$db = $connection->_db_name;
|
||||
$where = sql_query_where_parser($queryWhere);
|
||||
$class = 'MongoDB\Driver\BulkWrite';
|
||||
$bulk = new $class(array());
|
||||
if (isset($set['_id'])) {
|
||||
unset($set['_id']);
|
||||
}
|
||||
$removeFields = array();
|
||||
foreach ($set as $key => $value) {
|
||||
if ($value == 'NULL') {
|
||||
$removeFields[$key] = 1;
|
||||
unset($set[$key]);
|
||||
}
|
||||
}
|
||||
$update = array('$set' => $set);
|
||||
if (count($removeFields)) {
|
||||
$update['$unset'] = $removeFields;
|
||||
}
|
||||
$bulk->update($where, $update, array('upsert' => false));
|
||||
return $connection->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
|
||||
}
|
||||
|
||||
function delete($table, $queryWhere, $limit = 0) {
|
||||
global $connection;
|
||||
$db = $connection->_db_name;
|
||||
$where = sql_query_where_parser($queryWhere);
|
||||
$class = 'MongoDB\Driver\BulkWrite';
|
||||
$bulk = new $class(array());
|
||||
$bulk->delete($where, array('limit' => $limit));
|
||||
return $connection->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
|
||||
}
|
||||
|
||||
function insert($table, $set) {
|
||||
global $connection;
|
||||
$db = $connection->_db_name;
|
||||
$class = 'MongoDB\Driver\BulkWrite';
|
||||
$bulk = new $class(array());
|
||||
if ($set['_id'] == '') {
|
||||
unset($set['_id']);
|
||||
}
|
||||
$bulk->insert($set);
|
||||
return $connection->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
|
||||
}
|
||||
}
|
||||
|
||||
function get_databases($flush) {
|
||||
global $connection;
|
||||
@@ -517,9 +235,8 @@ if (isset($_GET["mongo"])) {
|
||||
$val = (float) $val;
|
||||
$op = $match[1];
|
||||
} elseif (preg_match('~^\(date\)(.+)~', $op, $match)) {
|
||||
$dateTime = new DateTime($val);
|
||||
$class = 'MongoDB\BSON\UTCDatetime';
|
||||
$val = new $class($dateTime->getTimestamp() * 1000);
|
||||
$dateTime = new \DateTime($val);
|
||||
$val = new \MongoDB\BSON\UTCDatetime($dateTime->getTimestamp() * 1000);
|
||||
$op = $match[1];
|
||||
}
|
||||
switch ($op) {
|
||||
@@ -557,8 +274,17 @@ if (isset($_GET["mongo"])) {
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
$operators = array(
|
||||
|
||||
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("mongodb");
|
||||
static $jush = "mongo";
|
||||
|
||||
var $editFunctions = array(array("json"));
|
||||
|
||||
var $operators = array(
|
||||
"=",
|
||||
"!=",
|
||||
">",
|
||||
@@ -580,8 +306,78 @@ if (isset($_GET["mongo"])) {
|
||||
"(date)<=",
|
||||
);
|
||||
|
||||
public $primary = "_id";
|
||||
|
||||
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
|
||||
$select = ($select == array("*")
|
||||
? array()
|
||||
: array_fill_keys($select, 1)
|
||||
);
|
||||
if (count($select) && !isset($select['_id'])) {
|
||||
$select['_id'] = 0;
|
||||
}
|
||||
$where = where_to_query($where);
|
||||
$sort = array();
|
||||
foreach ($order as $val) {
|
||||
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
|
||||
$sort[$val] = ($count ? -1 : 1);
|
||||
}
|
||||
if (isset($_GET['limit']) && is_numeric($_GET['limit']) && $_GET['limit'] > 0) {
|
||||
$limit = $_GET['limit'];
|
||||
}
|
||||
$limit = min(200, max(1, (int) $limit));
|
||||
$skip = $page * $limit;
|
||||
try {
|
||||
return new Result($this->_conn->_link->executeQuery("$connection->_db_name.$table", new \MongoDB\Driver\Query($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
|
||||
} catch (Exception $e) {
|
||||
$connection->error = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") {
|
||||
$db = $this->_conn->_db_name;
|
||||
$where = sql_query_where_parser($queryWhere);
|
||||
$bulk = new \MongoDB\Driver\BulkWrite(array());
|
||||
if (isset($set['_id'])) {
|
||||
unset($set['_id']);
|
||||
}
|
||||
$removeFields = array();
|
||||
foreach ($set as $key => $value) {
|
||||
if ($value == 'NULL') {
|
||||
$removeFields[$key] = 1;
|
||||
unset($set[$key]);
|
||||
}
|
||||
}
|
||||
$update = array('$set' => $set);
|
||||
if (count($removeFields)) {
|
||||
$update['$unset'] = $removeFields;
|
||||
}
|
||||
$bulk->update($where, $update, array('upsert' => false));
|
||||
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
|
||||
}
|
||||
|
||||
function delete($table, $queryWhere, $limit = 0) {
|
||||
$db = $this->_conn->_db_name;
|
||||
$where = sql_query_where_parser($queryWhere);
|
||||
$bulk = new \MongoDB\Driver\BulkWrite(array());
|
||||
$bulk->delete($where, array('limit' => $limit));
|
||||
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
|
||||
}
|
||||
|
||||
function insert($table, $set) {
|
||||
$db = $this->_conn->_db_name;
|
||||
$bulk = new \MongoDB\Driver\BulkWrite(array());
|
||||
if ($set['_id'] == '') {
|
||||
unset($set['_id']);
|
||||
}
|
||||
$bulk->insert($set);
|
||||
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function table($idf) {
|
||||
return $idf;
|
||||
}
|
||||
@@ -627,7 +423,7 @@ if (isset($_GET["mongo"])) {
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$connection = new Db;
|
||||
list($server, $username, $password) = $adminer->credentials();
|
||||
|
||||
if ($server == "") {
|
||||
@@ -739,16 +535,4 @@ if (isset($_GET["mongo"])) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function driver_config() {
|
||||
global $operators;
|
||||
return array(
|
||||
'possible_drivers' => array("mongo", "mongodb"),
|
||||
'jush' => "mongo",
|
||||
'operators' => $operators,
|
||||
'functions' => array(),
|
||||
'grouping' => array(),
|
||||
'edit_functions' => array(array("json")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -5,12 +5,14 @@
|
||||
* @author Jakub Vrana
|
||||
*/
|
||||
|
||||
namespace Adminer;
|
||||
|
||||
$drivers["mssql"] = "MS SQL";
|
||||
|
||||
if (isset($_GET["mssql"])) {
|
||||
define("DRIVER", "mssql");
|
||||
define('Adminer\DRIVER', "mssql");
|
||||
if (extension_loaded("sqlsrv")) {
|
||||
class Min_DB {
|
||||
class Db {
|
||||
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $errno, $error;
|
||||
|
||||
function _get_error() {
|
||||
@@ -52,7 +54,7 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return $this->query("USE " . idf_escape($database));
|
||||
return $this->query(use_sql($database));
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
@@ -83,7 +85,7 @@ if (isset($_GET["mssql"])) {
|
||||
return false;
|
||||
}
|
||||
if (sqlsrv_field_metadata($result)) {
|
||||
return new Min_Result($result);
|
||||
return new Result($result);
|
||||
}
|
||||
$this->affected_rows = sqlsrv_rows_affected($result);
|
||||
return true;
|
||||
@@ -103,7 +105,7 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
class Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
@@ -134,7 +136,7 @@ if (isset($_GET["mssql"])) {
|
||||
$this->_fields = sqlsrv_field_metadata($this->_result);
|
||||
}
|
||||
$field = $this->_fields[$this->_offset++];
|
||||
$return = new stdClass;
|
||||
$return = new \stdClass;
|
||||
$return->name = $field["Name"];
|
||||
$return->orgname = $field["Name"];
|
||||
$return->type = ($field["Type"] == 1 ? 254 : 0);
|
||||
@@ -152,106 +154,23 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mssql")) {
|
||||
class Min_DB {
|
||||
var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
} elseif (extension_loaded("pdo_sqlsrv")) {
|
||||
class Db extends PdoDb {
|
||||
var $extension = "PDO_SQLSRV";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @mssql_connect($server, $username, $password);
|
||||
if ($this->_link) {
|
||||
$result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
|
||||
if ($result) {
|
||||
$row = $result->fetch_row();
|
||||
$this->server_info = $this->result("sp_server_info 2", 2) . " [$row[0]] $row[1]";
|
||||
}
|
||||
} else {
|
||||
$this->error = mssql_get_last_message();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
$unicode = strlen($string) != strlen(utf8_decode($string));
|
||||
return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'";
|
||||
$this->dsn("sqlsrv:Server=" . str_replace(":", ",", $server), $username, $password);
|
||||
return true;
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return mssql_select_db($database);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @mssql_query($query, $this->_link); //! $unbuffered
|
||||
$this->error = "";
|
||||
if (!$result) {
|
||||
$this->error = mssql_get_last_message();
|
||||
return false;
|
||||
}
|
||||
if ($result === true) {
|
||||
$this->affected_rows = mssql_rows_affected($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return mssql_next_result($this->_result->_result);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
return mssql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = mssql_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return mssql_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return mssql_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function num_rows() {
|
||||
return mssql_num_rows($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$return = mssql_fetch_field($this->_result);
|
||||
$return->orgtable = $return->table;
|
||||
$return->orgname = $return->name;
|
||||
return $return;
|
||||
}
|
||||
|
||||
function seek($offset) {
|
||||
mssql_data_seek($this->_result, $offset);
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
mssql_free_result($this->_result);
|
||||
// database selection is separated from the connection so dbname in DSN can't be used
|
||||
return $this->query(use_sql($database));
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_dblib")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
class Db extends PdoDb {
|
||||
var $extension = "PDO_DBLIB";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
@@ -260,40 +179,95 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
// database selection is separated from the connection so dbname in DSN can't be used
|
||||
return $this->query("USE " . idf_escape($database));
|
||||
return $this->query(use_sql($database));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("SQLSRV", "PDO_SQLSRV", "PDO_DBLIB");
|
||||
static $jush = "mssql";
|
||||
|
||||
var $editFunctions = array(
|
||||
array(
|
||||
"date|time" => "getdate",
|
||||
), array(
|
||||
"int|decimal|real|float|money|datetime" => "+/-",
|
||||
"char|text" => "+",
|
||||
)
|
||||
);
|
||||
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
|
||||
var $functions = array("len", "lower", "round", "upper");
|
||||
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
var $onActions = "NO ACTION|CASCADE|SET NULL|SET DEFAULT";
|
||||
var $generated = array("PERSISTED", "VIRTUAL");
|
||||
|
||||
function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->types = array( //! use sys.types
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
|
||||
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
|
||||
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
|
||||
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
|
||||
);
|
||||
}
|
||||
|
||||
function insertUpdate($table, $rows, $primary) {
|
||||
foreach ($rows as $set) {
|
||||
$update = array();
|
||||
$where = array();
|
||||
foreach ($set as $key => $val) {
|
||||
$update[] = "$key = $val";
|
||||
if (isset($primary[idf_unescape($key)])) {
|
||||
$where[] = "$key = $val";
|
||||
}
|
||||
$fields = fields($table);
|
||||
$update = array();
|
||||
$where = array();
|
||||
$set = reset($rows);
|
||||
$columns = "c" . implode(", c", range(1, count($set)));
|
||||
$c = 0;
|
||||
$insert = array();
|
||||
foreach ($set as $key => $val) {
|
||||
$c++;
|
||||
$name = idf_unescape($key);
|
||||
if (!$fields[$name]["auto_increment"]) {
|
||||
$insert[$key] = "c$c";
|
||||
}
|
||||
//! can use only one query for all rows
|
||||
if (!queries("MERGE " . table($table) . " USING (VALUES(" . implode(", ", $set) . ")) AS source (c" . implode(", c", range(1, count($set))) . ") ON " . implode(" AND ", $where) //! source, c1 - possible conflict
|
||||
. " WHEN MATCHED THEN UPDATE SET " . implode(", ", $update)
|
||||
. " WHEN NOT MATCHED THEN INSERT (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ");" // ; is mandatory
|
||||
)) {
|
||||
return false;
|
||||
if (isset($primary[$name])) {
|
||||
$where[] = "$key = c$c";
|
||||
} else {
|
||||
$update[] = "$key = c$c";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
$values = array();
|
||||
foreach ($rows as $set) {
|
||||
$values[] = "(" . implode(", ", $set) . ")";
|
||||
}
|
||||
if ($where) {
|
||||
$identity = queries("SET IDENTITY_INSERT " . table($table) . " ON");
|
||||
$return = queries(
|
||||
"MERGE " . table($table) . " USING (VALUES\n\t" . implode(",\n\t", $values) . "\n) AS source ($columns) ON " . implode(" AND ", $where) //! source, c1 - possible conflict
|
||||
. ($update ? "\nWHEN MATCHED THEN UPDATE SET " . implode(", ", $update) : "")
|
||||
. "\nWHEN NOT MATCHED THEN INSERT (" . implode(", ", array_keys($identity ? $set : $insert)) . ") VALUES (" . ($identity ? $columns : implode(", ", $insert)) . ");" // ; is mandatory
|
||||
);
|
||||
if ($identity) {
|
||||
queries("SET IDENTITY_INSERT " . table($table) . " OFF");
|
||||
}
|
||||
} else {
|
||||
$return = queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES\n" . implode(",\n", $values));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function begin() {
|
||||
return queries("BEGIN TRANSACTION");
|
||||
}
|
||||
|
||||
function tableHelp($name, $is_view = false) {
|
||||
$links = array(
|
||||
"sys" => "catalog-views/sys-",
|
||||
"INFORMATION_SCHEMA" => "information-schema-views/",
|
||||
);
|
||||
$link = $links[get_schema()];
|
||||
if ($link) {
|
||||
return "relational-databases/system-$link" . preg_replace('~_~', '-', strtolower($name)) . "-transact-sql";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +282,7 @@ if (isset($_GET["mssql"])) {
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$connection = new Db;
|
||||
$credentials = $adminer->credentials();
|
||||
|
||||
if ($credentials[0] == "") {
|
||||
@@ -363,9 +337,11 @@ if (isset($_GET["mssql"])) {
|
||||
|
||||
function table_status($name = "") {
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT ao.name AS Name, ao.type_desc AS Engine, (SELECT value FROM fn_listextendedproperty(default, 'SCHEMA', schema_name(schema_id), 'TABLE', ao.name, null, null)) AS Comment
|
||||
foreach (
|
||||
get_rows("SELECT ao.name AS Name, ao.type_desc AS Engine, (SELECT value FROM fn_listextendedproperty(default, 'SCHEMA', schema_name(schema_id), 'TABLE', ao.name, null, null)) AS Comment
|
||||
FROM sys.all_objects AS ao
|
||||
WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row) {
|
||||
WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row
|
||||
) {
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
@@ -383,15 +359,19 @@ WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V')
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$comments = get_key_vals("SELECT objname, cast(value as varchar(max)) FROM fn_listextendedproperty('MS_DESCRIPTION', 'schema', " . q(get_schema()) . ", 'table', " . q($table) . ", 'column', NULL)");
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default], d.name default_constraint
|
||||
$table_id = $connection->result("SELECT object_id FROM sys.all_objects WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') AND name = " . q($table));
|
||||
foreach (
|
||||
get_rows("SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default], d.name default_constraint, i.is_primary_key
|
||||
FROM sys.all_columns c
|
||||
JOIN sys.all_objects o ON c.object_id = o.object_id
|
||||
JOIN sys.types t ON c.user_type_id = t.user_type_id
|
||||
LEFT JOIN sys.default_constraints d ON c.default_object_id = d.object_id
|
||||
WHERE o.schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND o.type IN ('S', 'U', 'V') AND o.name = " . q($table)
|
||||
) as $row) {
|
||||
LEFT JOIN sys.index_columns ic ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
||||
LEFT JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
||||
WHERE c.object_id = " . q($table_id)) as $row
|
||||
) {
|
||||
$type = $row["type"];
|
||||
$length = (preg_match("~char|binary~", $type)
|
||||
? $row["max_length"] / ($type[0] == 'n' ? 2 : 1)
|
||||
@@ -408,22 +388,27 @@ WHERE o.schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND o.type IN ('S', 'U',
|
||||
"auto_increment" => $row["is_identity"],
|
||||
"collation" => $row["collation_name"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
|
||||
"primary" => $row["is_identity"], //! or indexes.is_primary_key
|
||||
"primary" => $row["is_primary_key"],
|
||||
"comment" => $comments[$row["name"]],
|
||||
);
|
||||
}
|
||||
foreach (get_rows("SELECT * FROM sys.computed_columns WHERE object_id = " . q($table_id)) as $row) {
|
||||
$return[$row["name"]]["generated"] = ($row["is_persisted"] ? "PERSISTED" : "VIRTUAL");
|
||||
$return[$row["name"]]["default"] = $row["definition"];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
$return = array();
|
||||
// sp_statistics doesn't return information about primary key
|
||||
foreach (get_rows("SELECT i.name, key_ordinal, is_unique, is_primary_key, c.name AS column_name, is_descending_key
|
||||
foreach (
|
||||
get_rows("SELECT i.name, key_ordinal, is_unique, is_primary_key, c.name AS column_name, is_descending_key
|
||||
FROM sys.indexes i
|
||||
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
||||
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
||||
WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
, $connection2) as $row) {
|
||||
WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row
|
||||
) {
|
||||
$name = $row["name"];
|
||||
$return[$name]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
|
||||
$return[$name]["lengths"] = array();
|
||||
@@ -447,7 +432,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
return get_schema() == "INFORMATION_SCHEMA";
|
||||
}
|
||||
|
||||
function error() {
|
||||
@@ -460,7 +445,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
}
|
||||
|
||||
function drop_databases($databases) {
|
||||
return queries("DROP DATABASE " . implode(", ", array_map('idf_escape', $databases)));
|
||||
return queries("DROP DATABASE " . implode(", ", array_map('Adminer\idf_escape', $databases)));
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
@@ -488,6 +473,9 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
$val[1] = preg_replace("~( COLLATE )'(\\w+)'~", '\1\2', $val[1]);
|
||||
$comments[$field[0]] = $val[5];
|
||||
unset($val[5]);
|
||||
if (preg_match('~ AS ~', $val[3])) {
|
||||
unset($val[1], $val[2]);
|
||||
}
|
||||
if ($field[0] == "") {
|
||||
$alter["ADD"][] = "\n " . implode("", $val) . ($table == "" ? substr($foreign[$val[0]], 16 + strlen($val[0])) : ""); // 16 - strlen(" FOREIGN KEY ()")
|
||||
} else {
|
||||
@@ -542,10 +530,12 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
} else {
|
||||
$index[] = idf_escape($val[1]) . " ON " . table($table);
|
||||
}
|
||||
} elseif (!queries(($val[0] != "PRIMARY"
|
||||
? "CREATE $val[0] " . ($val[0] != "INDEX" ? "INDEX " : "") . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table)
|
||||
: "ALTER TABLE " . table($table) . " ADD PRIMARY KEY"
|
||||
) . " (" . implode(", ", $val[2]) . ")")) {
|
||||
} elseif (
|
||||
!queries(($val[0] != "PRIMARY"
|
||||
? "CREATE $val[0] " . ($val[0] != "INDEX" ? "INDEX " : "") . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table)
|
||||
: "ALTER TABLE " . table($table) . " ADD PRIMARY KEY"
|
||||
) . " (" . implode(", ", $val[2]) . ")")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -571,10 +561,14 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
|
||||
function foreign_keys($table) {
|
||||
$return = array();
|
||||
$on_actions = array("CASCADE", "NO ACTION", "SET NULL", "SET DEFAULT");
|
||||
foreach (get_rows("EXEC sp_fkeys @fktable_name = " . q($table) . ", @fktable_owner = " . q(get_schema())) as $row) {
|
||||
$foreign_key = &$return[$row["FK_NAME"]];
|
||||
$foreign_key["db"] = $row["PKTABLE_QUALIFIER"];
|
||||
$foreign_key["ns"] = $row["PKTABLE_OWNER"];
|
||||
$foreign_key["table"] = $row["PKTABLE_NAME"];
|
||||
$foreign_key["on_update"] = $on_actions[$row["UPDATE_RULE"]];
|
||||
$foreign_key["on_delete"] = $on_actions[$row["DELETE_RULE"]];
|
||||
$foreign_key["source"][] = $row["FKCOLUMN_NAME"];
|
||||
$foreign_key["target"][] = $row["PKCOLUMN_NAME"];
|
||||
}
|
||||
@@ -586,11 +580,11 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
}
|
||||
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('table', $views)));
|
||||
return queries("DROP VIEW " . implode(", ", array_map('Adminer\table', $views)));
|
||||
}
|
||||
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('table', $tables)));
|
||||
return queries("DROP TABLE " . implode(", ", array_map('Adminer\table', $tables)));
|
||||
}
|
||||
|
||||
function move_tables($tables, $views, $target) {
|
||||
@@ -601,7 +595,8 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
|
||||
if ($name == "") {
|
||||
return array();
|
||||
}
|
||||
$rows = get_rows("SELECT s.name [Trigger],
|
||||
$rows = get_rows(
|
||||
"SELECT s.name [Trigger],
|
||||
CASE WHEN OBJECTPROPERTY(s.id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT' WHEN OBJECTPROPERTY(s.id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY(s.id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE' END [Event],
|
||||
CASE WHEN OBJECTPROPERTY(s.id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [Timing],
|
||||
c.text
|
||||
@@ -618,13 +613,14 @@ WHERE s.xtype = 'TR' AND s.name = " . q($name)
|
||||
|
||||
function triggers($table) {
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT sys1.name,
|
||||
foreach (
|
||||
get_rows("SELECT sys1.name,
|
||||
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE' END [Event],
|
||||
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [Timing]
|
||||
FROM sysobjects sys1
|
||||
JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id
|
||||
WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
|
||||
) as $row) { // triggers are not schema-scoped
|
||||
WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row
|
||||
) { // triggers are not schema-scoped
|
||||
$return[$row["name"]] = array($row["Timing"], $row["Event"]);
|
||||
}
|
||||
return $return;
|
||||
@@ -651,23 +647,63 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
|
||||
}
|
||||
|
||||
function set_schema($schema) {
|
||||
$_GET["ns"] = $schema;
|
||||
return true; // ALTER USER is permanent
|
||||
}
|
||||
|
||||
function create_sql($table, $auto_increment, $style) {
|
||||
global $driver;
|
||||
if (is_view(table_status($table))) {
|
||||
$view = view($table);
|
||||
return "CREATE VIEW " . table($table) . " AS $view[select]";
|
||||
}
|
||||
$fields = array();
|
||||
$primary = false;
|
||||
foreach (fields($table) as $name => $field) {
|
||||
$val = process_field($field, $field);
|
||||
if ($val[6]) {
|
||||
$primary = true;
|
||||
}
|
||||
$fields[] = implode("", $val);
|
||||
}
|
||||
foreach (indexes($table) as $name => $index) {
|
||||
if (!$primary || $index["type"] != "PRIMARY") {
|
||||
$columns = array();
|
||||
foreach ($index["columns"] as $key => $val) {
|
||||
$columns[] = idf_escape($val) . ($index["descs"][$key] ? " DESC" : "");
|
||||
}
|
||||
$name = idf_escape($name);
|
||||
$fields[] = ($index["type"] == "INDEX" ? "INDEX $name" : "CONSTRAINT $name " . ($index["type"] == "UNIQUE" ? "UNIQUE" : "PRIMARY KEY")) . " (" . implode(", ", $columns) . ")";
|
||||
}
|
||||
}
|
||||
foreach ($driver->checkConstraints($table) as $name => $check) {
|
||||
$fields[] = "CONSTRAINT " . idf_escape($name) . " CHECK ($check)";
|
||||
}
|
||||
return "CREATE TABLE " . table($table) . " (\n\t" . implode(",\n\t", $fields) . "\n)";
|
||||
}
|
||||
|
||||
function foreign_keys_sql($table) {
|
||||
$fields = array();
|
||||
foreach (foreign_keys($table) as $foreign) {
|
||||
$fields[] = ltrim(format_foreign_key($foreign));
|
||||
}
|
||||
return ($fields ? "ALTER TABLE " . table($table) . " ADD\n\t" . implode(",\n\t", $fields) . ";\n\n" : "");
|
||||
}
|
||||
|
||||
function truncate_sql($table) {
|
||||
return "TRUNCATE TABLE " . table($table);
|
||||
}
|
||||
|
||||
function use_sql($database) {
|
||||
return "USE " . idf_escape($database);
|
||||
}
|
||||
|
||||
function show_variables() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
return array();
|
||||
function trigger_sql($table) {
|
||||
$return = "";
|
||||
foreach (triggers($table) as $name => $trigger) {
|
||||
$return .= create_trigger(" ON " . table($table), trigger($name)) . ";";
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function convert_field($field) {
|
||||
@@ -678,38 +714,6 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return preg_match('~^(check|comment|columns|database|drop_col|indexes|descidx|scheme|sql|table|trigger|view|view_trigger)$~', $feature); //! routine|
|
||||
}
|
||||
|
||||
function driver_config() {
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array( //! use sys.types
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
|
||||
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
|
||||
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
|
||||
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
return array(
|
||||
'possible_drivers' => array("SQLSRV", "MSSQL", "PDO_DBLIB"),
|
||||
'jush' => "mssql",
|
||||
'types' => $types,
|
||||
'structured_types' => $structured_types,
|
||||
'unsigned' => array(),
|
||||
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"),
|
||||
'functions' => array("len", "lower", "round", "upper"),
|
||||
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
|
||||
'edit_functions' => array(
|
||||
array(
|
||||
"date|time" => "getdate",
|
||||
), array(
|
||||
"int|decimal|real|float|money|datetime" => "+/-",
|
||||
"char|text" => "+",
|
||||
)
|
||||
),
|
||||
);
|
||||
return preg_match('~^(check|comment|columns|database|drop_col|dump|indexes|descidx|scheme|sql|table|trigger|view|view_trigger)$~', $feature); //! routine|
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers = array("server" => "MySQL") + $drivers;
|
||||
|
||||
if (!defined("DRIVER")) {
|
||||
define("DRIVER", "server"); // server - backwards compatibility
|
||||
if (!defined('Adminer\DRIVER')) {
|
||||
define('Adminer\DRIVER', "server"); // server - backwards compatibility
|
||||
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
|
||||
if (extension_loaded("mysqli")) {
|
||||
class Min_DB extends MySQLi {
|
||||
class Db extends \MySQLi {
|
||||
var $extension = "MySQLi";
|
||||
|
||||
function __construct() {
|
||||
@@ -27,7 +29,7 @@ if (!defined("DRIVER")) {
|
||||
$database,
|
||||
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
|
||||
(!is_numeric($port) ? $port : $socket),
|
||||
($ssl ? (empty($ssl['cert']) ? 2048 : 64) : 0) // 2048 - MYSQLI_CLIENT_SSL, 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
|
||||
($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);
|
||||
return $return;
|
||||
@@ -57,7 +59,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mysql") && !((ini_bool("sql.safe_mode") || ini_bool("mysql.allow_local_infile")) && extension_loaded("pdo_mysql"))) {
|
||||
class Min_DB {
|
||||
class Db {
|
||||
var
|
||||
$extension = "MySQL", ///< @var string extension name
|
||||
$server_info, ///< @var string server version
|
||||
@@ -127,7 +129,7 @@ if (!defined("DRIVER")) {
|
||||
/** Send query
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return mixed bool or Min_Result
|
||||
* @return mixed bool or Result
|
||||
*/
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
|
||||
@@ -142,7 +144,7 @@ if (!defined("DRIVER")) {
|
||||
$this->info = mysql_info($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
return new Result($result);
|
||||
}
|
||||
|
||||
/** Send query with more resultsets
|
||||
@@ -154,7 +156,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
/** Get current resultset
|
||||
* @return Min_Result
|
||||
* @return Result
|
||||
*/
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
@@ -182,7 +184,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
class Result {
|
||||
var
|
||||
$num_rows, ///< @var int number of rows in the result
|
||||
$_result, $_offset = 0 ///< @access private
|
||||
@@ -229,25 +231,25 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_mysql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
class Db extends PdoDb {
|
||||
var $extension = "PDO_MySQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
global $adminer;
|
||||
$options = array(PDO::MYSQL_ATTR_LOCAL_INFILE => false);
|
||||
$options = array(\PDO::MYSQL_ATTR_LOCAL_INFILE => false);
|
||||
$ssl = $adminer->connectSsl();
|
||||
if ($ssl) {
|
||||
if (!empty($ssl['key'])) {
|
||||
$options[PDO::MYSQL_ATTR_SSL_KEY] = $ssl['key'];
|
||||
if ($ssl['key']) {
|
||||
$options[\PDO::MYSQL_ATTR_SSL_KEY] = $ssl['key'];
|
||||
}
|
||||
if (!empty($ssl['cert'])) {
|
||||
$options[PDO::MYSQL_ATTR_SSL_CERT] = $ssl['cert'];
|
||||
if ($ssl['cert']) {
|
||||
$options[\PDO::MYSQL_ATTR_SSL_CERT] = $ssl['cert'];
|
||||
}
|
||||
if (!empty($ssl['ca'])) {
|
||||
$options[PDO::MYSQL_ATTR_SSL_CA] = $ssl['ca'];
|
||||
if ($ssl['ca']) {
|
||||
$options[\PDO::MYSQL_ATTR_SSL_CA] = $ssl['ca'];
|
||||
}
|
||||
if (!empty($ssl['verify'])) {
|
||||
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify'];
|
||||
if (isset($ssl['verify'])) {
|
||||
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify'];
|
||||
}
|
||||
}
|
||||
$this->dsn(
|
||||
@@ -269,7 +271,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, !$unbuffered);
|
||||
$this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, !$unbuffered);
|
||||
return parent::query($query, $unbuffered);
|
||||
}
|
||||
}
|
||||
@@ -278,7 +280,52 @@ if (!defined("DRIVER")) {
|
||||
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("MySQLi", "MySQL", "PDO_MySQL");
|
||||
static $jush = "sql"; ///< @var string JUSH identifier
|
||||
|
||||
var $unsigned = array("unsigned", "zerofill", "unsigned zerofill");
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL");
|
||||
var $functions = array("char_length", "date", "from_unixtime", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper");
|
||||
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
|
||||
function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->types = array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
|
||||
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
|
||||
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
|
||||
lang('Lists') => array("enum" => 65535, "set" => 64),
|
||||
lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
|
||||
lang('Geometry') => array("geometry" => 0, "point" => 0, "linestring" => 0, "polygon" => 0, "multipoint" => 0, "multilinestring" => 0, "multipolygon" => 0, "geometrycollection" => 0),
|
||||
);
|
||||
$this->editFunctions = array(
|
||||
array(
|
||||
"char" => "md5/sha1/password/encrypt/uuid",
|
||||
"binary" => "md5/sha1",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
number_type() => "+/-",
|
||||
"date" => "+ interval/- interval",
|
||||
"time" => "addtime/subtime",
|
||||
"char|text" => "concat",
|
||||
)
|
||||
);
|
||||
if (min_version('5.7.8', 10.2, $connection)) {
|
||||
$this->types[lang('Strings')]["json"] = 4294967295;
|
||||
}
|
||||
if (min_version('', 10.7, $connection)) {
|
||||
$this->types[lang('Strings')]["uuid"] = 128;
|
||||
$this->editFunctions[0]['uuid'] = 'uuid';
|
||||
}
|
||||
if (min_version(9, '', $connection)) {
|
||||
$this->types[lang('Numbers')]["vector"] = 16383;
|
||||
$this->editFunctions[0]['vector'] = 'string_to_vector';
|
||||
}
|
||||
if (min_version(5.7, 10.2, $connection)) {
|
||||
$this->generated = array("STORED", "VIRTUAL");
|
||||
}
|
||||
}
|
||||
|
||||
function insert($table, $set) {
|
||||
return ($set ? parent::insert($table, $set) : queries("INSERT INTO " . table($table) . " ()\nVALUES ()"));
|
||||
@@ -335,7 +382,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
}
|
||||
|
||||
function tableHelp($name) {
|
||||
function tableHelp($name, $is_view = false) {
|
||||
$maria = preg_match('~MariaDB~', $this->_conn->server_info);
|
||||
if (information_schema(DB)) {
|
||||
return strtolower("information-schema-" . ($maria ? "$name-table/" : str_replace("_", "-", $name) . "-table.html"));
|
||||
@@ -345,6 +392,14 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
}
|
||||
|
||||
function hasCStyleEscapes() {
|
||||
static $c_style;
|
||||
if ($c_style === null) {
|
||||
$sql_mode = $this->_conn->result("SHOW VARIABLES LIKE 'sql_mode'", 1);
|
||||
$c_style = (strpos($sql_mode, 'NO_BACKSLASH_ESCAPES') === false);
|
||||
}
|
||||
return $c_style;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -366,29 +421,15 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
/** Connect to the database
|
||||
* @return mixed Min_DB or string for error
|
||||
* @return mixed Db or string for error
|
||||
*/
|
||||
function connect() {
|
||||
global $adminer, $types, $structured_types, $edit_functions;
|
||||
$connection = new Min_DB;
|
||||
global $adminer;
|
||||
$connection = new Db;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
$connection->set_charset(charset($connection)); // available in MySQLi since PHP 5.0.5
|
||||
$connection->query("SET sql_quote_show_create = 1, autocommit = 1");
|
||||
if (min_version('5.7.8', 10.2, $connection)) {
|
||||
$structured_types[lang('Strings')][] = "json";
|
||||
$types["json"] = 4294967295;
|
||||
}
|
||||
if (min_version('', 10.7, $connection)) {
|
||||
$structured_types[lang('Strings')][] = "uuid";
|
||||
$types["uuid"] = 128;
|
||||
$edit_functions[0]['uuid'] = 'uuid';
|
||||
}
|
||||
if (min_version(9, '', $connection)) {
|
||||
$structured_types[lang('Numbers')][] = "vector";
|
||||
$types["vector"] = 16383;
|
||||
$edit_functions[0]['vector'] = 'string_to_vector';
|
||||
}
|
||||
return $connection;
|
||||
}
|
||||
$return = $connection->error;
|
||||
@@ -406,10 +447,7 @@ if (!defined("DRIVER")) {
|
||||
// SHOW DATABASES can take a very long time so it is cached
|
||||
$return = get_session("dbs");
|
||||
if ($return === null) {
|
||||
$query = (min_version(5)
|
||||
? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"
|
||||
: "SHOW DATABASES"
|
||||
); // SHOW DATABASES can be disabled by skip_show_database
|
||||
$query = "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"; // SHOW DATABASES can be disabled by skip_show_database
|
||||
$return = ($flush ? slow_query($query) : get_vals($query));
|
||||
restart_session();
|
||||
set_session("dbs", $return);
|
||||
@@ -484,15 +522,12 @@ if (!defined("DRIVER")) {
|
||||
* @return array [$name => $type]
|
||||
*/
|
||||
function tables_list() {
|
||||
return get_key_vals(min_version(5)
|
||||
? "SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME"
|
||||
: "SHOW TABLES"
|
||||
);
|
||||
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME");
|
||||
}
|
||||
|
||||
/** Count tables in all databases
|
||||
* @param array
|
||||
* @return array arra($db => $tables)
|
||||
* @return array [$db => $tables]
|
||||
*/
|
||||
function count_tables($databases) {
|
||||
$return = array();
|
||||
@@ -505,14 +540,17 @@ if (!defined("DRIVER")) {
|
||||
/** Get table status
|
||||
* @param string
|
||||
* @param bool return only "Name", "Engine" and "Comment" fields
|
||||
* @return array [$name => array("Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => )] or only inner array with $name
|
||||
* @return array [$name => ["Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => ]] or only inner array with $name
|
||||
*/
|
||||
function table_status($name = "", $fast = false) {
|
||||
$return = array();
|
||||
foreach (get_rows($fast && min_version(5)
|
||||
? "SELECT TABLE_NAME AS Name, ENGINE AS Engine, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() " . ($name != "" ? "AND TABLE_NAME = " . q($name) : "ORDER BY Name")
|
||||
: "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "")
|
||||
) as $row) {
|
||||
foreach (
|
||||
get_rows(
|
||||
$fast
|
||||
? "SELECT TABLE_NAME AS Name, ENGINE AS Engine, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() " . ($name != "" ? "AND TABLE_NAME = " . q($name) : "ORDER BY Name")
|
||||
: "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "")
|
||||
) as $row
|
||||
) {
|
||||
if ($row["Engine"] == "InnoDB") {
|
||||
// ignore internal comment, unnecessary since MySQL 5.1.21
|
||||
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]);
|
||||
@@ -549,28 +587,39 @@ if (!defined("DRIVER")) {
|
||||
|
||||
/** Get information about fields
|
||||
* @param string
|
||||
* @return array [$name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => )]
|
||||
* @return array [$name => ["field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => , "generated" => ]]
|
||||
*/
|
||||
function fields($table) {
|
||||
$return = array();
|
||||
foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) {
|
||||
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
|
||||
$return[$row["Field"]] = array(
|
||||
"field" => $row["Field"],
|
||||
"full_type" => $row["Type"],
|
||||
foreach (get_rows("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . q($table) . " ORDER BY ORDINAL_POSITION") as $row) {
|
||||
$field = $row["COLUMN_NAME"];
|
||||
$default = $row["COLUMN_DEFAULT"];
|
||||
$type = $row["COLUMN_TYPE"];
|
||||
$extra = $row["EXTRA"];
|
||||
// https://mariadb.com/kb/en/library/show-columns/, https://github.com/vrana/adminer/pull/359#pullrequestreview-276677186
|
||||
preg_match('~^(VIRTUAL|PERSISTENT|STORED)~', $extra, $generated);
|
||||
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $type, $match);
|
||||
$return[$field] = array(
|
||||
"field" => $field,
|
||||
"full_type" => $type,
|
||||
"type" => $match[1],
|
||||
"length" => $match[2],
|
||||
"unsigned" => ltrim($match[3] . $match[4]),
|
||||
"default" => ($row["Default"] != "" || preg_match("~char|set~", $match[1]) ? (preg_match('~text~', $match[1]) ? stripslashes(preg_replace("~^'(.*)'\$~", '\1', $row["Default"])) : $row["Default"]) : null),
|
||||
"null" => ($row["Null"] == "YES"),
|
||||
"auto_increment" => ($row["Extra"] == "auto_increment"),
|
||||
"on_update" => (preg_match('~^on update (.+)~i', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["Collation"],
|
||||
"privileges" => array_flip(preg_split('~, *~', $row["Privileges"])),
|
||||
"comment" => $row["Comment"],
|
||||
"primary" => ($row["Key"] == "PRI"),
|
||||
// https://mariadb.com/kb/en/library/show-columns/, https://github.com/vrana/adminer/pull/359#pullrequestreview-276677186
|
||||
"generated" => preg_match('~^(VIRTUAL|PERSISTENT|STORED)~', $row["Extra"]),
|
||||
"default" => ($generated
|
||||
? $row["GENERATION_EXPRESSION"]
|
||||
: ($default != "" || preg_match("~char|set~", $match[1])
|
||||
? (preg_match('~text~', $match[1]) ? stripslashes(preg_replace("~^'(.*)'\$~", '\1', $default)) : $default)
|
||||
: null
|
||||
)
|
||||
),
|
||||
"null" => ($row["IS_NULLABLE"] == "YES"),
|
||||
"auto_increment" => ($extra == "auto_increment"),
|
||||
"on_update" => (preg_match('~\bon update (\w+)~i', $extra, $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["COLLATION_NAME"],
|
||||
"privileges" => array_flip(explode(",", $row["PRIVILEGES"])),
|
||||
"comment" => $row["COLUMN_COMMENT"],
|
||||
"primary" => ($row["COLUMN_KEY"] == "PRI"),
|
||||
"generated" => ($generated[1] == "PERSISTENT" ? "STORED" : $generated[1]),
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
@@ -578,8 +627,8 @@ if (!defined("DRIVER")) {
|
||||
|
||||
/** Get table indexes
|
||||
* @param string
|
||||
* @param string Min_DB to use
|
||||
* @return array [$key_name => array("type" => , "columns" => array(), "lengths" => array(), "descs" => array())]
|
||||
* @param string Db to use
|
||||
* @return array [$key_name => ["type" => , "columns" => [], "lengths" => [], "descs" => []]]
|
||||
*/
|
||||
function indexes($table, $connection2 = null) {
|
||||
$return = array();
|
||||
@@ -595,25 +644,25 @@ if (!defined("DRIVER")) {
|
||||
|
||||
/** Get foreign keys in table
|
||||
* @param string
|
||||
* @return array [$name => array("db" => , "ns" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => )]
|
||||
* @return array [$name => ["db" => , "ns" => , "table" => , "source" => [], "target" => [], "on_delete" => , "on_update" => ]]
|
||||
*/
|
||||
function foreign_keys($table) {
|
||||
global $connection, $on_actions;
|
||||
global $connection, $driver;
|
||||
static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")';
|
||||
$return = array();
|
||||
$create_table = $connection->result("SHOW CREATE TABLE " . table($table), 1);
|
||||
if ($create_table) {
|
||||
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($on_actions))?(?: ON UPDATE ($on_actions))?~", $create_table, $matches, PREG_SET_ORDER);
|
||||
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($driver->onActions))?(?: ON UPDATE ($driver->onActions))?~", $create_table, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
preg_match_all("~$pattern~", $match[2], $source);
|
||||
preg_match_all("~$pattern~", $match[5], $target);
|
||||
$return[idf_unescape($match[1])] = array(
|
||||
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
|
||||
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
|
||||
"source" => array_map('idf_unescape', $source[0]),
|
||||
"target" => array_map('idf_unescape', $target[0]),
|
||||
"on_delete" => ($match[6] ? $match[6] : "RESTRICT"),
|
||||
"on_update" => ($match[7] ? $match[7] : "RESTRICT"),
|
||||
"source" => array_map('Adminer\idf_unescape', $source[0]),
|
||||
"target" => array_map('Adminer\idf_unescape', $target[0]),
|
||||
"on_delete" => ($match[6] ?: "RESTRICT"),
|
||||
"on_update" => ($match[7] ?: "RESTRICT"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -653,7 +702,7 @@ if (!defined("DRIVER")) {
|
||||
* @return bool
|
||||
*/
|
||||
function information_schema($db) {
|
||||
return (min_version(5) && $db == "information_schema")
|
||||
return ($db == "information_schema")
|
||||
|| (min_version(5.5) && $db == "performance_schema");
|
||||
}
|
||||
|
||||
@@ -731,7 +780,7 @@ if (!defined("DRIVER")) {
|
||||
/** Run commands to create or alter table
|
||||
* @param string "" to create
|
||||
* @param string new name
|
||||
* @param array of array($orig, $process_field, $after)
|
||||
* @param array of [$orig, $process_field, $after]
|
||||
* @param array of strings
|
||||
* @param string
|
||||
* @param string
|
||||
@@ -743,10 +792,16 @@ if (!defined("DRIVER")) {
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
$alter = array();
|
||||
foreach ($fields as $field) {
|
||||
$alter[] = ($field[1]
|
||||
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "")
|
||||
: "DROP " . idf_escape($field[0])
|
||||
);
|
||||
if ($field[1]) {
|
||||
$default = $field[1][3];
|
||||
if (preg_match('~ GENERATED~', $default)) {
|
||||
$field[1][3] = $field[1][2];
|
||||
$field[1][2] = $default;
|
||||
}
|
||||
$alter[] = ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "");
|
||||
} else {
|
||||
$alter[] = "DROP " . idf_escape($field[0]);
|
||||
}
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
$status = ($comment !== null ? " COMMENT=" . q($comment) : "")
|
||||
@@ -768,7 +823,7 @@ if (!defined("DRIVER")) {
|
||||
|
||||
/** Run commands to alter indexes
|
||||
* @param string escaped table name
|
||||
* @param array of array("index type", "name", array("column definition", ...)) or array("index type", "name", "DROP")
|
||||
* @param array of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
|
||||
* @return bool
|
||||
*/
|
||||
function alter_indexes($table, $alter) {
|
||||
@@ -794,7 +849,7 @@ if (!defined("DRIVER")) {
|
||||
* @return bool
|
||||
*/
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('table', $views)));
|
||||
return queries("DROP VIEW " . implode(", ", array_map('Adminer\table', $views)));
|
||||
}
|
||||
|
||||
/** Drop tables
|
||||
@@ -802,7 +857,7 @@ if (!defined("DRIVER")) {
|
||||
* @return bool
|
||||
*/
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('table', $tables)));
|
||||
return queries("DROP TABLE " . implode(", ", array_map('Adminer\table', $tables)));
|
||||
}
|
||||
|
||||
/** Move tables to other schema
|
||||
@@ -845,7 +900,8 @@ if (!defined("DRIVER")) {
|
||||
queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'");
|
||||
foreach ($tables as $table) {
|
||||
$name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
|
||||
if (($_POST["overwrite"] && !queries("\nDROP TABLE IF EXISTS $name"))
|
||||
if (
|
||||
($_POST["overwrite"] && !queries("\nDROP TABLE IF EXISTS $name"))
|
||||
|| !queries("CREATE TABLE $name LIKE " . table($table))
|
||||
|| !queries("INSERT INTO $name SELECT * FROM " . table($table))
|
||||
) {
|
||||
@@ -861,8 +917,10 @@ if (!defined("DRIVER")) {
|
||||
foreach ($views as $table) {
|
||||
$name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
|
||||
$view = view($table);
|
||||
if (($_POST["overwrite"] && !queries("DROP VIEW IF EXISTS $name"))
|
||||
|| !queries("CREATE VIEW $name AS $view[select]")) { //! USE to avoid db.table
|
||||
if (
|
||||
($_POST["overwrite"] && !queries("DROP VIEW IF EXISTS $name"))
|
||||
|| !queries("CREATE VIEW $name AS $view[select]") //! USE to avoid db.table
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -883,7 +941,7 @@ if (!defined("DRIVER")) {
|
||||
|
||||
/** Get defined triggers
|
||||
* @param string
|
||||
* @return array [$name => array($timing, $event)]
|
||||
* @return array [$name => [$timing, $event]]
|
||||
*/
|
||||
function triggers($table) {
|
||||
$return = array();
|
||||
@@ -894,7 +952,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
/** Get trigger options
|
||||
* @return array ["Timing" => array(), "Event" => array(), "Type" => array()]
|
||||
* @return array ["Timing" => [], "Event" => [], "Type" => []]
|
||||
*/
|
||||
function trigger_options() {
|
||||
return array(
|
||||
@@ -907,14 +965,14 @@ if (!defined("DRIVER")) {
|
||||
/** Get information about stored routine
|
||||
* @param string
|
||||
* @param string "FUNCTION" or "PROCEDURE"
|
||||
* @return array ["fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => , "language" => ]
|
||||
* @return array ["fields" => ["field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ], "returns" => , "definition" => , "language" => ]
|
||||
*/
|
||||
function routine($name, $type) {
|
||||
global $connection, $enum_length, $inout, $types;
|
||||
global $connection, $driver;
|
||||
$aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
|
||||
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
|
||||
$type_pattern = "((" . implode("|", array_merge(array_keys($types), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum_length)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
|
||||
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
|
||||
$type_pattern = "((" . implode("|", array_merge(array_keys($driver->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$driver->enumLength)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
|
||||
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $driver->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
|
||||
$create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
|
||||
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
|
||||
$fields = array();
|
||||
@@ -923,7 +981,7 @@ if (!defined("DRIVER")) {
|
||||
$fields[] = array(
|
||||
"field" => str_replace("``", "`", $param[2]) . $param[3],
|
||||
"type" => strtolower($param[5]),
|
||||
"length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
|
||||
"length" => preg_replace_callback("~$driver->enumLength~s", 'Adminer\normalize_enum', $param[6]),
|
||||
"unsigned" => strtolower(preg_replace('~\s+~', ' ', trim("$param[8] $param[7]"))),
|
||||
"null" => 1,
|
||||
"full_type" => $param[4],
|
||||
@@ -933,7 +991,7 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
return array(
|
||||
"fields" => $fields,
|
||||
"comment" => $connection->result("SELECT ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB) . " AND ROUTINE_NAME = " . q($name)),
|
||||
"comment" => $connection->result("SELECT ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE() AND ROUTINE_NAME = " . q($name)),
|
||||
) + ($type != "FUNCTION" ? array("definition" => $match[11]) : array(
|
||||
"returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]),
|
||||
"definition" => $match[17],
|
||||
@@ -945,7 +1003,7 @@ if (!defined("DRIVER")) {
|
||||
* @return array ["SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ]
|
||||
*/
|
||||
function routines() {
|
||||
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB));
|
||||
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
|
||||
}
|
||||
|
||||
/** Get list of available routine languages
|
||||
@@ -973,9 +1031,9 @@ if (!defined("DRIVER")) {
|
||||
}
|
||||
|
||||
/** Explain select
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
* @param string
|
||||
* @return Min_Result
|
||||
* @return Result
|
||||
*/
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN " . (min_version(5.1) && !min_version(5.7) ? "PARTITIONS " : "") . $query);
|
||||
@@ -990,35 +1048,40 @@ if (!defined("DRIVER")) {
|
||||
return ($where || $table_status["Engine"] != "InnoDB" ? null : $table_status["Rows"]);
|
||||
}
|
||||
|
||||
/* Not used is MySQL but checked in compile.php:
|
||||
/** Get user defined types
|
||||
* @return array
|
||||
*/
|
||||
* @return array [$id => $name]
|
||||
function types() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Get values of user defined type
|
||||
* @param int
|
||||
* @return string
|
||||
function type_values($id) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/** Get existing schemas
|
||||
* @return array
|
||||
*/
|
||||
function schemas() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Get current schema
|
||||
* @return string
|
||||
*/
|
||||
function get_schema() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/** Set current schema
|
||||
* @param string
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
* @return bool
|
||||
*/
|
||||
function set_schema($schema, $connection2 = null) {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/** Get SQL command to create table
|
||||
* @param string
|
||||
@@ -1070,19 +1133,6 @@ if (!defined("DRIVER")) {
|
||||
return get_key_vals("SHOW VARIABLES");
|
||||
}
|
||||
|
||||
/** Check if C-style escapes are supported
|
||||
* @return bool
|
||||
*/
|
||||
function is_c_style_escapes() {
|
||||
global $connection;
|
||||
static $c_style;
|
||||
if ($c_style === null) {
|
||||
$sql_mode = $connection->result("SHOW VARIABLES LIKE 'sql_mode'", 1);
|
||||
$c_style = (strpos($sql_mode, 'NO_BACKSLASH_ESCAPES') === false);
|
||||
}
|
||||
return $c_style;
|
||||
}
|
||||
|
||||
/** Get process list
|
||||
* @return array [$row]
|
||||
*/
|
||||
@@ -1137,7 +1187,7 @@ if (!defined("DRIVER")) {
|
||||
* @return bool
|
||||
*/
|
||||
function support($feature) {
|
||||
return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning" . (min_version(5) ? "" : "|routine|trigger|view"))) . (min_version('8.0.16', '10.2.1') ? "" : "|check") . "~", $feature);
|
||||
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);
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
@@ -1151,7 +1201,7 @@ if (!defined("DRIVER")) {
|
||||
/** Return query to get connection ID
|
||||
* @return string
|
||||
*/
|
||||
function connection_id(){
|
||||
function connection_id() {
|
||||
return "SELECT CONNECTION_ID()";
|
||||
}
|
||||
|
||||
@@ -1162,45 +1212,4 @@ if (!defined("DRIVER")) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT @@max_connections");
|
||||
}
|
||||
|
||||
/** Get driver config
|
||||
* @return array ['possible_drivers' => , 'jush' => , 'types' => , 'structured_types' => , 'unsigned' => , 'operators' => , 'functions' => , 'grouping' => , 'edit_functions' => ]
|
||||
*/
|
||||
function driver_config() {
|
||||
$types = array(); ///< @var array [$type => $maximum_unsigned_length, ...]
|
||||
$structured_types = array(); ///< @var array [$description => array($type, ...), ...]
|
||||
foreach (array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
|
||||
lang('Date and time') => array("dat`e" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
|
||||
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
|
||||
lang('Lists') => array("enum" => 65535, "set" => 64),
|
||||
lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
|
||||
lang('Geometry') => array("geometry" => 0, "point" => 0, "linestring" => 0, "polygon" => 0, "multipoint" => 0, "multilinestring" => 0, "multipolygon" => 0, "geometrycollection" => 0),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
return array(
|
||||
'possible_drivers' => array("MySQLi", "MySQL", "PDO_MySQL"),
|
||||
'jush' => "sql", ///< @var string JUSH identifier
|
||||
'types' => $types,
|
||||
'structured_types' => $structured_types,
|
||||
'unsigned' => array("unsigned", "zerofill", "unsigned zerofill"), ///< @var array number variants
|
||||
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"), ///< @var array operators used in select
|
||||
'functions' => array("char_length", "date", "from_unixtime", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper"), ///< @var array functions used in select
|
||||
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"), ///< @var array grouping functions used in select
|
||||
'edit_functions' => array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
|
||||
array(
|
||||
"char" => "md5/sha1/password/encrypt/uuid",
|
||||
"binary" => "md5/sha1",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
number_type() => "+/-",
|
||||
"date" => "+ interval/- interval",
|
||||
"time" => "addtime/subtime",
|
||||
"char|text" => "concat",
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers["oracle"] = "Oracle (beta)";
|
||||
|
||||
if (isset($_GET["oracle"])) {
|
||||
define("DRIVER", "oracle");
|
||||
define('Adminer\DRIVER', "oracle");
|
||||
if (extension_loaded("oci8")) {
|
||||
class Min_DB {
|
||||
class Db {
|
||||
var $extension = "oci8", $_link, $_result, $server_info, $affected_rows, $errno, $error;
|
||||
var $_current_db;
|
||||
|
||||
@@ -50,7 +52,7 @@ if (isset($_GET["oracle"])) {
|
||||
restore_error_handler();
|
||||
if ($return) {
|
||||
if (oci_num_fields($result)) {
|
||||
return new Min_Result($result);
|
||||
return new Result($result);
|
||||
}
|
||||
$this->affected_rows = oci_num_rows($result);
|
||||
oci_free_statement($result);
|
||||
@@ -79,7 +81,7 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
class Result {
|
||||
var $_result, $_offset = 1, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
@@ -105,7 +107,7 @@ if (isset($_GET["oracle"])) {
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$return = new stdClass;
|
||||
$return = new \stdClass;
|
||||
$return->name = oci_field_name($this->_result, $column);
|
||||
$return->orgname = $return->name;
|
||||
$return->type = oci_field_type($this->_result, $column);
|
||||
@@ -119,7 +121,7 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_oci")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
class Db extends PdoDb {
|
||||
var $extension = "PDO_OCI";
|
||||
var $_current_db;
|
||||
|
||||
@@ -138,7 +140,34 @@ if (isset($_GET["oracle"])) {
|
||||
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("OCI8", "PDO_OCI");
|
||||
static $jush = "oracle";
|
||||
|
||||
var $editFunctions = array(
|
||||
array( //! no parentheses
|
||||
"date" => "current_date",
|
||||
"timestamp" => "current_timestamp",
|
||||
), array(
|
||||
"number|float|double" => "+/-",
|
||||
"date|timestamp" => "+ interval/- interval",
|
||||
"char|clob" => "||",
|
||||
)
|
||||
);
|
||||
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
|
||||
var $functions = array("length", "lower", "round", "upper");
|
||||
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
|
||||
function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->types = array(
|
||||
lang('Numbers') => array("number" => 38, "binary_float" => 12, "binary_double" => 21),
|
||||
lang('Date and time') => array("date" => 10, "timestamp" => 29, "interval year" => 12, "interval day" => 28), //! year(), day() to second()
|
||||
lang('Strings') => array("char" => 2000, "varchar2" => 4000, "nchar" => 2000, "nvarchar2" => 4000, "clob" => 4294967295, "nclob" => 4294967295),
|
||||
lang('Binary') => array("raw" => 2000, "long raw" => 2147483648, "blob" => 4294967295, "bfile" => 4294967296),
|
||||
);
|
||||
}
|
||||
|
||||
//! support empty $set in insert()
|
||||
|
||||
@@ -157,14 +186,19 @@ if (isset($_GET["oracle"])) {
|
||||
$where[] = "$key = $val";
|
||||
}
|
||||
}
|
||||
if (!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")
|
||||
)) {
|
||||
if (
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasCStyleEscapes() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +213,7 @@ if (isset($_GET["oracle"])) {
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$connection = new Db;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
return $connection;
|
||||
@@ -188,7 +222,8 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("SELECT DISTINCT tablespace_name FROM (
|
||||
return get_vals(
|
||||
"SELECT DISTINCT tablespace_name FROM (
|
||||
SELECT tablespace_name FROM user_tablespaces
|
||||
UNION SELECT tablespace_name FROM all_tables WHERE tablespace_name IS NOT NULL
|
||||
)
|
||||
@@ -223,7 +258,7 @@ ORDER BY 1"
|
||||
|
||||
function get_current_db() {
|
||||
global $connection;
|
||||
$db = $connection->_current_db ? $connection->_current_db : DB;
|
||||
$db = $connection->_current_db ?: DB;
|
||||
unset($connection->_current_db);
|
||||
return $db;
|
||||
}
|
||||
@@ -237,13 +272,14 @@ ORDER BY 1"
|
||||
|
||||
function views_table($columns) {
|
||||
$owner = where_owner('');
|
||||
return "(SELECT $columns FROM all_views WHERE " . ($owner ? $owner : "rownum < 0") . ")";
|
||||
return "(SELECT $columns FROM all_views WHERE " . ($owner ?: "rownum < 0") . ")";
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
$view = views_table("view_name");
|
||||
$owner = where_owner(" AND ");
|
||||
return get_key_vals("SELECT table_name, 'table' FROM all_tables WHERE tablespace_name = " . q(DB) . "$owner
|
||||
return get_key_vals(
|
||||
"SELECT table_name, 'table' FROM all_tables WHERE tablespace_name = " . q(DB) . "$owner
|
||||
UNION SELECT view_name, 'view' FROM $view
|
||||
ORDER BY 1"
|
||||
); //! views don't have schema
|
||||
@@ -264,10 +300,11 @@ ORDER BY 1"
|
||||
$db = get_current_db();
|
||||
$view = views_table("view_name");
|
||||
$owner = where_owner(" AND ");
|
||||
foreach (get_rows('SELECT table_name "Name", \'table\' "Engine", avg_row_len * num_rows "Data_length", num_rows "Rows" FROM all_tables WHERE tablespace_name = ' . q($db) . $owner . ($name != "" ? " AND table_name = $search" : "") . "
|
||||
foreach (
|
||||
get_rows('SELECT table_name "Name", \'table\' "Engine", avg_row_len * num_rows "Data_length", num_rows "Rows" FROM all_tables WHERE tablespace_name = ' . q($db) . $owner . ($name != "" ? " AND table_name = $search" : "") . "
|
||||
UNION SELECT view_name, 'view', 0, 0 FROM $view" . ($name != "" ? " WHERE view_name = $search" : "") . "
|
||||
ORDER BY 1"
|
||||
) as $row) {
|
||||
ORDER BY 1") as $row
|
||||
) {
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
@@ -313,12 +350,14 @@ ORDER BY 1"
|
||||
function indexes($table, $connection2 = null) {
|
||||
$return = array();
|
||||
$owner = where_owner(" AND ", "aic.table_owner");
|
||||
foreach (get_rows("SELECT aic.*, ac.constraint_type, atc.data_default
|
||||
foreach (
|
||||
get_rows("SELECT aic.*, ac.constraint_type, atc.data_default
|
||||
FROM all_ind_columns aic
|
||||
LEFT JOIN all_constraints ac ON aic.index_name = ac.constraint_name AND aic.table_name = ac.table_name AND aic.index_owner = ac.owner
|
||||
LEFT JOIN all_tab_cols atc ON aic.column_name = atc.column_name AND aic.table_name = atc.table_name AND aic.index_owner = atc.owner
|
||||
WHERE aic.table_name = " . q($table) . "$owner
|
||||
ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row) {
|
||||
ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row
|
||||
) {
|
||||
$index_name = $row["INDEX_NAME"];
|
||||
$column_name = $row["DATA_DEFAULT"];
|
||||
$column_name = ($column_name ? trim($column_name, '"') : $row["COLUMN_NAME"]); // trim - possibly wrapped in quotes but never contains quotes inside
|
||||
@@ -341,7 +380,7 @@ ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row) {
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
return get_schema() == "INFORMATION_SCHEMA";
|
||||
}
|
||||
|
||||
function error() {
|
||||
@@ -464,7 +503,7 @@ AND c_src.TABLE_NAME = " . q($table);
|
||||
|
||||
function schemas() {
|
||||
$return = get_vals("SELECT DISTINCT owner FROM dba_segments WHERE owner IN (SELECT username FROM dba_users WHERE default_tablespace NOT IN ('SYSTEM','SYSAUX')) ORDER BY 1");
|
||||
return ($return ? $return : get_vals("SELECT DISTINCT owner FROM all_tables WHERE tablespace_name = " . q(DB) . " ORDER BY 1"));
|
||||
return ($return ?: get_vals("SELECT DISTINCT owner FROM all_tables WHERE tablespace_name = " . q(DB) . " ORDER BY 1"));
|
||||
}
|
||||
|
||||
function get_schema() {
|
||||
@@ -484,10 +523,6 @@ AND c_src.TABLE_NAME = " . q($table);
|
||||
return get_key_vals('SELECT name, display_value FROM v$parameter');
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function process_list() {
|
||||
return get_rows('SELECT sess.process AS "process", sess.username AS "user", sess.schemaname AS "schema", sess.status AS "status", sess.wait_class AS "wait_class", sess.seconds_in_wait AS "seconds_in_wait", sql.sql_text AS "sql_text", sess.machine AS "machine", sess.port AS "port"
|
||||
FROM v$session sess LEFT OUTER JOIN v$sql sql
|
||||
@@ -512,38 +547,4 @@ ORDER BY PROCESS
|
||||
function support($feature) {
|
||||
return preg_match('~^(columns|database|drop_col|indexes|descidx|processlist|scheme|sql|status|table|variables|view)$~', $feature); //!
|
||||
}
|
||||
|
||||
function driver_config() {
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array(
|
||||
lang('Numbers') => array("number" => 38, "binary_float" => 12, "binary_double" => 21),
|
||||
lang('Date and time') => array("date" => 10, "timestamp" => 29, "interval year" => 12, "interval day" => 28), //! year(), day() to second()
|
||||
lang('Strings') => array("char" => 2000, "varchar2" => 4000, "nchar" => 2000, "nvarchar2" => 4000, "clob" => 4294967295, "nclob" => 4294967295),
|
||||
lang('Binary') => array("raw" => 2000, "long raw" => 2147483648, "blob" => 4294967295, "bfile" => 4294967296),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
return array(
|
||||
'possible_drivers' => array("OCI8", "PDO_OCI"),
|
||||
'jush' => "oracle",
|
||||
'types' => $types,
|
||||
'structured_types' => $structured_types,
|
||||
'unsigned' => array(),
|
||||
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"),
|
||||
'functions' => array("length", "lower", "round", "upper"),
|
||||
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
|
||||
'edit_functions' => array(
|
||||
array( //! no parentheses
|
||||
"date" => "current_date",
|
||||
"timestamp" => "current_timestamp",
|
||||
), array(
|
||||
"number|float|double" => "+/-",
|
||||
"date|timestamp" => "+ interval/- interval",
|
||||
"char|clob" => "||",
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers["pgsql"] = "PostgreSQL";
|
||||
|
||||
if (isset($_GET["pgsql"])) {
|
||||
define("DRIVER", "pgsql");
|
||||
define('Adminer\DRIVER', "pgsql");
|
||||
if (extension_loaded("pgsql")) {
|
||||
class Min_DB {
|
||||
class Db {
|
||||
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error, $timeout;
|
||||
|
||||
function _error($errno, $error) {
|
||||
@@ -77,7 +79,7 @@ if (isset($_GET["pgsql"])) {
|
||||
$this->affected_rows = pg_affected_rows($result);
|
||||
$return = true;
|
||||
} else {
|
||||
$return = new Min_Result($result);
|
||||
$return = new Result($result);
|
||||
}
|
||||
if ($this->timeout) {
|
||||
$this->timeout = 0;
|
||||
@@ -112,7 +114,7 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
class Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
@@ -130,7 +132,7 @@ if (isset($_GET["pgsql"])) {
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$return = new stdClass;
|
||||
$return = new \stdClass;
|
||||
if (function_exists('pg_field_table')) {
|
||||
$return->orgtable = pg_field_table($this->_result, $column);
|
||||
}
|
||||
@@ -147,7 +149,7 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_pgsql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
class Db extends PdoDb {
|
||||
var $extension = "PDO_PgSQL", $timeout;
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
@@ -193,7 +195,48 @@ if (isset($_GET["pgsql"])) {
|
||||
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("PgSQL", "PDO_PgSQL");
|
||||
static $jush = "pgsql";
|
||||
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
|
||||
var $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
|
||||
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
|
||||
function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->types = array( //! arrays
|
||||
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
|
||||
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0),
|
||||
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
|
||||
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
|
||||
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "macaddr8" => 23, "txid_snapshot" => 0),
|
||||
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
|
||||
);
|
||||
if (min_version(9.2, 0, $connection)) {
|
||||
$this->types[lang('Strings')]["json"] = 4294967295;
|
||||
if (min_version(9.4, 0, $connection)) {
|
||||
$this->types[lang('Strings')]["jsonb"] = 4294967295;
|
||||
}
|
||||
}
|
||||
$this->editFunctions = array(
|
||||
array(
|
||||
"char" => "md5",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
number_type() => "+/-",
|
||||
"date|time" => "+ interval/- interval", //! escape
|
||||
"char|text" => "||",
|
||||
)
|
||||
);
|
||||
if (min_version(12, 0, $connection)) {
|
||||
$this->generated = array("STORED");
|
||||
}
|
||||
}
|
||||
|
||||
function setUserTypes($types) {
|
||||
$this->types[lang('User types')] = array_flip($types);
|
||||
}
|
||||
|
||||
function insertUpdate($table, $rows, $primary) {
|
||||
global $connection;
|
||||
@@ -206,9 +249,10 @@ if (isset($_GET["pgsql"])) {
|
||||
$where[] = "$key = $val";
|
||||
}
|
||||
}
|
||||
if (!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")
|
||||
)) {
|
||||
if (
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -238,10 +282,10 @@ if (isset($_GET["pgsql"])) {
|
||||
return $this->_conn->warnings();
|
||||
}
|
||||
|
||||
function tableHelp($name) {
|
||||
function tableHelp($name, $is_view = false) {
|
||||
$links = array(
|
||||
"information_schema" => "infoschema",
|
||||
"pg_catalog" => "catalog",
|
||||
"pg_catalog" => ($is_view ? "view" : "catalog"),
|
||||
);
|
||||
$link = $links[$_GET["ns"]];
|
||||
if ($link) {
|
||||
@@ -249,6 +293,13 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
function hasCStyleEscapes() {
|
||||
static $c_style;
|
||||
if ($c_style === null) {
|
||||
$c_style = ($this->_conn->result("SHOW standard_conforming_strings") == "off");
|
||||
}
|
||||
return $c_style;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -262,20 +313,12 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $adminer, $types, $structured_types;
|
||||
$connection = new Min_DB;
|
||||
global $adminer;
|
||||
$connection = new Db;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
if (min_version(9, 0, $connection)) {
|
||||
$connection->query("SET application_name = 'Adminer'");
|
||||
if (min_version(9.2, 0, $connection)) {
|
||||
$structured_types[lang('Strings')][] = "json";
|
||||
$types["json"] = 4294967295;
|
||||
if (min_version(9.4, 0, $connection)) {
|
||||
$structured_types[lang('Strings')][] = "jsonb";
|
||||
$types["jsonb"] = 4294967295;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $connection;
|
||||
}
|
||||
@@ -283,9 +326,9 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("SELECT d.datname FROM pg_database d JOIN pg_roles r ON d.datdba = r.oid
|
||||
WHERE d.datallowconn = TRUE AND has_database_privilege(d.datname, 'CONNECT') AND pg_has_role(r.rolname, 'USAGE')
|
||||
ORDER BY d.datname");
|
||||
return get_vals("SELECT datname FROM pg_database
|
||||
WHERE datallowconn = TRUE AND has_database_privilege(datname, 'CONNECT')
|
||||
ORDER BY datname");
|
||||
}
|
||||
|
||||
function limit($query, $where, $limit, $offset = 0, $separator = " ") {
|
||||
@@ -315,7 +358,7 @@ ORDER BY d.datname");
|
||||
|
||||
function tables_list() {
|
||||
$query = "SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = current_schema()";
|
||||
if (support('materializedview')) { // ' - support("materializedview") could be removed by compile.php
|
||||
if (support("materializedview")) {
|
||||
$query .= "
|
||||
UNION ALL
|
||||
SELECT matviewname, 'MATERIALIZED VIEW'
|
||||
@@ -328,12 +371,20 @@ ORDER BY 1";
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
return array(); // would require reconnect
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
if ($connection->select_db($db)) {
|
||||
$return[$db] = count(tables_list());
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT
|
||||
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\",
|
||||
pg_table_size(c.oid) AS \"Data_length\",
|
||||
@@ -345,8 +396,8 @@ ORDER BY 1";
|
||||
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
|
||||
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")) as $row //! Index_length, Auto_increment
|
||||
) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return ($name != "" ? $return[$name] : $return);
|
||||
@@ -366,7 +417,8 @@ WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
|
||||
'timestamp without time zone' => 'timestamp',
|
||||
'timestamp with time zone' => 'timestamptz',
|
||||
);
|
||||
foreach (get_rows("SELECT a.attname AS field, 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) ? ", a.attidentity" : "") . "
|
||||
foreach (
|
||||
get_rows("SELECT a.attname AS field, 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) ? ", 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
|
||||
@@ -375,8 +427,8 @@ WHERE c.relname = " . q($table) . "
|
||||
AND n.nspname = current_schema()
|
||||
AND NOT a.attisdropped
|
||||
AND a.attnum > 0
|
||||
ORDER BY a.attnum"
|
||||
) as $row) {
|
||||
ORDER BY a.attnum") as $row
|
||||
) {
|
||||
//! collation, primary
|
||||
preg_match('~([^([]+)(\((.*)\))?([a-z ]+)?((\[[0-9]*])*)$~', $row["full_type"], $match);
|
||||
list(, $type, $length, $row["length"], $addon, $array) = $match;
|
||||
@@ -392,6 +444,7 @@ ORDER BY a.attnum"
|
||||
if (in_array($row['attidentity'], array('a', 'd'))) {
|
||||
$row['default'] = 'GENERATED ' . ($row['attidentity'] == 'd' ? 'BY DEFAULT' : 'ALWAYS') . ' AS IDENTITY';
|
||||
}
|
||||
$row["generated"] = ($row["attgenerated"] == "s" ? "STORED" : "");
|
||||
$row["null"] = !$row["attnotnull"];
|
||||
$row["auto_increment"] = $row['attidentity'] || preg_match('~^nextval\(~i', $row["default"]);
|
||||
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
|
||||
@@ -411,16 +464,18 @@ ORDER BY a.attnum"
|
||||
$return = array();
|
||||
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($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", $connection2) as $row) {
|
||||
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 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]["columns"] = array();
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
$return[$relname]["descs"] = array();
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = ($indoption & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
if ($row["indkey"]) {
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = ($indoption & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
}
|
||||
}
|
||||
$return[$relname]["lengths"] = array();
|
||||
}
|
||||
@@ -428,22 +483,24 @@ ORDER BY a.attnum"
|
||||
}
|
||||
|
||||
function foreign_keys($table) {
|
||||
global $on_actions;
|
||||
global $driver;
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT conname, condeferrable::int AS deferrable, pg_get_constraintdef(oid) AS definition
|
||||
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())
|
||||
AND contype = 'f'::char
|
||||
ORDER BY conkey, conname") as $row) {
|
||||
ORDER BY conkey, conname") as $row
|
||||
) {
|
||||
if (preg_match('~FOREIGN KEY\s*\((.+)\)\s*REFERENCES (.+)\((.+)\)(.*)$~iA', $row['definition'], $match)) {
|
||||
$row['source'] = array_map('idf_unescape', array_map('trim', explode(',', $match[1])));
|
||||
$row['source'] = array_map('Adminer\idf_unescape', array_map('trim', explode(',', $match[1])));
|
||||
if (preg_match('~^(("([^"]|"")+"|[^"]+)\.)?"?("([^"]|"")+"|[^"]+)$~', $match[2], $match2)) {
|
||||
$row['ns'] = idf_unescape($match2[2]);
|
||||
$row['table'] = idf_unescape($match2[4]);
|
||||
}
|
||||
$row['target'] = array_map('idf_unescape', array_map('trim', explode(',', $match[3])));
|
||||
$row['on_delete'] = (preg_match("~ON DELETE ($on_actions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
|
||||
$row['on_update'] = (preg_match("~ON UPDATE ($on_actions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
|
||||
$row['target'] = array_map('Adminer\idf_unescape', array_map('trim', explode(',', $match[3])));
|
||||
$row['on_delete'] = (preg_match("~ON DELETE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
|
||||
$row['on_update'] = (preg_match("~ON UPDATE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
|
||||
$return[$row['conname']] = $row;
|
||||
}
|
||||
}
|
||||
@@ -461,7 +518,7 @@ ORDER BY conkey, conname") as $row) {
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return ($db == "information_schema");
|
||||
return get_schema() == "information_schema";
|
||||
}
|
||||
|
||||
function error() {
|
||||
@@ -522,9 +579,9 @@ ORDER BY conkey, conname") as $row) {
|
||||
}
|
||||
$alter[] = "ALTER $column TYPE$val[1]";
|
||||
$sequence_name = $table . "_" . idf_unescape($val[0]) . "_seq";
|
||||
$alter[] = "ALTER $column " . ($val[3] ? "SET$val[3]"
|
||||
$alter[] = "ALTER $column " . ($val[3] ? "SET" . preg_replace('~GENERATED ALWAYS(.*) STORED~', 'EXPRESSION\1', $val[3])
|
||||
: (isset($val[6]) ? "SET DEFAULT nextval(" . q($sequence_name) . ")"
|
||||
: "DROP DEFAULT"
|
||||
: "DROP DEFAULT" //! change to DROP EXPRESSION with generated columns
|
||||
));
|
||||
if (isset($val[6])) {
|
||||
$sequence = "CREATE SEQUENCE IF NOT EXISTS " . idf_escape($sequence_name) . " OWNED BY " . idf_escape($table) . ".$val[0]";
|
||||
@@ -548,9 +605,9 @@ ORDER BY conkey, conname") as $row) {
|
||||
if ($comment !== null) {
|
||||
$queries[] = "COMMENT ON TABLE " . table($name) . " IS " . q($comment);
|
||||
}
|
||||
if ($auto_increment != "") {
|
||||
// if ($auto_increment != "") {
|
||||
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . q($name) . ", ), $auto_increment)";
|
||||
}
|
||||
// }
|
||||
foreach ($queries as $query) {
|
||||
if (!queries($query)) {
|
||||
return false;
|
||||
@@ -591,7 +648,7 @@ ORDER BY conkey, conname") as $row) {
|
||||
}
|
||||
|
||||
function truncate_tables($tables) {
|
||||
return queries("TRUNCATE " . implode(", ", array_map('table', $tables)));
|
||||
return queries("TRUNCATE " . implode(", ", array_map('Adminer\table', $tables)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -601,10 +658,10 @@ ORDER BY conkey, conname") as $row) {
|
||||
|
||||
function drop_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
$status = table_status($table);
|
||||
if (!queries("DROP " . strtoupper($status["Engine"]) . " " . table($table))) {
|
||||
return false;
|
||||
}
|
||||
$status = table_status($table);
|
||||
if (!queries("DROP " . strtoupper($status["Engine"]) . " " . table($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -701,18 +758,15 @@ ORDER BY SPECIFIC_NAME');
|
||||
|
||||
function found_rows($table_status, $where) {
|
||||
global $connection;
|
||||
if (preg_match(
|
||||
"~ rows=([0-9]+)~",
|
||||
$connection->result("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")),
|
||||
$regs
|
||||
)) {
|
||||
if (preg_match("~ rows=([0-9]+)~", $connection->result("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")), $regs)) {
|
||||
return $regs[1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function types() {
|
||||
return get_key_vals("SELECT oid, typname
|
||||
return get_key_vals(
|
||||
"SELECT oid, typname
|
||||
FROM pg_type
|
||||
WHERE typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema())
|
||||
AND typtype IN ('b','d','e')
|
||||
@@ -720,6 +774,12 @@ AND typelem = 0"
|
||||
);
|
||||
}
|
||||
|
||||
function type_values($id) {
|
||||
// to get values from type string: unnest(enum_range(NULL::"$type"))
|
||||
$enums = get_vals("SELECT enumlabel FROM pg_enum WHERE enumtypid = $id ORDER BY enumsortorder");
|
||||
return ($enums ? "'" . implode("', '", array_map('addslashes', $enums)) . "'" : "");
|
||||
}
|
||||
|
||||
function schemas() {
|
||||
return get_vals("SELECT nspname FROM pg_namespace ORDER BY nspname");
|
||||
}
|
||||
@@ -730,17 +790,12 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
function set_schema($schema, $connection2 = null) {
|
||||
global $connection, $types, $structured_types;
|
||||
global $connection, $driver;
|
||||
if (!$connection2) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = $connection2->query("SET search_path TO " . idf_escape($schema));
|
||||
foreach (types() as $key => $type) { //! get types from current_schemas('t')
|
||||
if (!isset($types[$type])) {
|
||||
$types[$type] = $key;
|
||||
$structured_types[lang('User types')][] = $type;
|
||||
}
|
||||
}
|
||||
$driver->setUserTypes(types()); //! get types from current_schemas('t')
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -762,6 +817,7 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
function create_sql($table, $auto_increment, $style) {
|
||||
global $driver;
|
||||
$return_parts = array();
|
||||
$sequences = array();
|
||||
|
||||
@@ -771,8 +827,6 @@ AND typelem = 0"
|
||||
return rtrim("CREATE VIEW " . idf_escape($table) . " AS $view[select]", ";");
|
||||
}
|
||||
$fields = fields($table);
|
||||
$indexes = indexes($table);
|
||||
ksort($indexes);
|
||||
|
||||
if (!$status || empty($fields)) {
|
||||
return false;
|
||||
@@ -790,10 +844,10 @@ AND typelem = 0"
|
||||
// sequences for fields
|
||||
if (preg_match('~nextval\(\'([^\']+)\'\)~', $field['default'], $matches)) {
|
||||
$sequence_name = $matches[1];
|
||||
$sq = reset(get_rows(min_version(10)
|
||||
$sq = reset(get_rows((min_version(10)
|
||||
? "SELECT *, cache_size AS cache_value FROM pg_sequences WHERE schemaname = current_schema() AND sequencename = " . q(idf_unescape($sequence_name))
|
||||
: "SELECT * FROM $sequence_name"
|
||||
));
|
||||
), null, "-- "));
|
||||
$sequences[] = ($style == "DROP+CREATE" ? "DROP SEQUENCE IF EXISTS $sequence_name;\n" : "")
|
||||
. "CREATE SEQUENCE $sequence_name INCREMENT $sq[increment_by] MINVALUE $sq[min_value] MAXVALUE $sq[max_value]"
|
||||
. ($auto_increment && $sq['last_value'] ? " START " . ($sq["last_value"] + 1) : "")
|
||||
@@ -807,41 +861,20 @@ AND typelem = 0"
|
||||
$return = implode("\n\n", $sequences) . "\n\n$return";
|
||||
}
|
||||
|
||||
// primary + unique keys
|
||||
foreach ($indexes as $index_name => $index) {
|
||||
switch($index['type']) {
|
||||
case 'UNIQUE': $return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " UNIQUE (" . implode(', ', array_map('idf_escape', $index['columns'])) . ")"; break;
|
||||
case 'PRIMARY': $return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " PRIMARY KEY (" . implode(', ', array_map('idf_escape', $index['columns'])) . ")"; break;
|
||||
$primary = "";
|
||||
foreach (indexes($table) as $index_name => $index) {
|
||||
if ($index['type'] == 'PRIMARY') {
|
||||
$primary = $index_name;
|
||||
$return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " PRIMARY KEY (" . implode(', ', array_map('Adminer\idf_escape', $index['columns'])) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
$constraints = get_key_vals("SELECT conname, " . (min_version(8) ? "pg_get_constraintdef(pg_constraint.oid)" : "CONCAT('CHECK ', consrc)") . "
|
||||
FROM pg_catalog.pg_constraint
|
||||
INNER JOIN pg_catalog.pg_namespace ON pg_constraint.connamespace = pg_namespace.oid
|
||||
INNER JOIN pg_catalog.pg_class ON pg_constraint.conrelid = pg_class.oid AND pg_constraint.connamespace = pg_class.relnamespace
|
||||
WHERE pg_constraint.contype = 'c'
|
||||
AND conrelid != 0 -- handle only CONSTRAINTs here, not TYPES
|
||||
AND nspname = current_schema()
|
||||
AND relname = " . q($table) . "
|
||||
ORDER BY connamespace, conname"
|
||||
);
|
||||
foreach ($constraints as $conname => $consrc) {
|
||||
$return_parts[] = "CONSTRAINT " . idf_escape($conname) . " $consrc";
|
||||
foreach ($driver->checkConstraints($table) as $conname => $consrc) {
|
||||
$return_parts[] = "CONSTRAINT " . idf_escape($conname) . " CHECK $consrc";
|
||||
}
|
||||
|
||||
$return .= implode(",\n ", $return_parts) . "\n) WITH (oids = " . ($status['Oid'] ? 'true' : 'false') . ");";
|
||||
|
||||
// "basic" indexes after table definition
|
||||
foreach ($indexes as $index_name => $index) {
|
||||
if ($index['type'] == 'INDEX') {
|
||||
$columns = array();
|
||||
foreach ($index['columns'] as $key => $val) {
|
||||
$columns[] = idf_escape($val) . ($index['descs'][$key] ? " DESC" : "");
|
||||
}
|
||||
$return .= "\n\nCREATE INDEX " . idf_escape($index_name) . " ON " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " USING btree (" . implode(', ', $columns) . ");";
|
||||
}
|
||||
}
|
||||
|
||||
// comments for table & fields
|
||||
if ($status['Comment']) {
|
||||
$return .= "\n\nCOMMENT ON TABLE " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " IS " . q($status['Comment']) . ";";
|
||||
@@ -853,6 +886,10 @@ ORDER BY connamespace, conname"
|
||||
}
|
||||
}
|
||||
|
||||
foreach (get_rows("SELECT indexdef FROM pg_catalog.pg_indexes WHERE schemaname = current_schema() AND tablename = " . q($table) . ($primary ? " AND indexname != " . q($primary) : ""), null, "-- ") as $row) {
|
||||
$return .= "\n\n$row[indexdef];";
|
||||
}
|
||||
|
||||
return rtrim($return, ';');
|
||||
}
|
||||
|
||||
@@ -879,22 +916,10 @@ ORDER BY connamespace, conname"
|
||||
return get_key_vals("SHOW ALL");
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
global $connection;
|
||||
static $c_style;
|
||||
if ($c_style === null) {
|
||||
$c_style = ($connection->result("SHOW standard_conforming_strings") == "off");
|
||||
}
|
||||
return $c_style;
|
||||
}
|
||||
|
||||
function process_list() {
|
||||
return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid"));
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
}
|
||||
|
||||
function convert_field($field) {
|
||||
}
|
||||
|
||||
@@ -910,7 +935,7 @@ ORDER BY connamespace, conname"
|
||||
return queries("SELECT pg_terminate_backend(" . number($val) . ")");
|
||||
}
|
||||
|
||||
function connection_id(){
|
||||
function connection_id() {
|
||||
return "SELECT pg_backend_pid()";
|
||||
}
|
||||
|
||||
@@ -918,40 +943,4 @@ ORDER BY connamespace, conname"
|
||||
global $connection;
|
||||
return $connection->result("SHOW max_connections");
|
||||
}
|
||||
|
||||
function driver_config() {
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array( //! arrays
|
||||
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
|
||||
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0),
|
||||
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
|
||||
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
|
||||
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "macaddr8" => 23, "txid_snapshot" => 0),
|
||||
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
|
||||
) as $key => $val) { //! can be retrieved from pg_type
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
return array(
|
||||
'possible_drivers' => array("PgSQL", "PDO_PgSQL"),
|
||||
'jush' => "pgsql",
|
||||
'types' => $types,
|
||||
'structured_types' => $structured_types,
|
||||
'unsigned' => array(),
|
||||
'operators' => array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"), // no "SQL" to avoid CSRF
|
||||
'functions' => array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper"),
|
||||
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
|
||||
'edit_functions' => array(
|
||||
array(
|
||||
"char" => "md5",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
number_type() => "+/-",
|
||||
"date|time" => "+ interval/- interval", //! escape
|
||||
"char|text" => "||",
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,185 +1,103 @@
|
||||
<?php
|
||||
$drivers["sqlite"] = "SQLite 3";
|
||||
$drivers["sqlite2"] = "SQLite 2";
|
||||
namespace Adminer;
|
||||
|
||||
if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
define("DRIVER", (isset($_GET["sqlite"]) ? "sqlite" : "sqlite2"));
|
||||
if (class_exists(isset($_GET["sqlite"]) ? "SQLite3" : "SQLiteDatabase")) {
|
||||
if (isset($_GET["sqlite"])) {
|
||||
$drivers["sqlite"] = "SQLite";
|
||||
|
||||
class Min_SQLite {
|
||||
var $extension = "SQLite3", $server_info, $affected_rows, $errno, $error, $_link;
|
||||
if (isset($_GET["sqlite"])) {
|
||||
define('Adminer\DRIVER', "sqlite");
|
||||
if (class_exists("SQLite3")) {
|
||||
|
||||
function __construct($filename) {
|
||||
$this->_link = new SQLite3($filename);
|
||||
$version = $this->_link->version();
|
||||
$this->server_info = $version["versionString"];
|
||||
}
|
||||
class SqliteDb {
|
||||
var $extension = "SQLite3", $server_info, $affected_rows, $errno, $error, $_link;
|
||||
|
||||
function query($query) {
|
||||
$result = @$this->_link->query($query);
|
||||
$this->error = "";
|
||||
if (!$result) {
|
||||
$this->errno = $this->_link->lastErrorCode();
|
||||
$this->error = $this->_link->lastErrorMsg();
|
||||
return false;
|
||||
} elseif ($result->numColumns()) {
|
||||
return new Min_Result($result);
|
||||
}
|
||||
$this->affected_rows = $this->_link->changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return (is_utf8($string)
|
||||
? "'" . $this->_link->escapeString($string) . "'"
|
||||
: "x'" . reset(unpack('H*', $string)) . "'"
|
||||
);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetchArray();
|
||||
return $row ? $row[$field] : false;
|
||||
}
|
||||
function __construct($filename) {
|
||||
$this->_link = new \SQLite3($filename);
|
||||
$version = $this->_link->version();
|
||||
$this->server_info = $version["versionString"];
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_result->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetchArray(SQLITE3_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$type = $this->_result->columnType($column);
|
||||
return (object) array(
|
||||
"name" => $this->_result->columnName($column),
|
||||
"type" => $type,
|
||||
"charsetnr" => ($type == SQLITE3_BLOB ? 63 : 0), // 63 - binary
|
||||
);
|
||||
}
|
||||
|
||||
function __desctruct() {
|
||||
return $this->_result->finalize();
|
||||
function query($query) {
|
||||
$result = @$this->_link->query($query);
|
||||
$this->error = "";
|
||||
if (!$result) {
|
||||
$this->errno = $this->_link->lastErrorCode();
|
||||
$this->error = $this->_link->lastErrorMsg();
|
||||
return false;
|
||||
} elseif ($result->numColumns()) {
|
||||
return new Result($result);
|
||||
}
|
||||
$this->affected_rows = $this->_link->changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
class Min_SQLite {
|
||||
var $extension = "SQLite", $server_info, $affected_rows, $error, $_link;
|
||||
|
||||
function __construct($filename) {
|
||||
$this->server_info = sqlite_libversion();
|
||||
$this->_link = new SQLiteDatabase($filename);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$method = ($unbuffered ? "unbufferedQuery" : "query");
|
||||
$result = @$this->_link->$method($query, SQLITE_BOTH, $error);
|
||||
$this->error = "";
|
||||
if (!$result) {
|
||||
$this->error = $error;
|
||||
return false;
|
||||
} elseif ($result === true) {
|
||||
$this->affected_rows = $this->changes();
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . sqlite_escape_string($string) . "'";
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetch();
|
||||
return $row[$field];
|
||||
}
|
||||
function quote($string) {
|
||||
return (is_utf8($string)
|
||||
? "'" . $this->_link->escapeString($string) . "'"
|
||||
: "x'" . reset(unpack('H*', $string)) . "'"
|
||||
);
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
if (method_exists($result, 'numRows')) { // not available in unbuffered query
|
||||
$this->num_rows = $result->numRows();
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
$row = $this->_result->fetch(SQLITE_ASSOC);
|
||||
if (!$row) {
|
||||
return false;
|
||||
}
|
||||
$return = array();
|
||||
foreach ($row as $key => $val) {
|
||||
$return[idf_unescape($key)] = $val;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetch(SQLITE_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$name = $this->_result->fieldName($this->_offset++);
|
||||
$pattern = '(\[.*]|"(?:[^"]|"")*"|(.+))';
|
||||
if (preg_match("~^($pattern\\.)?$pattern\$~", $name, $match)) {
|
||||
$table = ($match[3] != "" ? $match[3] : idf_unescape($match[2]));
|
||||
$name = ($match[5] != "" ? $match[5] : idf_unescape($match[4]));
|
||||
}
|
||||
return (object) array(
|
||||
"name" => $name,
|
||||
"orgname" => $name,
|
||||
"orgtable" => $table,
|
||||
);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetchArray();
|
||||
return $row ? $row[$field] : false;
|
||||
}
|
||||
}
|
||||
|
||||
class Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_result->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetchArray(SQLITE3_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$type = $this->_result->columnType($column);
|
||||
return (object) array(
|
||||
"name" => $this->_result->columnName($column),
|
||||
"type" => $type,
|
||||
"charsetnr" => ($type == SQLITE3_BLOB ? 63 : 0), // 63 - binary
|
||||
);
|
||||
}
|
||||
|
||||
function __desctruct() {
|
||||
return $this->_result->finalize();
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_sqlite")) {
|
||||
class Min_SQLite extends Min_PDO {
|
||||
class SqliteDb extends PdoDb {
|
||||
var $extension = "PDO_SQLite";
|
||||
|
||||
function __construct($filename) {
|
||||
$this->dsn(DRIVER . ":$filename", "", "");
|
||||
}
|
||||
|
||||
function select_db($db) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (class_exists("Min_SQLite")) {
|
||||
class Min_DB extends Min_SQLite {
|
||||
if (class_exists('Adminer\SqliteDb')) {
|
||||
class Db extends SqliteDb {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct(":memory:");
|
||||
@@ -208,7 +126,36 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
|
||||
|
||||
|
||||
class Min_Driver extends Min_SQL {
|
||||
class Driver extends SqlDriver {
|
||||
static $possibleDrivers = array("SQLite3", "PDO_SQLite");
|
||||
static $jush = "sqlite";
|
||||
|
||||
protected $types = array(array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0));
|
||||
|
||||
var $editFunctions = array(
|
||||
array(
|
||||
// "text" => "date('now')/time('now')/datetime('now')",
|
||||
), array(
|
||||
"integer|real|numeric" => "+/-",
|
||||
// "text" => "date/time/datetime",
|
||||
"text" => "||",
|
||||
)
|
||||
);
|
||||
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"); // REGEXP can be user defined function
|
||||
var $functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
|
||||
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
|
||||
function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
if (min_version(3.31, 0, $connection)) {
|
||||
$this->generated = array("STORED", "VIRTUAL");
|
||||
}
|
||||
}
|
||||
|
||||
function structuredTypes() {
|
||||
return array_keys($this->types[0]);
|
||||
}
|
||||
|
||||
function insertUpdate($table, $rows, $primary) {
|
||||
$values = array();
|
||||
@@ -218,7 +165,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
return queries("REPLACE INTO " . table($table) . " (" . implode(", ", array_keys(reset($rows))) . ") VALUES\n" . implode(",\n", $values));
|
||||
}
|
||||
|
||||
function tableHelp($name) {
|
||||
function tableHelp($name, $is_view = false) {
|
||||
if ($name == "sqlite_sequence") {
|
||||
return "fileformat2.html#seqtab";
|
||||
}
|
||||
@@ -227,6 +174,10 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
}
|
||||
|
||||
function checkConstraints($table) {
|
||||
preg_match_all('~ CHECK *(\( *(((?>[^()]*[^() ])|(?1))*) *\))~', $this->_conn->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)), $matches); //! could be inside a comment
|
||||
return array_combine($matches[2], $matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +196,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
if ($password != "") {
|
||||
return lang('Database does not support password.');
|
||||
}
|
||||
return new Min_DB;
|
||||
return new Db;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
@@ -311,7 +262,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$primary = "";
|
||||
foreach (get_rows("PRAGMA table_info(" . table($table) . ")") as $row) {
|
||||
foreach (get_rows("PRAGMA table_" . (min_version(3.31) ? "x" : "") . "info(" . table($table) . ")") as $row) {
|
||||
$name = $row["name"];
|
||||
$type = strtolower($row["type"]);
|
||||
$default = $row["dflt_value"];
|
||||
@@ -334,13 +285,20 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
}
|
||||
$sql = $connection->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table));
|
||||
preg_match_all('~(("[^"]*+")+|[a-z0-9_]+)\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i', $sql, $matches, PREG_SET_ORDER);
|
||||
$idf = '(("[^"]*+")+|[a-z0-9_]+)';
|
||||
preg_match_all('~' . $idf . '\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i', $sql, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
$name = str_replace('""', '"', preg_replace('~^"|"$~', '', $match[1]));
|
||||
if ($return[$name]) {
|
||||
$return[$name]["collation"] = trim($match[3], "'");
|
||||
}
|
||||
}
|
||||
preg_match_all('~' . $idf . '\s.*GENERATED ALWAYS AS \((.+)\) (STORED|VIRTUAL)~i', $sql, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
$name = str_replace('""', '"', preg_replace('~^"|"$~', '', $match[1]));
|
||||
$return[$name]["default"] = $match[3];
|
||||
$return[$name]["generated"] = strtoupper($match[4]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -395,7 +353,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
$return = array();
|
||||
foreach (get_rows("PRAGMA foreign_key_list(" . table($table) . ")") as $row) {
|
||||
$foreign_key = &$return[$row["id"]];
|
||||
//! idf_unescape in SQLite2
|
||||
if (!$foreign_key) {
|
||||
$foreign_key = $row;
|
||||
}
|
||||
@@ -407,7 +364,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . q($name)))); //! identifiers may be inside []
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE type = 'view' AND name = " . q($name)))); //! identifiers may be inside []
|
||||
}
|
||||
|
||||
function collations() {
|
||||
@@ -444,7 +401,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$link = new Min_SQLite($db);
|
||||
$link = new SqliteDb($db);
|
||||
} catch (Exception $ex) {
|
||||
$connection->error = $ex->getMessage();
|
||||
return false;
|
||||
@@ -478,7 +435,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return " PRIMARY KEY" . (DRIVER == "sqlite" ? " AUTOINCREMENT" : "");
|
||||
return " PRIMARY KEY AUTOINCREMENT";
|
||||
}
|
||||
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
@@ -523,8 +480,20 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function recreate_table($table, $name, $fields, $originals, $foreign, $auto_increment = 0, $indexes = array()) {
|
||||
global $connection;
|
||||
/** Recreate table
|
||||
* @param string original name
|
||||
* @param string new name
|
||||
* @param array [process_field()], empty to preserve
|
||||
* @param array [$original => idf_escape($new_column)], empty to preserve
|
||||
* @param string [format_foreign_key()], empty to preserve
|
||||
* @param int set auto_increment to this value, 0 to preserve
|
||||
* @param array [[$type, $name, $columns]], empty to preserve
|
||||
* @param string CHECK constraint to drop
|
||||
* @param string CHECK constraint to add
|
||||
* @return bool
|
||||
*/
|
||||
function recreate_table($table, $name, $fields, $originals, $foreign, $auto_increment = 0, $indexes = array(), $drop_check = "", $add_check = "") {
|
||||
global $connection, $driver;
|
||||
if ($table != "") {
|
||||
if (!$fields) {
|
||||
foreach (fields($table) as $key => $field) {
|
||||
@@ -582,16 +551,27 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
queries("BEGIN");
|
||||
}
|
||||
foreach ($fields as $key => $field) {
|
||||
if (preg_match('~GENERATED~', $field[3])) {
|
||||
unset($originals[array_search($field[0], $originals)]);
|
||||
}
|
||||
$fields[$key] = " " . implode($field);
|
||||
}
|
||||
$fields = array_merge($fields, array_filter($foreign));
|
||||
foreach ($driver->checkConstraints($table) as $check) {
|
||||
if ($check != $drop_check) {
|
||||
$fields[] = " CHECK ($check)";
|
||||
}
|
||||
}
|
||||
if ($add_check) {
|
||||
$fields[] = " CHECK ($add_check)";
|
||||
}
|
||||
$temp_name = ($table == $name ? "adminer_$name" : $name);
|
||||
if (!queries("CREATE TABLE " . table($temp_name) . " (\n" . implode(",\n", $fields) . "\n)")) {
|
||||
// implicit ROLLBACK to not overwrite $connection->error
|
||||
return false;
|
||||
}
|
||||
if ($table != "") {
|
||||
if ($originals && !queries("INSERT INTO " . table($temp_name) . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('idf_escape', array_keys($originals))) . " FROM " . table($table))) {
|
||||
if ($originals && !queries("INSERT INTO " . table($temp_name) . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('Adminer\idf_escape', array_keys($originals))) . " FROM " . table($table))) {
|
||||
return false;
|
||||
}
|
||||
$triggers = array();
|
||||
@@ -600,7 +580,8 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
$triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]";
|
||||
}
|
||||
$auto_increment = $auto_increment ? 0 : $connection->result("SELECT seq FROM sqlite_sequence WHERE name = " . q($table)); // if $auto_increment is set then it will be updated later
|
||||
if (!queries("DROP TABLE " . table($table)) // drop before creating indexes and triggers to allow using old names
|
||||
if (
|
||||
!queries("DROP TABLE " . table($table)) // drop before creating indexes and triggers to allow using old names
|
||||
|| ($table == $name && !queries("ALTER TABLE " . table($temp_name) . " RENAME TO " . table($name)))
|
||||
|| !alter_indexes($name, $indexes)
|
||||
) {
|
||||
@@ -634,10 +615,11 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
}
|
||||
foreach (array_reverse($alter) as $val) {
|
||||
if (!queries($val[2] == "DROP"
|
||||
if (
|
||||
!queries($val[2] == "DROP"
|
||||
? "DROP INDEX " . idf_escape($val[1])
|
||||
: index_sql($table, $val[0], $val[1], "(" . implode(", ", $val[2]) . ")")
|
||||
)) {
|
||||
: index_sql($table, $val[0], $val[1], "(" . implode(", ", $val[2]) . ")"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -720,18 +702,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
function schemas() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function get_schema() {
|
||||
return "";
|
||||
}
|
||||
|
||||
function set_schema($scheme) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function create_sql($table, $auto_increment, $style) {
|
||||
global $connection;
|
||||
$return = $connection->result("SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q($table));
|
||||
@@ -739,7 +709,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
if ($name == '') {
|
||||
continue;
|
||||
}
|
||||
$return .= ";\n\n" . index_sql($table, $index['type'], $name, "(" . implode(", ", array_map('idf_escape', $index['columns'])) . ")");
|
||||
$return .= ";\n\n" . index_sql($table, $index['type'], $name, "(" . implode(", ", array_map('Adminer\idf_escape', $index['columns'])) . ")");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -756,19 +726,18 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
|
||||
function show_variables() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("PRAGMA pragma_list");
|
||||
while ($row = $result->fetch_row()) {
|
||||
$return[$row[0]] = $connection->result("PRAGMA $row[0]");
|
||||
foreach (get_rows("PRAGMA pragma_list") as $row) {
|
||||
$name = $row["name"];
|
||||
if ($name != "pragma_list" && $name != "compile_options") {
|
||||
foreach (get_rows("PRAGMA $name") as $row) {
|
||||
$return[$name] .= implode(", ", $row) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
$return = array();
|
||||
foreach (get_vals("PRAGMA compile_options") as $option) {
|
||||
@@ -786,29 +755,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return preg_match('~^(columns|database|drop_col|dump|indexes|descidx|move_col|sql|status|table|trigger|variables|view|view_trigger)$~', $feature);
|
||||
}
|
||||
|
||||
function driver_config() {
|
||||
$types = array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0);
|
||||
return array(
|
||||
'possible_drivers' => array((isset($_GET["sqlite"]) ? "SQLite3" : "SQLite"), "PDO_SQLite"),
|
||||
'jush' => "sqlite",
|
||||
'types' => $types,
|
||||
'structured_types' => array_keys($types),
|
||||
'unsigned' => array(),
|
||||
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"), // REGEXP can be user defined function
|
||||
'functions' => array("hex", "length", "lower", "round", "unixepoch", "upper"),
|
||||
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"),
|
||||
'edit_functions' => array(
|
||||
array(
|
||||
// "text" => "date('now')/time('now')/datetime('now')",
|
||||
), array(
|
||||
"integer|real|numeric" => "+/-",
|
||||
// "text" => "date/time/datetime",
|
||||
"text" => "||",
|
||||
)
|
||||
),
|
||||
);
|
||||
return preg_match('~^(check|columns|database|drop_col|dump|indexes|descidx|move_col|sql|status|table|trigger|variables|view|view_trigger)$~', $feature);
|
||||
}
|
||||
}
|
||||
|
@@ -1,21 +1,24 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["dump"];
|
||||
|
||||
if ($_POST && !$error) {
|
||||
$cookie = "";
|
||||
foreach (array("output", "format", "db_style", "routines", "events", "table_style", "auto_increment", "triggers", "data_style") as $key) {
|
||||
foreach (array("output", "format", "db_style", "types", "routines", "events", "table_style", "auto_increment", "triggers", "data_style") as $key) {
|
||||
$cookie .= "&$key=" . urlencode($_POST[$key]);
|
||||
}
|
||||
cookie("adminer_export", substr($cookie, 1));
|
||||
$tables = array_flip((array) $_POST["tables"]) + array_flip((array) $_POST["data"]);
|
||||
$ext = dump_headers(
|
||||
(count($tables) == 1 ? key($tables) : DB),
|
||||
(DB == "" || count($tables) > 1));
|
||||
(DB == "" || count($tables) > 1)
|
||||
);
|
||||
$is_sql = preg_match('~sql~', $_POST["format"]);
|
||||
|
||||
if ($is_sql) {
|
||||
echo "-- Adminer $VERSION " . $drivers[DRIVER] . " " . str_replace("\n", " ", $connection->server_info) . " dump\n\n";
|
||||
if ($jush == "sql") {
|
||||
if (JUSH == "sql") {
|
||||
echo "SET NAMES utf8;
|
||||
SET time_zone = '+00:00';
|
||||
SET foreign_key_checks = 0;
|
||||
@@ -52,6 +55,18 @@ SET foreign_key_checks = 0;
|
||||
}
|
||||
$out = "";
|
||||
|
||||
if ($_POST["types"]) {
|
||||
foreach (types() as $id => $type) {
|
||||
$enums = type_values($id);
|
||||
if ($enums) {
|
||||
$out .= ($style != 'DROP+CREATE' ? "DROP TYPE IF EXISTS " . idf_escape($type) . ";;\n" : "") . "CREATE TYPE " . idf_escape($type) . " AS ENUM ($enums);\n\n";
|
||||
} else {
|
||||
//! https://github.com/postgres/postgres/blob/REL_17_4/src/bin/pg_dump/pg_dump.c#L10846
|
||||
$out .= "-- Could not export type $type\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($_POST["routines"]) {
|
||||
foreach (routines() as $row) {
|
||||
$name = $row["ROUTINE_NAME"];
|
||||
@@ -70,7 +85,7 @@ SET foreign_key_checks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
echo ($out && $jush == 'sql' ? "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n" : $out);
|
||||
echo ($out && JUSH == 'sql' ? "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n" : $out);
|
||||
}
|
||||
|
||||
if ($_POST["table_style"] || $_POST["data_style"]) {
|
||||
@@ -105,7 +120,7 @@ SET foreign_key_checks = 0;
|
||||
}
|
||||
|
||||
// add FKs after creating tables (except in MySQL which uses SET FOREIGN_KEY_CHECKS=0)
|
||||
if (function_exists('foreign_keys_sql')) {
|
||||
if (function_exists('Adminer\foreign_keys_sql')) {
|
||||
foreach (table_status('', true) as $name => $table_status) {
|
||||
$table = (DB == "" || in_array($name, (array) $_POST["tables"]));
|
||||
if ($table && !is_view($table_status)) {
|
||||
@@ -126,7 +141,7 @@ SET foreign_key_checks = 0;
|
||||
}
|
||||
|
||||
if ($is_sql) {
|
||||
echo "-- " . $connection->result("SELECT NOW()") . "\n";
|
||||
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
@@ -140,7 +155,7 @@ page_header(lang('Export'), $error, ($_GET["export"] != "" ? array("table" => $_
|
||||
$db_style = array('', 'USE', 'DROP+CREATE', 'CREATE');
|
||||
$table_style = array('', 'DROP+CREATE', 'CREATE');
|
||||
$data_style = array('', 'TRUNCATE+INSERT', 'INSERT');
|
||||
if ($jush == "sql") { //! use insertUpdate() in all drivers
|
||||
if (JUSH == "sql") { //! use insertUpdate() in all drivers
|
||||
$data_style[] = 'INSERT+UPDATE';
|
||||
}
|
||||
parse_str($_COOKIE["adminer_export"], $row);
|
||||
@@ -156,7 +171,8 @@ echo "<tr><th>" . lang('Output') . "<td>" . html_select("output", $adminer->dump
|
||||
|
||||
echo "<tr><th>" . lang('Format') . "<td>" . html_select("format", $adminer->dumpFormat(), $row["format"], 0) . "\n"; // 0 - radio
|
||||
|
||||
echo ($jush == "sqlite" ? "" : "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"])
|
||||
echo (JUSH == "sqlite" ? "" : "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"])
|
||||
. (support("type") ? checkbox("types", 1, $row["types"], lang('User types')) : "")
|
||||
. (support("routine") ? checkbox("routines", 1, $row["routines"], lang('Routines')) : "")
|
||||
. (support("event") ? checkbox("events", 1, $row["events"], lang('Events')) : "")
|
||||
);
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["edit"];
|
||||
$fields = fields($TABLE);
|
||||
$where = (isset($_GET["select"]) ? ($_POST["check"] && count($_POST["check"]) == 1 ? where_check($_POST["check"][0], $fields) : "") : where($_GET, $fields));
|
||||
@@ -70,7 +72,7 @@ if ($_POST["save"]) {
|
||||
if ($_POST["clone"] && $field["auto_increment"]) {
|
||||
$as = "''";
|
||||
}
|
||||
if ($jush == "sql" && preg_match("~enum|set~", $field["type"])) {
|
||||
if (JUSH == "sql" && preg_match("~enum|set~", $field["type"])) {
|
||||
$as = "1*" . idf_escape($name);
|
||||
}
|
||||
$select[] = ($as ? "$as AS " : "") . idf_escape($name);
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
// To create Adminer just for Elasticsearch, run `../compile.php elastic`.
|
||||
|
||||
function adminer_object() {
|
||||
include_once "../plugins/plugin.php";
|
||||
include_once "../plugins/login-password-less.php";
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$EVENT = $_GET["event"];
|
||||
$intervals = array("YEAR", "QUARTER", "MONTH", "DAY", "HOUR", "MINUTE", "WEEK", "SECOND", "YEAR_MONTH", "DAY_HOUR", "DAY_MINUTE", "DAY_SECOND", "HOUR_MINUTE", "HOUR_SECOND", "MINUTE_SECOND");
|
||||
$statuses = array("ENABLED" => "ENABLE", "DISABLED" => "DISABLE", "SLAVESIDE_DISABLED" => "DISABLE ON SLAVE");
|
||||
@@ -16,13 +18,17 @@ if ($_POST && !$error) {
|
||||
) . " ON COMPLETION" . ($row["ON_COMPLETION"] ? "" : " NOT") . " PRESERVE"
|
||||
;
|
||||
|
||||
queries_redirect(substr(ME, 0, -1), ($EVENT != "" ? lang('Event has been altered.') : lang('Event has been created.')), queries(($EVENT != ""
|
||||
? "ALTER EVENT " . idf_escape($EVENT) . $schedule
|
||||
. ($EVENT != $row["EVENT_NAME"] ? "\nRENAME TO " . idf_escape($row["EVENT_NAME"]) : "")
|
||||
: "CREATE EVENT " . idf_escape($row["EVENT_NAME"]) . $schedule
|
||||
) . "\n" . $statuses[$row["STATUS"]] . " COMMENT " . q($row["EVENT_COMMENT"])
|
||||
. rtrim(" DO\n$row[EVENT_DEFINITION]", ";") . ";"
|
||||
));
|
||||
queries_redirect(
|
||||
substr(ME, 0, -1),
|
||||
($EVENT != "" ? lang('Event has been altered.') : lang('Event has been created.')),
|
||||
queries(
|
||||
($EVENT != ""
|
||||
? "ALTER EVENT " . idf_escape($EVENT) . $schedule . ($EVENT != $row["EVENT_NAME"] ? "\nRENAME TO " . idf_escape($row["EVENT_NAME"]) : "")
|
||||
: "CREATE EVENT " . idf_escape($row["EVENT_NAME"]) . $schedule
|
||||
) . "\n" . $statuses[$row["STATUS"]] . " COMMENT " . q($row["EVENT_COMMENT"])
|
||||
. rtrim(" DO\n$row[EVENT_DEFINITION]", ";") . ";"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +53,8 @@ if (!$row && $EVENT != "") {
|
||||
<p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($EVENT != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $EVENT)); ?><?php } ?>
|
||||
<?php if ($EVENT != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $EVENT)); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// caching headers added in compile.php
|
||||
|
||||
if ($_GET["file"] == "favicon.ico") {
|
||||
@@ -12,15 +14,34 @@ if ($_GET["file"] == "favicon.ico") {
|
||||
echo lzw_decompress(compile_file('../adminer/static/functions.js;static/editing.js', 'minify_js'));
|
||||
} elseif ($_GET["file"] == "jush.js") {
|
||||
header("Content-Type: text/javascript; charset=utf-8");
|
||||
echo lzw_decompress(compile_file('../externals/jush/modules/jush.js;../externals/jush/modules/jush-textarea.js;../externals/jush/modules/jush-txt.js;../externals/jush/modules/jush-js.js;../externals/jush/modules/jush-sql.js;../externals/jush/modules/jush-pgsql.js;../externals/jush/modules/jush-sqlite.js;../externals/jush/modules/jush-mssql.js;../externals/jush/modules/jush-oracle.js;../externals/jush/modules/jush-simpledb.js', 'minify_js'));
|
||||
echo lzw_decompress(compile_file('../externals/jush/modules/jush.js;
|
||||
../externals/jush/modules/jush-textarea.js;
|
||||
../externals/jush/modules/jush-txt.js;
|
||||
../externals/jush/modules/jush-js.js;
|
||||
../externals/jush/modules/jush-sql.js;
|
||||
../externals/jush/modules/jush-pgsql.js;
|
||||
../externals/jush/modules/jush-sqlite.js;
|
||||
../externals/jush/modules/jush-mssql.js;
|
||||
../externals/jush/modules/jush-oracle.js;
|
||||
../externals/jush/modules/jush-simpledb.js', 'minify_js'));
|
||||
} else {
|
||||
header("Content-Type: image/gif");
|
||||
switch ($_GET["file"]) {
|
||||
case "plus.gif": echo compile_file('../adminer/static/plus.gif'); break;
|
||||
case "cross.gif": echo compile_file('../adminer/static/cross.gif'); break;
|
||||
case "up.gif": echo compile_file('../adminer/static/up.gif'); break;
|
||||
case "down.gif": echo compile_file('../adminer/static/down.gif'); break;
|
||||
case "arrow.gif": echo compile_file('../adminer/static/arrow.gif'); break;
|
||||
case "plus.gif":
|
||||
echo compile_file('../adminer/static/plus.gif');
|
||||
break;
|
||||
case "cross.gif":
|
||||
echo compile_file('../adminer/static/cross.gif');
|
||||
break;
|
||||
case "up.gif":
|
||||
echo compile_file('../adminer/static/up.gif');
|
||||
break;
|
||||
case "down.gif":
|
||||
echo compile_file('../adminer/static/down.gif');
|
||||
break;
|
||||
case "arrow.gif":
|
||||
echo compile_file('../adminer/static/arrow.gif');
|
||||
break;
|
||||
}
|
||||
}
|
||||
exit;
|
||||
|
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["foreign"];
|
||||
$name = $_GET["name"];
|
||||
$row = $_POST;
|
||||
|
||||
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
|
||||
$message = ($_POST["drop"] ? lang('Foreign key has been dropped.') : ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.')));
|
||||
$location = ME . "table=" . urlencode($TABLE);
|
||||
|
||||
if (!$_POST["drop"]) {
|
||||
$row["source"] = array_filter($row["source"], 'strlen');
|
||||
ksort($row["source"]); // enforce input order
|
||||
@@ -17,18 +16,23 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-
|
||||
$row["target"] = $target;
|
||||
}
|
||||
|
||||
if ($jush == "sqlite") {
|
||||
queries_redirect($location, $message, recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($_POST["drop"] ? "" : " " . format_foreign_key($row)))));
|
||||
if (JUSH == "sqlite") {
|
||||
$result = recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($row["drop"] ? "" : " " . format_foreign_key($row))));
|
||||
} else {
|
||||
$alter = "ALTER TABLE " . table($TABLE);
|
||||
$drop = "\nDROP " . ($jush == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name);
|
||||
if ($_POST["drop"]) {
|
||||
query_redirect($alter . $drop, $location, $message);
|
||||
} else {
|
||||
query_redirect($alter . ($name != "" ? "$drop," : "") . "\nADD" . format_foreign_key($row), $location, $message);
|
||||
$error = lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.') . "<br>$error"; //! no partitioning
|
||||
$result = ($name == "" || queries("$alter DROP " . (JUSH == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name)));
|
||||
if (!$row["drop"]) {
|
||||
$result = queries("$alter ADD" . format_foreign_key($row));
|
||||
}
|
||||
}
|
||||
queries_redirect(
|
||||
ME . "table=" . urlencode($TABLE),
|
||||
($row["drop"] ? lang('Foreign key has been dropped.') : ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.'))),
|
||||
$result
|
||||
);
|
||||
if (!$row["drop"]) {
|
||||
$error = "$error<br>" . lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.'); //! no partitioning
|
||||
}
|
||||
}
|
||||
|
||||
page_header(lang('Foreign key'), $error, array("table" => $TABLE), h($TABLE));
|
||||
@@ -57,15 +61,22 @@ if ($row["db"] != "") {
|
||||
$connection->select_db($row["db"]);
|
||||
}
|
||||
if ($row["ns"] != "") {
|
||||
$orig_schema = get_schema();
|
||||
set_schema($row["ns"]);
|
||||
}
|
||||
$referencable = array_keys(array_filter(table_status('', true), 'fk_support'));
|
||||
$referencable = array_keys(array_filter(table_status('', true), 'Adminer\fk_support'));
|
||||
$target = array_keys(fields(in_array($row["table"], $referencable) ? $row["table"] : reset($referencable)));
|
||||
$onchange = "this.form['change-js'].value = '1'; this.form.submit();";
|
||||
echo "<p>" . lang('Target table') . ": " . html_select("table", $referencable, $row["table"], $onchange) . "\n";
|
||||
if ($jush == "pgsql") {
|
||||
echo lang('Schema') . ": " . html_select("ns", $adminer->schemas(), $row["ns"] != "" ? $row["ns"] : $_GET["ns"], $onchange);
|
||||
} elseif ($jush != "sqlite") {
|
||||
if (support("scheme")) {
|
||||
$schemas = array_filter($adminer->schemas(), function ($schema) {
|
||||
return !preg_match('~^information_schema$~i', $schema);
|
||||
});
|
||||
echo lang('Schema') . ": " . html_select("ns", $schemas, $row["ns"] != "" ? $row["ns"] : $_GET["ns"], $onchange);
|
||||
if ($row["ns"] != "") {
|
||||
set_schema($orig_schema);
|
||||
}
|
||||
} elseif (JUSH != "sqlite") {
|
||||
$dbs = array();
|
||||
foreach ($adminer->databases() as $db) {
|
||||
if (!information_schema($db)) {
|
||||
@@ -90,18 +101,20 @@ foreach ($row["source"] as $key => $val) {
|
||||
?>
|
||||
</table>
|
||||
<p>
|
||||
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + explode("|", $on_actions), $row["on_delete"]); ?>
|
||||
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + explode("|", $on_actions), $row["on_update"]); ?>
|
||||
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + explode("|", $driver->onActions), $row["on_delete"]); ?>
|
||||
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + explode("|", $driver->onActions), $row["on_update"]); ?>
|
||||
<?php echo doc_link(array(
|
||||
'sql' => "innodb-foreign-key-constraints.html",
|
||||
'mariadb' => "foreign-keys/",
|
||||
'pgsql' => "sql-createtable.html#SQL-CREATETABLE-REFERENCES",
|
||||
'mssql' => "ms174979.aspx",
|
||||
'oracle' => "https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm#sthref2903",
|
||||
'mssql' => "t-sql/statements/create-table-transact-sql",
|
||||
'oracle' => "SQLRF01111",
|
||||
)); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<noscript><p><input type="submit" name="add" value="<?php echo lang('Add column'); ?>"></noscript>
|
||||
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?><?php } ?>
|
||||
<?php if ($name != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// any method change in this file should be transferred to editor/include/adminer.inc.php and plugins/plugin.php
|
||||
|
||||
class Adminer {
|
||||
@@ -119,11 +121,11 @@ class Adminer {
|
||||
function loginForm() {
|
||||
global $drivers;
|
||||
echo "<table class='layout'>\n";
|
||||
echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);") . "\n");
|
||||
echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">' . "\n");
|
||||
echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);"));
|
||||
echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">');
|
||||
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" autofocus value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("qs('#username').form['auth[driver]'].onchange();"));
|
||||
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n");
|
||||
echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n");
|
||||
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">');
|
||||
echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">');
|
||||
echo "</table>\n";
|
||||
echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
|
||||
echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
|
||||
@@ -136,7 +138,7 @@ class Adminer {
|
||||
* @return string
|
||||
*/
|
||||
function loginFormField($name, $heading, $value) {
|
||||
return $heading . $value;
|
||||
return $heading . $value . "\n";
|
||||
}
|
||||
|
||||
/** Authorize the user
|
||||
@@ -174,14 +176,16 @@ class Adminer {
|
||||
* @return null
|
||||
*/
|
||||
function selectLinks($tableStatus, $set = "") {
|
||||
global $jush, $driver;
|
||||
global $driver;
|
||||
echo '<p class="links">';
|
||||
$links = array("select" => lang('Select data'));
|
||||
if (support("table") || support("indexes")) {
|
||||
$links["table"] = lang('Show structure');
|
||||
}
|
||||
$is_view = false;
|
||||
if (support("table")) {
|
||||
if (is_view($tableStatus)) {
|
||||
$is_view = is_view($tableStatus);
|
||||
if ($is_view) {
|
||||
$links["view"] = lang('Alter view');
|
||||
} else {
|
||||
$links["create"] = lang('Alter table');
|
||||
@@ -194,7 +198,7 @@ class Adminer {
|
||||
foreach ($links as $key => $val) {
|
||||
echo " <a href='" . h(ME) . "$key=" . urlencode($name) . ($key == "edit" ? $set : "") . "'" . bold(isset($_GET[$key])) . ">$val</a>";
|
||||
}
|
||||
echo doc_link(array($jush => $driver->tableHelp($name)), "?");
|
||||
echo doc_link(array(JUSH => $driver->tableHelp($name, $is_view)), "?");
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
@@ -230,7 +234,7 @@ class Adminer {
|
||||
* @return string
|
||||
*/
|
||||
function selectQuery($query, $start, $failed = false) {
|
||||
global $jush, $driver;
|
||||
global $driver;
|
||||
$return = "</p>\n"; // required for IE9 inline edit
|
||||
if (!$failed && ($warnings = $driver->warnings())) {
|
||||
$id = "warnings";
|
||||
@@ -238,7 +242,7 @@ class Adminer {
|
||||
. "$return<div id='$id' class='hidden'>\n$warnings</div>\n"
|
||||
;
|
||||
}
|
||||
return "<p><code class='jush-$jush'>" . h(str_replace("\n", " ", $query)) . "</code> <span class='time'>(" . format_time($start) . ")</span>"
|
||||
return "<p><code class='jush-" . JUSH . "'>" . h(str_replace("\n", " ", $query)) . "</code> <span class='time'>(" . format_time($start) . ")</span>"
|
||||
. (support("sql") ? " <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>" : "")
|
||||
. $return
|
||||
;
|
||||
@@ -309,10 +313,11 @@ class Adminer {
|
||||
* @return null
|
||||
*/
|
||||
function tableStructurePrint($fields) {
|
||||
global $structured_types;
|
||||
global $driver;
|
||||
echo "<div class='scrollable'>\n";
|
||||
echo "<table class='nowrap odds'>\n";
|
||||
echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . (support("comment") ? "<td>" . lang('Comment') : "") . "</thead>\n";
|
||||
$structured_types = $driver->structuredTypes();
|
||||
foreach ($fields as $field) {
|
||||
echo "<tr><th>" . h($field["field"]);
|
||||
$type = h($field["full_type"]);
|
||||
@@ -322,7 +327,8 @@ class Adminer {
|
||||
;
|
||||
echo ($field["null"] ? " <i>NULL</i>" : "");
|
||||
echo ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
|
||||
echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . h($field["default"]) . "</b>]</span>" : "");
|
||||
$default = h($field["default"]);
|
||||
echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . ($field["generated"] ? "<code class='jush-" . JUSH . "'>$default</code>" : $default) . "</b>]</span>" : "");
|
||||
echo (support("comment") ? "<td>" . h($field["comment"]) : "");
|
||||
echo "\n";
|
||||
}
|
||||
@@ -356,7 +362,7 @@ class Adminer {
|
||||
* @return null
|
||||
*/
|
||||
function selectColumnsPrint($select, $columns) {
|
||||
global $functions, $grouping;
|
||||
global $driver;
|
||||
print_fieldset("select", lang('Select'), $select);
|
||||
$i = 0;
|
||||
$select[""] = array();
|
||||
@@ -368,8 +374,8 @@ class Adminer {
|
||||
$val["col"],
|
||||
($key !== "" ? "selectFieldChange" : "selectAddRow")
|
||||
);
|
||||
echo "<div>" . ($functions || $grouping ? "<select name='columns[$i][fun]'>"
|
||||
. optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $functions, lang('Aggregation') => $grouping)), $val["fun"]) . "</select>"
|
||||
echo "<div>" . ($driver->functions || $driver->grouping ? "<select name='columns[$i][fun]'>"
|
||||
. optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $driver->functions, lang('Aggregation') => $driver->grouping)), $val["fun"]) . "</select>"
|
||||
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1)
|
||||
. script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "")
|
||||
. "($column)" : $column) . "</div>\n";
|
||||
@@ -388,7 +394,7 @@ class Adminer {
|
||||
print_fieldset("search", lang('Search'), $where);
|
||||
foreach ($indexes as $i => $index) {
|
||||
if ($index["type"] == "FULLTEXT") {
|
||||
echo "<div>(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST";
|
||||
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 script("qsl('input').oninput = selectFieldChange;", "");
|
||||
echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL");
|
||||
@@ -510,16 +516,16 @@ class Adminer {
|
||||
/** Process columns box in select
|
||||
* @param array selectable columns
|
||||
* @param array
|
||||
* @return array [array(select_expressions), array(group_expressions)]
|
||||
* @return array [[select_expressions], [group_expressions]]
|
||||
*/
|
||||
function selectColumnsProcess($columns, $indexes) {
|
||||
global $functions, $grouping;
|
||||
global $driver;
|
||||
$select = array(); // select expressions, empty for *
|
||||
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
|
||||
foreach ((array) $_GET["columns"] as $key => $val) {
|
||||
if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
|
||||
if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $driver->functions) || in_array($val["fun"], $driver->grouping)))) {
|
||||
$select[$key] = apply_sql_function($val["fun"], ($val["col"] != "" ? idf_escape($val["col"]) : "*"));
|
||||
if (!in_array($val["fun"], $grouping)) {
|
||||
if (!in_array($val["fun"], $driver->grouping)) {
|
||||
$group[] = $select[$key];
|
||||
}
|
||||
}
|
||||
@@ -537,7 +543,7 @@ class Adminer {
|
||||
$return = array();
|
||||
foreach ($indexes as $i => $index) {
|
||||
if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") {
|
||||
$return[] = "MATCH (" . implode(", ", array_map('idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
|
||||
$return[] = "MATCH (" . implode(", ", array_map('Adminer\idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
|
||||
}
|
||||
}
|
||||
foreach ((array) $_GET["where"] as $key => $val) {
|
||||
@@ -565,7 +571,8 @@ class Adminer {
|
||||
// find anywhere
|
||||
$cols = array();
|
||||
foreach ($fields as $name => $field) {
|
||||
if ((preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
|
||||
if (
|
||||
(preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
|
||||
&& (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"]))
|
||||
&& (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val["val"]))
|
||||
) {
|
||||
@@ -639,7 +646,7 @@ class Adminer {
|
||||
* @return string
|
||||
*/
|
||||
function messageQuery($query, $time, $failed = false) {
|
||||
global $jush, $driver;
|
||||
global $driver;
|
||||
restart_session();
|
||||
$history = &get_session("queries");
|
||||
if (!$history[$_GET["db"]]) {
|
||||
@@ -656,7 +663,7 @@ class Adminer {
|
||||
$return = "<a href='#$id' class='toggle'>" . lang('Warnings') . "</a>, $return<div id='$id' class='hidden'>\n$warnings</div>\n";
|
||||
}
|
||||
return " <span class='time'>" . @date("H:i:s") . "</span>" // @ - time zone may be not set
|
||||
. " $return<div id='$sql_id' class='hidden'><pre><code class='jush-$jush'>" . shorten_utf8($query, 1000) . "</code></pre>"
|
||||
. " $return<div id='$sql_id' class='hidden'><pre><code class='jush-" . JUSH . "'>" . shorten_utf8($query, 1000) . "</code></pre>"
|
||||
. ($time ? " <span class='time'>($time)</span>" : '')
|
||||
. (support("sql") ? '<p><a href="' . h(str_replace("db=" . urlencode(DB), "db=" . urlencode($_GET["db"]), ME) . 'sql=&history=' . (count($history[$_GET["db"]]) - 1)) . '">' . lang('Edit') . '</a>' : '')
|
||||
. '</div>'
|
||||
@@ -678,10 +685,10 @@ class Adminer {
|
||||
* @return array
|
||||
*/
|
||||
function editFunctions($field) {
|
||||
global $edit_functions;
|
||||
global $driver;
|
||||
$return = ($field["null"] ? "NULL/" : "");
|
||||
$update = isset($_GET["select"]) || where($_GET);
|
||||
foreach ($edit_functions as $key => $functions) {
|
||||
foreach ($driver->editFunctions as $key => $functions) {
|
||||
if (!$key || (!isset($_GET["call"]) && $update)) { // relative functions
|
||||
foreach ($functions as $pattern => $val) {
|
||||
if (!$pattern || preg_match("~$pattern~", $field["type"])) {
|
||||
@@ -769,7 +776,7 @@ class Adminer {
|
||||
* @return array empty to disable export
|
||||
*/
|
||||
function dumpFormat() {
|
||||
return array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
|
||||
return (support("dump") ? array('sql' => 'SQL') : array()) + array('csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
|
||||
}
|
||||
|
||||
/** Export database structure
|
||||
@@ -821,15 +828,25 @@ class Adminer {
|
||||
* @return null prints data
|
||||
*/
|
||||
function dumpData($table, $style, $query) {
|
||||
global $connection, $jush;
|
||||
global $connection;
|
||||
if ($style) {
|
||||
$max_packet = ($jush == "sqlite" ? 0 : 1048576); // default, minimum is 1024
|
||||
$max_packet = (JUSH == "sqlite" ? 0 : 1048576); // default, minimum is 1024
|
||||
$fields = array();
|
||||
$identity_insert = false;
|
||||
if ($_POST["format"] == "sql") {
|
||||
if ($style == "TRUNCATE+INSERT") {
|
||||
echo truncate_sql($table) . ";\n";
|
||||
}
|
||||
$fields = fields($table);
|
||||
if (JUSH == "mssql") {
|
||||
foreach ($fields as $field) {
|
||||
if ($field["auto_increment"]) {
|
||||
echo "SET IDENTITY_INSERT " . table($table) . " ON;\n";
|
||||
$identity_insert = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers
|
||||
if ($result) {
|
||||
@@ -862,7 +879,7 @@ class Adminer {
|
||||
dump_csv($row);
|
||||
} else {
|
||||
if (!$insert) {
|
||||
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', $keys)) . ") VALUES";
|
||||
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('Adminer\idf_escape', $keys)) . ") VALUES";
|
||||
}
|
||||
foreach ($row as $key => $val) {
|
||||
if ($generated[$key]) {
|
||||
@@ -892,6 +909,9 @@ class Adminer {
|
||||
} elseif ($_POST["format"] == "sql") {
|
||||
echo "-- " . str_replace("\n", " ", $connection->error) . "\n";
|
||||
}
|
||||
if ($identity_insert) {
|
||||
echo "SET IDENTITY_INSERT " . table($table) . " OFF;\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,7 +965,7 @@ class Adminer {
|
||||
* @return null
|
||||
*/
|
||||
function navigation($missing) {
|
||||
global $VERSION, $jush, $drivers, $connection;
|
||||
global $VERSION, $drivers, $connection;
|
||||
?>
|
||||
<h1>
|
||||
<?php echo $this->name(); ?>
|
||||
@@ -984,7 +1004,7 @@ class Adminer {
|
||||
echo script_src("../externals/jush/modules/jush-txt.js");
|
||||
echo script_src("../externals/jush/modules/jush-js.js");
|
||||
if (support("sql")) {
|
||||
echo script_src("../externals/jush/modules/jush-$jush.js");
|
||||
echo script_src("../externals/jush/modules/jush-" . JUSH . ".js");
|
||||
?>
|
||||
<script<?php echo nonce(); ?>>
|
||||
<?php
|
||||
@@ -993,9 +1013,9 @@ 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 . ": [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
|
||||
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
|
||||
echo "jushLinks.$val = jushLinks.$jush;\n";
|
||||
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
|
||||
}
|
||||
}
|
||||
$server_info = $connection->server_info;
|
||||
@@ -1011,9 +1031,7 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
|
||||
$actions[] = "<a href='" . h(ME) . "sql='" . bold(isset($_GET["sql"]) && !isset($_GET["import"])) . ">" . lang('SQL command') . "</a>";
|
||||
$actions[] = "<a href='" . h(ME) . "import='" . bold(isset($_GET["import"])) . ">" . lang('Import') . "</a>";
|
||||
}
|
||||
if (support("dump")) {
|
||||
$actions[] = "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>";
|
||||
}
|
||||
$actions[] = "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>";
|
||||
}
|
||||
$in_db = $_GET["ns"] !== "" && !$missing && DB != "";
|
||||
if ($in_db) {
|
||||
@@ -1091,5 +1109,4 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$connection = '';
|
||||
|
||||
$has_token = $_SESSION["token"];
|
||||
@@ -64,7 +66,8 @@ if ($auth) {
|
||||
$permanent[$key] = "$key:" . base64_encode($private ? encrypt_string($password, $private) : "");
|
||||
cookie("adminer_permanent", implode(" ", $permanent));
|
||||
}
|
||||
if (count($_POST) == 1 // 1 - auth
|
||||
if (
|
||||
count($_POST) == 1 // 1 - auth
|
||||
|| DRIVER != $vendor
|
||||
|| SERVER != $server
|
||||
|| $_GET["username"] !== $username // "0" == "00"
|
||||
@@ -130,7 +133,7 @@ function auth_error($error) {
|
||||
$error = lang('Session support must be enabled.');
|
||||
}
|
||||
$params = session_get_cookie_params();
|
||||
cookie("adminer_key", ($_COOKIE["adminer_key"] ? $_COOKIE["adminer_key"] : rand_string()), $params["lifetime"]);
|
||||
cookie("adminer_key", ($_COOKIE["adminer_key"] ?: rand_string()), $params["lifetime"]);
|
||||
page_header(lang('Login'), $error, null);
|
||||
echo "<form action='' method='post'>\n";
|
||||
echo "<div>";
|
||||
@@ -144,10 +147,10 @@ function auth_error($error) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET["username"]) && !class_exists("Min_DB")) {
|
||||
if (isset($_GET["username"]) && !class_exists('Adminer\Db')) {
|
||||
unset($_SESSION["pwds"][DRIVER]);
|
||||
unset_permanent();
|
||||
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false);
|
||||
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", Driver::$possibleDrivers)), false);
|
||||
page_footer("auth");
|
||||
exit;
|
||||
}
|
||||
@@ -161,7 +164,10 @@ if (isset($_GET["username"]) && is_string(get_password())) {
|
||||
}
|
||||
check_invalid_login();
|
||||
$connection = connect();
|
||||
$driver = new Min_Driver($connection);
|
||||
$driver = new Driver($connection);
|
||||
if ($adminer->operators === null) {
|
||||
$adminer->operators = $driver->operators;
|
||||
}
|
||||
}
|
||||
|
||||
$login = null;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
include "../adminer/include/version.inc.php";
|
||||
include "../adminer/include/errors.inc.php";
|
||||
include "../adminer/include/coverage.inc.php";
|
||||
@@ -33,7 +35,7 @@ if ($_GET["script"] == "version") {
|
||||
exit;
|
||||
}
|
||||
|
||||
global $adminer, $connection, $driver, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $has_token, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
|
||||
global $adminer, $connection, $driver, $drivers, $error, $HTTPS, $LANG, $langs, $permanent, $has_token, $token, $translations, $VERSION; // allows including Adminer inside a function
|
||||
|
||||
if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
|
||||
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
|
||||
@@ -50,11 +52,7 @@ $HTTPS = ($_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")) || ini_bool
|
||||
if (!defined("SID")) {
|
||||
session_cache_limiter(""); // to allow restarting session
|
||||
session_name("adminer_sid"); // use specific session name to get own namespace
|
||||
$params = array(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS);
|
||||
if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
|
||||
$params[] = true; // HttpOnly
|
||||
}
|
||||
call_user_func_array('session_set_cookie_params', $params); // ini_set() may be disabled
|
||||
session_set_cookie_params(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS, true); // ini_set() may be disabled
|
||||
session_start();
|
||||
}
|
||||
|
||||
@@ -80,27 +78,16 @@ include "./include/adminer.inc.php";
|
||||
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
|
||||
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
|
||||
|
||||
$config = driver_config();
|
||||
$possible_drivers = $config['possible_drivers'];
|
||||
$jush = $config['jush'];
|
||||
$types = $config['types'];
|
||||
$structured_types = $config['structured_types'];
|
||||
$unsigned = $config['unsigned'];
|
||||
$operators = $config['operators'];
|
||||
$functions = $config['functions'];
|
||||
$grouping = $config['grouping'];
|
||||
$edit_functions = $config['edit_functions'];
|
||||
if ($adminer->operators === null) {
|
||||
$adminer->operators = $operators;
|
||||
}
|
||||
|
||||
define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost
|
||||
define("DB", $_GET["db"]); // for the sake of speed and size
|
||||
define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?'
|
||||
. (sid() ? SID . '&' : '')
|
||||
. (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
|
||||
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
|
||||
. (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '')
|
||||
define('Adminer\JUSH', Driver::$jush);
|
||||
define('Adminer\SERVER', $_GET[DRIVER]); // read from pgsql=localhost
|
||||
define('Adminer\DB', $_GET["db"]); // for the sake of speed and size
|
||||
define(
|
||||
'Adminer\ME',
|
||||
preg_replace('~\?.*~', '', relative_uri()) . '?'
|
||||
. (sid() ? SID . '&' : '')
|
||||
. (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
|
||||
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
|
||||
. (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '')
|
||||
);
|
||||
|
||||
include "../adminer/include/design.inc.php";
|
||||
@@ -108,5 +95,3 @@ include "../adminer/include/xxtea.inc.php";
|
||||
include "../adminer/include/auth.inc.php";
|
||||
include "./include/editing.inc.php";
|
||||
include "./include/connect.inc.php";
|
||||
|
||||
$on_actions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()
|
||||
|
@@ -1,6 +1,18 @@
|
||||
<?php
|
||||
function connect_error() {
|
||||
global $adminer, $connection, $token, $error, $drivers;
|
||||
namespace Adminer;
|
||||
|
||||
if (isset($_GET["status"])) {
|
||||
$_GET["variables"] = $_GET["status"];
|
||||
}
|
||||
if (isset($_GET["import"])) {
|
||||
$_GET["sql"] = $_GET["import"];
|
||||
}
|
||||
|
||||
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
|
||||
if (DB != "" || $_GET["refresh"]) {
|
||||
restart_session();
|
||||
set_session("dbs", null);
|
||||
}
|
||||
if (DB != "") {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true);
|
||||
@@ -11,13 +23,15 @@ function connect_error() {
|
||||
|
||||
page_header(lang('Select database'), $error, false);
|
||||
echo "<p class='links'>\n";
|
||||
foreach (array(
|
||||
'database' => lang('Create database'),
|
||||
'privileges' => lang('Privileges'),
|
||||
'processlist' => lang('Process list'),
|
||||
'variables' => lang('Variables'),
|
||||
'status' => lang('Status'),
|
||||
) as $key => $val) {
|
||||
foreach (
|
||||
array(
|
||||
'database' => lang('Create database'),
|
||||
'privileges' => lang('Privileges'),
|
||||
'processlist' => lang('Process list'),
|
||||
'variables' => lang('Variables'),
|
||||
'status' => lang('Status'),
|
||||
) as $key => $val
|
||||
) {
|
||||
if (support($key)) {
|
||||
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
|
||||
}
|
||||
@@ -33,7 +47,7 @@ function connect_error() {
|
||||
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
|
||||
echo "<thead><tr>"
|
||||
. (support("database") ? "<td>" : "")
|
||||
. "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>"
|
||||
. "<th>" . lang('Database') . (get_session("dbs") !== null ? " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>" : "")
|
||||
. "<td>" . lang('Collation')
|
||||
. "<td>" . lang('Tables')
|
||||
. "<td>" . lang('Size') . " - <a href='" . h(ME) . "dbsize=1'>" . lang('Compute') . "</a>" . script("qsl('a').onclick = partial(ajaxSetHtml, '" . js_escape(ME) . "script=connect');", "")
|
||||
@@ -71,21 +85,6 @@ function connect_error() {
|
||||
}
|
||||
|
||||
page_footer("db");
|
||||
}
|
||||
|
||||
if (isset($_GET["status"])) {
|
||||
$_GET["variables"] = $_GET["status"];
|
||||
}
|
||||
if (isset($_GET["import"])) {
|
||||
$_GET["sql"] = $_GET["import"];
|
||||
}
|
||||
|
||||
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
|
||||
if (DB != "" || $_GET["refresh"]) {
|
||||
restart_session();
|
||||
set_session("dbs", null);
|
||||
}
|
||||
connect_error(); // separate function to catch SQLite error
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// coverage is used in tests and removed in compilation
|
||||
if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer_coverage.ser")) {
|
||||
function save_coverage() {
|
||||
@@ -14,5 +16,5 @@ if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer_cov
|
||||
}
|
||||
}
|
||||
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
|
||||
register_shutdown_function('save_coverage');
|
||||
register_shutdown_function('Adminer\save_coverage');
|
||||
}
|
||||
|
@@ -1,13 +1,19 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
if (!ob_get_level()) {
|
||||
ob_start(null, 4096);
|
||||
}
|
||||
|
||||
/** Print HTML header
|
||||
* @param string used in title, breadcrumb and heading, should be HTML escaped
|
||||
* @param string
|
||||
* @param mixed array("key" => "link", "key2" => array("link", "desc")), null for nothing, false for driver only, true for driver and server
|
||||
* @param mixed ["key" => "link", "key2" => ["link", "desc"]], null for nothing, false for driver only, true for driver and server
|
||||
* @param string used after colon in title and heading, should be HTML escaped
|
||||
* @return null
|
||||
*/
|
||||
function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
|
||||
global $LANG, $VERSION, $adminer, $drivers, $jush;
|
||||
global $LANG, $VERSION, $adminer, $drivers;
|
||||
page_headers();
|
||||
if (is_ajax() && $error) {
|
||||
page_messages($error);
|
||||
@@ -62,14 +68,14 @@ var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>';
|
||||
var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>';
|
||||
</script>
|
||||
|
||||
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
|
||||
<div id="help" class="jush-<?php echo JUSH; ?> jsonly hidden"></div>
|
||||
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?>
|
||||
|
||||
<div id="content">
|
||||
<?php
|
||||
if ($breadcrumb !== null) {
|
||||
$link = substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1);
|
||||
echo '<p id="breadcrumb"><a href="' . h($link ? $link : ".") . '">' . $drivers[DRIVER] . '</a> » ';
|
||||
echo '<p id="breadcrumb"><a href="' . h($link ?: ".") . '">' . $drivers[DRIVER] . '</a> » ';
|
||||
$link = substr(preg_replace('~\b(db|ns)=[^&]*&~', '', ME), 0, -1);
|
||||
$server = $adminer->serverName(SERVER);
|
||||
$server = ($server != "" ? $server : lang('Server'));
|
||||
@@ -103,7 +109,7 @@ var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>';
|
||||
$databases = null;
|
||||
}
|
||||
stop_session();
|
||||
define("PAGE_HEADER", 1);
|
||||
define('Adminer\PAGE_HEADER', 1);
|
||||
}
|
||||
|
||||
/** Send HTTP headers
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers = array();
|
||||
|
||||
/** Add a driver
|
||||
@@ -20,16 +22,43 @@ function get_driver($id) {
|
||||
return $drivers[$id];
|
||||
}
|
||||
|
||||
/*abstract*/ class Min_SQL {
|
||||
abstract class SqlDriver {
|
||||
static $possibleDrivers = array();
|
||||
static $jush; ///< @var string JUSH identifier
|
||||
|
||||
var $_conn;
|
||||
protected $types = array(); ///< @var array [$description => [$type => $maximum_unsigned_length, ...], ...]
|
||||
var $editFunctions = array(); ///< @var array of ["$type|$type2" => "$function/$function2"] functions used in editing, [0] - edit and insert, [1] - edit only
|
||||
var $unsigned = array(); ///< @var array number variants
|
||||
var $operators = array(); ///< @var array operators used in select
|
||||
var $functions = array(); ///< @var array functions used in select
|
||||
var $grouping = array(); ///< @var array grouping functions used in select
|
||||
var $onActions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()
|
||||
var $inout = "IN|OUT|INOUT";
|
||||
var $enumLength = "'(?:''|[^'\\\\]|\\\\.)*'";
|
||||
var $generated = array();
|
||||
|
||||
/** Create object for performing database operations
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
*/
|
||||
function __construct($connection) {
|
||||
$this->_conn = $connection;
|
||||
}
|
||||
|
||||
/** Get all types
|
||||
* @return array [$type => $maximum_unsigned_length, ...]
|
||||
*/
|
||||
function types() {
|
||||
return call_user_func_array('array_merge', array_values($this->types));
|
||||
}
|
||||
|
||||
/** Get structured types
|
||||
* @return array [$description => [$type, ...], ...]
|
||||
*/
|
||||
function structuredTypes() {
|
||||
return array_map('array_keys', $this->types);
|
||||
}
|
||||
|
||||
/** Select data from table
|
||||
* @param string
|
||||
* @param array result of $adminer->selectColumnsProcess()[0]
|
||||
@@ -39,15 +68,15 @@ function get_driver($id) {
|
||||
* @param int result of $adminer->selectLimitProcess()
|
||||
* @param int index of page starting at zero
|
||||
* @param bool whether to print the query
|
||||
* @return Min_Result
|
||||
* @return Result
|
||||
*/
|
||||
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
|
||||
global $adminer, $jush;
|
||||
global $adminer;
|
||||
$is_group = (count($group) < count($select));
|
||||
$query = $adminer->selectQueryBuild($select, $where, $group, $order, $limit, $page);
|
||||
if (!$query) {
|
||||
$query = "SELECT" . limit(
|
||||
($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table),
|
||||
($_GET["page"] != "last" && $limit != "" && $group && $is_group && JUSH == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table),
|
||||
($where ? "\nWHERE " . implode(" AND ", $where) : "") . ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""),
|
||||
($limit != "" ? +$limit : null),
|
||||
($page ? $limit * $page : 0),
|
||||
@@ -108,7 +137,7 @@ function get_driver($id) {
|
||||
* @param array of arrays with escaped columns in keys and quoted data in values
|
||||
* @return bool
|
||||
*/
|
||||
/*abstract*/ function insertUpdate($table, $rows, $primary) {
|
||||
function insertUpdate($table, $rows, $primary) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -188,9 +217,30 @@ function get_driver($id) {
|
||||
|
||||
/** Get help link for table
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return string relative URL or null
|
||||
*/
|
||||
function tableHelp($name) {
|
||||
function tableHelp($name, $is_view = false) {
|
||||
}
|
||||
|
||||
/** Check if C-style escapes are supported
|
||||
* @return bool
|
||||
*/
|
||||
function hasCStyleEscapes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get defined check constraints
|
||||
* @param string
|
||||
* @return array [$name => $clause]
|
||||
*/
|
||||
function checkConstraints($table) {
|
||||
// MariaDB contains CHECK_CONSTRAINTS.TABLE_NAME, MySQL and PostrgreSQL not
|
||||
return get_key_vals("SELECT c.CONSTRAINT_NAME, CHECK_CLAUSE
|
||||
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS c
|
||||
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS t ON c.CONSTRAINT_SCHEMA = t.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = t.CONSTRAINT_NAME
|
||||
WHERE c.CONSTRAINT_SCHEMA = " . q($_GET["ns"] != "" ? $_GET["ns"] : DB) . "
|
||||
AND t.TABLE_NAME = " . q($table) . "
|
||||
AND CHECK_CLAUSE NOT LIKE '% IS NOT NULL'"); // ignore default IS NOT NULL checks in PostrgreSQL
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,16 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// This file is not used in Adminer Editor.
|
||||
|
||||
/** Print select result
|
||||
* @param Min_Result
|
||||
* @param Min_DB connection to examine indexes
|
||||
* @param Result
|
||||
* @param Db connection to examine indexes
|
||||
* @param array
|
||||
* @param int
|
||||
* @return array $orgtables
|
||||
*/
|
||||
function select($result, $connection2 = null, $orgtables = array(), $limit = 0) {
|
||||
global $jush;
|
||||
$links = array(); // colno => orgtable - create links from these columns
|
||||
$indexes = array(); // orgtable => array(column => colno) - primary keys
|
||||
$columns = array(); // orgtable => array(column => ) - not selected columns in primary key
|
||||
@@ -27,7 +28,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
|
||||
$orgtable = $field->orgtable;
|
||||
$orgname = $field->orgname;
|
||||
$return[$field->table] = $orgtable;
|
||||
if ($orgtables && $jush == "sql") { // MySQL EXPLAIN
|
||||
if ($orgtables && JUSH == "sql") { // MySQL EXPLAIN
|
||||
$links[$j] = ($name == "table" ? "table=" : ($name == "possible_keys" ? "indexes=" : null));
|
||||
} elseif ($orgtable != "") {
|
||||
if (!isset($indexes[$orgtable])) {
|
||||
@@ -64,7 +65,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
|
||||
foreach ($row as $key => $val) {
|
||||
$link = "";
|
||||
if (isset($links[$key]) && !$columns[$links[$key]]) {
|
||||
if ($orgtables && $jush == "sql") { // MySQL EXPLAIN
|
||||
if ($orgtables && JUSH == "sql") { // MySQL EXPLAIN
|
||||
$table = $row[array_search("table=", $links)];
|
||||
$link = ME . $links[$key] . urlencode($orgtables[$table] != "" ? $orgtables[$table] : $table);
|
||||
} else {
|
||||
@@ -151,8 +152,7 @@ function set_adminer_settings($settings) {
|
||||
* @return null
|
||||
*/
|
||||
function textarea($name, $value, $rows = 10, $cols = 80) {
|
||||
global $jush;
|
||||
echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-$jush' spellcheck='false' wrap='off'>";
|
||||
echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-" . JUSH . "' spellcheck='false' wrap='off'>";
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $val) { // not implode() to save memory
|
||||
echo h($val[0]) . "\n\n\n"; // $val == array($query, $time, $elapsed)
|
||||
@@ -207,12 +207,13 @@ function json_row($key, $val = null) {
|
||||
* @return null
|
||||
*/
|
||||
function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_types = array()) {
|
||||
global $structured_types, $types, $unsigned, $on_actions;
|
||||
global $driver;
|
||||
$type = $field["type"];
|
||||
?><td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
|
||||
if ($type && !isset($types[$type]) && !isset($foreign_keys[$type]) && !in_array($type, $extra_types)) {
|
||||
if ($type && !array_key_exists($type, $driver->types()) && !isset($foreign_keys[$type]) && !in_array($type, $extra_types)) {
|
||||
$extra_types[] = $type;
|
||||
}
|
||||
$structured_types = $driver->structuredTypes();
|
||||
if ($foreign_keys) {
|
||||
$structured_types[lang('Foreign keys')] = $foreign_keys;
|
||||
}
|
||||
@@ -224,12 +225,12 @@ function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_ty
|
||||
<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?>
|
||||
aria-labelledby="label-length"><td class="options"><?php
|
||||
echo ($collations ? "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>' : '');
|
||||
echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
|
||||
echo ($driver->unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($driver->unsigned, $field["unsigned"]) . '</select>' : '');
|
||||
echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>'
|
||||
. optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? "CURRENT_TIMESTAMP" : $field["on_update"]))
|
||||
. '</select>' : ''
|
||||
);
|
||||
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $on_actions), $field["on_delete"]) . "</select> " : " "); // space for IE
|
||||
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $driver->onActions), $field["on_delete"]) . "</select> " : " "); // space for IE
|
||||
}
|
||||
|
||||
/** Get partition info
|
||||
@@ -253,7 +254,8 @@ function get_partitions_info($table) {
|
||||
* @return string
|
||||
*/
|
||||
function process_length($length) {
|
||||
global $enum_length;
|
||||
global $driver;
|
||||
$enum_length = $driver->enumLength;
|
||||
return (preg_match("~^\\s*\\(?\\s*$enum_length(?:\\s*,\\s*$enum_length)*+\\s*\\)?\\s*\$~", $length) && preg_match_all("~$enum_length~", $length, $matches)
|
||||
? "(" . implode(",", $matches[0]) . ")"
|
||||
: preg_replace('~^[0-9].*~', '(\0)', preg_replace('~[^-0-9,+()[\]]~', '', $length))
|
||||
@@ -266,11 +268,11 @@ function process_length($length) {
|
||||
* @return string
|
||||
*/
|
||||
function process_type($field, $collate = "COLLATE") {
|
||||
global $unsigned;
|
||||
global $driver;
|
||||
return " $field[type]"
|
||||
. process_length($field["length"])
|
||||
. (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], $unsigned) ? " $field[unsigned]" : "")
|
||||
. (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . q($field["collation"]) : "")
|
||||
. (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], $driver->unsigned) ? " $field[unsigned]" : "")
|
||||
. (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . (JUSH == "mssql" ? $field["collation"] : q($field["collation"])) : "")
|
||||
;
|
||||
}
|
||||
|
||||
@@ -300,12 +302,16 @@ function process_field($field, $type_field) {
|
||||
* @return string
|
||||
*/
|
||||
function default_value($field) {
|
||||
global $jush;
|
||||
global $driver;
|
||||
$default = $field["default"];
|
||||
return ($default === null ? "" : " DEFAULT " .
|
||||
(!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default))
|
||||
? q($default) : str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", ($jush == "sqlite" ? "($default)" : $default)))
|
||||
);
|
||||
$generated = $field["generated"];
|
||||
return ($default === null ? "" : (in_array($generated, $driver->generated)
|
||||
? (JUSH == "mssql" ? " AS ($default)" . ($generated == "VIRTUAL" ? "" : " $generated") . "" : " GENERATED ALWAYS AS ($default) $generated")
|
||||
: " DEFAULT " . (!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default))
|
||||
? q($default)
|
||||
: str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", (JUSH == "sqlite" ? "($default)" : $default))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/** Get type class to use in CSS
|
||||
@@ -313,12 +319,14 @@ function default_value($field) {
|
||||
* @return string class=''
|
||||
*/
|
||||
function type_class($type) {
|
||||
foreach (array(
|
||||
'char' => 'text',
|
||||
'date' => 'time|year',
|
||||
'binary' => 'blob',
|
||||
'enum' => 'set',
|
||||
) as $key => $val) {
|
||||
foreach (
|
||||
array(
|
||||
'char' => 'text',
|
||||
'date' => 'time|year',
|
||||
'binary' => 'blob',
|
||||
'enum' => 'set',
|
||||
) as $key => $val
|
||||
) {
|
||||
if (preg_match("~$key|$val~", $type)) {
|
||||
return " class='$key'";
|
||||
}
|
||||
@@ -333,13 +341,13 @@ function type_class($type) {
|
||||
* @return null
|
||||
*/
|
||||
function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = array()) {
|
||||
global $inout;
|
||||
global $driver;
|
||||
$fields = array_values($fields);
|
||||
$default_class = (($_POST ? $_POST["defaults"] : adminer_setting("defaults")) ? "" : " class='hidden'");
|
||||
$comment_class = (($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : " class='hidden'");
|
||||
?>
|
||||
<thead><tr>
|
||||
<?php if ($type == "PROCEDURE") { ?><td><?php } ?>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" : ""); ?>
|
||||
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
|
||||
<td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?>
|
||||
<td id="label-length"><?php echo lang('Length'); ?>
|
||||
@@ -351,7 +359,7 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
|
||||
'mariadb' => "auto_increment/",
|
||||
'sqlite' => "autoinc.html",
|
||||
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
|
||||
'mssql' => "ms186775.aspx",
|
||||
'mssql' => "t-sql/statements/create-table-transact-sql-identity-property",
|
||||
)); ?>
|
||||
<td id="label-default"<?php echo $default_class; ?>><?php echo lang('Default value'); ?>
|
||||
<?php echo (support("comment") ? "<td id='label-comment'$comment_class>" . lang('Comment') : ""); ?>
|
||||
@@ -367,13 +375,22 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
|
||||
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])) && (support("drop_col") || $orig == "");
|
||||
?>
|
||||
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $inout), $field["inout"]) : ""); ?>
|
||||
<th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" data-maxlength="64" autocapitalize="off" aria-labelledby="label-name"><?php } ?>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $driver->inout), $field["inout"]) : "") . "<th>"; ?>
|
||||
<?php if ($display) { ?>
|
||||
<input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" data-maxlength="64" autocapitalize="off" aria-labelledby="label-name">
|
||||
<?php } ?>
|
||||
<input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($orig); ?>"><?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?>
|
||||
<?php if ($type == "TABLE") { ?>
|
||||
<?php
|
||||
if ($type == "TABLE") {
|
||||
?>
|
||||
<td><?php echo checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); ?>
|
||||
<td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?> aria-labelledby="label-ai"></label><td<?php echo $default_class; ?>><?php
|
||||
echo checkbox("fields[$i][has_default]", 1, $field["has_default"], "", "", "", "label-default"); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" aria-labelledby="label-default"><?php
|
||||
<td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php echo ($field["auto_increment"] ? " checked" : ""); ?> aria-labelledby="label-ai"></label><td<?php echo $default_class; ?>><?php
|
||||
echo ($driver->generated
|
||||
? "<select name='fields[$i][generated]'>" . optionlist(array_merge(array("", "DEFAULT"), $driver->generated), $field["generated"]) . "</select> "
|
||||
: checkbox("fields[$i][generated]", 1, $field["generated"], "", "", "", "label-default")
|
||||
);
|
||||
?>
|
||||
<input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" aria-labelledby="label-default"><?php
|
||||
echo (support("comment") ? "<td$comment_class><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' data-maxlength='" . (min_version(5.5) ? 1024 : 255) . "' aria-labelledby='label-comment'>" : "");
|
||||
}
|
||||
echo "<td>";
|
||||
@@ -496,11 +513,10 @@ function drop_create($drop, $create, $drop_created, $test, $drop_test, $location
|
||||
* @return string
|
||||
*/
|
||||
function create_trigger($on, $row) {
|
||||
global $jush;
|
||||
$timing_event = " $row[Timing] $row[Event]" . (preg_match('~ OF~', $row["Event"]) ? " $row[Of]" : ""); // SQL injection
|
||||
return "CREATE TRIGGER "
|
||||
. idf_escape($row["Trigger"])
|
||||
. ($jush == "mssql" ? $on . $timing_event : $timing_event . $on)
|
||||
. (JUSH == "mssql" ? $on . $timing_event : $timing_event . $on)
|
||||
. rtrim(" $row[Type]\n$row[Statement]", ";")
|
||||
. ";"
|
||||
;
|
||||
@@ -512,13 +528,13 @@ function create_trigger($on, $row) {
|
||||
* @return string
|
||||
*/
|
||||
function create_routine($routine, $row) {
|
||||
global $inout, $jush;
|
||||
global $driver;
|
||||
$set = array();
|
||||
$fields = (array) $row["fields"];
|
||||
ksort($fields); // enforce fields order
|
||||
foreach ($fields as $field) {
|
||||
if ($field["field"] != "") {
|
||||
$set[] = (preg_match("~^($inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET");
|
||||
$set[] = (preg_match("~^($driver->inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET");
|
||||
}
|
||||
}
|
||||
$definition = rtrim($row["definition"], ";");
|
||||
@@ -527,24 +543,10 @@ function create_routine($routine, $row) {
|
||||
. " (" . implode(", ", $set) . ")"
|
||||
. ($routine == "FUNCTION" ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
|
||||
. ($row["language"] ? " LANGUAGE $row[language]" : "")
|
||||
. ($jush == "pgsql" ? " AS " . q($definition) : "\n$definition;")
|
||||
. (JUSH == "pgsql" ? " AS " . q($definition) : "\n$definition;")
|
||||
;
|
||||
}
|
||||
|
||||
/** Get defined check constraints
|
||||
* @param string
|
||||
* @return array [$name => $clause]
|
||||
*/
|
||||
function check_constraints($table) {
|
||||
// MariaDB contains CHECK_CONSTRAINTS.TABLE_NAME, MySQL and PostrgreSQL not
|
||||
return get_key_vals("SELECT c.CONSTRAINT_NAME, CHECK_CLAUSE
|
||||
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS c
|
||||
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS t ON c.CONSTRAINT_SCHEMA = t.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = t.CONSTRAINT_NAME
|
||||
WHERE c.CONSTRAINT_SCHEMA = " . q($_GET["ns"] != "" ? $_GET["ns"] : DB) . "
|
||||
AND t.TABLE_NAME = " . q($table) . "
|
||||
AND CHECK_CLAUSE NOT LIKE '% IS NOT NULL'"); // ignore default IS NOT NULL checks in PostrgreSQL
|
||||
}
|
||||
|
||||
/** Remove current user definer from SQL command
|
||||
* @param string
|
||||
* @return string
|
||||
@@ -558,16 +560,16 @@ function remove_definer($query) {
|
||||
* @return string
|
||||
*/
|
||||
function format_foreign_key($foreign_key) {
|
||||
global $on_actions;
|
||||
global $driver;
|
||||
$db = $foreign_key["db"];
|
||||
$ns = $foreign_key["ns"];
|
||||
return " FOREIGN KEY (" . implode(", ", array_map('idf_escape', $foreign_key["source"])) . ") REFERENCES "
|
||||
return " FOREIGN KEY (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["source"])) . ") REFERENCES "
|
||||
. ($db != "" && $db != $_GET["db"] ? idf_escape($db) . "." : "")
|
||||
. ($ns != "" && $ns != $_GET["ns"] ? idf_escape($ns) . "." : "")
|
||||
. table($foreign_key["table"])
|
||||
. " (" . implode(", ", array_map('idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions
|
||||
. (preg_match("~^($on_actions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "")
|
||||
. (preg_match("~^($on_actions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "")
|
||||
. idf_escape($foreign_key["table"])
|
||||
. " (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions
|
||||
. (preg_match("~^($driver->onActions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "")
|
||||
. (preg_match("~^($driver->onActions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "")
|
||||
;
|
||||
}
|
||||
|
||||
@@ -596,34 +598,37 @@ function tar_file($filename, $tmp_file) {
|
||||
function ini_bytes($ini) {
|
||||
$val = ini_get($ini);
|
||||
switch (strtolower(substr($val, -1))) {
|
||||
case 'g': $val = (int)$val * 1024; // no break
|
||||
case 'm': $val = (int)$val * 1024; // no break
|
||||
case 'k': $val = (int)$val * 1024;
|
||||
case 'g':
|
||||
$val = (int) $val * 1024; // no break
|
||||
case 'm':
|
||||
$val = (int) $val * 1024; // no break
|
||||
case 'k':
|
||||
$val = (int) $val * 1024;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
/** Create link to database documentation
|
||||
* @param array $jush => $path
|
||||
* @param array JUSH => $path
|
||||
* @param string HTML code
|
||||
* @return string HTML code
|
||||
*/
|
||||
function doc_link($paths, $text = "<sup>?</sup>") {
|
||||
global $jush, $connection;
|
||||
global $connection;
|
||||
$server_info = $connection->server_info;
|
||||
$version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits
|
||||
$urls = array(
|
||||
'sql' => "https://dev.mysql.com/doc/refman/$version/en/",
|
||||
'sqlite' => "https://www.sqlite.org/",
|
||||
'pgsql' => "https://www.postgresql.org/docs/$version/",
|
||||
'mssql' => "https://msdn.microsoft.com/library/",
|
||||
'mssql' => "https://learn.microsoft.com/en-us/sql/",
|
||||
'oracle' => "https://www.oracle.com/pls/topic/lookup?ctx=db" . preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s', '\1\2', $server_info) . "&id=",
|
||||
);
|
||||
if (preg_match('~MariaDB~', $server_info)) {
|
||||
$urls['sql'] = "https://mariadb.com/kb/en/";
|
||||
$paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql']));
|
||||
}
|
||||
return ($paths[$jush] ? "<a href='" . h($urls[$jush] . $paths[$jush]) . "'" . target_blank() . ">$text</a>" : "");
|
||||
return ($paths[JUSH] ? "<a href='" . h($urls[JUSH] . $paths[JUSH] . (JUSH == 'mssql' ? "?view=sql-server-ver$version" : "")) . "'" . target_blank() . ">$text</a>" : "");
|
||||
}
|
||||
|
||||
/** Wrap gzencode() for usage in ob_start()
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
function adminer_errors($errno, $errstr) {
|
||||
return !!preg_match('~^(Trying to access array offset on( value of type)? null|Undefined (array key|property))~', $errstr);
|
||||
}
|
||||
namespace Adminer;
|
||||
|
||||
error_reporting(6135); // errors and warnings
|
||||
set_error_handler('adminer_errors', E_WARNING);
|
||||
set_error_handler(function ($errno, $errstr) {
|
||||
return !!preg_match('~^(Trying to access array offset on( value of type)? null|Undefined (array key|property))~', $errstr);
|
||||
}, E_WARNING);
|
||||
|
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// This file is used both in Adminer and Adminer Editor.
|
||||
|
||||
/** Get database connection
|
||||
* @return Min_DB
|
||||
* @return Db
|
||||
*/
|
||||
function connection() {
|
||||
// can be used in customization, $connection is minified
|
||||
@@ -96,7 +98,7 @@ function bracket_escape($idf, $back = false) {
|
||||
/** Check if connection has at least the given version
|
||||
* @param string required version
|
||||
* @param string required MariaDB version
|
||||
* @param Min_DB defaults to $connection
|
||||
* @param Db defaults to $connection
|
||||
* @return bool
|
||||
*/
|
||||
function min_version($version, $maria_db = "", $connection2 = null) {
|
||||
@@ -113,7 +115,7 @@ function min_version($version, $maria_db = "", $connection2 = null) {
|
||||
}
|
||||
|
||||
/** Get connection charset
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
* @return string
|
||||
*/
|
||||
function charset($connection) {
|
||||
@@ -354,7 +356,7 @@ function get_vals($query, $column = 0) {
|
||||
|
||||
/** Get keys from first column and values from second
|
||||
* @param string
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
* @param bool
|
||||
* @return array
|
||||
*/
|
||||
@@ -379,7 +381,7 @@ function get_key_vals($query, $connection2 = null, $set_keys = true) {
|
||||
|
||||
/** Get all rows of result
|
||||
* @param string
|
||||
* @param Min_DB
|
||||
* @param Db
|
||||
* @param string
|
||||
* @return array of associative arrays
|
||||
*/
|
||||
@@ -392,7 +394,7 @@ function get_rows($query, $connection2 = null, $error = "<p class='error'>") {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[] = $row;
|
||||
}
|
||||
} elseif (!$result && !is_object($connection2) && $error && (defined("PAGE_HEADER") || $error == "-- ")) {
|
||||
} elseif (!$result && !is_object($connection2) && $error && (defined('Adminer\PAGE_HEADER') || $error == "-- ")) {
|
||||
echo $error . error() . "\n";
|
||||
}
|
||||
return $return;
|
||||
@@ -435,19 +437,19 @@ function escape_key($key) {
|
||||
* @return string
|
||||
*/
|
||||
function where($where, $fields = array()) {
|
||||
global $connection, $jush;
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ((array) $where["where"] as $key => $val) {
|
||||
$key = bracket_escape($key, 1); // 1 - back
|
||||
$column = escape_key($key);
|
||||
$return[] = $column
|
||||
. ($jush == "sql" && $fields[$key]["type"] == "json" ? " = CAST(" . q($val) . " AS JSON)"
|
||||
: ($jush == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
|
||||
: ($jush == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text
|
||||
. (JUSH == "sql" && $fields[$key]["type"] == "json" ? " = CAST(" . q($val) . " AS JSON)"
|
||||
: (JUSH == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
|
||||
: (JUSH == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text
|
||||
: " = " . unconvert_field($fields[$key], q($val))
|
||||
)))
|
||||
; //! enum and set
|
||||
if ($jush == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
|
||||
if (JUSH == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
|
||||
$return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
|
||||
}
|
||||
}
|
||||
@@ -502,17 +504,19 @@ function convert_fields($columns, $fields, $select = array()) {
|
||||
/** Set cookie valid on current path
|
||||
* @param string
|
||||
* @param string
|
||||
* @param int number of seconds, 0 for session cookie
|
||||
* @param int number of seconds, 0 for session cookie, 2592000 - 30 days
|
||||
* @return bool
|
||||
*/
|
||||
function cookie($name, $value, $lifetime = 2592000) { // 2592000 - 30 days
|
||||
function cookie($name, $value, $lifetime = 2592000) {
|
||||
global $HTTPS;
|
||||
return header("Set-Cookie: $name=" . urlencode($value)
|
||||
. ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
|
||||
. "; path=" . preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"])
|
||||
. ($HTTPS ? "; secure" : "")
|
||||
. "; HttpOnly; SameSite=lax",
|
||||
false);
|
||||
return header(
|
||||
"Set-Cookie: $name=" . urlencode($value)
|
||||
. ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
|
||||
. "; path=" . preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"])
|
||||
. ($HTTPS ? "; secure" : "")
|
||||
. "; HttpOnly; SameSite=lax",
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/** Restart stopped session
|
||||
@@ -633,7 +637,7 @@ function query_redirect($query, $location, $message, $redirect = true, $execute
|
||||
|
||||
/** Execute and remember query
|
||||
* @param string or null to return remembered queries, end with ';' to use DELIMITER
|
||||
* @return Min_Result or array($queries, $time) if $query = null
|
||||
* @return Result or [$queries, $time] if $query = null
|
||||
*/
|
||||
function queries($query) {
|
||||
global $connection;
|
||||
@@ -731,7 +735,8 @@ function get_file($key, $decompress = false) {
|
||||
}
|
||||
$name = $file["name"][$key];
|
||||
$tmp_name = $file["tmp_name"][$key];
|
||||
$content = file_get_contents($decompress && preg_match('~\.gz$~', $name)
|
||||
$content = file_get_contents(
|
||||
$decompress && preg_match('~\.gz$~', $name)
|
||||
? "compress.zlib://$tmp_name"
|
||||
: $tmp_name
|
||||
); //! may not be reachable because of open_basedir
|
||||
@@ -806,7 +811,7 @@ function format_number($val) {
|
||||
*/
|
||||
function friendly_url($val) {
|
||||
// used for blobs and export
|
||||
return preg_replace('~[^a-z0-9_]~i', '-', $val);
|
||||
return preg_replace('~\W~i', '-', $val);
|
||||
}
|
||||
|
||||
/** Print hidden fields
|
||||
@@ -846,12 +851,12 @@ function hidden_fields_get() {
|
||||
*/
|
||||
function table_status1($table, $fast = false) {
|
||||
$return = table_status($table, $fast);
|
||||
return ($return ? $return : array("Name" => $table));
|
||||
return ($return ?: array("Name" => $table));
|
||||
}
|
||||
|
||||
/** Find out foreign keys for each column
|
||||
* @param string
|
||||
* @return array [$col => array()]
|
||||
* @return array [$col => []]
|
||||
*/
|
||||
function column_foreign_keys($table) {
|
||||
global $adminer;
|
||||
@@ -873,13 +878,13 @@ function column_foreign_keys($table) {
|
||||
* @return null
|
||||
*/
|
||||
function enum_input($type, $attrs, $field, $value, $empty = null) {
|
||||
global $adminer, $jush;
|
||||
global $adminer;
|
||||
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
|
||||
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === 0) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
|
||||
foreach ($matches[1] as $i => $val) {
|
||||
$val = stripcslashes(str_replace("''", "'", $val));
|
||||
$checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
|
||||
$return .= " <label><input type='$type'$attrs value='" . ($jush == "sql" ? $i+1 : h($val)) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
|
||||
$return .= " <label><input type='$type'$attrs value='" . (JUSH == "sql" ? $i+1 : h($val)) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -891,7 +896,7 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
|
||||
* @return null
|
||||
*/
|
||||
function input($field, $value, $function) {
|
||||
global $types, $structured_types, $adminer, $jush;
|
||||
global $driver, $adminer;
|
||||
$name = h(bracket_escape($field["field"]));
|
||||
echo "<td class='function'>";
|
||||
if (is_array($value) && !$function) {
|
||||
@@ -902,18 +907,20 @@ function input($field, $value, $function) {
|
||||
$value = call_user_func_array('json_encode', $args); //! requires PHP 5.2
|
||||
$function = "json";
|
||||
}
|
||||
$reset = ($jush == "mssql" && $field["auto_increment"]);
|
||||
$reset = (JUSH == "mssql" && $field["auto_increment"]);
|
||||
if ($reset && !$_POST["save"]) {
|
||||
$function = null;
|
||||
}
|
||||
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
|
||||
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
|
||||
$attrs = " name='fields[$name]'$disabled";
|
||||
if ($jush == "pgsql" && in_array($field["type"], (array) $structured_types[lang('User types')])) {
|
||||
$enums = get_vals("SELECT enumlabel FROM pg_enum WHERE enumtypid = " . $types[$field["type"]] . " ORDER BY enumsortorder");
|
||||
$types = $driver->types();
|
||||
$structured_types = $driver->structuredTypes();
|
||||
if (in_array($field["type"], (array) $structured_types[lang('User types')])) {
|
||||
$enums = type_values($types[$field["type"]]);
|
||||
if ($enums) {
|
||||
$field["type"] = "enum";
|
||||
$field["length"] = "'" . implode("','", array_map('addslashes', $enums)) . "'";
|
||||
$field["length"] = $enums;
|
||||
}
|
||||
}
|
||||
if ($field["type"] == "enum") {
|
||||
@@ -942,7 +949,7 @@ function input($field, $value, $function) {
|
||||
} elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
|
||||
echo "<input type='file' name='fields-$name'>";
|
||||
} elseif (($text = preg_match('~text|lob|memo~i', $field["type"])) || preg_match("~\n~", $value)) {
|
||||
if ($text && $jush != "sqlite") {
|
||||
if ($text && JUSH != "sqlite") {
|
||||
$attrs .= " cols='50' rows='12'";
|
||||
} else {
|
||||
$rows = min(12, substr_count($value, "\n") + 1);
|
||||
@@ -957,7 +964,7 @@ function input($field, $value, $function) {
|
||||
? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0))
|
||||
: ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)
|
||||
);
|
||||
if ($jush == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
|
||||
if (JUSH == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
|
||||
$maxlength += 7; // microtime
|
||||
}
|
||||
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
|
||||
@@ -1279,9 +1286,8 @@ function is_shortable($field) {
|
||||
* @return string
|
||||
*/
|
||||
function count_rows($table, $where, $is_group, $group) {
|
||||
global $jush;
|
||||
$query = " FROM " . table($table) . ($where ? " WHERE " . implode(" AND ", $where) : "");
|
||||
return ($is_group && ($jush == "sql" || count($group) == 1)
|
||||
return ($is_group && (JUSH == "sql" || count($group) == 1)
|
||||
? "SELECT COUNT(DISTINCT " . implode(", ", $group) . ")$query"
|
||||
: "SELECT COUNT(*)" . ($is_group ? " FROM (SELECT 1$query GROUP BY " . implode(", ", $group) . ") x" : $query)
|
||||
);
|
||||
@@ -1311,7 +1317,7 @@ var timeout = setTimeout(function () {
|
||||
}
|
||||
ob_flush();
|
||||
flush();
|
||||
$return = @get_key_vals(($slow_query ? $slow_query : $query), $connection2, false); // @ - may be killed
|
||||
$return = @get_key_vals(($slow_query ?: $query), $connection2, false); // @ - may be killed
|
||||
if ($connection2) {
|
||||
echo script("clearTimeout(timeout);");
|
||||
ob_flush();
|
||||
@@ -1391,7 +1397,7 @@ function on_help($command, $side = 0) {
|
||||
* @return null
|
||||
*/
|
||||
function edit_form($table, $fields, $row, $update) {
|
||||
global $adminer, $jush, $token, $error;
|
||||
global $adminer, $token, $error;
|
||||
$table_name = $adminer->tableName(table_status1($table, true));
|
||||
page_header(
|
||||
($update ? lang('Edit') : lang('Insert')),
|
||||
@@ -1411,6 +1417,7 @@ function edit_form($table, $fields, $row, $update) {
|
||||
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
|
||||
} else {
|
||||
echo "<table class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
|
||||
$first = 0;
|
||||
foreach ($fields as $name => $field) {
|
||||
echo "<tr><th>" . $adminer->fieldName($field);
|
||||
$default = $_GET["set"][bracket_escape($name)];
|
||||
@@ -1421,7 +1428,7 @@ function edit_form($table, $fields, $row, $update) {
|
||||
}
|
||||
}
|
||||
$value = ($row !== null
|
||||
? ($row[$name] != "" && $jush == "sql" && preg_match("~enum|set~", $field["type"])
|
||||
? ($row[$name] != "" && JUSH == "sql" && preg_match("~enum|set~", $field["type"])
|
||||
? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name])
|
||||
: (is_bool($row[$name]) ? +$row[$name] : $row[$name])
|
||||
)
|
||||
@@ -1451,6 +1458,9 @@ function edit_form($table, $fields, $row, $update) {
|
||||
$value = "";
|
||||
$function = "uuid";
|
||||
}
|
||||
if ($field["auto_increment"] || $function == "now" || $function == "uuid") {
|
||||
$first++;
|
||||
}
|
||||
input($field, $value, $function);
|
||||
echo "\n";
|
||||
}
|
||||
@@ -1477,7 +1487,7 @@ function edit_form($table, $fields, $row, $update) {
|
||||
}
|
||||
}
|
||||
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n"
|
||||
: ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[1].firstChild);"))
|
||||
: ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[2*$first+1].firstChild);"))
|
||||
);
|
||||
if (isset($_GET["select"])) {
|
||||
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// not used in a single language version
|
||||
|
||||
$langs = array(
|
||||
@@ -63,7 +65,7 @@ function get_lang() {
|
||||
*/
|
||||
function lang($idf, $number = null) {
|
||||
global $LANG, $translations;
|
||||
$translation = ($translations[$idf] ? $translations[$idf] : $idf);
|
||||
$translation = ($translations[$idf] ?: $idf);
|
||||
if (is_array($translation)) {
|
||||
$pos = ($number == 1 ? 0
|
||||
: ($LANG == 'cs' || $LANG == 'sk' ? ($number && $number < 5 ? 1 : 2) // different forms for 1, 2-4, other
|
||||
|
@@ -1,29 +1,23 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// PDO can be used in several database drivers
|
||||
if (extension_loaded('pdo')) {
|
||||
/*abstract*/ class Min_PDO {
|
||||
abstract class PdoDb {
|
||||
var $_result, $server_info, $affected_rows, $errno, $error, $pdo;
|
||||
|
||||
function __construct() {
|
||||
global $adminer;
|
||||
$pos = array_search("SQL", $adminer->operators);
|
||||
if ($pos !== false) {
|
||||
unset($adminer->operators[$pos]);
|
||||
}
|
||||
}
|
||||
|
||||
function dsn($dsn, $username, $password, $options = array()) {
|
||||
$options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
|
||||
$options[PDO::ATTR_STATEMENT_CLASS] = array('Min_PDOStatement');
|
||||
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
|
||||
$options[\PDO::ATTR_STATEMENT_CLASS] = array('Adminer\PdoDbStatement');
|
||||
try {
|
||||
$this->pdo = new PDO($dsn, $username, $password, $options);
|
||||
$this->pdo = new \PDO($dsn, $username, $password, $options);
|
||||
} catch (Exception $ex) {
|
||||
auth_error(h($ex->getMessage()));
|
||||
}
|
||||
$this->server_info = @$this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$this->server_info = @$this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
|
||||
}
|
||||
|
||||
/*abstract function select_db($database);*/
|
||||
abstract function select_db($database);
|
||||
|
||||
function quote($string) {
|
||||
return $this->pdo->quote($string);
|
||||
@@ -80,15 +74,15 @@ if (extension_loaded('pdo')) {
|
||||
}
|
||||
}
|
||||
|
||||
class Min_PDOStatement extends PDOStatement {
|
||||
class PdoDbStatement extends \PDOStatement {
|
||||
var $_offset = 0, $num_rows;
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->fetch(PDO::FETCH_ASSOC);
|
||||
return $this->fetch(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->fetch(PDO::FETCH_NUM);
|
||||
return $this->fetch(\PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
@@ -98,5 +92,11 @@ if (extension_loaded('pdo')) {
|
||||
$row->charsetnr = (in_array("blob", (array) $row->flags) ? 63 : 0);
|
||||
return $row;
|
||||
}
|
||||
|
||||
function seek($offset) {
|
||||
for ($i=0; $i < $offset; $i++) {
|
||||
$this->fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
class TmpFile {
|
||||
var $handler;
|
||||
@@ -18,5 +19,4 @@ class TmpFile {
|
||||
fpassthru($this->handler);
|
||||
fclose($this->handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,2 +1,4 @@
|
||||
<?php
|
||||
$VERSION = "4.17.0";
|
||||
namespace Adminer;
|
||||
|
||||
$VERSION = "5.0.0";
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
/** PHP implementation of XXTEA encryption algorithm
|
||||
* @author Ma Bingyao <andot@ujn.edu.cn>
|
||||
* @link http://www.coolcode.cn/?action=show&id=128
|
||||
|
@@ -7,12 +7,11 @@
|
||||
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
|
||||
*/
|
||||
|
||||
namespace Adminer;
|
||||
|
||||
include "./include/bootstrap.inc.php";
|
||||
include "./include/tmpfile.inc.php";
|
||||
|
||||
$enum_length = "'(?:''|[^'\\\\]|\\\\.)*'";
|
||||
$inout = "IN|OUT|INOUT";
|
||||
|
||||
if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) {
|
||||
$_GET["edit"] = $_GET["select"];
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["indexes"];
|
||||
$index_types = array("PRIMARY", "UNIQUE", "INDEX");
|
||||
$table_status = table_status($TABLE, true);
|
||||
@@ -10,7 +12,7 @@ if (preg_match('~MyISAM|M?aria' . (min_version(5.7, '10.2.2') ? '|InnoDB' : '')
|
||||
}
|
||||
$indexes = indexes($TABLE);
|
||||
$primary = array();
|
||||
if ($jush == "mongo") { // doesn't support primary key
|
||||
if (JUSH == "mongo") { // doesn't support primary key
|
||||
$primary = $indexes["_id_"];
|
||||
unset($index_types[0]);
|
||||
unset($indexes["_id_"]);
|
||||
@@ -35,27 +37,28 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
$desc = $index["descs"][$key];
|
||||
$set[] = idf_escape($column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
|
||||
$columns[] = $column;
|
||||
$lengths[] = ($length ? $length : null);
|
||||
$lengths[] = ($length ?: null);
|
||||
$descs[] = $desc;
|
||||
}
|
||||
}
|
||||
|
||||
if ($columns) {
|
||||
$existing = $indexes[$name];
|
||||
if ($existing) {
|
||||
ksort($existing["columns"]);
|
||||
ksort($existing["lengths"]);
|
||||
ksort($existing["descs"]);
|
||||
if ($index["type"] == $existing["type"]
|
||||
&& array_values($existing["columns"]) === $columns
|
||||
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
|
||||
&& array_values($existing["descs"]) === $descs
|
||||
) {
|
||||
// skip existing index
|
||||
unset($indexes[$name]);
|
||||
continue;
|
||||
}
|
||||
$existing = $indexes[$name];
|
||||
if ($existing) {
|
||||
ksort($existing["columns"]);
|
||||
ksort($existing["lengths"]);
|
||||
ksort($existing["descs"]);
|
||||
if (
|
||||
$index["type"] == $existing["type"]
|
||||
&& array_values($existing["columns"]) === $columns
|
||||
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
|
||||
&& array_values($existing["descs"]) === $descs
|
||||
) {
|
||||
// skip existing index
|
||||
unset($indexes[$name]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($columns) {
|
||||
$alter[] = array($index["type"], $name, $set);
|
||||
}
|
||||
}
|
||||
@@ -93,7 +96,7 @@ if (!$row) {
|
||||
$indexes[] = array("columns" => array(1 => ""));
|
||||
$row["indexes"] = $indexes;
|
||||
}
|
||||
$lengths = ($jush == "sql" || $jush == "mssql");
|
||||
$lengths = (JUSH == "sql" || JUSH == "mssql");
|
||||
$show_options = ($_POST ? $_POST["options"] : adminer_setting("index_options"));
|
||||
?>
|
||||
|
||||
@@ -133,7 +136,7 @@ foreach ($row["indexes"] as $index) {
|
||||
" name='indexes[$j][columns][$i]' title='" . lang('Column') . "'",
|
||||
($fields ? array_combine($fields, $fields) : $fields),
|
||||
$column,
|
||||
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape($jush == "sql" ? "" : $_GET["indexes"] . "_") . "')"
|
||||
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape(JUSH == "sql" ? "" : $_GET["indexes"] . "_") . "')"
|
||||
);
|
||||
echo "<span class='idxopts" . ($show_options ? "" : " hidden") . "'>";
|
||||
echo ($lengths ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : "");
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'تسجيل الدخول',
|
||||
'Logout successful.' => 'تم تسجيل الخروج بنجاح.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Система',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'লগইন',
|
||||
'Logout successful.' => 'সফলভাবে লগআউট হয়েছে।',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistem',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Inicia la sessió',
|
||||
'Logout successful.' => 'Desconnexió correcta.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Systém',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'System' => 'System',
|
||||
'Server' => 'Server',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Login',
|
||||
'Logout successful.' => 'Abmeldung erfolgreich.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Σύστημα',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Too many unsuccessful logins, try again in %d minute.', 'Too many unsuccessful logins, try again in %d minutes.'),
|
||||
'Query executed OK, %d row(s) affected.' => array('Query executed OK, %d row affected.', 'Query executed OK, %d rows affected.'),
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Login',
|
||||
'Logout successful.' => 'Sesión finalizada con éxito.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Logi sisse',
|
||||
'Logout successful.' => 'Väljalogimine õnnestus.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'سیستم',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Järjestelmä',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Authentification',
|
||||
'Logout successful.' => 'Au revoir !',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Conectar',
|
||||
'Logout successful.' => 'Pechouse a sesión con éxito.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'התחברות',
|
||||
'Logout successful.' => 'ההתחברות הצליחה',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Belépés',
|
||||
'Logout successful.' => 'Sikeres kilépés.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistem',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Autenticazione',
|
||||
'Logout successful.' => 'Uscita effettuata con successo.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'ログイン',
|
||||
'Logout successful.' => 'ログアウト',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'შესვლა',
|
||||
'Logout successful.' => 'გამოხვედით სისტემიდან.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'$1-$3-$5' => '$1-$3-$5',
|
||||
'%.3f s' => '%.3f 초',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistema',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Ieiet',
|
||||
'Logout successful.' => 'Jūs veiksmīgi izgājāt no sistēmas.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistem',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Aanmelden',
|
||||
'Logout successful.' => 'Successvol afgemeld.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'System' => 'System',
|
||||
'Server' => 'Server',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Rodzaj bazy',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Entrar',
|
||||
'Logout successful.' => 'Saída bem sucedida.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Entrar',
|
||||
'Logout successful.' => 'Sessão terminada com sucesso.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Intră',
|
||||
'Logout successful.' => 'Ați ieșit cu succes.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Войти',
|
||||
'Logout successful.' => 'Вы успешно покинули систему.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'Prihlásiť sa',
|
||||
'Logout successful.' => 'Odhlásenie prebehlo v poriadku.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistem',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Систем',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'System',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'நுழை',
|
||||
'Logout successful.' => 'வெற்றிகரமாய் வெளியேறியாயிற்று.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
'Login' => 'เข้าสู่ระบบ',
|
||||
'Logout successful.' => 'ออกจากระบบเรียบร้อยแล้ว.',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Sistem',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Система Бази Даних',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Hệ thống',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => 'Xx',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => '資料庫系統',
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$translations = array(
|
||||
// label for database system selection (MySQL, SQLite, ...)
|
||||
'System' => '系统',
|
||||
|
@@ -20,9 +20,7 @@ function adminer_object() {
|
||||
new AdminerDumpXml,
|
||||
new AdminerDumpAlter,
|
||||
//~ new AdminerSqlLog("past-" . rtrim(`git describe --tags --abbrev=0`) . ".sql"),
|
||||
//~ new AdminerEditCalendar(script_src("../externals/jquery-ui/jquery-1.4.4.js") . script_src("../externals/jquery-ui/ui/jquery.ui.core.js") . script_src("../externals/jquery-ui/ui/jquery.ui.widget.js") . script_src("../externals/jquery-ui/ui/jquery.ui.datepicker.js") . script_src("../externals/jquery-ui/ui/jquery.ui.mouse.js") . script_src("../externals/jquery-ui/ui/jquery.ui.slider.js") . script_src("../externals/jquery-timepicker/jquery-ui-timepicker-addon.js") . "<link rel='stylesheet' href='../externals/jquery-ui/themes/base/jquery.ui.all.css'>\n<style>\n.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }\n.ui-timepicker-div dl { text-align: left; }\n.ui-timepicker-div dl dt { height: 25px; }\n.ui-timepicker-div dl dd { margin: -25px 0 10px 65px; }\n.ui-timepicker-div td { font-size: 90%; }\n</style>\n", "../externals/jquery-ui/ui/i18n/jquery.ui.datepicker-%s.js"),
|
||||
//~ new AdminerTinymce("../externals/tinymce/jscripts/tiny_mce/tiny_mce_dev.js"),
|
||||
//~ new AdminerWymeditor(array("../externals/wymeditor/src/jquery/jquery.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.explorer.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.mozilla.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.opera.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.safari.js")),
|
||||
new AdminerFileUpload(""),
|
||||
new AdminerJsonColumn,
|
||||
new AdminerSlugify,
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
page_header(lang('Privileges'));
|
||||
|
||||
echo '<p class="links"><a href="' . h(ME) . 'user=">' . lang('Create user') . "</a>";
|
||||
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["procedure"]);
|
||||
namespace Adminer;
|
||||
|
||||
$PROCEDURE = ($_GET["name"] ?: $_GET["procedure"]);
|
||||
$routine = (isset($_GET["function"]) ? "FUNCTION" : "PROCEDURE");
|
||||
$row = $_POST;
|
||||
$row["fields"] = (array) $row["fields"];
|
||||
@@ -44,7 +46,7 @@ $routine_languages = routine_languages();
|
||||
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", $row["returns"], $collations, array(), (JUSH == "pgsql" ? array("void", "trigger") : array()));
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
@@ -53,6 +55,8 @@ if (isset($_GET["function"])) {
|
||||
<p><?php textarea("definition", $row["definition"]); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($PROCEDURE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $PROCEDURE)); ?><?php } ?>
|
||||
<?php if ($PROCEDURE != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $PROCEDURE)); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
if (support("kill")) {
|
||||
if ($_POST && !$error) {
|
||||
$killed = 0;
|
||||
@@ -22,7 +24,6 @@ echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(ta
|
||||
// HTML valid because there is always at least one process
|
||||
$i = -1;
|
||||
foreach (process_list() as $i => $row) {
|
||||
|
||||
if (!$i) {
|
||||
echo "<thead><tr lang='en'>" . (support("kill") ? "<th>" : "");
|
||||
foreach ($row as $key => $val) {
|
||||
@@ -34,13 +35,13 @@ foreach (process_list() as $i => $row) {
|
||||
}
|
||||
echo "</thead>\n";
|
||||
}
|
||||
echo "<tr>" . (support("kill") ? "<td>" . checkbox("kill[]", $row[$jush == "sql" ? "Id" : "pid"], 0) : "");
|
||||
echo "<tr>" . (support("kill") ? "<td>" . checkbox("kill[]", $row[JUSH == "sql" ? "Id" : "pid"], 0) : "");
|
||||
foreach ($row as $key => $val) {
|
||||
echo "<td>" . (
|
||||
($jush == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") ||
|
||||
($jush == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
|
||||
($jush == "oracle" && $key == "sql_text" && $val != "")
|
||||
? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
|
||||
(JUSH == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") ||
|
||||
(JUSH == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
|
||||
(JUSH == "oracle" && $key == "sql_text" && $val != "")
|
||||
? "<code class='jush-" . JUSH . "'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
|
||||
: h($val)
|
||||
);
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
page_header(lang('Database schema'), "", array(), h(DB . ($_GET["ns"] ? ".$_GET[ns]" : "")));
|
||||
|
||||
$table_pos = array();
|
||||
$table_pos_js = array();
|
||||
$SCHEMA = ($_GET["schema"] ? $_GET["schema"] : $_COOKIE["adminer_schema-" . str_replace(".", "_", DB)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name
|
||||
$SCHEMA = ($_GET["schema"] ?: $_COOKIE["adminer_schema-" . str_replace(".", "_", DB)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name
|
||||
preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $SCHEMA, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $i => $match) {
|
||||
$table_pos[$match[1]] = array($match[2], $match[3]);
|
||||
@@ -26,7 +28,7 @@ foreach (table_status('', true) as $table => $table_status) {
|
||||
$field["pos"] = $pos;
|
||||
$schema[$table]["fields"][$name] = $field;
|
||||
}
|
||||
$schema[$table]["pos"] = ($table_pos[$table] ? $table_pos[$table] : array($top, 0));
|
||||
$schema[$table]["pos"] = ($table_pos[$table] ?: array($top, 0));
|
||||
foreach ($adminer->foreignKeys($table) as $val) {
|
||||
if (!$val["db"]) {
|
||||
$left = $base_left;
|
||||
@@ -82,7 +84,10 @@ foreach ($schema as $name => $table) {
|
||||
$left1 = $left - $table_pos[$name][1];
|
||||
$i = 0;
|
||||
foreach ($columns as $target) {
|
||||
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'><div style='height: .5em; border-bottom: 1px solid Gray; width: " . (-$left1) . "em;'></div></div>";
|
||||
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'>"
|
||||
. "<div style='height: .5em; border-bottom: 1px solid Gray; width: " . (-$left1) . "em;'></div>"
|
||||
. "</div>"
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$row = $_POST;
|
||||
|
||||
if ($_POST && !$error) {
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
header("Content-Type: text/javascript; charset=utf-8");
|
||||
|
||||
if ($_GET["script"] == "db") {
|
||||
@@ -12,10 +14,12 @@ if ($_GET["script"] == "db") {
|
||||
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
|
||||
if ($table_status[$key] != "") {
|
||||
$val = format_number($table_status[$key]);
|
||||
json_row("$key-$name", ($key == "Rows" && $val && $table_status["Engine"] == ($jush == "pgsql" ? "table" : "InnoDB")
|
||||
? "~ $val"
|
||||
: $val
|
||||
));
|
||||
if ($val >= 0) {
|
||||
json_row("$key-$name", ($key == "Rows" && $val && $table_status["Engine"] == (JUSH == "pgsql" ? "table" : "InnoDB")
|
||||
? "~ $val"
|
||||
: $val
|
||||
));
|
||||
}
|
||||
if (isset($sums[$key])) {
|
||||
// ignore innodb_file_per_table because it is not active for tables created before it was enabled
|
||||
$sums[$key] += ($table_status["Engine"] != "InnoDB" || $key != "Data_free" ? $table_status[$key] : 0);
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["select"];
|
||||
$table_status = table_status1($TABLE);
|
||||
$indexes = indexes($TABLE);
|
||||
@@ -31,7 +33,7 @@ if ($_GET["val"] && is_ajax()) {
|
||||
header("Content-Type: text/plain; charset=utf-8");
|
||||
foreach ($_GET["val"] as $unique_idf => $row) {
|
||||
$as = convert_field($fields[key($row)]);
|
||||
$select = array($as ? $as : idf_escape(key($row)));
|
||||
$select = array($as ?: idf_escape(key($row)));
|
||||
$where[] = where_check($unique_idf, $fields);
|
||||
$return = $driver->select($TABLE, $select, $where, $select);
|
||||
if ($return) {
|
||||
@@ -97,7 +99,7 @@ if ($_POST && !$error) {
|
||||
$affected = 0;
|
||||
$set = array();
|
||||
if (!$_POST["delete"]) {
|
||||
foreach ($columns as $name => $val) { //! should check also for edit or insert privileges
|
||||
foreach ($_POST["fields"] as $name => $val) {
|
||||
$val = process_input($fields[$name]);
|
||||
if ($val !== null && ($_POST["clone"] || $val !== false)) {
|
||||
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
|
||||
@@ -144,7 +146,8 @@ if ($_POST && !$error) {
|
||||
}
|
||||
queries_redirect(remove_from_uri($_POST["all"] && $_POST["delete"] ? "page" : ""), $message, $result);
|
||||
if (!$_POST["delete"]) {
|
||||
edit_form($TABLE, $fields, (array) $_POST["fields"], !$_POST["clone"]);
|
||||
$post_fields = (array) $_POST["fields"];
|
||||
edit_form($TABLE, array_intersect_key($fields, $post_fields), $post_fields, !$_POST["clone"]);
|
||||
page_footer();
|
||||
exit;
|
||||
}
|
||||
@@ -198,14 +201,14 @@ if ($_POST && !$error) {
|
||||
} else {
|
||||
$set = array();
|
||||
foreach ($matches2[1] as $i => $col) {
|
||||
$set[idf_escape($cols[$i])] = ($col == "" && $fields[$cols[$i]]["null"] ? "NULL" : q(str_replace('""', '"', preg_replace('~^"|"$~', '', $col))));
|
||||
$set[idf_escape($cols[$i])] = ($col == "" && $fields[$cols[$i]]["null"] ? "NULL" : q(preg_match('~^".*"$~s', $col) ? str_replace('""', '"', substr($col, 1, -1)) : $col));
|
||||
}
|
||||
$rows[] = $set;
|
||||
}
|
||||
}
|
||||
$result = (!$rows || $driver->insertUpdate($TABLE, $rows, $primary));
|
||||
if ($result) {
|
||||
$result = $driver->commit();
|
||||
$driver->commit();
|
||||
}
|
||||
queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result);
|
||||
$driver->rollback(); // after queries_redirect() to not overwrite error
|
||||
@@ -226,9 +229,10 @@ $set = null;
|
||||
if (isset($rights["insert"]) || !support("table")) {
|
||||
$params = array();
|
||||
foreach ((array) $_GET["where"] as $val) {
|
||||
if (isset($foreign_keys[$val["col"]]) && count($foreign_keys[$val["col"]]) == 1
|
||||
&& ($val["op"] == "=" || (!$val["op"] && (is_array($val["val"]) || !preg_match('~[_%]~', $val["val"]))) // LIKE in Editor
|
||||
)) {
|
||||
if (
|
||||
isset($foreign_keys[$val["col"]]) && count($foreign_keys[$val["col"]]) == 1
|
||||
&& ($val["op"] == "=" || (!$val["op"] && (is_array($val["val"]) || !preg_match('~[_%]~', $val["val"])))) // LIKE in Editor
|
||||
) {
|
||||
$params["set" . "[" . bracket_escape($val["col"]) . "]"] = $val["val"];
|
||||
}
|
||||
}
|
||||
@@ -288,21 +292,21 @@ if (!$columns && support("table")) {
|
||||
if (!$result) {
|
||||
echo "<p class='error'>" . error() . "\n";
|
||||
} else {
|
||||
if ($jush == "mssql" && $page) {
|
||||
if (JUSH == "mssql" && $page) {
|
||||
$result->seek($limit * $page);
|
||||
}
|
||||
$email_fields = array();
|
||||
echo "<form action='' method='post' enctype='multipart/form-data'>\n";
|
||||
$rows = array();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($page && $jush == "oracle") {
|
||||
if ($page && JUSH == "oracle") {
|
||||
unset($row["RNUM"]);
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
|
||||
if ($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql") {
|
||||
if ($_GET["page"] != "last" && $limit != "" && $group && $is_group && JUSH == "sql") {
|
||||
$found_rows = $connection->result(" SELECT FOUND_ROWS()"); // space to allow mysql.trace_mode
|
||||
}
|
||||
|
||||
@@ -376,9 +380,9 @@ if (!$columns && support("table")) {
|
||||
}
|
||||
$unique_idf = "";
|
||||
foreach ($unique_array as $key => $val) {
|
||||
if (($jush == "sql" || $jush == "pgsql") && preg_match('~char|text|enum|set~', $fields[$key]["type"]) && strlen($val) > 64) {
|
||||
if ((JUSH == "sql" || JUSH == "pgsql") && preg_match('~char|text|enum|set~', $fields[$key]["type"]) && strlen($val) > 64) {
|
||||
$key = (strpos($key, '(') ? $key : idf_escape($key)); //! columns looking like functions
|
||||
$key = "MD5(" . ($jush != 'sql' || preg_match("~^utf8~", $fields[$key]["collation"]) ? $key : "CONVERT($key USING " . charset($connection) . ")") . ")";
|
||||
$key = "MD5(" . (JUSH != 'sql' || preg_match("~^utf8~", $fields[$key]["collation"]) ? $key : "CONVERT($key USING " . charset($connection) . ")") . ")";
|
||||
$val = md5($val);
|
||||
}
|
||||
$unique_idf .= "&" . ($val !== null ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val === false ? "f" : $val) : "null%5B%5D=" . urlencode($key));
|
||||
@@ -433,7 +437,7 @@ if (!$columns && support("table")) {
|
||||
$val = select_value($val, $link, $field, $text_length);
|
||||
$id = h("val[$unique_idf][" . bracket_escape($key) . "]");
|
||||
$value = $_POST["val"][$unique_idf][bracket_escape($key)];
|
||||
$editable = !is_array($row[$key]) && is_utf8($val) && $rows[$n][$key] == $row[$key] && !$functions[$key];
|
||||
$editable = !is_array($row[$key]) && is_utf8($val) && $rows[$n][$key] == $row[$key] && !$functions[$key] && !$field["generated"];
|
||||
$text = preg_match('~text|lob~', $field["type"]);
|
||||
echo "<td id='$id'";
|
||||
if (($_GET["modify"] && $editable) || $value !== null) {
|
||||
@@ -443,7 +447,7 @@ if (!$columns && support("table")) {
|
||||
$long = strpos($val, "<i>…</i>");
|
||||
echo " data-text='" . ($long ? 2 : ($text ? 1 : 0)) . "'"
|
||||
. ($editable ? "" : " data-warning='" . h(lang('Use edit link to modify this value.')) . "'")
|
||||
. ">$val</td>"
|
||||
. ">$val"
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -469,7 +473,7 @@ if (!$columns && support("table")) {
|
||||
if ($_GET["page"] != "last") {
|
||||
if ($limit == "" || (count($rows) < $limit && ($rows || !$page))) {
|
||||
$found_rows = ($page ? $page * $limit : 0) + count($rows);
|
||||
} elseif ($jush != "sql" || !$is_group) {
|
||||
} elseif (JUSH != "sql" || !$is_group) {
|
||||
$found_rows = ($is_group ? false : found_rows($table_status, $where));
|
||||
if ($found_rows < max(1e4, 2 * ($page + 1) * $limit)) {
|
||||
// slow with big tables
|
||||
@@ -500,7 +504,7 @@ if (!$columns && support("table")) {
|
||||
: floor(($found_rows - 1) / $limit)
|
||||
);
|
||||
echo "<fieldset>";
|
||||
if ($jush != "simpledb") {
|
||||
if (JUSH != "simpledb") {
|
||||
echo "<legend><a href='" . h(remove_from_uri("page")) . "'>" . lang('Page') . "</a></legend>";
|
||||
echo script("qsl('a').onclick = function () { pageClick(this.href, +prompt('" . lang('Page') . "', '" . ($page + 1) . "')); return false; };");
|
||||
echo pagination(0, $page) . ($page > 5 ? " …" : "");
|
||||
@@ -526,9 +530,8 @@ if (!$columns && support("table")) {
|
||||
echo "<fieldset>";
|
||||
echo "<legend>" . lang('Whole result') . "</legend>";
|
||||
$display_rows = ($exact_count ? "" : "~ ") . $found_rows;
|
||||
echo checkbox("all", 1, 0, ($found_rows !== false ? ($exact_count ? "" : "~ ") . lang('%d row(s)', $found_rows) : ""),
|
||||
"var checked = formChecked(this, /check/); selectCount('selected', this.checked ? '$display_rows' : checked); selectCount('selected2', this.checked || !checked ? '$display_rows' : checked);"
|
||||
) . "\n";
|
||||
$onclick = "var checked = formChecked(this, /check/); selectCount('selected', this.checked ? '$display_rows' : checked); selectCount('selected2', this.checked || !checked ? '$display_rows' : checked);";
|
||||
echo checkbox("all", 1, 0, ($found_rows !== false ? ($exact_count ? "" : "~ ") . lang('%d row(s)', $found_rows) : ""), $onclick) . "\n";
|
||||
echo "</fieldset>\n";
|
||||
|
||||
if ($adminer->selectCommandPrint()) {
|
||||
@@ -569,7 +572,7 @@ if (!$columns && support("table")) {
|
||||
echo "<div>";
|
||||
echo "<a href='#import'>" . lang('Import') . "</a>";
|
||||
echo script("qsl('a').onclick = partial(toggle, 'import');", "");
|
||||
echo "<span id='import' class='hidden'>: ";
|
||||
echo "<span id='import'" . ($_POST["import"] ? "" : " class='hidden'") . ">: ";
|
||||
echo "<input type='file' name='csv_file'> ";
|
||||
echo html_select("separator", array("csv" => "CSV,", "csv;" => "CSV;", "tsv" => "TSV"), $adminer_import["format"], 1); // 1 - select
|
||||
echo " <input type='submit' name='import' value='" . lang('Import') . "'>";
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$SEQUENCE = $_GET["sequence"];
|
||||
$row = $_POST;
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
if (!$error && $_POST["export"]) {
|
||||
dump_headers("sql");
|
||||
$adminer->dumpTable("", "");
|
||||
@@ -59,7 +61,7 @@ if (!$error && $_POST) {
|
||||
}
|
||||
$commands = 0;
|
||||
$errors = array();
|
||||
$parse = '[\'"' . ($jush == "sql" ? '`#' : ($jush == "sqlite" ? '`[' : ($jush == "mssql" ? '[' : ''))) . ']|/\*|-- |$' . ($jush == "pgsql" ? '|\$[^$]*\$' : '');
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|-- |$' . (JUSH == "pgsql" ? '|\$[^$]*\$' : '');
|
||||
$total_start = microtime(true);
|
||||
parse_str($_COOKIE["adminer_export"], $adminer_export);
|
||||
$dump_format = $adminer->dumpFormat();
|
||||
@@ -81,7 +83,7 @@ if (!$error && $_POST) {
|
||||
$offset = $pos + strlen($found);
|
||||
|
||||
if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
|
||||
$c_style_escapes = is_c_style_escapes() || ($jush == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
|
||||
$c_style_escapes = $driver->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
|
||||
|
||||
$pattern = ($found == '/*' ? '\*/'
|
||||
: ($found == '[' ? ']'
|
||||
@@ -105,8 +107,8 @@ if (!$error && $_POST) {
|
||||
$empty = false;
|
||||
$q = substr($query, 0, $pos);
|
||||
$commands++;
|
||||
$print = "<pre id='sql-$commands'><code class='jush-$jush'>" . $adminer->sqlCommandQuery($q) . "</code></pre>\n";
|
||||
if ($jush == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
|
||||
$print = "<pre id='sql-$commands'><code class='jush-" . JUSH . "'>" . $adminer->sqlCommandQuery($q) . "</code></pre>\n";
|
||||
if (JUSH == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
|
||||
// PHP doesn't support setting SQLITE_LIMIT_ATTACHED
|
||||
echo $print;
|
||||
echo "<p class='error'>" . lang('ATTACH queries are not supported.') . "\n";
|
||||
@@ -263,7 +265,7 @@ if (!isset($_GET["import"]) && $history) {
|
||||
list($q, $time, $elapsed) = $val;
|
||||
echo '<a href="' . h(ME . "sql=&history=$key") . '">' . lang('Edit') . "</a>"
|
||||
. " <span class='time' title='" . @date('Y-m-d', $time) . "'>" . @date("H:i:s", $time) . "</span>" // @ - time zone may be not set
|
||||
. " <code class='jush-$jush'>" . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $q)))), 80, "</code>")
|
||||
. " <code class='jush-" . JUSH . "'>" . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $q)))), 80, "</code>")
|
||||
. ($elapsed ? " <span class='time'>($elapsed)</span>" : "")
|
||||
. "<br>\n"
|
||||
;
|
||||
|
@@ -22,10 +22,12 @@ td img { max-width: 200px; max-height: 200px; }
|
||||
code { background: #eee; }
|
||||
tbody tr:hover td, tbody tr:hover th { background: #eee; }
|
||||
pre { margin: 1em 0 0; }
|
||||
td pre { margin: 0; }
|
||||
pre, textarea { font: 100%/1.25 monospace; }
|
||||
pre.jush { background: #fff; }
|
||||
input, textarea { box-sizing: border-box; }
|
||||
input, select { vertical-align: middle; }
|
||||
input[type="radio"] { vertical-align: text-bottom; }
|
||||
input.default { box-shadow: 1px 1px 1px #777; }
|
||||
input.required { box-shadow: 1px 1px 1px red; }
|
||||
input.maxlength { box-shadow: 1px 1px 1px red; }
|
||||
|
@@ -238,9 +238,13 @@ function editFields() {
|
||||
els = qsa('[name$="[type]"]');
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
mixin(els[i], {
|
||||
onfocus: function () { lastType = selectValue(this); },
|
||||
onfocus: function () {
|
||||
lastType = selectValue(this);
|
||||
},
|
||||
onchange: editingTypeChange,
|
||||
onmouseover: function (event) { helpMouseover.call(this, event, getTarget(event).value, 1) },
|
||||
onmouseover: function (event) {
|
||||
helpMouseover.call(this, event, getTarget(event).value, 1);
|
||||
},
|
||||
onmouseout: helpMouseout
|
||||
});
|
||||
}
|
||||
@@ -286,7 +290,8 @@ function editingClick(event) {
|
||||
function editingInput(event) {
|
||||
var el = getTarget(event);
|
||||
if (/\[default]$/.test(el.name)) {
|
||||
el.previousSibling.checked = true;
|
||||
el.previousElementSibling.checked = true;
|
||||
el.previousElementSibling.selectedIndex = Math.max(el.previousElementSibling.selectedIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,8 +360,9 @@ function editingAddRow(focus) {
|
||||
if (/\[(orig|field|comment|default)/.test(tags[i].name)) {
|
||||
tags2[i].value = '';
|
||||
}
|
||||
if (/\[(has_default)/.test(tags[i].name)) {
|
||||
if (/\[(generated)/.test(tags[i].name)) {
|
||||
tags2[i].checked = false;
|
||||
tags2[i].selectedIndex = 0;
|
||||
}
|
||||
}
|
||||
tags[0].oninput = editingNameChange;
|
||||
@@ -418,8 +424,9 @@ function editingTypeChange() {
|
||||
}
|
||||
el.oninput.apply(el);
|
||||
}
|
||||
if (lastType == 'timestamp' && el.name == name + '[has_default]' && /timestamp/i.test(formField(type.form, name + '[default]').value)) {
|
||||
if (lastType == 'timestamp' && el.name == name + '[generated]' && /timestamp/i.test(formField(type.form, name + '[default]').value)) {
|
||||
el.checked = false;
|
||||
el.selectedIndex = 0;
|
||||
}
|
||||
if (el.name == name + '[collation]') {
|
||||
alterClass(el, 'hidden', !/(char|text|enum|set)$/.test(text));
|
||||
@@ -692,7 +699,7 @@ var that, x, y; // em and tablePos defined in schema.inc.php
|
||||
* @this HTMLElement
|
||||
*/
|
||||
function schemaMousedown(event) {
|
||||
if ((event.which ? event.which : event.button) == 1) {
|
||||
if ((event.which || event.button) == 1) {
|
||||
that = this;
|
||||
x = event.clientX - this.offsetLeft;
|
||||
y = event.clientY - this.offsetTop;
|
||||
@@ -711,7 +718,7 @@ function schemaMousemove(event) {
|
||||
for (var i=0; i < divs.length; i++) {
|
||||
if (divs[i].className == 'references') {
|
||||
var div2 = qs('[id="' + (/^refs/.test(divs[i].id) ? 'refd' : 'refs') + divs[i].id.substr(4) + '"]');
|
||||
var ref = (tablePos[divs[i].title] ? tablePos[divs[i].title] : [ div2.parentNode.offsetTop / em, 0 ]);
|
||||
var ref = (tablePos[divs[i].title] || [ div2.parentNode.offsetTop / em, 0 ]);
|
||||
var left1 = -1;
|
||||
var id = divs[i].id.replace(/^ref.(.+)-.+/, '$1');
|
||||
if (divs[i].parentNode != div2.parentNode) {
|
||||
|
@@ -884,7 +884,8 @@ function addEvent(el, action, handler) {
|
||||
* @param HTMLElement
|
||||
*/
|
||||
function focus(el) {
|
||||
setTimeout(function () { // this has to be an anonymous function because Firefox passes some arguments to setTimeout callback
|
||||
setTimeout(function () {
|
||||
// this has to be an anonymous function because Firefox passes some arguments to setTimeout callback
|
||||
el.focus();
|
||||
}, 0);
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["table"];
|
||||
$fields = fields($TABLE);
|
||||
if (!$fields) {
|
||||
@@ -42,12 +44,14 @@ if (!is_view($table_status)) {
|
||||
echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td></thead>\n";
|
||||
foreach ($foreign_keys as $name => $foreign_key) {
|
||||
echo "<tr title='" . h($name) . "'>";
|
||||
echo "<th><i>" . implode("</i>, <i>", array_map('h', $foreign_key["source"])) . "</i>";
|
||||
echo "<th><i>" . implode("</i>, <i>", array_map('Adminer\h', $foreign_key["source"])) . "</i>";
|
||||
echo "<td><a href='" . h($foreign_key["db"] != "" ? preg_replace('~db=[^&]*~', "db=" . urlencode($foreign_key["db"]), ME) : ($foreign_key["ns"] != "" ? preg_replace('~ns=[^&]*~', "ns=" . urlencode($foreign_key["ns"]), ME) : ME)) . "table=" . urlencode($foreign_key["table"]) . "'>"
|
||||
. ($foreign_key["db"] != "" ? "<b>" . h($foreign_key["db"]) . "</b>." : "") . ($foreign_key["ns"] != "" ? "<b>" . h($foreign_key["ns"]) . "</b>." : "") . h($foreign_key["table"])
|
||||
. ($foreign_key["db"] != "" && $foreign_key["db"] != DB ? "<b>" . h($foreign_key["db"]) . "</b>." : "")
|
||||
. ($foreign_key["ns"] != "" && $foreign_key["ns"] != $_GET["ns"] ? "<b>" . h($foreign_key["ns"]) . "</b>." : "")
|
||||
. h($foreign_key["table"])
|
||||
. "</a>"
|
||||
;
|
||||
echo "(<i>" . implode("</i>, <i>", array_map('h', $foreign_key["target"])) . "</i>)";
|
||||
echo "(<i>" . implode("</i>, <i>", array_map('Adminer\h', $foreign_key["target"])) . "</i>)";
|
||||
echo "<td>" . h($foreign_key["on_delete"]);
|
||||
echo "<td>" . h($foreign_key["on_update"]);
|
||||
echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
|
||||
@@ -60,12 +64,12 @@ if (!is_view($table_status)) {
|
||||
|
||||
if (support("check")) {
|
||||
echo "<h3 id='checks'>" . lang('Checks') . "</h3>\n";
|
||||
$check_constraints = check_constraints($TABLE);
|
||||
$check_constraints = $driver->checkConstraints($TABLE);
|
||||
if ($check_constraints) {
|
||||
echo "<table>\n";
|
||||
foreach ($check_constraints as $key => $val) {
|
||||
echo "<tr title='" . h($key) . "'>";
|
||||
echo "<td><code class='jush-$jush'>" . h($val);
|
||||
echo "<td><code class='jush-" . JUSH . "'>" . h($val);
|
||||
echo "<td><a href='" . h(ME . 'check=' . urlencode($TABLE) . '&name=' . urlencode($key)) . "'>" . lang('Alter') . "</a>";
|
||||
echo "\n";
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["trigger"];
|
||||
$name = $_GET["name"];
|
||||
$trigger_options = trigger_options();
|
||||
@@ -8,7 +10,7 @@ if ($_POST) {
|
||||
if (!$error && in_array($_POST["Timing"], $trigger_options["Timing"]) && in_array($_POST["Event"], $trigger_options["Event"]) && in_array($_POST["Type"], $trigger_options["Type"])) {
|
||||
// don't use drop_create() because there may not be more triggers for the same action
|
||||
$on = " ON " . table($TABLE);
|
||||
$drop = "DROP TRIGGER " . idf_escape($name) . ($jush == "pgsql" ? $on : "");
|
||||
$drop = "DROP TRIGGER " . idf_escape($name) . (JUSH == "pgsql" ? $on : "");
|
||||
$location = ME . "table=" . urlencode($TABLE);
|
||||
if ($_POST["drop"]) {
|
||||
query_redirect($drop, $location, lang('Trigger has been dropped.'));
|
||||
@@ -44,6 +46,8 @@ page_header(($name != "" ? lang('Alter trigger') . ": " . h($name) : lang('Creat
|
||||
<p><?php textarea("Statement", $row["Statement"]); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?><?php } ?>
|
||||
<?php if ($name != "") { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$TYPE = $_GET["type"];
|
||||
$row = $_POST;
|
||||
|
||||
@@ -22,9 +24,17 @@ if (!$row) {
|
||||
<p>
|
||||
<?php
|
||||
if ($TYPE != "") {
|
||||
$types = $driver->types();
|
||||
$enums = type_values($types[$TYPE]);
|
||||
if ($enums) {
|
||||
echo "<code class='jush-" . JUSH . "'>ENUM (" . h($enums) . ")</code>\n<p>";
|
||||
}
|
||||
echo "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm(lang('Drop %s?', $TYPE)) . "\n";
|
||||
} else {
|
||||
echo "<input name='name' value='" . h($row['name']) . "' autocapitalize='off'>\n";
|
||||
echo lang('Name') . ": <input name='name' value='" . h($row['name']) . "' autocapitalize='off'>\n";
|
||||
echo doc_link(array(
|
||||
'pgsql' => "datatype-enum.html",
|
||||
), "?");
|
||||
textarea("as", $row["as"]);
|
||||
echo "<p><input type='submit' value='" . lang('Save') . "'>\n";
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$USER = $_GET["user"];
|
||||
$privileges = array("" => array("All privileges" => ""));
|
||||
foreach (get_rows("SHOW PRIVILEGES") as $row) {
|
||||
@@ -84,10 +86,11 @@ if ($_POST && !$error) {
|
||||
$grant = array_diff($grant, $old_grant);
|
||||
unset($grants[$object]);
|
||||
}
|
||||
if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && (
|
||||
if (
|
||||
preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && (
|
||||
!grant("REVOKE", $revoke, $match[2], " ON $match[1] FROM $new_user") //! SQL injection
|
||||
|| !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user")
|
||||
)) {
|
||||
|| !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user"))
|
||||
) {
|
||||
$error = true;
|
||||
break;
|
||||
}
|
||||
@@ -135,7 +138,7 @@ if ($_POST) {
|
||||
<tr><th><?php echo lang('Server'); ?><td><input name="host" data-maxlength="60" value="<?php echo h($row["host"]); ?>" autocapitalize="off">
|
||||
<tr><th><?php echo lang('Username'); ?><td><input name="user" data-maxlength="80" value="<?php echo h($row["user"]); ?>" autocapitalize="off">
|
||||
<tr><th><?php echo lang('Password'); ?><td><input name="pass" id="pass" value="<?php echo h($row["pass"]); ?>" autocomplete="new-password">
|
||||
<?php if (!$row["hashed"]) { echo script("typePassword(qs('#pass'));"); } ?>
|
||||
<?php echo ($row["hashed"] ? "" : script("typePassword(qs('#pass'));")); ?>
|
||||
<?php echo (min_version(8) ? "" : checkbox("hashed", 1, $row["hashed"], lang('Hashed'), "typePassword(this.form['pass'], this.checked);")); ?>
|
||||
</table>
|
||||
|
||||
@@ -150,14 +153,16 @@ foreach ($grants as $object => $grant) {
|
||||
}
|
||||
echo "</thead>\n";
|
||||
|
||||
foreach (array(
|
||||
"" => "",
|
||||
"Server Admin" => lang('Server'),
|
||||
"Databases" => lang('Database'),
|
||||
"Tables" => lang('Table'),
|
||||
"Columns" => lang('Column'),
|
||||
"Procedures" => lang('Routine'),
|
||||
) as $context => $desc) {
|
||||
foreach (
|
||||
array(
|
||||
"" => "",
|
||||
"Server Admin" => lang('Server'),
|
||||
"Databases" => lang('Database'),
|
||||
"Tables" => lang('Table'),
|
||||
"Columns" => lang('Column'),
|
||||
"Procedures" => lang('Routine'),
|
||||
) as $context => $desc
|
||||
) {
|
||||
foreach ((array) $privileges[$context] as $privilege => $comment) {
|
||||
echo "<tr><td" . ($desc ? ">$desc<td" : " colspan='2'") . ' lang="en" title="' . h($comment) . '">' . h($privilege);
|
||||
$i = 0;
|
||||
@@ -184,6 +189,8 @@ echo "</table>\n";
|
||||
?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if (isset($_GET["host"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', "$USER@$_GET[host]")); ?><?php } ?>
|
||||
<?php if (isset($_GET["host"])) { ?>
|
||||
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', "$USER@$_GET[host]")); ?>
|
||||
<?php } ?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$status = isset($_GET["status"]);
|
||||
page_header($status ? lang('Status') : lang('Variables'));
|
||||
|
||||
@@ -9,8 +11,8 @@ if (!$variables) {
|
||||
echo "<table>\n";
|
||||
foreach ($variables as $key => $val) {
|
||||
echo "<tr>";
|
||||
echo "<th><code class='jush-" . $jush . ($status ? "status" : "set") . "'>" . h($key) . "</code>";
|
||||
echo "<td>" . h($val);
|
||||
echo "<th><code class='jush-" . JUSH . ($status ? "status" : "set") . "'>" . h($key) . "</code>";
|
||||
echo "<td>" . nl_br(h($val));
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user