1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-30 09:39:51 +02:00

Compare commits

...

364 Commits

Author SHA1 Message Date
Jakub Vrana
8d7cb5954d Release 5.0.0 2025-03-07 09:40:15 +01:00
Jakub Vrana
47700f2763 PostgreSQL: Fix exporting foreign keys 2025-03-07 08:02:06 +01:00
Jakub Vrana
a4a8f48a9c PHPCS: Ignore compiled files 2025-03-07 07:56:35 +01:00
Jakub Vrana
770a77ac33 Wrap long lines 2025-03-07 07:44:26 +01:00
Jakub Vrana
8ceaf36de7 Editor: Fix getting fields 2025-03-07 07:17:05 +01:00
Jakub Vrana
517d2d1c2f MS SQL: Support computed columns 2025-03-07 06:42:27 +01:00
Jakub Vrana
af5d519266 SQLite: Support generated columns 2025-03-07 06:07:25 +01:00
Jakub Vrana
c045b20a8e Allow creating generated columns (bug #857) 2025-03-07 05:18:56 +01:00
Jakub Vrana
874307a27f Fix undefined variable 2025-03-07 04:56:31 +01:00
Jakub Vrana
c27b91a167 MySQL: Drop support for MySQL 4 2025-03-07 03:58:42 +01:00
Jakub Vrana
afe03ef720 MySQL: Display generated value in table structure 2025-03-07 03:58:33 +01:00
Jakub Vrana
c0e2ab22d5 Syntax highlight generated expressions 2025-03-06 19:47:05 +01:00
Jakub Vrana
7351980beb Skip generated columns in multi-edit (bug #882) 2025-03-06 19:32:19 +01:00
Jakub Vrana
7b5a20334d Don't allow inline edit of generated columns 2025-03-06 18:59:20 +01:00
Jakub Vrana
6262b120f5 PostgreSQL: Skip editing generated columns 2025-03-06 18:44:18 +01:00
Jakub Vrana
bd27ca0b2b Add comment 2025-03-06 18:36:26 +01:00
Jakub Vrana
aa7cf70d25 JS: Use || 2025-03-06 18:23:20 +01:00
Jakub Vrana
94a4f61db2 PHP: Use ?: 2025-03-06 18:12:22 +01:00
Jakub Vrana
dc50bf17ea SQLite: Remove useless condition 2025-03-06 17:55:45 +01:00
Jakub Vrana
f05f4b4cbc Change $jush to constant 2025-03-06 17:51:20 +01:00
Jakub Vrana
0541680d73 Move constants to namespace 2025-03-06 17:34:21 +01:00
Jakub Vrana
5a84ff7647 PostgreSQL: Display ? instead of -1 rows in table overview (bug #883) 2025-03-06 17:08:32 +01:00
Jakub Vrana
edd7c67797 Delete incorporated plugin 2025-03-06 14:59:48 +01:00
Jakub Vrana
c6f825a786 Move $enum_length to Driver 2025-03-06 14:51:24 +01:00
Jakub Vrana
f711135574 Move $inout to Driver 2025-03-06 14:49:08 +01:00
Jakub Vrana
2b16f51933 PDO: Support search by expression.
This reverts b848764.
2025-03-06 14:40:13 +01:00
Jakub Vrana
d268e0ebb4 ClickHouse: Check for allow_url_fopen 2025-03-06 14:30:50 +01:00
Jakub Vrana
5fdaae27dc Move possible drivers and JUSH to Driver 2025-03-06 14:27:58 +01:00
Jakub Vrana
049536da90 Mongo: Use $this->_conn 2025-03-06 14:10:05 +01:00
Jakub Vrana
bddce074fa Mongo: Add Driver outside of if 2025-03-06 14:08:19 +01:00
Jakub Vrana
347d9f1f55 Move on_actions to Driver 2025-03-06 14:04:47 +01:00
Jakub Vrana
a8feb00098 Move unsigned to Driver 2025-03-06 13:58:15 +01:00
Jakub Vrana
69d7d76dc5 Move operators, functions and grouping to Driver 2025-03-06 13:51:49 +01:00
Jakub Vrana
2f0cd4185b Move edit functions to Driver 2025-03-06 13:28:04 +01:00
Jakub Vrana
37a75f3759 Move types to Driver 2025-03-06 12:35:20 +01:00
Takashi SHIRAI
d2add4dd72 Fix the primary key for MS SQL
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-03-06 08:54:59 +01:00
Jakub Vrana
f5d47d46a0 Use anonymous function 2025-03-05 17:08:29 +01:00
Jakub Vrana
e8d9a126be Rely on PHP 5.3 2025-03-05 17:05:19 +01:00
Jakub Vrana
12f0a4bc9a Inform about namespace use 2025-03-05 16:54:53 +01:00
Jakub Vrana
d9df9693e3 Code style: Add more checks 2025-03-05 16:33:22 +01:00
Jakub Vrana
873d6d50fd Code style: explain rules 2025-03-05 15:55:33 +01:00
Jakub Vrana
c873ceba17 Use PHP 5.3 functions 2025-03-05 15:54:13 +01:00
Jakub Vrana
0bf8861dd1 Plugins: Use namespace for driver functions 2025-03-05 15:54:08 +01:00
Jakub Vrana
137ac2396b Fix plugin autoloading 2025-03-05 15:39:48 +01:00
Jakub Vrana
755d7b47ac Code style: Check camel caps except in drivers 2025-03-05 15:37:16 +01:00
Jakub Vrana
dd947fc1ee Don't check code style in compiled files 2025-03-05 15:36:25 +01:00
Jakub Vrana
105999f62e Code style: Indent long statements 2025-03-05 15:01:21 +01:00
Jakub Vrana
ed5de27dd3 Code style: Indent long statements 2025-03-05 14:59:13 +01:00
Jakub Vrana
293e031498 Plugins: Add missing namespaces 2025-03-05 14:51:55 +01:00
Jakub Vrana
a7f097e78c Code style: Indent long statements 2025-03-05 14:51:17 +01:00
Jakub Vrana
af68e30742 Code style: Remove newline before } 2025-03-05 14:38:48 +01:00
Jakub Vrana
f820fa1c26 Mark abstract classes 2025-03-05 14:31:53 +01:00
Jakub Vrana
f468c095ae Make root namespace explicit 2025-03-05 14:25:09 +01:00
Jakub Vrana
c10b614ee1 Mongo: inline class names 2025-03-05 14:20:54 +01:00
Jakub Vrana
f5b255230b Don't require namespace in example 2025-03-05 14:15:32 +01:00
Jakub Vrana
54568ddef6 PDO: Support namespaces 2025-03-05 14:15:17 +01:00
Jakub Vrana
3da09dd31a Rename Min_ classes 2025-03-05 14:12:42 +01:00
Jakub Vrana
45ac930e06 Update todo 2025-03-05 13:45:42 +01:00
Jakub Vrana
e801753519 Remove extra newline 2025-03-05 13:45:23 +01:00
Jakub Vrana
a4e9f7b87b Fix tests 2025-03-05 13:31:50 +01:00
Jakub Vrana
35829eedaf Use namespace 2025-03-05 13:31:03 +01:00
Jakub Vrana
44c2e979f7 Compile: Support else after if (support) 2025-03-05 13:19:17 +01:00
Jakub Vrana
2a8b4009b1 Namespaces in compile 2025-03-05 13:14:21 +01:00
Jakub Vrana
6ceebc99df Add namespace in lang.php 2025-03-05 13:10:41 +01:00
Jakub Vrana
2f49bfb67e Return accidentally removed error message 2025-03-05 13:10:41 +01:00
Jakub Vrana
e1e085f312 Use namespace in callbacks 2025-03-05 13:10:40 +01:00
Jakub Vrana
50e7a65e6e Use namespaces in plugins 2025-03-05 13:10:40 +01:00
Jakub Vrana
52c5392089 PHP: Use namespace 2025-03-05 13:10:40 +01:00
Jakub Vrana
5a708df6ca Coding style: Check newline at {} 2025-03-05 13:10:40 +01:00
Jakub Vrana
c52ba0308e Specify coding style and follow it 2025-03-05 13:10:37 +01:00
Jakub Vrana
422668f2d7 Composer: Exclude drivers from classmap 2025-03-05 06:35:54 +01:00
Jakub Vrana
f0335f7f8b Hide Refresh link if it does nothing 2025-03-04 19:58:26 +01:00
Jakub Vrana
cc635acd20 Remove unnecessary function 2025-03-04 19:52:07 +01:00
Jakub Vrana
63dd38c44d PostgreSQL: Compute size of all databases (bug #881) 2025-03-04 19:40:42 +01:00
Jakub Vrana
e411c229ab Fix enum alignment 2025-03-04 18:53:01 +01:00
Jakub Vrana
b9d6529442 Remove margin from td pre 2025-03-04 18:46:28 +01:00
Jakub Vrana
0426bd4610 Designs: Fix logout button 2025-03-04 18:44:40 +01:00
Jakub Vrana
c7d283d262 Designs: Fix background of pre.jush 2025-03-04 18:34:07 +01:00
Jakub Vrana
d61678f5cb Reapply "Fix background color of <pre> used as edit field"
This reverts commit 9b25969fb2.
2025-03-04 18:11:32 +01:00
Jakub Vrana
94088474dd Design bilal-dark: Add missing icons 2025-03-04 18:10:23 +01:00
Jakub Vrana
9b25969fb2 Revert "Fix background color of <pre> used as edit field"
This reverts commit 0717bce535.
2025-03-04 11:04:26 +01:00
Jakub Vrana
996b178406 MySQL: Fix connecting with self-signed cert 2025-03-03 16:06:10 +01:00
Jakub Vrana
116827060f PostgreSQL, MS SQL, Oracle: Hide table actions for information_schema 2025-03-03 15:54:08 +01:00
Jakub Vrana
af87336116 Add TODO 2025-03-03 15:43:04 +01:00
jfonsato
17939b56c4 PostgreSQL: Show only accessible databases 2025-03-03 15:34:43 +01:00
Christian Weiske
d5a17835ff Elastic: Fix text search on boolean fields
When searching in all fields for a text value, an error was thrown
with ElasticSearch 7.17.23 when the index contains boolean fields:

> query_shard_exception: failed to create query:
> Can't parse boolean value [textvalue], expected [true] or [false]

This patch fixes that problem by skipping boolean fields when the
search word is not the string "true" or "false".
2025-03-03 10:40:38 +01:00
Matrixman
4967a40410 New version of design rmSOFT
New version of design rmSOFT
2025-03-03 09:36:21 +01:00
Jan Tojnar
4cdcb44bee Use more [] in doc-comments
Follow up to 42de70d032
2025-03-03 08:39:17 +01:00
Jakub Vrana
160beb726a MS SQL: Link help from sys tables 2025-03-03 08:18:20 +01:00
Jakub Vrana
fb3b23617d Don't autofocus computed fields in insert form 2025-03-03 06:34:02 +01:00
Jakub Vrana
dfe3cc1888 Warn about failed type export 2025-03-03 05:17:00 +01:00
Jakub Vrana
c1704d83c1 Add comment 2025-03-03 05:16:15 +01:00
Jakub Vrana
364a4bce1f Update todo 2025-02-28 17:28:35 +01:00
Jakub Vrana
d9bca2df37 Speed up with disabled output buffering 2025-02-28 15:37:18 +01:00
Jakub Vrana
315ffc9d8b CSV import: Don't unquote " in unquoted values 2025-02-28 14:40:31 +01:00
Denitz
530b3dd1e5 Add Reset button for tables-filter plugin 2025-02-28 13:52:32 +01:00
Jakub Vrana
980c22fe8d MS SQL: Don't insert identity without IDENTITY_INSERT 2025-02-27 09:42:33 +01:00
Jakub Vrana
26d1e51916 PostgreSQL: Display ENUM types 2025-02-27 09:41:31 +01:00
Jakub Vrana
6d889b9f99 Add test for check constraints 2025-02-27 08:26:05 +01:00
Jakub Vrana
7e4ee77cc0 Fix Create table test 2025-02-27 08:10:44 +01:00
Jakub Vrana
742fd7dcb6 Remove <datalist> from tests 2025-02-27 08:09:45 +01:00
Jakub Vrana
d23a0eb77e PostgreSQL: Export ENUM types (bug #587) 2025-02-26 23:55:17 +01:00
Jakub Vrana
5eac6a44bd PostgreSQL: Link enum doc 2025-02-26 23:38:07 +01:00
Jakub Vrana
db300bc38b MS SQL: Specify columns in CSV import 2025-02-26 22:49:22 +01:00
Jakub Vrana
48a680658c MS SQL: Do not update primary key in CSV import 2025-02-26 22:47:16 +01:00
Jakub Vrana
70f9ff75fc MS SQL: Fix CSV import (bug #859) 2025-02-26 22:40:28 +01:00
Jakub Vrana
81340ff7e5 MS SQL: Compute arrays in insertUpdate only once 2025-02-26 22:35:00 +01:00
Jakub Vrana
89b097c699 Don't hide import if there was an error 2025-02-26 22:28:01 +01:00
Jakub Vrana
e075f4bd8b MS SQL: Import all CSV rows with one command 2025-02-26 22:27:43 +01:00
Jakub Vrana
e8fa48a257 MS SQL: Set identity_insert in CSV import 2025-02-26 22:11:41 +01:00
Takashi SHIRAI
0ed3c5cb19 Fix insertUpdate for mssql
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-26 22:04:58 +01:00
Jakub Vrana
2f237dfa04 MS SQL export: Create foreign keys after all tables 2025-02-26 21:39:45 +01:00
Jakub Vrana
afdc78a07b PostgreSQL: Sort PRIMARY and UNIQUE indexes first 2025-02-26 21:28:02 +01:00
Jakub Vrana
3dc87c1811 PostgreSQL: Do not alter indexes with expressions 2025-02-26 21:24:47 +01:00
Jakub Vrana
de7bb79132 Remove empty string 2025-02-26 20:01:56 +01:00
Jakub Vrana
f81658ecfe PostgreSQL: Add missing CHECK in export 2025-02-26 19:56:16 +01:00
Jakub Vrana
a603de853d PostgreSQL: Move primary key in export back to table 2025-02-26 19:55:49 +01:00
Jakub Vrana
2998db57d4 PostgreSQL: Print errors in export 2025-02-26 19:37:18 +01:00
Jakub Vrana
9aaa429528 PostgreSQL: Fix export of indexes with expressions (bug #768) 2025-02-26 19:27:19 +01:00
Jakub Vrana
ba70be12a4 PostgreSQL: Fix help link to pg_catalog views 2025-02-26 19:21:13 +01:00
Jakub Vrana
4b47326ffa Use use_sql 2025-02-26 18:47:25 +01:00
Jakub Vrana
848cd482e2 MS SQL: Add support for PDO_SQLSRV extension 2025-02-26 18:08:18 +01:00
Takashi SHIRAI
15cd83fc39 Add seek() to Min_PDOStatement for mssql.
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-26 17:43:35 +01:00
Jakub Vrana
4de6e47c0a Use \W in friendly_url() 2025-02-26 16:48:02 +01:00
Jakub Vrana
45f24a8f62 Delete unused functions 2025-02-26 16:48:02 +01:00
Jakub Vrana
cf835515b1 Support compiling Elastic driver 2025-02-26 16:48:02 +01:00
Jakub Vrana
c38b967fc4 Foreign keys: Switch schema back after getting the tables 2025-02-26 16:48:02 +01:00
Jakub Vrana
efb1eb9d6b MS SQL: Remove support for MSSQL extension 2025-02-26 16:48:02 +01:00
Jakub Vrana
ce1031e017 MS SQL: Split altering foreign key to two commands 2025-02-26 16:48:02 +01:00
Jakub Vrana
d54be5ac2e MS SQL: Display foreign keys ON UPDATE and ON DELETE 2025-02-26 16:47:55 +01:00
Jakub Vrana
76cc7c6614 MS SQL: Set identity_insert in export 2025-02-26 16:47:24 +01:00
Jakub Vrana
54dd702763 Fix bug number 2025-02-26 16:47:24 +01:00
Jakub Vrana
dfd26d0704 MS SQL: Support export 2025-02-26 16:47:18 +01:00
Jakub Vrana
0f8460b5e8 PostgreSQL: Use function for exporting constraints 2025-02-26 12:35:25 +01:00
Jakub Vrana
09883aa2f5 SQLite: Remove support for SQLite version 2 2025-02-26 12:20:37 +01:00
Jakub Vrana
e3a2b1b57a SQLite: Support CHECK constraint 2025-02-26 12:20:37 +01:00
Jakub Vrana
a28d95a023 SQLite: Constraint getting view by name to views only 2025-02-26 12:20:37 +01:00
Jakub Vrana
ab025e74a3 SQLite: Display all rows of variable values 2025-02-26 12:20:37 +01:00
Jakub Vrana
8077ef41c1 SQLite: Add command Check tables 2025-02-26 12:20:36 +01:00
Jakub Vrana
9d8864a6c7 Compile: Fix removing single driver login form field 2025-02-26 12:20:36 +01:00
Jakub Vrana
e107ef52d5 Move \n to loginFormField 2025-02-26 12:20:36 +01:00
Jakub Vrana
57ec1f924d Allow compiling driver from plugins 2025-02-26 12:20:36 +01:00
Jakub Vrana
491b481b7f Use __DIR__ 2025-02-26 12:20:36 +01:00
Jakub Vrana
e327d31a08 Hide SQL export if driver doesn't support it 2025-02-26 12:20:34 +01:00
Denitz
708a4e9494 Update table-structure.php 2025-02-25 16:44:25 +01:00
Jakub Vrana
c55ad679ac Use Default setup for CodeQL analysis 2025-02-25 16:41:08 +01:00
Jakub Vrana
dccbdfde97 MongoDB: Remove support for deprecated extension mongo 2025-02-25 15:59:04 +01:00
Jakub Vrana
09091c0dac Develop 2025-02-25 07:32:48 +01:00
Jakub Vrana
bb22a965b2 Release 4.17.1 2025-02-25 07:31:42 +01:00
Jakub Vrana
4f0da70733 Move is_c_style_escapes to Min_Driver 2025-02-25 07:26:08 +01:00
Jakub Vrana
a1235f68ff SQLite: Disable backslash escapes 2025-02-25 07:15:57 +01:00
Jakub Vrana
0138f3b0a5 Oracle: Fix foreign key doc link 2025-02-25 07:09:10 +01:00
Jakub Vrana
192ae38d57 MS SQL: Link doc with current version 2025-02-25 06:58:10 +01:00
Jakub Vrana
620e147b8c Check: Add doc link 2025-02-25 06:54:07 +01:00
Jakub Vrana
644cde4855 MS SQL: Update doc_links 2025-02-25 06:52:27 +01:00
Jakub Vrana
c15576bbf8 Use get_rows() 2025-02-25 06:36:32 +01:00
Jakub Vrana
0d8028ddc5 Compile: Do not warn about functions without declared support 2025-02-25 06:30:22 +01:00
Jakub Vrana
242f5a1ed8 MySQL: Fix typo in the date type (regression from 4.17.0) 2025-02-25 05:41:41 +01:00
Jakub Vrana
d12ea17b17 Remove bogus comment 2025-02-25 05:41:12 +01:00
Jakub Vrana
a7365a50b1 Remove border-collapse: separate in designs after removing cellspacing 2025-02-24 16:41:35 +01:00
Jakub Vrana
b5beffb37c Develop 2025-02-24 12:21:15 +01:00
Jakub Vrana
6b20230d50 Release 4.17.0 2025-02-24 12:20:55 +01:00
Jakub Vrana
836dba07af Warn about missing functions only in single-driver compile 2025-02-24 10:05:31 +01:00
Jakub Vrana
883e0a6619 MySQL 9+: Support vector type 2025-02-23 23:01:43 +01:00
Jakub Vrana
5000e7dc16 Inline function 2025-02-23 18:48:50 +01:00
Jakub Vrana
798432935d PostgreSQL 8+: Fix exporting table constraints 2025-02-23 18:47:11 +01:00
Jakub Vrana
08060f3253 PostgreSQL: Export functions 2025-02-23 18:28:33 +01:00
Jakub Vrana
6d59ed6d7e Fix comment 2025-02-23 18:17:11 +01:00
Jakub Vrana
eb0d5c3c5e Print SQL errors as comments in export 2025-02-23 17:42:23 +01:00
Jakub Vrana
04d707ef94 Anonymous functions require PHP 5.3 2025-02-23 17:07:01 +01:00
Jakub Vrana
004ac1c782 Use less brackets 2025-02-23 17:04:43 +01:00
Jakub Vrana
3ad62d55c8 Show comments at routine call (bug #874) 2025-02-23 16:35:23 +01:00
Jakub Vrana
42de70d032 Use [] in doc-comments 2025-02-23 14:39:14 +01:00
Jakub Vrana
aa2907190e MS SQL: Don't support C-style escapes 2025-02-23 14:39:14 +01:00
Jakub Vrana
5c8b6a3408 Use $connection->result 2025-02-23 14:39:13 +01:00
Jakub Vrana
7f883b9302 Fit number 100 in .size (text length) 2025-02-23 13:40:41 +01:00
Jakub Vrana
27db0914ca Style auto_increment value 2025-02-23 13:40:14 +01:00
Jakub Vrana
483cbf1616 Fix indent 2025-02-23 13:36:37 +01:00
Jakub Vrana
08a956cf2a Offer original values in multi-row editing (regression from 4.16.0) 2025-02-23 13:28:21 +01:00
Jakub Vrana
9d992e4be6 MySQL: Don't offer empty enum value in edit
MySQL errors if there's an invalid value on the first row of INSERT or
UPDATE, regardless of the sql_mode variable.
2025-02-23 13:24:30 +01:00
Jakub Vrana
7ece69a8c4 Remove unused HTLM attribute 2025-02-23 11:42:05 +01:00
Jakub Vrana
1838df9465 Narrows screens: Move lang and logout under h1 2025-02-23 11:25:07 +01:00
Jakub Vrana
4e6ad13eac Move Logout button on narrow screens
This avoids overlapping Logout and breadcrumb.
The button also didn't display on far right due to width: fit-content.
2025-02-23 10:59:56 +01:00
Jakub Vrana
ba35e11bae Ignore error in dropping old constraint 2025-02-23 08:41:33 +01:00
Jakub Vrana
834f4b6c5b Specify viewport width 2025-02-23 08:35:09 +01:00
Jakub Vrana
176f2923cd Fix comment 2025-02-22 23:18:18 +01:00
Jakub Vrana
aaaca731cd MS SQL: Support CHECK constraint 2025-02-22 21:21:47 +01:00
Jakub Vrana
ee9932a0dd PostgreSQL: Support CHECK constraint 2025-02-22 21:08:23 +01:00
Jakub Vrana
c34c672df9 Support constraint checks in compile 2025-02-22 20:40:14 +01:00
Joe Koop
550289de51 MySQL: Support CHECK constraint
added list of check constraints to mysql table view

added create, alter, drop check constraints (mysql)

chore: use the correct function to sql-escape

fix: feature detection for check constraints (mysql)

fix: get check constraint info (mysql)

correct the capitalization of a section title

to be consistent with the other section titles

added a missing `</thead>`
2025-02-22 20:37:59 +01:00
Jakub Vrana
f652ff807e Update CodeQL 2025-02-22 19:01:06 +01:00
Jakub Vrana
746603bdc7 Update tests 2025-02-22 16:31:02 +01:00
Jakub Vrana
e9d9a30844 Use password in example 2025-02-22 16:21:07 +01:00
Jakub Vrana
4d5de895e2 Use new Katalon format 2025-02-22 16:20:31 +01:00
Jakub Vrana
e282ced59e PostgreSQL: Constraint enum values in editing (bug #270) 2025-02-22 13:42:28 +01:00
Jakub Vrana
20d722b882 PostgreSQL: Link user defined types 2025-02-22 12:36:58 +01:00
Jakub Vrana
c1c3b84fff Fix links to PostgreSQL docs 2025-02-22 12:18:14 +01:00
Jakub Vrana
b176a0fbd4 Add TODO 2025-02-22 12:16:15 +01:00
Jakub Vrana
8456779e18 MS SQL: Allow changing default values 2025-02-22 11:08:23 +01:00
Jakub Vrana
3b69ff4ce2 MS SQL: Fix length of nvarchar columns 2025-02-22 10:39:14 +01:00
Jakub Vrana
3a101e873f MS SQL: Allow adding default values 2025-02-22 10:36:44 +01:00
Jakub Vrana
6ecef5eca6 MS SQL: Display default values (bug #732) 2025-02-22 10:11:03 +01:00
Jakub Vrana
707958c63d Remove (beta) from MS SQL 2025-02-22 09:50:20 +01:00
Jakub Vrana
5d18df1d82 MS SQL: Allow altering table in non-default schema (bug #405) 2025-02-22 09:42:36 +01:00
Jakub Vrana
8602304d86 Hide index column options by default 2025-02-22 09:25:39 +01:00
Jakub Vrana
e744fecd98 Make space for the Use button 2025-02-22 08:12:04 +01:00
Jakub Vrana
b58e03f5fc Editor: PDO: Select value of foreign key in edit (bug #847) 2025-02-22 07:56:22 +01:00
Jakub Vrana
40a86bffa2 Add HTML newlines 2025-02-21 21:40:59 +01:00
Jakub Vrana
b7b22486b2 Fix undefined variable in SQL export 2025-02-21 21:35:25 +01:00
Jakub Vrana
cbf7373b54 Wrap long lines in designs 2025-02-21 21:31:58 +01:00
Jakub Vrana
b29767dcfb Use CSS to highlight odd rows 2025-02-21 21:27:41 +01:00
Jakub Vrana
db75be9ba7 Add TODO 2025-02-21 18:40:07 +01:00
Jakub Vrana
67c991846e Hide collations if empty 2025-02-21 18:21:41 +01:00
Jakub Vrana
7d3266b369 MySQL: Fix links to information_schema help 2025-02-21 17:31:56 +01:00
Sebastian Butsch
5f3a820571 Set body width to auto 2025-02-21 17:20:17 +01:00
Jakub Vrana
e7df6bf616 Remove CSS vendor prefixes 2025-02-21 17:01:54 +01:00
Jakub Vrana
1d8bd0a210 Wrap connection error message 2025-02-21 14:29:22 +01:00
Jakub Vrana
6fe9827eea Trim trailing whitespace 2025-02-21 13:59:17 +01:00
Jakub Vrána
7900062d4d Update funding 2025-02-21 11:57:52 +01:00
Jakub Vrana
63cffbbc8a Fix style 2025-02-21 10:57:11 +01:00
Jakub Vrana
0b3baa1e23 Fix Latvian plurals 2025-02-21 09:40:31 +01:00
Jakub Vrana
e3fbc56b6f SQLite: Show all supported pragmas in Variables 2025-02-20 18:11:18 +01:00
Jakub Vrana
00607012af Update TODO 2025-02-20 17:59:02 +01:00
Jakub Vrana
e4e5941b90 Wrap long lines 2025-02-20 17:58:00 +01:00
Jakub Vrana
097f2a1242 Develop 2025-02-20 16:40:14 +01:00
Jakub Vrana
c81bed0baa Fix indent 2025-02-20 16:27:39 +01:00
Jakub Vrana
9c9fc4a85b Release 4.16.0 2025-02-20 15:58:15 +01:00
Jakub Vrana
b46b1dd574 Fix typo in comment 2025-02-20 11:47:38 +01:00
Jakub Vrana
f248fb29b1 PostgreSQL: Support adding auto_increment (bug #761) 2025-02-20 11:13:50 +01:00
Jakub Vrana
94f75f9798 PostgreSQL: Support dropping auto_increment 2025-02-20 11:12:39 +01:00
Jakub Vrana
f2e2c6e4ac SQLite: Fix expressions in default values (bug #860) 2025-02-20 09:37:43 +01:00
Jakub Vrana
e321a26ee5 Move functions unused in Editor 2025-02-20 09:11:59 +01:00
Jakub Vrana
f35dd89c65 Fix style 2025-02-20 08:37:13 +01:00
Bilal Yameen
8f2b4ced62 Dark theme for Adminer 2025-02-19 21:22:57 +01:00
Peter Knut
5eb3446908 MSSQL: Allow to set Encrypt and TrustServerCertificate with AdminerLoginSsl plugin (issue #5)
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/connection-string-syntax#use-trustservercertificate
2025-02-19 21:20:53 +01:00
Peter Knut
a685d414ad Change version layout 2025-02-19 20:47:36 +01:00
Pavel Železný
7c9fec4e6b Fix mysqli ssl without server certificate 2025-02-19 20:17:48 +01:00
araisch
224cbfed56 MySQL SSL: Allow disabling cert verification 2025-02-19 19:20:37 +01:00
Jakub Vrana
490d274662 Update TODO 2025-02-19 19:10:36 +01:00
Peter Knut
3a27c4f64c Editor: Fix searching in tables
Thanks to ytetsuro (https://github.com/vrana/adminer/pull/473)
2025-02-19 19:04:47 +01:00
Jakub Vrana
bd6ebcaab9 Remove spaces 2025-02-19 19:00:47 +01:00
Peter Knut
1f97968e65 PostgreSQL: Allow to set connection's sslmode with AdminerLoginSsl plugin
Thanks to wodka (https://github.com/vrana/adminer/pull/427/files)
2025-02-19 18:54:24 +01:00
Vladimir
dfb33a323d Add .gitattributes, exclude tests from archive 2025-02-19 17:03:34 +01:00
Jakub Vrana
869c2b92ea Remove design submodules 2025-02-19 15:13:46 +01:00
Jakub Vrana
675dbaad73 SQLite: Fix getting result of queries with no rows 2025-02-19 15:06:55 +01:00
Jakub Vrana
a001a3a061 SQLite: Fix altering forign keys (bug #841) 2025-02-19 15:02:11 +01:00
Jakub Vrana
df451f4374 MySQL: Fix saving bit(64) values (bug #839) 2025-02-19 14:57:41 +01:00
Jakub Vrana
9def8d7f95 MS SQL: Foreign keys in non-default schema (bug #833) 2025-02-19 14:36:54 +01:00
Vladimir Goncharov
2385bf72bd support for array values in clickhouse driver 2025-02-19 14:36:07 +01:00
Jakub Vrana
12427467f7 Fix lowercase title 2025-02-19 14:36:07 +01:00
Jakub Vrana
2bec4ca11b Avoid global variables in plugins drivers 2025-02-19 14:36:07 +01:00
panji
e676303a26 MongoDB: Execute commands against the selected DB 2025-02-19 14:36:04 +01:00
Jakub Vrana
9261abc415 PostgreSQL: Preserve whitespace in EXPLAIN (bug #827) 2025-02-19 14:35:19 +01:00
Jakub Vrana
e5c05fe26c Elastic 5: Do not set Content-Type without content 2025-02-19 12:31:44 +01:00
Tim Alexander
21bf7e0570 Fix German Translation Errors 2025-02-19 12:07:19 +01:00
Jakub Vrana
93f04464a2 Oracle: Remove NOT REGEXP (bug #804) 2025-02-19 11:16:46 +01:00
Jakub Vrana
e03713ce2d Add LICENSE 2025-02-19 11:16:46 +01:00
Takashi SHIRAI
2da5683b99 Support to access tablespaces of granted tables
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-19 11:16:46 +01:00
Jakub Vrana
8ff20622fb Develop 2025-02-19 11:16:46 +01:00
Jakub Vrana
9ef14dbf77 Release 2025-02-19 11:16:46 +01:00
Jakub Vrana
274fa2259b Escape unknown field in select 2025-02-19 11:16:45 +01:00
Jakub Vrana
7541149522 Use Unicode 2025-02-19 11:16:45 +01:00
Jakub Vrana
2a3626faae SimpleDB: Disable XML entity loader 2025-02-19 11:16:45 +01:00
Jakub Vrana
d94e348f57 Use a better random string 2025-02-19 11:16:45 +01:00
Jakub Vrana
51dbfb6987 Hide error message from HTTP servers 2025-02-19 11:16:45 +01:00
Jakub Vrana
578c9fca92 Don't allow path in HTTP servers 2025-02-19 11:16:45 +01:00
Jakub Vrana
d9289355d7 Fix style 2025-02-19 11:16:45 +01:00
Jakub Vrana
874b9ee746 Use autofocus HTML attribute 2025-02-19 11:16:45 +01:00
Jakub Vrana
17974cdf76 VersionNoverify plugin: Do not block other plugins 2025-02-19 11:16:44 +01:00
Jakub Vrana
2d8b6ec771 Add PHP 8.1-8.4 2025-02-19 11:16:44 +01:00
Adrian Jones
5982060f3b Fix links to MySQL docs
It was directing to https://dev.mysql.com/doc/refman/9.2en/select.html instead of https://dev.mysql.com/doc/refman/9.2/en/select.html
2025-02-19 11:16:44 +01:00
Saiful Alam Rakib
6496ff5a47 Fix the UI of pappu687 for latest version 2025-02-19 11:16:44 +01:00
Jakub Vrana
6aa55d806b Bump version 2025-02-19 11:16:44 +01:00
Peter Knut
0ef358a6b5 Release 4.14.0 2025-02-19 11:16:44 +01:00
Peter Knut
882e9d02a0 PostgreSQL: Fix renaming database 2025-02-19 11:16:44 +01:00
Peter Knut
e346f47384 PostgreSQL: Fix starting value of exported autoincrement
Thanks to @OmlineEditor (https://github.com/adminerevo/adminerevo/issues/113)
2025-02-19 11:16:44 +01:00
Peter Knut
fdd02a5485 Modify naming of new foreign rows
Regexp is used to unify implementation with other similar situations. This also prevents false detection in CodeQL security scanning.
2025-02-19 11:16:43 +01:00
Lucas Sandery
7238bc7900 Update lucas-sandery theme
::file-selector-button got standardised.
2025-02-19 11:16:43 +01:00
Peter Knut
15ac0889c0 Bump version to 4.14-dev 2025-02-19 11:16:43 +01:00
Peter Knut
ab40931365 Fix main visual glitches in designs, remove broken designs 2025-02-19 11:16:43 +01:00
Peter Knut
5d6e9fff65 Bump version to 4.12.1-dev 2025-02-19 11:16:43 +01:00
Kian-Meng Ang
d6d86fa26a Fix some typos
https://github.com/adminerevo/adminerevo/pull/210
2025-02-19 11:16:43 +01:00
Peter Knut
f25ffb36f9 Update German translation
Thanks to wintstar (https://github.com/adminerevo/adminerevo/issues/219)
2025-02-19 11:16:43 +01:00
Peter Knut
49fd7858ac Release 4.12 2025-02-19 11:16:43 +01:00
Peter Knut
0628b8de02 MSSQL, MongoDB: Connect to localhost with default port if server is not specified 2025-02-19 11:16:42 +01:00
Peter Knut
99434644ef MongoDB: Fix parsing WHERE condition from SQL query
Thanks to herobank110 (https://github.com/vrana/adminer/pull/491)
2025-02-19 11:16:42 +01:00
vukbgit
5492b3e055 MariaDB: Add support for UUID data type
- MariaDB >= 10.7
- UUID string data type
- uuid() function for UUID type on new/edit item form
2025-02-19 11:16:42 +01:00
Peter Knut
84b69da58d Fix SQL query code direction if RTL language is used 2025-02-19 11:16:42 +01:00
Peter Knut
a51d0f4701 Bump version to 4.12.0-dev 2025-02-19 11:16:42 +01:00
Peter Knut
7cd82c8fd7 Release 4.11 2025-02-19 11:16:42 +01:00
Peter Knut
d065c9ba51 MySQL: Fix highlighting current table in menu on macOS 2025-02-19 11:16:41 +01:00
Peter Knut
f79340a0b5 Update CS and SK translations 2025-02-19 11:16:41 +01:00
HyP3r
4bc9a29f3e MS SQL: Prefix Unicode strings with 'N' so they are treated correctly 2025-02-19 11:16:41 +01:00
Peter Knut
81530227c2 MariaDB: Fix several links to documentation pages 2025-02-19 11:16:41 +01:00
Peter Knut
d8217d6ee2 Bump version to 4.10.1-dev 2025-02-19 11:16:41 +01:00
Peter Knut
02c13131e3 Release 4.10.0 2025-02-19 11:16:41 +01:00
Jakub Vrana
21c339901c PHP <5.6 compatibility 2025-02-19 11:16:41 +01:00
Peter Knut
06c4fd4855 Print username next to the logout button 2025-02-19 11:16:41 +01:00
Peter Knut
0a473cef18 Update readme.txt 2025-02-19 11:16:41 +01:00
Roy-Orbison
652a09bb91 Plugin to auto-include adminer.js when present 2025-02-19 11:16:40 +01:00
Peter Knut
47a9453ace Do not display empty action links in main menu 2025-02-19 11:16:40 +01:00
Peter Knut
d4f99d5cdc Bump version to 4.10-dev 2025-02-19 11:16:40 +01:00
Peter Knut
72ed1b5cdc Release 4.9.4 2025-02-19 11:16:40 +01:00
Peter Knut
4e825a36d3 Editor: Fix building links with array parameters
This solves a situation when enum data type has a foreign key to another table.
2025-02-19 11:16:40 +01:00
Peter Knut
927444ffdd Editor: Fix array conversion to string (issue #3) 2025-02-19 11:16:40 +01:00
Peter Knut
d9976c25fc Firefox: Fix opening a database to the new browser's tab with Ctrl+click 2025-02-19 11:16:40 +01:00
Peter Knut
c5fa212b26 Unify displaying of 'New item' action based on privileges 2025-02-19 11:16:40 +01:00
Peter Knut
edef2b1a3d Fix the width of inline edit field 2025-02-19 11:16:39 +01:00
Peter Knut
7eccd59856 Bump version to 4.9.4-dev 2025-02-19 11:16:39 +01:00
Peter Knut
476b957565 Release 4.9.3 2025-02-19 11:16:39 +01:00
Peter Knut
8e43fffe53 Hide invalid edit form if table record is not found 2025-02-19 11:16:39 +01:00
Peter Knut
d2c6ea21b6 PostgreSQL: Fix editing record that contains a field with GENERATED ALWAYS default value
Fields with GENERATED ALWAYS default values are also disabled.

Thanks to PurpleTape (https://github.com/adminerevo/adminerevo/issues/201).
2025-02-19 11:16:39 +01:00
SeaEagle
a310d52327 MySQL: Fix where clause for JSON column
Issue: https://github.com/adminerevo/adminerevo/issues/175
2025-02-19 11:16:39 +01:00
Peter Knut
0717bce535 Fix background color of <pre> used as edit field 2025-02-19 11:16:39 +01:00
Peter Knut
53aad3bb62 Do not include unchanged PARTITION BY definition into ALTER TABLE query 2025-02-19 11:16:39 +01:00
Peter Knut
99cd514a29 MariaDB: Fix comparing CURRENT_TIMESTAMP definition while altering a table 2025-02-19 11:16:39 +01:00
Peter Knut
8ea4892523 MySQL, PostgreSQL: Fix queries splitting and string constants
Thanks to alxivnov (https://github.com/vrana/adminer/pull/490).
2025-02-19 11:16:38 +01:00
Michael Graß
74e4bb9a6f Do not limit unlimited memory, fix number conversion warning 2025-02-19 11:16:38 +01:00
Peter Knut
3d2d39e7d0 Bump version to 4.9.3-dev 2025-02-19 11:16:38 +01:00
Peter Knut
06a4d294bd Release 4.9.2 2025-02-19 11:16:38 +01:00
Peter Knut
0d5e5819a0 Basic JS code cleanup 2025-02-19 11:16:38 +01:00
khoazero123
b17ffcc512 PostgreSQL: Fix exporting CREATE TABLE with sequence default value 2025-02-19 11:16:38 +01:00
Roy-Orbison
d91bd659a5 Function to retrieve driver name
Plugins cannot access $drivers global after compilation.
2025-02-19 11:16:38 +01:00
Peter Knut
1efb87fcbe PostgreSQL: Fix exporting CREATE TABLE query with GENERATED default values
Thanks to GottfriedCP (https://github.com/adminerevo/adminerevo/issues/157)
2025-02-19 11:16:38 +01:00
Peter Knut
d8f1521b60 PostreSQL: Fix search condition for network address types, add macaddr8 type
This fixes issue https://github.com/adminerevo/adminerevo/issues/115
2025-02-19 11:16:38 +01:00
Peter Knut
cb6e2f9a86 Bump version to 4.9.2-dev 2025-02-19 11:16:37 +01:00
Peter Knut
4824c578bf Release 4.9.1 2025-02-19 11:16:37 +01:00
Jakub Vrana
f4607d763c Ignore undefined property PHP warning 2025-02-19 11:16:37 +01:00
Peter Knut
12293ce215 PostgreSQL: Fix documentation link for SERIAL type
Thanks to leggiero (https://github.com/vrana/adminer/pull/432)
2025-02-19 11:16:37 +01:00
caltong
c47d933ab0 PostgreSQL: Make data length calculation more accurate 2025-02-19 11:16:37 +01:00
Thomas Daniels
6e6785ebc4 PostgreSQL: Show only accessible databases 2025-02-19 11:16:37 +01:00
Peter Knut
6d848bf165 Replace deprecated <acronym> with <abbr> 2025-02-19 11:16:37 +01:00
Peter Knut
2189947c43 AdminerLoginOtp: Autocomplete hints for OTP input field, code refactoring
Tanks to SGCBB (https://github.com/vrana/adminer/pull/488)
2025-02-19 11:16:37 +01:00
Sneda8
b6f9f58712 PHP 8.3 error suppression
PHP 8.3 has shortened the array access on null error message to "Trying to access array offset on null". This commit changes the regular expression used to circumvent errors.
2025-02-19 11:16:36 +01:00
Peter Knut
fdeb9557cd Improved displaying of long table names in menu 2025-02-19 11:16:36 +01:00
Peter Knut
11e1290b5b Add .editorconfig file
Thanks to cweiske (https://github.com/adminerevo/adminerevo/pull/163).
2025-02-19 11:16:36 +01:00
Peter Knut
ac9fd04f87 Fix field selection in Elasticsearch
Thanks to cweiske: https://github.com/adminerevo/adminerevo/pull/159
2025-02-19 11:16:36 +01:00
Peter Knut
2128c05e53 Bump version to 4.9.1-dev 2025-02-19 11:16:36 +01:00
Peter Knut
550db0691e Release 4.9 2025-02-19 11:16:36 +01:00
Adrian Jones
4484f5f620 Fix uninitialized string offset
This can happen if you include an unpaired single or double quote, eg: SELECT * FROM table_name WHERE field_name = 'test
2025-02-19 11:16:36 +01:00
Denitz
c2f8ccc8d8 Skip dump of generated columns 2025-02-19 11:16:36 +01:00
Peter Knut
bd279b2758 Update changes.txt 2025-02-19 11:16:36 +01:00
Peter Knut
76575a95f1 Move Elastic drivers to plugins, driver for Elastic 7+ is the default 2025-02-19 11:16:35 +01:00
Peter Knut
95bab4c077 Modify tables hierarchy for Elasticsearch 7
- Properly display list of databases, indexes, aliases and fields.
- Fix search and delete queries.
2025-02-19 11:16:35 +01:00
Peter Knut
e85af88227 New Elasticsearch 7 plugin as a copy of the old one 2025-02-19 11:16:35 +01:00
Peter Knut
c6bb98ad22 Improve code readability by using of empty lines 2025-02-19 11:16:35 +01:00
Peter Knut
2a0f17b6d9 Compatibility with Elasticsearch 7.14
- Removed empty body from requests.
- Fix deleting records.
2025-02-19 11:16:35 +01:00
Peter Knut
dc1ad9e8ed Fix global search in all tables 2025-02-19 11:16:35 +01:00
Peter Knut
1270748f74 Fix version condition for deprecated mapping types
Mapping types are still supported in version 6, but only one mapping type can be created.
In version 7, mapping types are deprecated and there is only one system '_doc' mapping type.
See: https://www.elastic.co/guide/en/elasticsearch/reference/6.0/removal-of-types.html
2025-02-19 11:16:35 +01:00
Peter Knut
266fda37a1 Fix searching if "anywhere" field is selected
- Allow to search only in fields with index.
2025-02-19 11:16:35 +01:00
Peter Knut
1f14ab470f Replace deprecated "filtered" query with "bool" query
- Allow to choose "must", "should", "must_not" condition.
- Add system "_id" column to the field list. So it can be used in search condition.
2025-02-19 11:16:35 +01:00
Peter Knut
501234c2d1 Fix undefined $sql variable 2025-02-19 11:16:34 +01:00
Peter Knut
197ab976b8 Update changes.txt 2025-02-16 18:03:17 +01:00
Peter Knut
b2759df1f9 Disable redirections in HTTP based drivers 2025-02-16 18:03:17 +01:00
Peter Knut
de07f00ccb Bump version to 4.9.0-dev 2025-02-16 18:03:16 +01:00
Peter Knut
031d2c6a34 Make jush and JsShring submodules available 2025-02-16 18:03:16 +01:00
Lucas Sandery
e2810adc05 Allow responsive styles on larger devices
and fix a media query.

Signed-off-by: Lucas Sandery <lucas-sandery@users.noreply.github.com>
(cherry picked from commit 4b0b011b93f9b684e5ab81f493f239f478fc3f2b)
2025-02-16 18:03:16 +01:00
Peter Knut
baeeb362f7 Fix and complete Slovak translation 2025-02-16 18:03:16 +01:00
Lukáš Rajchl
347ac77bab Update Czech translation
(cherry picked from commit 7338eadd7c)
2025-02-16 18:03:16 +01:00
Anastasia
6b9eb3f446 Update Russian translation
(cherry picked from commit 33fcfbc13b)
2025-02-16 18:03:16 +01:00
Gerry Demaret
f58b13e994 Update Dutch translation
(cherry picked from commit 6024d73ae6)
2025-02-16 18:03:16 +01:00
Lionel Laffineur
fe295bc78a Update French and Italian translations
(cherry picked from commit 496ab9a262)
2025-02-16 18:03:09 +01:00
Hossain Ahmed Saiman
b39469eb9f Bangla language corrections
Some informal words has been replaced with formal words. Some incorrect words has been corrected.

(cherry picked from commit a4ebae8706)

(cherry picked from commit 965598b640)
2025-02-15 14:05:39 +01:00
@krysits.COM
20684a5166 Add Latvian language translation
(cherry picked from commit fad4ce785b)
2025-02-15 14:04:34 +01:00
195 changed files with 7848 additions and 6325 deletions

20
.editorconfig Normal file
View File

@@ -0,0 +1,20 @@
# https://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{php,css,js,xml}]
indent_style = tab
[*.json]
indent_style = space
indent_size = 4
[*.md]
indent_style = space
trim_trailing_whitespace = false
max_line_length = 120

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.gitmodules export-ignore
/.travis.yml export-ignore
/tests export-ignore

3
.github/FUNDING.yml vendored
View File

@@ -1,2 +1,3 @@
github: vrana
patreon: jakubvrana
custom: ["https://sourceforge.net/p/adminer/donate/"]
custom: ["https://www.paypal.com/donate/?item_name=Donation+to+Adminer&business=jakub%40vrana.cz"]

View File

@@ -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@v1
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@v1
# 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@v1

10
.gitmodules vendored
View File

@@ -1,12 +1,6 @@
[submodule "jush"]
path = externals/jush
url = git://github.com/vrana/jush
url = https://github.com/vrana/jush
[submodule "JsShrink"]
path = externals/JsShrink
url = git://github.com/vrana/JsShrink
[submodule "designs/hydra"]
path = designs/hydra
url = https://github.com/Niyko/Hydra-Dark-Theme-for-Adminer
[submodule "designs/pepa-linha-dark"]
path = designs/pepa-linha-dark
url = https://github.com/pepa-linha/Adminer-Design-Dark/
url = https://github.com/vrana/JsShrink

View File

@@ -6,4 +6,8 @@ php:
- 7.3
- 7.4
- 8.0
- 8.1
- 8.2
- 8.3
- 8.4
script: git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.php$' | xargs -n1 -P8 php -l | grep -v 'No syntax errors'; test $? -eq 1

1
LICENSE Normal file
View File

@@ -0,0 +1 @@
Apache License 2.0 or GPL 2

View File

@@ -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"));
@@ -32,7 +34,7 @@ if (!$error && $_POST) {
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
$start = microtime(true);
$result = $connection->multi_query($query);
$affected = $connection->affected_rows; // getting warnigns overwrites this
$affected = $connection->affected_rows; // getting warnings overwrites this
echo $adminer->selectQuery($query, $start, !$result);
if (!$result) {
@@ -64,7 +66,7 @@ if (!$error && $_POST) {
<form action="" method="post">
<?php
if ($in) {
echo "<table cellspacing='0' class='layout'>\n";
echo "<table class='layout'>\n";
foreach ($in as $key) {
$field = $routine["fields"][$key];
$name = $field["field"];
@@ -88,3 +90,25 @@ if ($in) {
<input type="submit" value="<?php echo lang('Call'); ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>
<pre>
<?php
function pre_tr($s) {
return preg_replace('~^~m', '<tr>', preg_replace('~\|~', '<td>', preg_replace('~\|$~m', "", rtrim($s))));
}
$table = '(\+--[-+]+\+\n)';
$row = '(\| .* \|\n)';
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)&gt; )(.+)~',
"\\1<code class='jush-sql'>\\3</code>",
preg_replace('~(.+)\n---+\n~', "<b>\\1</b>\n", h($routine['comment']))
)
);
?>
</pre>

51
adminer/check.inc.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
namespace Adminer;
$TABLE = $_GET["check"];
$name = $_GET["name"];
$row = $_POST;
if ($row && !$error) {
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),
($row["drop"] ? lang('Check has been dropped.') : ($name != "" ? lang('Check has been altered.') : lang('Check has been created.'))),
$result
);
}
page_header(($name != "" ? lang('Alter check') . ": " . h($name) : lang('Create check')), $error, array("table" => $TABLE));
if (!$row) {
$checks = $driver->checkConstraints($TABLE);
$row = array("name" => $name, "clause" => $checks[$name]);
}
?>
<form action="" method="post">
<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 } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -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,22 +48,19 @@ 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;
}
if ($key == $row["auto_increment_col"]) {
$field["auto_increment"] = true;
}
$process_field = process_field($field, $type_field);
$all_fields[] = array($field["orig"], $process_field, $after);
if (!$orig_field || $process_field != process_field($orig_field, $orig_field)) {
if (!$orig_field || $process_field !== process_field($orig_field, $orig_field)) {
$fields[] = array($field["orig"], $process_field, $after);
if ($field["orig"] != "" || $after) {
$use_all_fields = true;
}
}
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"]),
@@ -82,21 +81,40 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
}
$partitioning = "";
if ($partition_by[$row["partition_by"]]) {
if (support("partitioning")) {
if (isset($partition_by[$row["partition_by"]])) {
$params = array_filter($row, function ($key) {
return preg_match('~^partition~', $key);
}, ARRAY_FILTER_USE_KEY);
foreach ($params["partition_names"] as $key => $name) {
if ($name == "") {
unset($params["partition_names"][$key]);
unset($params["partition_values"][$key]);
}
}
if ($params != get_partitions_info($TABLE)) {
$partitions = array();
if ($row["partition_by"] == 'RANGE' || $row["partition_by"] == 'LIST') {
foreach (array_filter($row["partition_names"]) as $key => $val) {
$value = $row["partition_values"][$key];
$partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($row["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
foreach ($params["partition_names"] as $key => $name) {
$value = $params["partition_values"][$key];
$partitions[] = "\n PARTITION " . idf_escape($name) . " VALUES " . ($params["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
}
}
$partitioning .= "\nPARTITION BY $row[partition_by]($row[partition])" . ($partitions // $row["partition"] can be expression, not only column
? " (" . implode(",", $partitions) . "\n)"
: ($row["partitions"] ? " PARTITIONS " . (+$row["partitions"]) : "")
);
} elseif (support("partitioning") && preg_match("~partitioned~", $table_status["Create_options"])) {
// $params["partition"] can be expression, not only column
$partitioning .= "\nPARTITION BY $params[partition_by]($params[partition])";
if ($partitions) {
$partitioning .= " (" . implode(",", $partitions) . "\n)";
} elseif ($params["partitions"]) {
$partitioning .= " PARTITIONS " . (+$params["partitions"]);
}
}
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
$partitioning .= "\nREMOVE PARTITIONING";
}
}
$message = lang('Table has been altered.');
if ($TABLE == "") {
@@ -108,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"] : ""),
@@ -122,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" => "")),
@@ -136,18 +155,14 @@ 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;
}
if (support("partitioning")) {
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($TABLE);
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row();
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
$partitions[""] = "";
$row["partition_names"] = array_keys($partitions);
$row["partition_values"] = array_values($partitions);
$row += get_partitions_info($TABLE);
$row["partition_names"][] = "";
$row["partition_values"][] = "";
}
}
}
@@ -166,16 +181,15 @@ foreach ($engines as $engine) {
<form action="" method="post" id="form">
<p>
<?php if (support("columns") || $TABLE == "") { ?>
<?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?>
<?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 } ?>
<?php if (support("columns")) { ?>
<div class="scrollable">
<table cellspacing="0" id="edit-fields" class="nowrap">
<table id="edit-fields" class="nowrap">
<?php
edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
?>
@@ -183,7 +197,7 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
<?php echo script("editFields();"); ?>
</div>
<p>
<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
<?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"));
@@ -200,7 +214,9 @@ echo (support("comment")
<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"]);
@@ -210,7 +226,7 @@ if (support("partitioning")) {
<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?>
(<input name="partition" value="<?php echo h($row["partition"]); ?>">)
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
<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) {

View File

@@ -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]) {
@@ -59,14 +61,13 @@ if ($_POST) {
<p>
<?php
echo ($_POST["add_x"] || strpos($name, "\n")
? '<textarea id="name" name="name" rows="10" cols="40">' . h($name) . '</textarea><br>'
: '<input name="name" id="name" value="' . h($name) . '" data-maxlength="64" autocapitalize="off">'
? '<textarea autofocus name="name" rows="10" cols="40">' . h($name) . '</textarea><br>'
: '<input name="name" autofocus value="' . h($name) . '" data-maxlength="64" autocapitalize="off">'
) . "\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",
)) : "");
echo script("focus(qs('#name'));");
?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php

View File

@@ -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>";
}
@@ -61,12 +69,12 @@ if ($adminer->homepage()) {
echo " <input type='submit' name='search' value='" . lang('Search') . "'>\n";
echo "</div></fieldset>\n";
if ($_POST["search"] && $_POST["query"] != "") {
$_GET["where"][0]["op"] = "LIKE %%";
$_GET["where"][0]["op"] = $driver->convertOperator("LIKE %%");
search_tables();
}
}
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo "<table class='nowrap checkable odds'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);", "");
@@ -85,13 +93,14 @@ if ($adminer->homepage()) {
foreach ($tables_list as $name => $type) {
$view = ($type !== null && !preg_match('~table|sequence~i', $type));
$id = h("Table-" . $name);
echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "", "", $id);
echo '<tr><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "", "", $id);
echo '<th>' . (support("table") || support("indexes") ? "<a href='" . h(ME) . "table=" . urlencode($name) . "' title='" . lang('Show structure') . "' id='$id'>" . h($name) . '</a>' : h($name));
if ($view) {
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '" title="' . lang('Alter view') . '">' . (preg_match('~materialized~i', $type) ? lang('Materialized view') : lang('View')) . '</a>';
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '" title="' . lang('Select data') . '">?</a>';
} else {
foreach (array(
foreach (
array(
"Engine" => array(),
"Collation" => array(),
"Data_length" => array("create", lang('Alter table')),
@@ -99,7 +108,8 @@ if ($adminer->homepage()) {
"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) {
) 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>"
@@ -109,32 +119,35 @@ if ($adminer->homepage()) {
$tables++;
}
echo (support("comment") ? "<td id='Comment-" . h($name) . "'>" : "");
echo "\n";
}
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'>";
}
echo "\n";
echo "</table>\n";
echo "</div>\n";
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">');
@@ -159,12 +172,11 @@ if ($adminer->homepage()) {
echo "<h3 id='routines'>" . lang('Routines') . "</h3>\n";
$routines = routines();
if ($routines) {
echo "<table cellspacing='0'>\n";
echo "<table class='odds'>\n";
echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td></thead>\n";
odd('');
foreach ($routines as $row) {
$name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first
echo '<tr' . odd() . '>';
echo '<tr>';
echo '<th><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . h($row["ROUTINE_NAME"]) . '</a>';
echo '<td>' . h($row["ROUTINE_TYPE"]);
echo '<td>' . h($row["DTD_IDENTIFIER"]);
@@ -182,11 +194,10 @@ if ($adminer->homepage()) {
echo "<h3 id='sequences'>" . lang('Sequences') . "</h3>\n";
$sequences = get_vals("SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = current_schema() ORDER BY sequence_name");
if ($sequences) {
echo "<table cellspacing='0'>\n";
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Name') . "</thead>\n";
odd('');
foreach ($sequences as $val) {
echo "<tr" . odd() . "><th><a href='" . h(ME) . "sequence=" . urlencode($val) . "'>" . h($val) . "</a>\n";
echo "<tr><th><a href='" . h(ME) . "sequence=" . urlencode($val) . "'>" . h($val) . "</a>\n";
}
echo "</table>\n";
}
@@ -197,11 +208,10 @@ if ($adminer->homepage()) {
echo "<h3 id='user-types'>" . lang('User types') . "</h3>\n";
$user_types = types();
if ($user_types) {
echo "<table cellspacing='0'>\n";
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Name') . "</thead>\n";
odd('');
foreach ($user_types as $val) {
echo "<tr" . odd() . "><th><a href='" . h(ME) . "type=" . urlencode($val) . "'>" . h($val) . "</a>\n";
echo "<tr><th><a href='" . h(ME) . "type=" . urlencode($val) . "'>" . h($val) . "</a>\n";
}
echo "</table>\n";
}
@@ -212,7 +222,7 @@ if ($adminer->homepage()) {
echo "<h3 id='events'>" . lang('Events') . "</h3>\n";
$rows = get_rows("SHOW EVENTS");
if ($rows) {
echo "<table cellspacing='0'>\n";
echo "<table>\n";
echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "<td></thead>\n";
foreach ($rows as $row) {
echo "<tr>";

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["download"];
$fields = fields($TABLE);
header("Content-Type: application/octet-stream");

View File

@@ -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->executeCommand('admin', array('ping' => 1));
$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,93 +110,14 @@ 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;
$return = array();
foreach ($connection->executeCommand('admin', array('listDatabases' => 1)) as $dbs) {
foreach ($connection->executeCommand($connection->_db_name, array('listDatabases' => 1)) as $dbs) {
foreach ($dbs->databases as $db) {
$return[] = $db->name;
}
@@ -480,7 +198,11 @@ if (isset($_GET["mongo"])) {
}
function sql_query_where_parser($queryWhere) {
$queryWhere = preg_replace('~^\sWHERE \(?\(?(.+?)\)?\)?$~', '\1', $queryWhere);
$queryWhere = preg_replace('~^\s*WHERE\s*~', "", $queryWhere);
while ($queryWhere[0] == "(") {
$queryWhere = preg_replace('~^\((.*)\)$~', "$1", $queryWhere);
}
$wheres = explode(' AND ', $queryWhere);
$wheresOr = explode(') OR (', $queryWhere);
$where = array();
@@ -513,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) {
@@ -553,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(
"=",
"!=",
">",
@@ -576,7 +306,77 @@ 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;
@@ -623,8 +423,13 @@ if (isset($_GET["mongo"])) {
function connect() {
global $adminer;
$connection = new Min_DB;
$connection = new Db;
list($server, $username, $password) = $adminer->credentials();
if ($server == "") {
$server = "localhost:27017";
}
$options = array();
if ($username . $password != "") {
$options["username"] = $username;
@@ -730,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")),
);
}
}

View File

@@ -5,12 +5,14 @@
* @author Jakub Vrana
*/
$drivers["mssql"] = "MS SQL (beta)";
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() {
@@ -24,8 +26,15 @@ if (isset($_GET["mssql"])) {
function connect($server, $username, $password) {
global $adminer;
$db = $adminer->database();
$connection_info = array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8");
$ssl = $adminer->connectSsl();
if (isset($ssl["Encrypt"])) {
$connection_info["Encrypt"] = $ssl["Encrypt"];
}
if (isset($ssl["TrustServerCertificate"])) {
$connection_info["TrustServerCertificate"] = $ssl["TrustServerCertificate"];
}
$db = $adminer->database();
if ($db != "") {
$connection_info["Database"] = $db;
}
@@ -40,11 +49,12 @@ if (isset($_GET["mssql"])) {
}
function quote($string) {
return "'" . str_replace("'", "''", $string) . "'";
$unicode = strlen($string) != strlen(utf8_decode($string));
return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'";
}
function select_db($database) {
return $this->query("USE " . idf_escape($database));
return $this->query(use_sql($database));
}
function query($query, $unbuffered = false) {
@@ -75,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;
@@ -95,7 +105,7 @@ if (isset($_GET["mssql"])) {
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $_fields, $num_rows;
function __construct($result) {
@@ -126,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);
@@ -144,105 +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) {
return "'" . 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) {
@@ -251,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) {
$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) {
$update[] = "$key = $val";
if (isset($primary[idf_unescape($key)])) {
$where[] = "$key = $val";
$c++;
$name = idf_unescape($key);
if (!$fields[$name]["auto_increment"]) {
$insert[$key] = "c$c";
}
if (isset($primary[$name])) {
$where[] = "$key = c$c";
} else {
$update[] = "$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;
$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");
}
return true;
} 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";
}
}
}
@@ -299,8 +282,13 @@ if (isset($_GET["mssql"])) {
function connect() {
global $adminer;
$connection = new Min_DB;
$connection = new Db;
$credentials = $adminer->credentials();
if ($credentials[0] == "") {
$credentials[0] = "localhost:1433";
}
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
@@ -349,7 +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 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) {
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
) {
if ($name != "") {
return $row;
}
@@ -367,43 +359,56 @@ if (isset($_GET["mssql"])) {
}
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]
$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.parent_column_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.default_constraints d ON c.default_object_id = d.object_id
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 == "decimal" ? "$row[precision],$row[scale]" : ""));
$length = (preg_match("~char|binary~", $type)
? $row["max_length"] / ($type[0] == 'n' ? 2 : 1)
: ($type == "decimal" ? "$row[precision],$row[scale]" : "")
);
$return[$row["name"]] = array(
"field" => $row["name"],
"full_type" => $type . ($length ? "($length)" : ""),
"type" => $type,
"length" => $length,
"default" => $row["default"],
"default" => (preg_match("~^\('(.*)'\)$~", $row["default"], $match) ? str_replace("''", "'", $match[1]) : $row["default"]),
"default_constraint" => $row["default_constraint"],
"null" => $row["is_nullable"],
"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();
@@ -427,7 +432,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function information_schema($db) {
return false;
return get_schema() == "INFORMATION_SCHEMA";
}
function error() {
@@ -440,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) {
@@ -458,6 +463,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = array();
$comments = array();
$orig_fields = fields($table);
foreach ($fields as $field) {
$column = idf_escape($field[0]);
$val = $field[1];
@@ -467,14 +473,28 @@ 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 {
$default = $val[3];
unset($val[3]); // default values are set separately
unset($val[6]); //! identity can't be removed
if ($column != $val[0]) {
queries("EXEC sp_rename " . q(table($table) . ".$column") . ", " . q(idf_unescape($val[0])) . ", 'COLUMN'");
}
$alter["ALTER COLUMN " . implode("", $val)][] = "";
$orig_field = $orig_fields[$field[0]];
if (default_value($orig_field) != $default) {
if ($orig_field["default"] !== null) {
$alter["DROP"][] = " " . idf_escape($orig_field["default_constraint"]);
}
if ($default) {
$alter["ADD"][] = "\n $default FOR $column";
}
}
}
}
}
@@ -488,7 +508,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
$alter[""] = $foreign;
}
foreach ($alter as $key => $val) {
if (!queries("ALTER TABLE " . idf_escape($name) . " $key" . implode(",", $val))) {
if (!queries("ALTER TABLE " . table($name) . " $key" . implode(",", $val))) {
return false;
}
}
@@ -510,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"
} 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]) . ")")) {
) . " (" . implode(", ", $val[2]) . ")")
) {
return false;
}
}
@@ -539,10 +561,14 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
function foreign_keys($table) {
$return = array();
foreach (get_rows("EXEC sp_fkeys @fktable_name = " . q($table)) as $row) {
$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"];
}
@@ -554,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) {
@@ -569,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
@@ -586,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;
@@ -619,19 +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 trigger_sql($table) {
$return = "";
foreach (triggers($table) as $name => $trigger) {
$return .= create_trigger(" ON " . table($table), trigger($name)) . ";";
}
function show_status() {
return array();
return $return;
}
function convert_field($field) {
@@ -642,38 +714,6 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
}
function support($feature) {
return preg_match('~^(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|
}
}

View File

@@ -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 ? 64 : 0) // 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,22 +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 (isset($ssl['verify'])) {
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify'];
}
}
$this->dsn(
@@ -266,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);
}
}
@@ -275,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 ()"));
@@ -332,16 +382,24 @@ 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(($maria ? "information-schema-$name-table/" : str_replace("_", "-", $name) . "-table.html"));
return strtolower("information-schema-" . ($maria ? "$name-table/" : str_replace("_", "-", $name) . "-table.html"));
}
if (DB == "mysql") {
return ($maria ? "mysql$name-table/" : "system-database.html"); //! more precise link
return ($maria ? "mysql$name-table/" : "system-schema.html"); //! more precise link
}
}
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;
}
}
@@ -363,19 +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;
$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;
}
return $connection;
}
$return = $connection->error;
@@ -393,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);
@@ -468,18 +519,15 @@ if (!defined("DRIVER")) {
}
/** Get tables list
* @return array array($name => $type)
* @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 array($db => $tables)
* @return array [$db => $tables]
*/
function count_tables($databases) {
$return = array();
@@ -492,14 +540,17 @@ if (!defined("DRIVER")) {
/** Get table status
* @param string
* @param bool return only "Name", "Engine" and "Comment" fields
* @return array 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)
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) {
) as $row
) {
if ($row["Engine"] == "InnoDB") {
// ignore internal comment, unnecessary since MySQL 5.1.21
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]);
@@ -508,6 +559,8 @@ if (!defined("DRIVER")) {
$row["Comment"] = "";
}
if ($name != "") {
// MariaDB: Table name is returned as lowercase on macOS, so we fix it here.
$row["Name"] = $name;
return $row;
}
$return[$row["Name"]] = $row;
@@ -534,28 +587,39 @@ if (!defined("DRIVER")) {
/** Get information about fields
* @param string
* @return array 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;
@@ -563,8 +627,8 @@ if (!defined("DRIVER")) {
/** Get table indexes
* @param string
* @param string Min_DB to use
* @return array 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();
@@ -580,25 +644,25 @@ if (!defined("DRIVER")) {
/** Get foreign keys in table
* @param string
* @return array 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"),
);
}
}
@@ -607,7 +671,7 @@ if (!defined("DRIVER")) {
/** Get view SELECT
* @param string
* @return array array("select" => )
* @return array ["select" => ]
*/
function view($name) {
global $connection;
@@ -638,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");
}
@@ -716,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
@@ -728,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) : "")
@@ -753,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) {
@@ -779,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
@@ -787,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
@@ -830,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))
) {
@@ -846,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;
}
}
@@ -856,7 +929,7 @@ if (!defined("DRIVER")) {
/** Get information about trigger
* @param string trigger name
* @return array array("Trigger" => , "Timing" => , "Event" => , "Of" => , "Type" => , "Statement" => )
* @return array ["Trigger" => , "Timing" => , "Event" => , "Of" => , "Type" => , "Statement" => ]
*/
function trigger($name) {
if ($name == "") {
@@ -868,7 +941,7 @@ if (!defined("DRIVER")) {
/** Get defined triggers
* @param string
* @return array array($name => array($timing, $event))
* @return array [$name => [$timing, $event]]
*/
function triggers($table) {
$return = array();
@@ -879,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(
@@ -892,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();
@@ -908,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],
@@ -916,22 +989,21 @@ if (!defined("DRIVER")) {
"collation" => strtolower($param[9]),
);
}
if ($type != "FUNCTION") {
return array("fields" => $fields, "definition" => $match[11]);
}
return array(
"fields" => $fields,
"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],
"language" => "SQL", // available in information_schema.ROUTINES.PARAMETER_STYLE
);
"language" => "SQL", // available in information_schema.ROUTINES.BODY_STYLE
));
}
/** Get list of routines
* @return array ("SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => )
* @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
@@ -959,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);
@@ -976,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
@@ -1050,21 +1127,21 @@ if (!defined("DRIVER")) {
}
/** Get server variables
* @return array ($name => $value)
* @return array [$name => $value]
*/
function show_variables() {
return get_key_vals("SHOW VARIABLES");
}
/** Get process list
* @return array ($row)
* @return array [$row]
*/
function process_list() {
return get_rows("SHOW FULL PROCESSLIST");
}
/** Get status variables
* @return array ($name => $value)
* @return array [$name => $value]
*/
function show_status() {
return get_key_vals("SHOW STATUS");
@@ -1096,7 +1173,7 @@ if (!defined("DRIVER")) {
$return = "UNHEX($return)";
}
if ($field["type"] == "bit") {
$return = "CONV($return, 2, 10) + 0";
$return = "CONVERT(b$return, UNSIGNED)";
}
if (preg_match("~geometry|point|linestring|polygon~", $field["type"])) {
$prefix = (min_version(8) ? "ST_" : "");
@@ -1106,11 +1183,11 @@ if (!defined("DRIVER")) {
}
/** Check whether a feature is supported
* @param string "comment", "copy", "database", "descidx", "drop_col", "dump", "event", "indexes", "kill", "materializedview", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger"
* @param string "check", "comment", "copy", "database", "descidx", "drop_col", "dump", "event", "indexes", "kill", "materializedview", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger"
* @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"))) . "~", $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
@@ -1135,45 +1212,4 @@ if (!defined("DRIVER")) {
global $connection;
return $connection->result("SELECT @@max_connections");
}
/** Get driver config
* @return array 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("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),
) 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",
)
),
);
}
}

View File

@@ -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,13 @@ if (isset($_GET["oracle"])) {
}
function get_databases() {
return get_vals("SELECT tablespace_name FROM user_tablespaces ORDER BY 1");
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
)
ORDER BY 1"
);
}
function limit($query, $where, $limit, $offset = 0, $separator = " ") {
@@ -218,7 +258,7 @@ if (isset($_GET["oracle"])) {
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;
}
@@ -232,13 +272,14 @@ if (isset($_GET["oracle"])) {
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
@@ -259,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;
}
@@ -308,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
@@ -336,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() {
@@ -459,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() {
@@ -503,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 REGEXP", "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" => "||",
)
),
);
}
}

View File

@@ -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) {
@@ -20,6 +22,10 @@ if (isset($_GET["pgsql"])) {
$db = $adminer->database();
set_error_handler(array($this, '_error'));
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
$ssl = $adminer->connectSsl();
if (isset($ssl["mode"])) {
$this->_string .= " sslmode='" . $ssl["mode"] . "'";
}
$this->_link = @pg_connect("$this->_string dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'", PGSQL_CONNECT_FORCE_NEW);
if (!$this->_link && $db != "") {
// try to connect directly with database for performance
@@ -36,7 +42,7 @@ if (isset($_GET["pgsql"])) {
}
function quote($string) {
return "'" . pg_escape_string($this->_link, $string) . "'";
return pg_escape_literal($this->_link, $string);
}
function value($val, $field) {
@@ -73,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;
@@ -108,7 +114,7 @@ if (isset($_GET["pgsql"])) {
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
@@ -126,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);
}
@@ -143,14 +149,19 @@ 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) {
global $adminer;
$db = $adminer->database();
$this->dsn("pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'", $username, $password); //! client_encoding is supported since 9.1 but we can't yet use min_version here
//! connect without DB in case of an error
//! client_encoding is supported since 9.1, but we can't yet use min_version here
$dsn = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'";
$ssl = $adminer->connectSsl();
if (isset($ssl["mode"])) {
$dsn .= " sslmode='" . $ssl["mode"] . "'";
}
$this->dsn($dsn, $username, $password);
return true;
}
@@ -184,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;
@@ -197,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;
}
}
@@ -213,12 +266,12 @@ if (isset($_GET["pgsql"])) {
}
function convertSearch($idf, $val, $field) {
return (preg_match('~char|text'
. (!preg_match('~LIKE~', $val["op"]) ? '|date|time(stamp)?|boolean|uuid|' . number_type() : '')
. '~', $field["type"])
? $idf
: "CAST($idf AS text)"
);
$textTypes = "char|text";
if (strpos($val["op"], "LIKE") === false) {
$textTypes .= "|date|time(stamp)?|boolean|uuid|inet|cidr|macaddr|" . number_type();
}
return (preg_match("~$textTypes~", $field["type"]) ? $idf : "CAST($idf AS text)");
}
function quoteBinary($s) {
@@ -229,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) {
@@ -240,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;
}
}
@@ -253,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;
}
@@ -274,7 +326,9 @@ if (isset($_GET["pgsql"])) {
}
function get_databases() {
return get_vals("SELECT datname FROM pg_database WHERE has_database_privilege(datname, 'CONNECT') ORDER BY 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 = " ") {
@@ -304,7 +358,7 @@ if (isset($_GET["pgsql"])) {
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'
@@ -317,17 +371,33 @@ 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 c.relname AS \"Name\", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\", pg_relation_size(c.oid) AS \"Data_length\", pg_total_relation_size(c.oid) - pg_relation_size(c.oid) AS \"Index_length\", obj_description(c.oid, 'pg_class') AS \"Comment\", " . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\", c.reltuples as \"Rows\", n.nspname
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\",
pg_indexes_size(c.oid) AS \"Index_length\",
obj_description(c.oid, 'pg_class') AS \"Comment\",
" . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
c.reltuples as \"Rows\",
n.nspname
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);
@@ -347,8 +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
@@ -357,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;
@@ -374,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);
@@ -393,62 +464,49 @@ 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();
$return[$relname]["descs"] = array();
if ($row["indkey"]) {
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
}
}
$return[$relname]["lengths"] = array();
}
return $return;
}
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;
}
}
return $return;
}
function constraints($table) {
global $on_actions;
$return = array();
foreach (get_rows("SELECT conname, 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") as $row) {
$return[$row['conname']] = $row['consrc'];
}
return $return;
}
function view($name) {
global $connection;
return array("select" => trim($connection->result("SELECT pg_get_viewdef(" . $connection->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
@@ -460,7 +518,7 @@ ORDER BY connamespace, conname") as $row) {
}
function information_schema($db) {
return ($db == "information_schema");
return get_schema() == "information_schema";
}
function error() {
@@ -483,7 +541,8 @@ ORDER BY connamespace, conname") as $row) {
}
function rename_database($name, $collation) {
//! current database cannot be renamed
global $connection;
$connection->close();
return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
}
@@ -497,6 +556,7 @@ ORDER BY connamespace, conname") as $row) {
if ($table != "" && $table != $name) {
$queries[] = "ALTER TABLE " . table($table) . " RENAME TO " . table($name);
}
$sequence = "";
foreach ($fields as $field) {
$column = idf_escape($field[0]);
$val = $field[1];
@@ -518,10 +578,15 @@ ORDER BY connamespace, conname") as $row) {
$queries[] = "ALTER TABLE " . table($name) . " RENAME $column TO $val[0]";
}
$alter[] = "ALTER $column TYPE$val[1]";
if (!$val[6]) {
$alter[] = "ALTER $column " . ($val[3] ? "SET$val[3]" : "DROP DEFAULT");
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
$sequence_name = $table . "_" . idf_unescape($val[0]) . "_seq";
$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" //! 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]";
}
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
}
if ($field[0] != "" || $val5 != "") {
$queries[] = "COMMENT ON COLUMN " . table($name) . ".$val[0] IS " . ($val5 != "" ? substr($val5, 9) : "''");
@@ -534,12 +599,15 @@ ORDER BY connamespace, conname") as $row) {
} elseif ($alter) {
array_unshift($queries, "ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter));
}
if ($sequence) {
array_unshift($queries, $sequence);
}
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;
@@ -580,7 +648,7 @@ ORDER BY connamespace, 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;
}
@@ -690,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_vals("SELECT 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')
@@ -709,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");
}
@@ -719,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 $type) { //! get types from current_schemas('t')
if (!isset($types[$type])) {
$types[$type] = 0;
$structured_types[lang('User types')][] = $type;
}
}
$driver->setUserTypes(types()); //! get types from current_schemas('t')
return $return;
}
@@ -751,8 +817,7 @@ AND typelem = 0"
}
function create_sql($table, $auto_increment, $style) {
global $connection;
$return = '';
global $driver;
$return_parts = array();
$sequences = array();
@@ -762,9 +827,6 @@ AND typelem = 0"
return rtrim("CREATE VIEW " . idf_escape($table) . " AS $view[select]", ";");
}
$fields = fields($table);
$indexes = indexes($table);
ksort($indexes);
$constraints = constraints($table);
if (!$status || empty($fields)) {
return false;
@@ -773,7 +835,7 @@ AND typelem = 0"
$return = "CREATE TABLE " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " (\n ";
// fields' definitions
foreach ($fields as $field_name => $field) {
foreach ($fields as $field) {
$part = idf_escape($field['field']) . ' ' . $field['full_type']
. default_value($field)
. ($field['attnotnull'] ? " NOT NULL" : "");
@@ -782,12 +844,15 @@ AND typelem = 0"
// sequences for fields
if (preg_match('~nextval\(\'([^\']+)\'\)~', $field['default'], $matches)) {
$sequence_name = $matches[1];
$sq = reset(get_rows(min_version(10)
? "SELECT *, cache_size AS cache_value FROM pg_sequences WHERE schemaname = current_schema() AND sequencename = " . q($sequence_name)
$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]" : "") . " CACHE $sq[cache_value];";
. "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) : "")
. " CACHE $sq[cache_value];"
;
}
}
@@ -796,32 +861,21 @@ 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'])) . ")";
}
}
foreach ($constraints as $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) . ");";
}
}
// coments for table & fields
// comments for table & fields
if ($status['Comment']) {
$return .= "\n\nCOMMENT ON TABLE " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " IS " . q($status['Comment']) . ";";
}
@@ -832,6 +886,10 @@ AND typelem = 0"
}
}
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, ';');
}
@@ -862,9 +920,6 @@ AND typelem = 0"
return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid"));
}
function show_status() {
}
function convert_field($field) {
}
@@ -873,7 +928,7 @@ AND typelem = 0"
}
function support($feature) {
return preg_match('~^(database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
return preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
}
function kill_process($val) {
@@ -888,40 +943,4 @@ AND typelem = 0"
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, "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" => "||",
)
),
);
}
}

View File

@@ -1,17 +1,17 @@
<?php
$drivers["sqlite"] = "SQLite 3";
$drivers["sqlite2"] = "SQLite 2";
namespace Adminer;
$drivers["sqlite"] = "SQLite";
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"])) {
define('Adminer\DRIVER', "sqlite");
if (class_exists("SQLite3")) {
class Min_SQLite {
class SqliteDb {
var $extension = "SQLite3", $server_info, $affected_rows, $errno, $error, $_link;
function __construct($filename) {
$this->_link = new SQLite3($filename);
$this->_link = new \SQLite3($filename);
$version = $this->_link->version();
$this->server_info = $version["versionString"];
}
@@ -24,7 +24,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$this->error = $this->_link->lastErrorMsg();
return false;
} elseif ($result->numColumns()) {
return new Min_Result($result);
return new Result($result);
}
$this->affected_rows = $this->_link->changes();
return true;
@@ -47,11 +47,11 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return false;
}
$row = $result->_result->fetchArray();
return $row[$field];
return $row ? $row[$field] : false;
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
@@ -81,105 +81,23 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
}
} 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];
}
}
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,
);
}
}
}
} 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"];
@@ -319,7 +270,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
"field" => $name,
"type" => (preg_match('~int~i', $type) ? "integer" : (preg_match('~char|clob|text~i', $type) ? "text" : (preg_match('~blob~i', $type) ? "blob" : (preg_match('~real|floa|doub~i', $type) ? "real" : "numeric")))),
"full_type" => $type,
"default" => (preg_match("~'(.*)'~", $default, $match) ? str_replace("''", "'", $match[1]) : ($default == "NULL" ? null : $default)),
"default" => (preg_match("~^'(.*)'$~", $default, $match) ? str_replace("''", "'", $match[1]) : ($default == "NULL" ? null : $default)),
"null" => !$row["notnull"],
"privileges" => array("select" => 1, "insert" => 1, "update" => 1),
"primary" => $row["pk"],
@@ -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, $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,10 +726,14 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function show_variables() {
global $connection;
$return = array();
foreach (array("auto_vacuum", "cache_size", "count_changes", "default_cache_size", "empty_result_callbacks", "encoding", "foreign_keys", "full_column_names", "fullfsync", "journal_mode", "journal_size_limit", "legacy_file_format", "locking_mode", "page_size", "max_page_count", "read_uncommitted", "recursive_triggers", "reverse_unordered_selects", "secure_delete", "short_column_names", "synchronous", "temp_store", "temp_store_directory", "schema_version", "integrity_check", "quick_check") as $key) {
$return[$key] = $connection->result("PRAGMA $key");
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;
}
@@ -781,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);
}
}

View File

@@ -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,16 +55,28 @@ SET foreign_key_checks = 0;
}
$out = "";
if ($_POST["routines"]) {
foreach (array("FUNCTION", "PROCEDURE") as $routine) {
foreach (get_rows("SHOW $routine STATUS WHERE Db = " . q($db), null, "-- ") as $row) {
$create = remove_definer($connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2));
set_utf8mb4($create);
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") . "$create;;\n\n";
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"];
$routine = $row["ROUTINE_TYPE"];
$create = create_routine($routine, array("name" => $name) + routine($row["SPECIFIC_NAME"], $routine));
set_utf8mb4($create);
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($name) . ";;\n" : "") . "$create;\n\n";
}
}
if ($_POST["events"]) {
foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) {
$create = remove_definer($connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3));
@@ -70,9 +85,7 @@ SET foreign_key_checks = 0;
}
}
if ($out) {
echo "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n";
}
echo ($out && JUSH == 'sql' ? "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n" : $out);
}
if ($_POST["table_style"] || $_POST["data_style"]) {
@@ -107,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)) {
@@ -128,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;
}
@@ -137,12 +150,12 @@ page_header(lang('Export'), $error, ($_GET["export"] != "" ? array("table" => $_
?>
<form action="" method="post">
<table cellspacing="0" class="layout">
<table class="layout">
<?php
$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);
@@ -158,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')) : "")
);
@@ -174,7 +188,7 @@ echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style,
<p><input type="submit" value="<?php echo lang('Export'); ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<table cellspacing="0">
<table>
<?php
echo script("qsl('table').onclick = dumpClick;");
$prefixes = array();

View File

@@ -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);

15
adminer/elastic.php Normal file
View File

@@ -0,0 +1,15 @@
<?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";
include_once "../plugins/drivers/elastic.php";
include_once "../plugins/drivers/elastic5.php";
return new AdminerPlugin(array(
// TODO: inline the result of password_hash() so that the password is not visible in source codes
new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)),
));
}
include "./index.php";

View File

@@ -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"]) : "")
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]", ";") . ";"
));
)
);
}
}
@@ -35,7 +41,7 @@ if (!$row && $EVENT != "") {
?>
<form action="" method="post">
<table cellspacing="0" class="layout">
<table class="layout">
<tr><th><?php echo lang('Name'); ?><td><input name="EVENT_NAME" value="<?php echo h($row["EVENT_NAME"]); ?>" data-maxlength="64" autocapitalize="off">
<tr><th title="datetime"><?php echo lang('Start'); ?><td><input name="STARTS" value="<?php echo h("$row[EXECUTE_AT]$row[STARTS]"); ?>">
<tr><th title="datetime"><?php echo lang('End'); ?><td><input name="ENDS" value="<?php echo h($row["ENDS"]); ?>">
@@ -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>

View File

@@ -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;

View File

@@ -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)) {
@@ -77,7 +88,7 @@ if ($jush == "pgsql") {
?>
<input type="hidden" name="change-js" value="">
<noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript>
<table cellspacing="0">
<table>
<thead><tr><th id="label-source"><?php echo lang('Source'); ?><th id="label-target"><?php echo lang('Target'); ?></thead>
<?php
$j = 0;
@@ -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>

View File

@@ -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 {
@@ -13,14 +15,14 @@ class Adminer {
}
/** Connection parameters
* @return array ($server, $username, $password)
* @return array [$server, $username, $password]
*/
function credentials() {
return array(SERVER, $_GET["username"], get_password());
}
/** Get SSL connection options
* @return array array("key" => filename, "cert" => filename, "ca" => filename) or null
* @return array ["key" => filename, "cert" => filename, "ca" => filename] or null
*/
function connectSsl() {
}
@@ -118,12 +120,12 @@ class Adminer {
*/
function loginForm() {
global $drivers;
echo "<table cellspacing='0' 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('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(qs('#username')); 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 "<table class='layout'>\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">');
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
;
@@ -248,8 +252,7 @@ class Adminer {
* @param string query to be executed
* @return string escaped query to be printed
*/
function sqlCommandQuery($query)
{
function sqlCommandQuery($query) {
return shorten_utf8(trim($query), 1000);
}
@@ -310,15 +313,22 @@ class Adminer {
* @return null
*/
function tableStructurePrint($fields) {
global $driver;
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap'>\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" . odd() . "><th>" . h($field["field"]);
echo "<td><span title='" . h($field["collation"]) . "'>" . h($field["full_type"]) . "</span>";
echo "<tr><th>" . h($field["field"]);
$type = h($field["full_type"]);
echo "<td><span title='" . h($field["collation"]) . "'>"
. (in_array($type, (array) $structured_types[lang('User types')]) ? "<a href='" . h(ME . 'type=' . urlencode($type)) . "'>$type</a>" : $type)
. "</span>"
;
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";
}
@@ -331,7 +341,7 @@ class Adminer {
* @return null
*/
function tableIndexesPrint($indexes) {
echo "<table cellspacing='0'>\n";
echo "<table>\n";
foreach ($indexes as $name => $index) {
ksort($index["columns"]); // enforce correct columns order
$print = array();
@@ -352,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();
@@ -364,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";
@@ -384,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");
@@ -506,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];
}
}
@@ -533,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) {
@@ -561,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"]))
) {
@@ -635,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"]]) {
@@ -652,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>'
@@ -674,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"])) {
@@ -706,7 +717,7 @@ class Adminer {
if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
. enum_input("radio", $attrs, $field, $value, 0) // 0 - empty
. enum_input("radio", $attrs, $field, $value, $value === 0 ? 0 : null) // 0 - empty value
;
}
return "";
@@ -765,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
@@ -817,20 +828,32 @@ class Adminer {
* @return null prints data
*/
function dumpData($table, $style, $query) {
global $connection, $jush;
$max_packet = ($jush == "sqlite" ? 0 : 1048576); // default, minimum is 1024
global $connection;
if ($style) {
$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) {
$insert = "";
$buffer = "";
$keys = array();
$generated = array();
$suffix = "";
$fetch_function = ($table != '' ? 'fetch_assoc' : 'fetch_row');
while ($row = $result->$fetch_function()) {
@@ -838,6 +861,10 @@ class Adminer {
$values = array();
foreach ($row as $val) {
$field = $result->fetch_field();
if ($fields[$field->name]['generated']) {
$generated[$field->name] = true;
continue;
}
$keys[] = $field->name;
$key = idf_escape($field->name);
$values[] = "$key = VALUES($key)";
@@ -852,9 +879,13 @@ 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]) {
unset($row[$key]);
continue;
}
$field = $fields[$key];
$row[$key] = ($val !== null
? unconvert_field($field, preg_match(number_type(), $field["type"]) && !preg_match('~\[~', $field["full_type"]) && is_numeric($val) ? $val : q(($val === false ? 0 : $val)))
@@ -878,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";
}
}
}
@@ -931,13 +965,17 @@ class Adminer {
* @return null
*/
function navigation($missing) {
global $VERSION, $jush, $drivers, $connection;
global $VERSION, $drivers, $connection;
?>
<h1>
<?php echo $this->name(); ?> <span class="version"><?php echo $VERSION; ?></span>
<?php echo $this->name(); ?>
<span class="version">
<?php echo $VERSION; ?>
<a href="https://www.adminer.org/#download"<?php echo target_blank(); ?> id="version"><?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?></a>
</span>
</h1>
<?php
switch_lang();
if ($missing == "auth") {
$output = "";
foreach ((array) $_SESSION["pwds"] as $vendor => $servers) {
@@ -966,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
@@ -975,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;
@@ -987,18 +1025,24 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
<?php
}
$this->databasesPrint($missing);
$actions = array();
if (DB == "" || !$missing) {
echo "<p class='links'>" . (support("sql") ? "<a href='" . h(ME) . "sql='" . bold(isset($_GET["sql"]) && !isset($_GET["import"])) . ">" . lang('SQL command') . "</a>\n<a href='" . h(ME) . "import='" . bold(isset($_GET["import"])) . ">" . lang('Import') . "</a>\n" : "") . "";
if (support("dump")) {
echo "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>\n";
if (support("sql")) {
$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>";
}
$actions[] = "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>";
}
if ($_GET["ns"] !== "" && !$missing && DB != "") {
echo '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>\n";
if (!$tables) {
echo "<p class='message'>" . lang('No tables.') . "\n";
} else {
$in_db = $_GET["ns"] !== "" && !$missing && DB != "";
if ($in_db) {
$actions[] = '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>";
}
echo ($actions ? "<p class='links'>\n" . implode("\n", $actions) . "\n" : "");
if ($in_db) {
if ($tables) {
$this->tablesPrint($tables);
} else {
echo "<p class='message'>" . lang('No tables.') . "</p>\n";
}
}
}
@@ -1020,9 +1064,9 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
<?php
hidden_fields_get();
$db_events = script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");
echo "<span title='" . lang('database') . "'>" . lang('DB') . "</span>: " . ($databases
echo "<span title='" . lang('Database') . "'>" . lang('DB') . "</span>: " . ($databases
? "<select name='db'>" . optionlist(array("" => "") + $databases, DB) . "</select>$db_events"
: "<input name='db' value='" . h(DB) . "' autocapitalize='off'>\n"
: "<input name='db' value='" . h(DB) . "' autocapitalize='off' size='19'>\n"
);
echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n";
if (support("scheme")) {
@@ -1065,5 +1109,4 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
}
echo "</ul>\n";
}
}

View File

@@ -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,12 +164,15 @@ 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;
if (!is_object($connection) || ($login = $adminer->login($_GET["username"], get_password())) !== true) {
$error = (is_string($connection) ? h($connection) : (is_string($login) ? $login : lang('Invalid credentials.')));
$error = (is_string($connection) ? nl_br(h($connection)) : (is_string($login) ? $login : lang('Invalid credentials.')));
auth_error($error . (preg_match('~^ | $~', get_password()) ? '<br>' . lang('There is a space in the input password which might be the cause.') : ''));
}

View File

@@ -1,11 +1,8 @@
<?php
function adminer_errors($errno, $errstr) {
return !!preg_match('~^(Trying to access array offset on value of type null|Undefined array key)~', $errstr);
}
error_reporting(6135); // errors and warnings
set_error_handler('adminer_errors', E_WARNING);
namespace Adminer;
include "../adminer/include/version.inc.php";
include "../adminer/include/errors.inc.php";
include "../adminer/include/coverage.inc.php";
// disable filter.default
@@ -38,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"];
@@ -55,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();
}
@@ -81,39 +74,24 @@ include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/oracle.inc.php";
include "../adminer/drivers/mssql.inc.php";
include "../adminer/drivers/mongo.inc.php";
include "../adminer/drivers/elastic.inc.php";
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()) . '?'
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/version.inc.php";
include "../adminer/include/design.inc.php";
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()

View File

@@ -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(
foreach (
array(
'database' => lang('Create database'),
'privileges' => lang('Privileges'),
'processlist' => lang('Process list'),
'variables' => lang('Variables'),
'status' => lang('Status'),
) as $key => $val) {
) as $key => $val
) {
if (support($key)) {
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
}
@@ -29,11 +43,11 @@ function connect_error() {
$scheme = support("scheme");
$collations = collations();
echo "<form action='' method='post'>\n";
echo "<table cellspacing='0' class='checkable'>\n";
echo "<table class='checkable odds'>\n";
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');", "")
@@ -45,7 +59,7 @@ function connect_error() {
foreach ($databases as $db => $tables) {
$root = h(ME) . "db=" . urlencode($db);
$id = h("Db-" . $db);
echo "<tr" . odd() . ">" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
echo "<tr>" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
echo "<th><a href='$root' id='$id'>" . h($db) . "</a>";
$collation = h(db_collation($db, $collations));
echo "<td>" . (support("database") ? "<a href='$root" . ($scheme ? "&amp;ns=" : "") . "&amp;database=' title='" . lang('Alter database') . "'>$collation</a>" : $collation);
@@ -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;
}

View File

@@ -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');
}

View File

@@ -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);
@@ -20,6 +26,7 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width">
<title><?php echo $title_page; ?></title>
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css">
<?php echo script_src("../adminer/static/functions.js"); ?>
@@ -61,32 +68,32 @@ 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> &raquo; ';
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'));
if ($breadcrumb === false) {
echo "$server\n";
} else {
echo "<a href='" . h($link) . "' accesskey='1' title='Alt+Shift+1'>$server</a> &raquo; ";
echo "<a href='" . h($link) . "' accesskey='1' title='Alt+Shift+1'>$server</a> » ";
if ($_GET["ns"] != "" || (DB != "" && is_array($breadcrumb))) {
echo '<a href="' . h($link . "&db=" . urlencode(DB) . (support("scheme") ? "&ns=" : "")) . '">' . h(DB) . '</a> &raquo; ';
echo '<a href="' . h($link . "&db=" . urlencode(DB) . (support("scheme") ? "&ns=" : "")) . '">' . h(DB) . '</a> » ';
}
if (is_array($breadcrumb)) {
if ($_GET["ns"] != "") {
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h($_GET["ns"]) . '</a> &raquo; ';
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h($_GET["ns"]) . '</a> » ';
}
foreach ($breadcrumb as $key => $val) {
$desc = (is_array($val) ? $val[1] : h($val));
if ($desc != "") {
echo "<a href='" . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . "'>$desc</a> &raquo; ";
echo "<a href='" . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . "'>$desc</a> » ";
}
}
}
@@ -102,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
@@ -178,18 +185,19 @@ function page_footer($missing = "") {
?>
</div>
<?php switch_lang(); ?>
<div id="menu">
<?php $adminer->navigation($missing); ?>
</div>
<?php if ($missing != "auth") { ?>
<form action="" method="post">
<p class="logout">
<?php echo h($_GET["username"]) . "\n"; ?>
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</p>
</form>
<?php } ?>
<div id="menu">
<?php $adminer->navigation($missing); ?>
</div>
<?php
echo script("setupSubmitHighlight(document);");
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$drivers = array();
/** Add a driver
@@ -11,16 +13,52 @@ function add_driver($id, $name) {
$drivers[$id] = $name;
}
/*abstract*/ class Min_SQL {
/** Get driver name
* @param string
* @return string
*/
function get_driver($id) {
global $drivers;
return $drivers[$id];
}
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]
@@ -30,15 +68,15 @@ function add_driver($id, $name) {
* @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),
@@ -99,7 +137,7 @@ function add_driver($id, $name) {
* @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;
}
@@ -134,7 +172,7 @@ function add_driver($id, $name) {
/** Convert column to be searchable
* @param string escaped column name
* @param array array("op" => , "val" => )
* @param array ["op" => , "val" => ]
* @param array
* @return string
*/
@@ -142,6 +180,14 @@ function add_driver($id, $name) {
return $idf;
}
/** Convert operator so it can be used in search
* @param string $operator
* @return string
*/
function convertOperator($operator) {
return $operator;
}
/** Convert value returned by database to actual value
* @param string
* @param array
@@ -171,9 +217,30 @@ function add_driver($id, $name) {
/** 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
}
}

View File

@@ -1,24 +1,26 @@
<?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
$blobs = array(); // colno => bool - display bytes for blobs
$types = array(); // colno => type - display char in <code>
$return = array(); // table => orgtable - mapping to use in EXPLAIN
odd(''); // reset odd for each result
for ($i=0; (!$limit || $i < $limit) && ($row = $result->fetch_row()); $i++) {
if (!$i) {
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap'>\n";
echo "<table class='nowrap odds'>\n";
echo "<thead><tr>";
for ($j=0; $j < count($row); $j++) {
$field = $result->fetch_field();
@@ -26,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])) {
@@ -59,11 +61,11 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
}
echo "</thead>\n";
}
echo "<tr" . odd() . ">";
echo "<tr>";
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 {
@@ -97,7 +99,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
/** Get referencable tables with single column primary key except self
* @param string
* @return array ($table_name => $field)
* @return array [$table_name => $field]
*/
function referencable_primary($self) {
$return = array(); // table_name => field
@@ -150,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)
@@ -162,6 +163,41 @@ function textarea($name, $value, $rows = 10, $cols = 80) {
echo "</textarea>";
}
/** Generate HTML <select> or <input> if $options are empty
* @param string
* @param array
* @param string
* @param string
* @param string
* @return string
*/
function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
$tag = ($options ? "select" : "input");
return "<$tag$attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
}
/** Print table columns for type edit
* @param string
* @param array
@@ -171,22 +207,46 @@ function textarea($name, $value, $rows = 10, $cols = 80) {
* @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)) {
?><td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
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;
}
echo optionlist(array_merge($extra_types, $structured_types), $type);
?></select><td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?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 "<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 (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
?></select><td><input
name="<?php echo h($key); ?>[length]"
value="<?php echo h($field["length"]); ?>"
size="3"
<?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 ($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("|", $driver->onActions), $field["on_delete"]) . "</select> " : " "); // space for IE
}
/** Get partition info
* @param string
* @return array
*/
function get_partitions_info($table) {
global $connection;
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
$return = array();
list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row();
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
$return["partition_names"] = array_keys($partitions);
$return["partition_values"] = array_values($partitions);
return $return;
}
/** Filter length value including enums
@@ -194,7 +254,8 @@ echo optionlist(array_merge($extra_types, $structured_types), $type);
* @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))
@@ -207,20 +268,24 @@ 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"])) : "")
;
}
/** Create SQL string from field
* @param array basic field information
* @param array information about field type
* @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
* @return array ["field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT"]
*/
function process_field($field, $type_field) {
// MariaDB exports CURRENT_TIMESTAMP as a function.
if ($field["on_update"]) {
$field["on_update"] = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $field["on_update"]);
}
return array(
idf_escape(trim($field["field"])),
process_type($type_field),
@@ -237,8 +302,16 @@ function process_field($field, $type_field) {
* @return string
*/
function default_value($field) {
global $driver;
$default = $field["default"];
return ($default === null ? "" : " DEFAULT " . (preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default) ? q($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
@@ -246,12 +319,14 @@ function default_value($field) {
* @return string class=''
*/
function type_class($type) {
foreach (array(
foreach (
array(
'char' => 'text',
'date' => 'time|year',
'binary' => 'blob',
'enum' => 'set',
) as $key => $val) {
) as $key => $val
) {
if (preg_match("~$key|$val~", $type)) {
return " class='$key'";
}
@@ -266,25 +341,25 @@ 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'); ?>
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?>
<?php if ($type == "TABLE") { ?>
<td id="label-null">NULL
<td><input type="radio" name="auto_increment_col" value=""><acronym id="label-ai" title="<?php echo lang('Auto Increment'); ?>">AI</acronym><?php echo doc_link(array(
<td><input type="radio" name="auto_increment_col" value=""><abbr id="label-ai" title="<?php echo lang('Auto Increment'); ?>">AI</abbr><?php echo doc_link(array(
'sql' => "example-auto-increment.html",
'mariadb' => "auto_increment/",
'sqlite' => "autoinc.html",
'pgsql' => "datatype.html#DATATYPE-SERIAL",
'mssql' => "ms186775.aspx",
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
'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') : ""); ?>
@@ -300,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>";
@@ -429,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]", ";")
. ";"
;
@@ -445,22 +528,22 @@ 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("\n$row[definition]", ";");
$definition = rtrim($row["definition"], ";");
return "CREATE $routine "
. idf_escape(trim($row["name"]))
. " (" . implode(", ", $set) . ")"
. (isset($_GET["function"]) ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
. ($routine == "FUNCTION" ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
. ($row["language"] ? " LANGUAGE $row[language]" : "")
. ($jush == "pgsql" ? " AS " . q($definition) : "$definition;")
. (JUSH == "pgsql" ? " AS " . q($definition) : "\n$definition;")
;
}
@@ -473,20 +556,20 @@ function remove_definer($query) {
}
/** Format foreign key to use in SQL query
* @param array ("db" => string, "ns" => string, "table" => string, "source" => array, "target" => array, "on_delete" => one of $on_actions, "on_update" => one of $on_actions)
* @param array ["db" => string, "ns" => string, "table" => string, "source" => array, "target" => array, "on_delete" => one of $on_actions, "on_update" => one of $on_actions]
* @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]" : "")
;
}
@@ -515,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 *= 1024; // no break
case 'm': $val *= 1024; // no break
case 'k': $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/library/";
$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()
@@ -550,7 +636,7 @@ function doc_link($paths, $text = "<sup>?</sup>") {
* @return string
*/
function ob_gzencode($string) {
// ob_start() callback recieves an optional parameter $phase but gzencode() accepts optional parameter $level
// ob_start() callback receives an optional parameter $phase but gzencode() accepts optional parameter $level
return gzencode($string);
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Adminer;
error_reporting(6135); // errors and warnings
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);

View File

@@ -1,6 +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
@@ -94,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) {
@@ -107,11 +111,11 @@ function min_version($version, $maria_db = "", $connection2 = null) {
$server_info = $match[1];
$version = $maria_db;
}
return (version_compare($server_info, $version) >= 0);
return $version && version_compare($server_info, $version) >= 0;
}
/** Get connection charset
* @param Min_DB
* @param Db
* @return string
*/
function charset($connection) {
@@ -200,7 +204,11 @@ function optionlist($options, $selected = null, $use_keys = false) {
$opts = $v;
}
foreach ($opts as $key => $val) {
$return .= '<option' . ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '') . (($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '') . '>' . h($val);
$return .= '<option'
. ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '')
. ($selected !== null && ($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '')
. '>' . h($val)
;
}
if (is_array($v)) {
$return .= '</optgroup>';
@@ -232,22 +240,6 @@ function html_select($name, $options, $value = "", $onchange = true, $labelled_b
return $return;
}
/** Generate HTML <select> or <input> if $options are empty
* @param string
* @param array
* @param string
* @param string
* @param string
* @return string
*/
function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
$tag = ($options ? "select" : "input");
return "<$tag$attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
}
/** Get onclick confirmation
* @param string
* @param string
@@ -280,18 +272,6 @@ function bold($bold, $class = "") {
return ($bold ? " class='active $class'" : ($class ? " class='$class'" : ""));
}
/** Generate class for odd rows
* @param string return this for odd rows, empty to reset counter
* @return string
*/
function odd($return = ' class="odd"') {
static $i = 0;
if (!$return) { // reset counter
$i = -1;
}
return ($i++ % 2 ? $return : '');
}
/** Escape string for JavaScript apostrophes
* @param string
* @return string
@@ -300,25 +280,6 @@ function js_escape($string) {
return addcslashes($string, "\r\n'\\/"); // slash for <script>
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
}
/** Get INI boolean value
* @param string
* @return bool
@@ -328,7 +289,7 @@ function ini_bool($ini) {
return (preg_match('~^(on|true|yes)$~i', $val) || (int) $val); // boolean values set by php_value are strings
}
/** Check if SID is neccessary
/** Check if SID is necessary
* @return bool
*/
function sid() {
@@ -395,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
*/
@@ -420,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
*/
@@ -433,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")) {
} elseif (!$result && !is_object($connection2) && $error && (defined('Adminer\PAGE_HEADER') || $error == "-- ")) {
echo $error . error() . "\n";
}
return $return;
@@ -476,18 +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" && 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";
}
}
@@ -542,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)
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);
false
);
}
/** Restart stopped session
@@ -673,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;
@@ -771,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
@@ -846,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
@@ -886,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 array($col => array())
* @return array [$col => []]
*/
function column_foreign_keys($table) {
global $adminer;
@@ -919,7 +884,7 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
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='" . ($i+1) . "'" . ($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;
}
@@ -931,7 +896,7 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
* @return null
*/
function input($field, $value, $function) {
global $types, $adminer, $jush;
global $driver, $adminer;
$name = h(bracket_escape($field["field"]));
echo "<td class='function'>";
if (is_array($value) && !$function) {
@@ -942,18 +907,28 @@ 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);
$attrs = " name='fields[$name]'";
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
$attrs = " name='fields[$name]'$disabled";
$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"] = $enums;
}
}
if ($field["type"] == "enum") {
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
} else {
$has_function = (in_array($function, $functions) || isset($functions[$function]));
echo (count($functions) > 1
? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
? "<select name='function[$name]'$disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
. script("qsl('select').onchange = functionChange;", "")
: h(reset($functions))
@@ -962,8 +937,8 @@ function input($field, $value, $function) {
if ($input != "") {
echo $input;
} elseif (preg_match('~bool~', $field["type"])) {
echo "<input type='hidden'$attrs value='0'>" .
"<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
echo "<input type='hidden'$attrs value='0'>"
. "<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
} elseif ($field["type"] == "set") { //! 64 bits
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
@@ -974,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);
@@ -985,8 +960,11 @@ function input($field, $value, $function) {
echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
} else {
// int(3) is only a display hint
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match) ? ((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"])) {
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match)
? ((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"])) {
$maxlength += 7; // microtime
}
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
@@ -1018,6 +996,11 @@ function input($field, $value, $function) {
*/
function process_input($field) {
global $adminer, $driver;
if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) {
return null;
}
$idf = bracket_escape($field["field"]);
$function = $_POST["function"][$idf];
$value = $_POST["fields"][$idf];
@@ -1241,7 +1224,7 @@ function select_value($val, $link, $field, $text_length) {
. "<td>" . select_value($v, $link, $field, $text_length)
;
}
return "<table cellspacing='0'>$return</table>";
return "<table>$return</table>";
}
if (!$link) {
$link = $adminer->selectLink($val, $field);
@@ -1303,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)
);
@@ -1335,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();
@@ -1415,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')),
@@ -1426,6 +1408,7 @@ function edit_form($table, $fields, $row, $update) {
$adminer->editRowPrint($table, $fields, $row, $update);
if ($row === false) {
echo "<p class='error'>" . lang('No rows.') . "\n";
return;
}
?>
<form action="" method="post" enctype="multipart/form-data" id="form">
@@ -1433,8 +1416,8 @@ function edit_form($table, $fields, $row, $update) {
if (!$fields) {
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
} else {
echo "<table cellspacing='0' class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
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)];
@@ -1445,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])
)
@@ -1471,6 +1454,13 @@ function edit_form($table, $fields, $row, $update) {
$value = "";
$function = "now";
}
if ($field["type"] == "uuid" && $value == "uuid()") {
$value = "";
$function = "uuid";
}
if ($field["auto_increment"] || $function == "now" || $function == "uuid") {
$first++;
}
input($field, $value, $function);
echo "\n";
}
@@ -1497,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"]));

View File

@@ -1,11 +1,13 @@
<?php
namespace Adminer;
// not used in a single language version
$langs = array(
'en' => 'English', // Jakub Vrána - https://www.vrana.cz
'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr
'bg' => 'Български', // Deyan Delchev
'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com
'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com, Hossain Ahmed Saiman - hossain.ahmed@altscope.com
'bs' => 'Bosanski', // Emir Kurtovic
'ca' => 'Català', // Joan Llosas
'cs' => 'Čeština', // Jakub Vrána - https://www.vrana.cz
@@ -26,6 +28,7 @@ $langs = array(
'ka' => 'ქართული', // Saba Khmaladze skhmaladze@uglt.org
'ko' => '한국어', // dalli - skcha67@gmail.com
'lt' => 'Lietuvių', // Paulius Leščinskas - http://www.lescinskas.lt
'lv' => 'Latviešu', // Kristaps Lediņš - https://krysits.com
'ms' => 'Bahasa Melayu', // Pisyek
'nl' => 'Nederlands', // Maarten Balliauw - http://blog.maartenballiauw.be
'no' => 'Norsk', // Iver Odin Kvello, mupublishing.com
@@ -62,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
@@ -70,9 +73,10 @@ function lang($idf, $number = null) {
: ($LANG == 'pl' ? ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2) // different forms for 1, 2-4 except 12-14, other
: ($LANG == 'sl' ? ($number % 100 == 1 ? 0 : ($number % 100 == 2 ? 1 : ($number % 100 == 3 || $number % 100 == 4 ? 2 : 3))) // different forms for 1, 2, 3-4, other
: ($LANG == 'lt' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1, 12-19, other
: ($LANG == 'lv' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number ? 1 : 2)) // different forms for 1 except 11, other, 0
: ($LANG == 'bs' || $LANG == 'ru' || $LANG == 'sr' || $LANG == 'uk' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1 except 11, 2-4 except 12-14, other
: 1 // different forms for 1, other
))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
)))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
$translation = $translation[$pos];
}
$args = func_get_args();

View File

@@ -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();
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Adminer;
class TmpFile {
var $handler;
@@ -18,5 +19,4 @@ class TmpFile {
fpassthru($this->handler);
fclose($this->handler);
}
}

View File

@@ -1,2 +1,4 @@
<?php
$VERSION = "4.8.2-dev";
namespace Adminer;
$VERSION = "5.0.0";

View File

@@ -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

View File

@@ -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"];
}
@@ -59,6 +58,8 @@ if (isset($_GET["download"])) {
include "./sequence.inc.php";
} elseif (isset($_GET["type"])) {
include "./type.inc.php";
} elseif (isset($_GET["check"])) {
include "./check.inc.php";
} elseif (isset($_GET["trigger"])) {
include "./trigger.inc.php";
} elseif (isset($_GET["user"])) {

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["indexes"];
$index_types = array("PRIMARY", "UNIQUE", "INDEX");
$table_status = table_status($TABLE, true);
@@ -10,13 +12,15 @@ 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_"]);
}
$row = $_POST;
if ($row) {
set_adminer_settings(array("index_options" => $row["options"]));
}
if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
$alter = array();
foreach ($row["indexes"] as $index) {
@@ -33,18 +37,18 @@ 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"]
if (
$index["type"] == $existing["type"]
&& array_values($existing["columns"]) === $columns
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
&& array_values($existing["descs"]) === $descs
@@ -54,6 +58,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
continue;
}
}
if ($columns) {
$alter[] = array($index["type"], $name, $set);
}
}
@@ -91,14 +96,21 @@ if (!$row) {
$indexes[] = array("columns" => array(1 => ""));
$row["indexes"] = $indexes;
}
$lengths = (JUSH == "sql" || JUSH == "mssql");
$show_options = ($_POST ? $_POST["options"] : adminer_setting("index_options"));
?>
<form action="" method="post">
<div class="scrollable">
<table cellspacing="0" class="nowrap">
<table class="nowrap">
<thead><tr>
<th id="label-type"><?php echo lang('Index Type'); ?>
<th><input type="submit" class="wayoff"><?php echo lang('Column (length)'); ?>
<th><input type="submit" class="wayoff"><?php
echo lang('Column') . ($lengths ? "<span class='idxopts" . ($show_options ? "" : " hidden") . "'> (" . lang('length') . ")</span>" : "");
if ($lengths || support("descidx")) {
echo checkbox("options", 1, $show_options, lang('Options'), "indexOptionsShow(this.checked)", "jsonly") . "\n";
}
?>
<th id="label-name"><?php echo lang('Name'); ?>
<th><noscript><?php echo "<input type='image' class='icon' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?></noscript>
</thead>
@@ -124,11 +136,12 @@ 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 ($jush == "sql" || $jush == "mssql" ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : "");
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') . "'>" : "");
echo (support("descidx") ? checkbox("indexes[$j][descs][$i]", 1, $index["descs"][$key], lang('descending')) : "");
echo " </span>";
echo "</span> </span>";
$i++;
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'تسجيل الدخول',
'Logout successful.' => 'تم تسجيل الخروج بنجاح.',
@@ -30,7 +32,6 @@ $translations = array(
'Create database' => 'إنشاء قاعدة بيانات',
'SQL command' => 'استعلام SQL',
'Logout' => 'تسجيل الخروج',
'database' => 'قاعدة بيانات',
'Use' => 'استعمال',
'No tables.' => 'لا توجد جداول.',
'select' => 'تحديد',
@@ -94,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'نوع المؤشر',
'Column (length)' => 'العمود (الطول)',
'length' => 'الطول',
'View has been dropped.' => 'تم مسح العرض.',
'View has been altered.' => 'تم تعديل العرض.',
'View has been created.' => 'تم إنشاء العرض.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Система',
@@ -78,7 +80,6 @@ $translations = array(
'Data' => 'Данни',
'Database' => 'База данни',
'database' => 'база данни',
'Use' => 'Избор',
'Select database' => 'Избор на база данни',
'Invalid database.' => 'Невалидна база данни.',
@@ -193,7 +194,7 @@ $translations = array(
'Alter indexes' => 'Промяна на индекси',
'Add next' => 'Добавяне на следващ',
'Index Type' => 'Вид на индекса',
'Column (length)' => 'Колона (дължина)',
'length' => 'дължина',
'Foreign keys' => 'Препратки',
'Foreign key' => 'Препратка',

View File

@@ -1,53 +1,54 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'লগইন',
'Logout successful.' => 'লগআউট সম্পন্ন হয়েছে।',
'Logout successful.' => 'সফলভাবে লগআউট হয়েছে।',
'Invalid credentials.' => 'ভুল পাসওয়ার্ড।',
'Server' => 'সার্ভার',
'Username' => 'ইউজারের নাম',
'Password' => 'পাসওয়ার্ড',
'Select database' => 'ডাটাবেজ নির্বাচন কর',
'Invalid database.' => 'ভুল ডাটাবেজ।',
'Select database' => 'ডাটাবেজ নির্বাচন করুন',
'Invalid database.' => 'অকার্যকর ডাটাবেজ।',
'Table has been dropped.' => 'টেবিল মুছে ফেলা হয়েছে।',
'Table has been altered.' => 'টেবিল সম্পাদনা করা হয়েছে।',
'Table has been altered.' => 'টেবিল পরিবর্তন করা হয়েছে।',
'Table has been created.' => 'টেবিল তৈরী করা হয়েছে।',
'Alter table' => 'টেবিল সম্পাদনা',
'Create table' => 'টেবিল তৈরী কর',
'Alter table' => 'টেবিল পরিবর্তন করুন',
'Create table' => 'টেবিল তৈরী করুন',
'Table name' => 'টেবিলের নাম',
'engine' => 'ইন্জিন',
'collation' => 'কলোকেশন',
'collation' => 'সমষ্টি',
'Column name' => 'কলামের নাম',
'Type' => 'টাইপ',
'Type' => 'ধরণ',
'Length' => 'দৈর্ঘ্য',
'Auto Increment' => 'স্বয়ংক্রিয় বৃদ্ধি',
'Options' => 'অপশন',
'Save' => 'সংরক্ষণ',
'Options' => 'বিকল্পসমূহ',
'Save' => 'সংরক্ষণ করুন',
'Drop' => 'মুছে ফেলো',
'Database has been dropped.' => 'ডাটাবেজ মুছে ফেলা হয়েছে।',
'Database has been created.' => 'ডাটাবেজ তৈরী করা হয়েছে।',
'Database has been renamed.' => 'ডাটাবেজের নতুন নামকরণ করা হয়েছে।',
'Database has been altered.' => 'ডাটাবেজ সম্পাদনা করা হয়েছে।',
'Alter database' => 'ডাটাবেজ সম্পাদনা',
'Create database' => 'ডাটাবেজ তৈরী',
'SQL command' => 'SQL-কোয়্যারী',
'Database has been altered.' => 'ডাটাবেজ পরিবর্তন করা হয়েছে।',
'Alter database' => 'ডাটাবেজ পরিবর্তন করুন',
'Create database' => 'ডাটাবেজ তৈরী করুন',
'SQL command' => 'SQL-কমান্ড',
'Logout' => 'লগআউট',
'database' => 'ডাটাবেজ',
'Use' => 'ব্যবহার',
'No tables.' => 'কোন টেবিল নাই।',
'select' => 'নির্বাচন',
'Item has been deleted.' => 'বিষয়বস্তু মুছে ফেলা হয়েছে।',
'Item has been updated.' => 'বিষয়বস্তু আপডেট করা হয়েছে।',
'Item has been updated.' => 'বিষয়বস্তু হালনাগাদ করা হয়েছে।',
'Item%s has been inserted.' => 'বিষয়বস্তুসমূহ সংযোজন করা হয়েছে।',
'Edit' => 'সম্পাদনা',
'Insert' => 'সংযোজন',
'Save and insert next' => 'সংরক্ষন ও পরবর্তী সংযোজন',
'Delete' => 'মুছে ফেল',
'Save and insert next' => 'সংরক্ষন ও পরবর্তী সংযোজন করুন',
'Delete' => 'মুছে ফেলুন',
'Database' => 'ডাটাবেজ',
'Routines' => 'রুটিনসমূহ',
'Indexes have been altered.' => 'সূচীসমূহ সম্পাদনা করা হয়েছে।',
'Indexes' => 'সূচীসমূহ',
'Alter indexes' => 'সূচীসমূহ সম্পাদনা',
'Add next' => 'সংযোজন',
'Alter indexes' => 'সূচীসমূহ পরিবর্তন করুন',
'Add next' => 'পরবর্তী সংযোজন করুন',
'Language' => 'ভাষা',
'Select' => 'নির্বাচন',
'New item' => 'নতুন বিষয়বস্তু',
@@ -60,18 +61,18 @@ $translations = array(
'edit' => 'সম্পাদনা',
'Page' => 'পৃষ্ঠা',
'Query executed OK, %d row(s) affected.' => array('কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।', 'কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।'),
'Error in query' => 'কোয়্যারীতে ভুল আছে।',
'Error in query' => 'অনুসন্ধানে ভুল আছে।',
'Execute' => 'সম্পাদন করো',
'Table' => 'টেবিল',
'Foreign keys' => 'ফরেন কী',
'Triggers' => 'ট্রিগার',
'View' => 'ভিউ',
'Unable to select the table' => 'টেবিল নির্বাচন করতে অক্ষম',
'Invalid CSRF token. Send the form again.' => 'অবৈধ CSRF টোকেন। ফর্ম আবার পাঠা।',
'Invalid CSRF token. Send the form again.' => 'অবৈধ CSRF টোকেন। ফর্মটি আবার পাঠা।',
'Comment' => 'মন্তব্য',
'Default values' => 'ডিফল্ট মান',
'%d byte(s)' => array('%d বাইট', '%d বাইটসমূহ'),
'No commands to execute.' => 'সম্পাদন করার মত কোন নির্দেশ নই।',
'No commands to execute.' => 'সম্পাদন করার মত কোন নির্দেশ নই।',
'Unable to upload a file.' => 'ফাইল আপলোড করা সম্ভব হচ্ছে না।',
'File upload' => 'ফাইল আপলোড',
'File uploads are disabled.' => 'ফাইল আপলোড নিষ্ক্রিয় করা আছে।',
@@ -80,70 +81,70 @@ $translations = array(
'No extension' => 'কোন এক্সটেনশান নাই',
'None of the supported PHP extensions (%s) are available.' => 'কোন PHP সমর্থিত এক্সটেনশন (%s) পাওয়া যায় নাই।',
'Session support must be enabled.' => 'সেশন সমর্থন সক্রিয় করা আবশ্যক।',
'Session expired, please login again.' => 'সেশনের মেয়াদ শেষ হয়েছে, আবার লগইন করুন।',
'Session expired, please login again.' => 'সেশনের মেয়াদ শেষ হয়েছে, আবার লগইন করুন।',
'Text length' => 'টেক্সট দৈর্ঘ্য',
'Foreign key has been dropped.' => 'ফরেন কী মুছে ফেলা হয়েছে।',
'Foreign key has been altered.' => 'ফরেন কী সম্পাদনা করা হয়েছে।',
'Foreign key has been altered.' => 'ফরেন কী পরিবর্তন করা হয়েছে।',
'Foreign key has been created.' => 'ফরেন কী তৈরী করা হয়েছে।',
'Foreign key' => 'ফরেন কী ',
'Target table' => 'টার্গেট টেবিল',
'Change' => 'পরিবর্তন',
'Source' => 'উৎস',
'Target' => 'লক্ষ্য',
'Add column' => 'কলাম সংযোজন',
'Alter' => 'সম্পাদনা',
'Add foreign key' => 'ফরেন কী সংযোজন কর',
'Add column' => 'কলাম সংযোজন করুন',
'Alter' => 'পরিবর্তন',
'Add foreign key' => 'ফরেন কী সংযোজন করুন',
'ON DELETE' => 'অন ডিলিট',
'ON UPDATE' => 'অন আপডেট',
'Index Type' => 'সূচী-ধরণ',
'Column (length)' => 'কলাম (দৈর্ঘ্য)',
'length' => 'দৈর্ঘ্য',
'View has been dropped.' => 'ভিউ মুছে ফেলা হয়েছে।',
'View has been altered.' => 'ভিউ সম্পাদনা করা হয়েছে।',
'View has been altered.' => 'ভিউ পরিবর্তন করা হয়েছে।',
'View has been created.' => 'ভিউ তৈরী করা হয়েছে।',
'Alter view' => 'ভিউ সম্পাদনা কর',
'Create view' => 'ভিউ তৈরী কর',
'Alter view' => 'ভিউ পরিবর্তন করুন',
'Create view' => 'ভিউ তৈরী করুন',
'Name' => 'নাম',
'Process list' => 'প্রসেস তালিকা',
'%d process(es) have been killed.' => array('%d টি প্রসেস(সমূহ) বিনষ্ট করা হয়েছে।', '%d টি প্রসেস(সমূহ) বিনষ্ট করা হয়েছে।'),
'Kill' => 'বিনষ্ট করো',
'Parameter name' => 'প্যারামিটারের নাম',
'Database schema' => 'ডাটাবেজ স্কিমা',
'Create procedure' => 'প্রসিডিওর তৈরী কর',
'Create function' => 'ফাংশন তৈরী কর',
'Create procedure' => 'কার্যপ্রণালী তৈরী করুন',
'Create function' => 'ফাংশন তৈরী করুন',
'Routine has been dropped.' => 'রুটিন মুছে ফেলা হয়েছে।',
'Routine has been altered.' => 'রুটিন সম্পাদনা করা হয়েছে।',
'Routine has been altered.' => 'রুটিন পরিবর্তন করা হয়েছে।',
'Routine has been created.' => 'রুটিন তৈরী করা হয়েছে।',
'Alter function' => 'ফাংশন সম্পাদনা কর',
'Alter procedure' => 'প্রসিডিওর সম্পাদনা কর',
'Alter function' => 'ফাংশন পরিবর্তন করুন',
'Alter procedure' => 'কার্যপ্রণালী পরিবর্তন করুন',
'Return type' => 'রিটার্ন টাইপ',
'Add trigger' => 'ট্রিগার সংযোজন কর',
'Add trigger' => 'ট্রিগার সংযোজন করুন',
'Trigger has been dropped.' => 'ট্রিগার মুছে ফেলা হয়েছে।',
'Trigger has been altered.' => 'ট্রিগার সম্পাদনা করা হয়েছে।',
'Trigger has been altered.' => 'ট্রিগার পরিবর্তন করা হয়েছে।',
'Trigger has been created.' => 'ট্রিগার তৈরী করা হয়েছে।',
'Alter trigger' => 'ট্রিগার সম্পাদনা কর',
'Create trigger' => 'ট্রিগার তৈরী কর',
'Alter trigger' => 'ট্রিগার পরিবর্তন করুন',
'Create trigger' => 'ট্রিগার তৈরী করুন',
'Time' => 'সময়',
'Event' => 'ইভেন্ট',
'%s version: %s through PHP extension %s' => 'ভার্সন %s: %s, %s PHP এক্সটেনশনের মধ্য দিয়ে',
'%d row(s)' => array('%d সারি', '%d সারি সমূহ'),
'Remove' => 'অপসারণ',
'Are you sure?' => 'তুমি কি নিশ্চিত?',
'Remove' => 'মুছে ফেলুন',
'Are you sure?' => 'আপনি কি নিশ্চিত?',
'Privileges' => 'প্রিভিলেজেস',
'Create user' => 'ইউজার তৈরী কর',
'User has been dropped.' => 'ইউজার মুছে ফেলা হয়েছে।',
'User has been altered.' => 'ইউজার সম্পাদনা করা হয়েছে।',
'User has been created.' => 'ইউজার তৈরী করা হয়েছে।',
'Hashed' => 'হ্যাড',
'Create user' => 'ব্যবহারকারি তৈরী করুন',
'User has been dropped.' => 'ব্যবহারকারি মুছে ফেলা হয়েছে।',
'User has been altered.' => 'ব্যবহারকারি সম্পাদনা করা হয়েছে।',
'User has been created.' => 'ব্যবহারকারি তৈরী করা হয়েছে।',
'Hashed' => 'হ্যাড',
'Column' => 'কলাম',
'Routine' => 'রুটিন',
'Grant' => 'গ্র্যান্ট',
'Revoke' => 'রিভোক',
'Grant' => 'অনুমতি',
'Revoke' => 'প্রত্যাহার',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'খুব বড় POST ডাটা। ডাটা সংক্ষিপ্ত করো অথবা %s কনফিগারেশন নির্দেশ বৃদ্ধি করো',
'Logged as: %s' => '%s হিসাবে লগড',
'Move up' => 'উপরে স্থানান্তর',
'Move down' => 'নীচে স্থানান্তর',
'Functions' => 'ফাংশন সমূহ',
'Aggregation' => 'মোট পরিমাণ',
'Aggregation' => 'সমষ্টি',
'Export' => 'এক্সপোর্ট',
'Output' => 'আউটপুট',
'open' => 'খোলা',
@@ -162,8 +163,8 @@ $translations = array(
'Schedule' => 'সময়সূচি',
'Start' => 'শুরু',
'End' => 'সমাপ্তি',
'Status' => 'স্ট্যাটাস',
'On completion preserve' => 'সমাপ্ত হওয়ার পর সংরক্ষন কর',
'Status' => 'অবস্থা',
'On completion preserve' => 'সমাপ্ত হওয়ার পর সংরক্ষন করুন',
'Tables and views' => 'টেবিল এবং ভিউ সমূহ',
'Data Length' => 'ডাটার দৈর্ঘ্য',
'Index Length' => 'ইনডেক্স এর দৈর্ঘ্য',
@@ -175,14 +176,14 @@ $translations = array(
'Repair' => 'মেরামত',
'Truncate' => 'ছাঁটাই',
'Tables have been truncated.' => 'টেবিল ছাঁটাই করা হয়েছে',
'Rows' => 'সারি',
'Rows' => 'সারিসমূহ',
',' => ',',
'0123456789' => '০১২৩৪৫৬৭৮৯',
'Tables have been moved.' => 'টেবিল স্থানান্তর করা হয়েছে।',
'Move to other database' => 'অন্য ডাটাবেজে স্থানান্তর কর',
'Move' => 'স্থানান্তর কর',
'Move to other database' => 'অন্য ডাটাবেজে স্থানান্তর করুন',
'Move' => 'স্থানান্তর করুন',
'Engine' => 'ইঞ্জিন',
'Save and continue edit' => 'সংরক্ষণ কর এবং সম্পাদনা চালিয়ে যা',
'Save and continue edit' => 'সংরক্ষণ করুন এবং সম্পাদনা চালিয়ে যা',
'original' => 'প্রকৃত',
'Tables have been dropped.' => 'টেবিলসমূহ মুছে ফেলা হয়েছে।',
'%d item(s) have been affected.' => '%d টি বিষয়বস্তু প্রভাবিত হয়েছে',
@@ -196,7 +197,7 @@ $translations = array(
'%d row(s) have been imported.' => array('%d টি সারি(সমূহ) ইমপোর্ট করা হয়েছে।', '%d টি সারি(সমূহ) ইমপোর্ট করা হয়েছে।'),
'anywhere' => 'যে কোন স্থানে',
'Import' => 'ইমপোর্ট',
'Stop on error' => 'ত্রুটি পেলে থেমে যা',
'Stop on error' => 'ত্রুটি পেলে থেমে যা',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 't.m.[jjjj]',
@@ -216,14 +217,14 @@ $translations = array(
'E-mail' => '​​ই-মেইল',
'From' => 'থেকে',
'Subject' => 'বিষয়',
'Send' => 'পাঠা',
'Send' => 'পাঠা',
'%d e-mail(s) have been sent.' => array('%d ইমেইল(গুলি) পাঠানো হয়েছে।', '%d ইমেইল(গুলি) পাঠানো হয়েছে।'),
'Webserver file %s' => 'ওয়েবসার্ভার ফাইল %s',
'File does not exist.' => 'ফাইলর কোন অস্তিত্ব নেই।',
'File does not exist.' => 'ফাইলটির কোন অস্তিত্ব নেই।',
'%d in total' => 'সর্বমোটঃ %d টি',
'Permanent login' => 'স্থায়ী লগইন',
'Databases have been dropped.' => 'ডাটাবেজসমূহ মুছে ফেলা হয়েছে।',
'Search data in tables' => 'টেবিলে খোঁজ করো',
'Search data in tables' => 'টেবিলে তথ্য খুঁজুন',
'Schema' => 'স্কিমা',
'Alter schema' => 'স্কিমা পরিবর্তন করো',
'Create schema' => 'স্কিমা তৈরী করো',
@@ -236,32 +237,32 @@ $translations = array(
'Sequence has been dropped.' => 'অনুক্রম মুছে ফেলা হয়েছে।',
'Sequence has been created.' => 'অনুক্রম তৈরি করা হয়েছে।',
'Sequence has been altered.' => 'অনুক্রম সম্পাদনা করা হয়েছে।',
'User types' => 'ইউজারের টাইপ',
'Create type' => 'টাইপ তৈরী কর',
'Alter type' => 'টাইপ পরিবর্তন কর',
'Type has been dropped.' => 'টাইপ মুছে ফেলা হয়েছে।',
'Type has been created.' => 'টাইপ তৈরি করা হয়েছে।',
'Use edit link to modify this value.' => 'এই মান পরিবর্তনের জন্য সম্পাদনা লিঙ্ক ব্যবহার কর।',
'User types' => 'ব্যবহারকারির ধরণ',
'Create type' => 'ধরণ তৈরী করুন',
'Alter type' => 'ধরণ পরিবর্তন করুন',
'Type has been dropped.' => 'ধরণ মুছে ফেলা হয়েছে।',
'Type has been created.' => 'ধরণ তৈরি করা হয়েছে।',
'Use edit link to modify this value.' => 'এই মানটি পরিবর্তনের জন্য সম্পাদনা লিঙ্ক ব্যবহার করুন।',
'last' => 'সর্বশেষ',
'From server' => 'সার্ভার থেকে',
'System' => 'সিস্টেম',
'Select data' => 'তথ্য নির্বাচন করো',
'Show structure' => 'গঠন দেখা',
'Show structure' => 'গঠন দেখা',
'empty' => 'খালি',
'Network' => 'নেটওয়ার্ক',
'Geometry' => 'জ্যামিতি',
'File exists.' => 'ফাইল রয়েছে।',
'Attachments' => 'সংযুক্তি',
'%d query(s) executed OK.' => array('SQL-কোয়্যারী সফলভাবে সম্পন্ন হয়েছে', '%d SQL-কোয়্যারীসমূহ সফলভাবে সম্পন্ন হয়েছে'),
'Show only errors' => 'শুধুমাত্র ত্রুটি দেখা',
'Attachments' => 'সংযুক্তিগুলো',
'%d query(s) executed OK.' => array('SQL-অনুসন্ধান সফলভাবে সম্পন্ন হয়েছে', '%d SQL-অনুসন্ধানসমূহ সফলভাবে সম্পন্ন হয়েছে'),
'Show only errors' => 'শুধুমাত্র ত্রুটিগুলো দেখা',
'Refresh' => 'রিফ্রেশ',
'Invalid schema.' => 'অবৈধ স্কিমা।',
'Please use one of the extensions %s.' => 'কোন একটা এক্সটেনশন %s ব্যবহার কর।',
'Please use one of the extensions %s.' => 'কোন একটা এক্সটেনশন %s ব্যবহার করুন।',
'now' => 'এখন',
'ltr' => 'ltr',
'Tables have been copied.' => 'টেবিল কপি করা হয়েছে।',
'Tables have been copied.' => 'টেবিলগুলো কপি করা হয়েছে।',
'Copy' => 'কপি',
'Permanent link' => 'স্থায়ী লিংক',
'Edit all' => 'সকল সম্পাদনা কর',
'Edit all' => 'সবগুলো সম্পাদনা করুন',
'HH:MM:SS' => 'HH:MM:SS',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistem',
@@ -73,7 +75,6 @@ $translations = array(
'Data' => 'Podaci',
'Database' => 'Baza podataka',
'database' => 'baza podataka',
'Use' => 'Koristi',
'Select database' => 'Izaberite bazu',
'Invalid database.' => 'Neispravna baza podataka.',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Ažuriraj indekse',
'Add next' => 'Dodaj slijedeći',
'Index Type' => 'Tip indeksa',
'Column (length)' => 'kolumna (dužina)',
'length' => 'dužina',
'Foreign keys' => 'Strani ključevi',
'Foreign key' => 'Strani ključ',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Inicia la sessió',
'Logout successful.' => 'Desconnexió correcta.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Crea una base de dades',
'SQL command' => 'Ordre SQL',
'Logout' => 'Desconnecta',
'database' => 'base de dades',
'Use' => 'Utilitza',
'No tables.' => 'No hi ha cap taula.',
'select' => 'registres',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipus d\'índex',
'Column (length)' => 'Columna (longitud)',
'length' => 'longitud',
'View has been dropped.' => 'S\'ha suprimit la vista.',
'View has been altered.' => 'S\'ha modificat la vista.',
'View has been created.' => 'S\'ha creat la vista.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Systém',
@@ -23,7 +25,7 @@ $translations = array(
'No extension' => 'Žádné rozšíření',
'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).',
'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
'Disable %s or enable %s or %s extensions.' => 'Zakažte %s nebo povolte extenze %s nebo %s.',
'Disable %s or enable %s or %s extensions.' => 'Zakažte %s nebo povolte rozšíření %s nebo %s.',
'Session support must be enabled.' => 'Session proměnné musí být povolené.',
'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
'The action will be performed after successful login with the same credentials.' => 'Akce bude provedena po úspěšném přihlášení se stejnými přihlašovacími údaji.',
@@ -88,7 +90,6 @@ $translations = array(
'Data' => 'Data',
'Database' => 'Databáze',
'database' => 'databáze',
'DB' => 'DB',
'Use' => 'Vybrat',
'Select database' => 'Vybrat databázi',
@@ -206,7 +207,7 @@ $translations = array(
'Alter indexes' => 'Pozměnit indexy',
'Add next' => 'Přidat další',
'Index Type' => 'Typ indexu',
'Column (length)' => 'Sloupec (délka)',
'length' => 'délka',
'Foreign keys' => 'Cizí klíče',
'Foreign key' => 'Cizí klíč',
@@ -256,8 +257,8 @@ $translations = array(
'%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'),
'Page' => 'Stránka',
'last' => 'poslední',
'Load more data' => 'Nahrát další data',
'Loading' => 'Nahrává se',
'Load more data' => 'Načíst další data',
'Loading' => 'Načítá se',
'Whole result' => 'Celý výsledek',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtů'),
@@ -346,4 +347,12 @@ $translations = array(
'Type has been dropped.' => 'Typ byl odstraněn.',
'Type has been created.' => 'Typ byl vytvořen.',
'Alter type' => 'Pozměnit typ',
// Table check constraints
'Checks' => 'Kontroly',
'Create check' => 'Vytvořit kontrolu',
'Alter check' => 'Změnit kontrolu',
'Check has been created.' => 'Kontrola byla vytvořena.',
'Check has been altered.' => 'Kontrola byla změněna.',
'Check has been dropped.' => 'Kontrola byla odstraněna.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'System' => 'System',
'Server' => 'Server',
@@ -64,7 +66,6 @@ $translations = array(
'Format' => 'Format',
'Data' => 'Data',
'Database' => 'Database',
'database' => 'database',
'Use' => 'Brug',
'Select database' => 'Vælg database',
'Invalid database.' => 'Ugyldig database.',
@@ -165,7 +166,7 @@ $translations = array(
'Alter indexes' => 'Ændre indekser',
'Add next' => 'Læg til næste',
'Index Type' => 'Indekstype',
'Column (length)' => 'Kolonne (længde)',
'length' => 'længde',
'Foreign keys' => 'Fremmednøgler',
'Foreign key' => 'Fremmednøgle',
'Foreign key has been dropped.' => 'Fremmednøglen er slettet.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Login',
'Logout successful.' => 'Abmeldung erfolgreich.',
@@ -32,8 +34,7 @@ $translations = array(
'Create database' => 'Datenbank erstellen',
'SQL command' => 'SQL-Kommando',
'Logout' => 'Abmelden',
'database' => 'Datenbank',
'Use' => 'Benutzung',
'Use' => 'Auswählen',
'No tables.' => 'Keine Tabellen.',
'select' => 'zeigen',
'Item has been deleted.' => 'Datensatz wurde gelöscht.',
@@ -97,7 +98,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Index-Typ',
'Column (length)' => 'Spalte (Länge)',
'length' => 'Länge',
'View has been dropped.' => 'View wurde entfernt.',
'View has been altered.' => 'View wurde geändert.',
'View has been created.' => 'View wurde erstellt.',
@@ -280,10 +281,25 @@ $translations = array(
'If you did not send this request from Adminer then close this page.' => 'Wenn Sie diese Anfrage nicht von Adminer gesendet haben, schließen Sie diese Seite.',
'You can upload a big SQL file via FTP and import it from server.' => 'Sie können eine große SQL-Datei per FTP hochladen und dann vom Server importieren.',
'You are offline.' => 'Sie sind offline.',
'You have no privileges to update this table.' => 'Sie haben keine Rechte, um diese Tabelle zu aktualisieren.',
'You have no privileges to update this table.' => 'Sie haben keine Rechte, diese Tabelle zu aktualisieren.',
'Saving' => 'Speichere',
'yes' => 'ja',
'no' => 'nein',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Das Master-Passwort ist abgelaufen. <a href="https://www.adminer.org/de/extension/"%s>Implementieren</a> Sie die %s Methode, um es permanent zu machen.',
'%d / ' => '%d / ',
'Drop %s?' => '%s entfernen?',
'Materialized view' => 'Strukturierte Ansicht',
'Vacuum' => 'Vacuum',
'overwrite' => 'überschreiben',
'DB' => 'DB',
'ATTACH queries are not supported.' => 'ATTACH Abfragen werden nicht unterstützt.',
'Warnings' => 'Warnungen',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer unterstützt den Zugriff auf eine Datenbank ohne Passwort nicht, <a href="https://www.adminer.org/en/password/"%s>mehr Informationen</a>.',
'Full table scan' => 'Vollständige Überprüfung der Tabelle',
'The action will be performed after successful login with the same credentials.' => 'Die Aktion wird nach erfolgreicher Anmeldung mit denselben Anmeldedaten ausgeführt.',
'Connecting to privileged ports is not allowed.' => 'Die Verbindung zu privilegierten Ports ist nicht erlaubt.',
'There is a space in the input password which might be the cause.' => 'Es gibt ein Leerzeichen im Eingabepasswort, das die Ursache sein könnte.',
'Unknown error.' => 'Unbekannter Fehler.',
'Database does not support password.' => 'Die Datenbank unterstützt kein Passwort.',
'Disable %s or enable %s or %s extensions.' => 'Deaktivieren Sie %s oder aktivieren Sie die Erweiterungen %s oder %s.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Σύστημα',
@@ -79,7 +81,6 @@ $translations = array(
'Data' => 'Δεδομένα',
'Database' => 'Β. Δεδομένων',
'database' => 'β. δεδομένων',
'Use' => 'χρήση',
'Select database' => 'Επιλέξτε Β.Δ.',
'Invalid database.' => 'Λανθασμένη Β.Δ.',
@@ -194,7 +195,7 @@ $translations = array(
'Alter indexes' => 'Τροποποίηση δεικτών',
'Add next' => 'Προσθήκη επόμενου',
'Index Type' => 'Τύπος δείκτη',
'Column (length)' => 'Στήλη (μήκος)',
'length' => 'μήκος',
'Foreign keys' => 'Εξαρτημένα κλειδιά',
'Foreign key' => 'Εξαρτημένο κλειδί',

View File

@@ -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.'),

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Login',
'Logout successful.' => 'Sesión finalizada con éxito.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Crear Base de datos',
'SQL command' => 'Comando SQL',
'Logout' => 'Cerrar sesión',
'database' => 'base de datos',
'Use' => 'Usar',
'No tables.' => 'No existen tablas.',
'select' => 'registros',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'AL BORRAR',
'ON UPDATE' => 'AL ACTUALIZAR',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Columna (longitud)',
'length' => 'longitud',
'View has been dropped.' => 'Vista eliminada.',
'View has been altered.' => 'Vista modificada.',
'View has been created.' => 'Vista creada.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Logi sisse',
'Logout successful.' => 'Väljalogimine õnnestus.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Loo uus andmebaas',
'SQL command' => 'SQL-Päring',
'Logout' => 'Logi välja',
'database' => 'andmebaas',
'Use' => 'Kasuta',
'No tables.' => 'Tabeleid ei leitud.',
'select' => 'kuva',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Indeksi tüüp',
'Column (length)' => 'Veerg (pikkus)',
'length' => 'pikkus',
'View has been dropped.' => 'Vaade (VIEW) on edukalt kustutatud.',
'View has been altered.' => 'Vaade (VIEW) on edukalt muudetud.',
'View has been created.' => 'Vaade (VIEW) on edukalt loodud.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'سیستم',
@@ -77,7 +79,6 @@ $translations = array(
'Data' => 'داده',
'Database' => 'پایگاه داده',
'database' => 'پایگاه داده',
'Use' => 'استفاده',
'Select database' => 'انتخاب پایگاه داده',
'Invalid database.' => 'پایگاه داده نامعتبر.',
@@ -192,7 +193,7 @@ $translations = array(
'Alter indexes' => 'ویرایش ایندکسها',
'Add next' => 'افرودن بعدی',
'Index Type' => 'نوع ایندکس',
'Column (length)' => 'ستون (طول)',
'length' => 'طول',
'Foreign keys' => 'کلیدهای خارجی',
'Foreign key' => 'کلید خارجی',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Järjestelmä',
@@ -79,7 +81,6 @@ $translations = array(
'Data' => 'Data',
'Database' => 'Tietokanta',
'database' => 'tietokanta',
'Use' => 'Käytä',
'Select database' => 'Valitse tietokanta',
'Invalid database.' => 'Tietokanta ei kelpaa.',
@@ -194,7 +195,7 @@ $translations = array(
'Alter indexes' => 'Muuta indeksejä',
'Add next' => 'Lisää seuraava',
'Index Type' => 'Indeksityyppi',
'Column (length)' => 'Sarake (pituus)',
'length' => 'pituus',
'Foreign keys' => 'Vieraat avaimet',
'Foreign key' => 'Vieras avain',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Authentification',
'Logout successful.' => 'Au revoir !',
@@ -30,7 +32,6 @@ $translations = array(
'Create database' => 'Créer une base de données',
'SQL command' => 'Requête SQL',
'Logout' => 'Déconnexion',
'database' => 'base de données',
'Use' => 'Utiliser',
'No tables.' => 'Aucune table.',
'select' => 'select',
@@ -94,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Type d\'index',
'Column (length)' => 'Colonne (longueur)',
'length' => 'longueur',
'View has been dropped.' => 'La vue a été effacée.',
'View has been altered.' => 'La vue a été modifiée.',
'View has been created.' => 'La vue a été créée.',
@@ -288,4 +289,16 @@ $translations = array(
'Default value' => 'Valeur par défaut',
'If you did not send this request from Adminer then close this page.' => 'Si vous n\'avez pas envoyé cette requête depuis Adminer, alors fermez cette page.',
'You are offline.' => 'Vous êtes hors ligne.',
'Drop %s?' => 'Supprimer %s?',
'overwrite' => 'écraser',
'DB' => 'BD',
'ATTACH queries are not supported.' => 'Requêtes ATTACH ne sont pas supportées.',
'Warnings' => 'Avertissements',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer ne supporte pas l\'accès aux bases de données sans mot de passe, <a href="https://www.adminer.org/en/password/"%s>plus d\'information</a>.',
'The action will be performed after successful login with the same credentials.' => 'Cette action sera exécutée après s\'être connecté avec les mêmes données de connexion.',
'Connecting to privileged ports is not allowed.' => 'La connexion aux ports privilégiés n\'est pas autorisée.',
'There is a space in the input password which might be the cause.' => 'Il y a un espace dans le mot de passe entré qui pourrait en être la cause.',
'Unknown error.' => 'Erreur inconnue',
'Database does not support password.' => 'La base de données ne support pas les mots de passe',
'Disable %s or enable %s or %s extensions.' => 'Désactiver %s ou activer %s or %s extensions.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Conectar',
'Logout successful.' => 'Pechouse a sesión con éxito.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Crear Base de datos',
'SQL command' => 'Comando SQL',
'Logout' => 'Pechar sesión',
'database' => 'base de datos',
'Use' => 'Usar',
'No tables.' => 'Nengunha táboa.',
'select' => 'selecciona',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'AO BORRAR (ON DELETE)',
'ON UPDATE' => 'AO ACTUALIZAR (ON UPDATE)',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Columna (lonxitude)',
'length' => 'lonxitude',
'View has been dropped.' => 'Eliminouse a vista.',
'View has been altered.' => 'Modificouse a vista.',
'View has been created.' => 'Creouse a vista.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'התחברות',
'Logout successful.' => 'ההתחברות הצליחה',
@@ -30,7 +32,6 @@ $translations = array(
'Create database' => 'צור מסד נתונים',
'SQL command' => 'שאילתת SQL',
'Logout' => 'התנתק',
'database' => 'מסד נתונים',
'Use' => 'השתמש',
'No tables.' => 'אין טבלאות',
'select' => 'בחר',
@@ -94,7 +95,7 @@ $translations = array(
'ON DELETE' => 'בעת מחיקה',
'ON UPDATE' => 'בעת עידכון',
'Index Type' => 'סוג אינדקס',
'Column (length)' => 'עמודה (אורך)',
'length' => 'אורך',
'View has been dropped.' => 'התצוגה הושלכה',
'View has been altered.' => 'התצוגה שונתה',
'View has been created.' => 'התצוגה נוצרה',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Belépés',
'Logout successful.' => 'Sikeres kilépés.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Adatbázis létrehozása',
'SQL command' => 'SQL parancs',
'Logout' => 'Kilépés',
'database' => 'adatbázis',
'Use' => 'Használ',
'No tables.' => 'Nincs tábla.',
'select' => 'kiválasztás',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'törléskor',
'ON UPDATE' => 'frissítéskor',
'Index Type' => 'Index típusa',
'Column (length)' => 'Oszop (méret)',
'length' => 'méret',
'View has been dropped.' => 'A nézet eldobva.',
'View has been altered.' => 'A nézet módosult.',
'View has been created.' => 'A nézet létrejött.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistem',
@@ -73,7 +75,6 @@ $translations = array(
'Data' => 'Data',
'Database' => 'Basis data',
'database' => 'basis data',
'Use' => 'Gunakan',
'Select database' => 'Pilih basis data',
'Invalid database.' => 'Basis data tidak sah.',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Ubah indeks',
'Add next' => 'Tambah setelahnya',
'Index Type' => 'Jenis Indeks',
'Column (length)' => 'Kolom (panjang)',
'length' => 'panjang',
'Foreign keys' => 'Kunci asing',
'Foreign key' => 'Kunci asing',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Autenticazione',
'Logout successful.' => 'Uscita effettuata con successo.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Crea database',
'SQL command' => 'Comando SQL',
'Logout' => 'Esci',
'database' => 'database',
'Use' => 'Usa',
'No tables.' => 'No tabelle.',
'select' => 'seleziona',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo indice',
'Column (length)' => 'Colonna (lunghezza)',
'length' => 'lunghezza',
'View has been dropped.' => 'Vista eliminata.',
'View has been altered.' => 'Vista modificata.',
'View has been created.' => 'Vista creata.',
@@ -265,4 +266,39 @@ $translations = array(
'Permanent link' => 'Link permanente',
'Edit all' => 'Modifica tutto',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => 'Scartare %s?',
'Tables have been optimized.' => 'Le tabelle sono state ottimizzate',
'Materialized view' => 'Vista materializzata',
'Vacuum' => 'Aspira',
'Selected' => 'Selezionato',
'overwrite' => 'sovrascrivi',
'DB' => 'DB',
'File must be in UTF-8 encoding.' => 'Il file deve avere codifica UTF-8.',
'Modify' => 'Modifica',
'Load more data' => 'Carica piú dati',
'Loading' => 'Caricamento',
'ATTACH queries are not supported.' => 'ATTACH queries non sono supportate.',
'Warnings' => 'Attenzione',
'%d / ' => '%d / ',
'Limit rows' => 'Limite righe',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer non supporta accesso a databse senza password, <a href="https://www.adminer.org/it/password/"%s>piú informazioni</a>.',
'Default value' => 'Valore predefinito',
'Full table scan' => 'Analizza intera tabella',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Troppi tentativi infruttuosi di login, si prega di riprovare in %d minuto.', 'Troppi tentativi infruttuosi di login, si prega di riprovare in %d minuti.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'La password principale é scaduta. <a href="https://www.adminer.org/it/extension/"%s>Implementare</a> %s come metodo per renderla permanente.',
'The action will be performed after successful login with the same credentials.' => 'La azione verrá eseguita dopo un login valido con le stesse credenziali.',
'Connecting to privileged ports is not allowed.' => 'LA connessione a porte privilegiate non é permessa.',
'There is a space in the input password which might be the cause.' => 'Esiste uno spazio nella passoword inserita che potrebbe essere la causa.',
'If you did not send this request from Adminer then close this page.' => 'Se non hai inviato tu la richiesta tramite Adminer puoi chiudere la pagina.',
'You can upload a big SQL file via FTP and import it from server.' => 'Puoi caricare un grande file SQL tramite FTP ed impirtarlo dal server.',
'Size' => 'Taglia',
'Compute' => 'Elabora',
'You are offline.' => 'Sei disconnesso.',
'You have no privileges to update this table.' => 'Non hai i privilegi per aggiornare questa tabella.',
'Saving' => 'Salvataggio',
'Unknown error.' => 'Errore sconosciuto',
'Database does not support password.' => 'Il database non supporta password.',
'Disable %s or enable %s or %s extensions.' => 'Disabilita %s o abilita %s oppure %s estensioni.',
'yes' => 'si',
'no' => 'no',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'ログイン',
'Logout successful.' => 'ログアウト',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'データベースを作成',
'SQL command' => 'SQLコマンド',
'Logout' => 'ログアウト',
'database' => 'データベース',
'Use' => '使用',
'No tables.' => 'テーブルがありません。',
'select' => '選択',
@@ -95,7 +96,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => '索引の型',
'Column (length)' => '列(長さ',
'length' => '長さ',
'View has been dropped.' => 'ビューを削除しました',
'View has been altered.' => 'ビューを変更しました',
'View has been created.' => 'ビューを作成しました',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'შესვლა',
'Logout successful.' => 'გამოხვედით სისტემიდან.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'ბაზის შექმნა',
'SQL command' => 'SQL-ბრძანება',
'Logout' => 'გასვლა',
'database' => 'ბაზა',
'Use' => 'არჩევა',
'No tables.' => 'ბაზაში ცხრილი არაა.',
'select' => 'არჩევა',
@@ -94,7 +95,7 @@ $translations = array(
'ON DELETE' => 'წაშლისას',
'ON UPDATE' => 'განახლებისას',
'Index Type' => 'ინდექსის სახეობა',
'Column (length)' => 'ველი (სიგრძე)',
'length' => 'სიგრძე',
'View has been dropped.' => 'წარმოდგენა წაიშალა.',
'View has been altered.' => 'წარმოდგენა შეიცვალა.',
'View has been created.' => 'წარმოდგენა შეიქმნა.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'$1-$3-$5' => '$1-$3-$5',
'%.3f s' => '%.3f 초',
@@ -46,7 +48,7 @@ $translations = array(
'Clone' => '복제',
'collation' => '정렬',
'Collation' => '정렬',
'Column (length)' => '열 (길이)',
'length' => '길이',
'Column name' => '열 이름',
'Column' => '열',
'Comment' => '주석',
@@ -71,7 +73,6 @@ $translations = array(
'Database has been dropped.' => '데이터베이스를 삭제했습니다.',
'Database has been renamed.' => '데이터베이스의 이름을 바꾸었습니다.',
'Database schema' => '데이터베이스 구조',
'database' => '데이터베이스',
'Database' => '데이터베이스',
'Databases have been dropped.' => '데이터베이스를 삭제했습니다.',
'Date and time' => '시간',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistema',
@@ -73,7 +75,6 @@ $translations = array(
'Data' => 'Duomenys',
'Database' => 'Duomenų bazė',
'database' => 'duomenų bazė',
'Use' => 'Naudoti',
'Select database' => 'Pasirinkti duomenų bazę',
'Invalid database.' => 'Neteisinga duomenų bazė.',
@@ -182,7 +183,7 @@ $translations = array(
'Alter indexes' => 'Redaguoti indeksus',
'Add next' => 'Pridėti kitą',
'Index Type' => 'Indekso tipas',
'Column (length)' => 'Stulpelis (ilgis)',
'length' => 'ilgis',
'Foreign keys' => 'Išoriniai raktai',
'Foreign key' => 'Išorinis raktas',

304
adminer/lang/lv.inc.php Normal file
View File

@@ -0,0 +1,304 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Ieiet',
'Logout successful.' => 'Jūs veiksmīgi izgājāt no sistēmas.',
'Invalid credentials.' => 'Nepareizs lietotāja vārds vai parole.',
'Server' => 'Serveris',
'Username' => 'Lietotājs',
'Password' => 'Parole',
'Select database' => 'Izvēlēties datubāzi',
'Invalid database.' => 'Nederīga datubāze.',
'Table has been dropped.' => 'Tabula dzēsta.',
'Table has been altered.' => 'Tabula mainīta.',
'Table has been created.' => 'Tabula izveidota.',
'Alter table' => 'Mainīt tabulu',
'Create table' => 'Izveidot tabulu',
'Table name' => 'Tabulas nosaukums',
'engine' => 'Tabulas tips',
'collation' => 'Kolācija',
'Column name' => 'Lauka nosaukums',
'Type' => 'Tips',
'Length' => 'Garums',
'Auto Increment' => 'Auto inkrements',
'Options' => 'Opcijas',
'Save' => 'Saglabāt',
'Drop' => 'Dzēst',
'Database has been dropped.' => 'Datubāze tika nodzēsta.',
'Database has been created.' => 'Datubāze tika izveidota.',
'Database has been renamed.' => 'Datubāze tika pārsaukta.',
'Database has been altered.' => 'Datubāze tika mainīta.',
'Alter database' => 'Mainīt datubāzi',
'Create database' => 'Izveidot datubāzi',
'SQL command' => 'SQL pieprasījums',
'Logout' => 'Iziet',
'Use' => 'Lietot',
'No tables.' => 'Datubāzē nav tabulu.',
'select' => 'izvēlēties',
'Item has been deleted.' => 'Ieraksts dzests.',
'Item has been updated.' => 'Ieraksts atjaunots.',
'Item%s has been inserted.' => 'Ieraksti tika ievietoti.',
'Edit' => 'Rediģēt',
'Insert' => 'Ievietot',
'Save and insert next' => 'Saglabāt un ievietot nākamo',
'Delete' => 'Dzēst',
'Database' => 'Datubāze',
'Routines' => 'Procedūras un funkcijas',
'Indexes have been altered.' => 'Indeksi mainīti.',
'Indexes' => 'Indeksi',
'Alter indexes' => 'Izmainīt indeksus',
'Add next' => 'Pievienot vēl',
'Language' => 'Valoda',
'Select' => 'Izvēlēties',
'New item' => 'Jauns ieraksts',
'Search' => 'Meklēšana',
'Sort' => 'Kārtošana',
'descending' => 'dilstoši',
'Limit' => 'Limits',
'No rows.' => 'Nav rindu.',
'Action' => 'Darbība',
'edit' => 'rediģēt',
'Page' => 'Lapa',
'Query executed OK, %d row(s) affected.' => array('Pieprasījums pabeigts, izmainīts %d ieraksts.', 'Pieprasījums pabeigts, izmainīti %d ieraksti.', 'Pieprasījums pabeigts, izmainīti %d ieraksti.'),
'Error in query' => 'Kļūda pieprasījumā',
'Execute' => 'Izpidīt',
'Table' => 'Tabula',
'Foreign keys' => 'Ārejā atslēgas',
'Triggers' => 'Trigeri',
'View' => 'Skats',
'Unable to select the table' => 'Tabula nav pieejama',
'Invalid CSRF token. Send the form again.' => 'Nederīgs CSRF žetons. Nosūtiet formu vēl vienu reizi.',
'Comment' => 'Komentārs',
'Default values' => 'Noklusētā vērtība',
'%d byte(s)' => array('%d baits', '%d baiti', '%d baiti'),
'No commands to execute.' => 'Nav izpildāmu komandu.',
'Unable to upload a file.' => 'Neizdevās ielādēt failu uz servera.',
'File upload' => 'Augšupielāde',
'File uploads are disabled.' => 'Augšupielādes aizliegtas.',
'Routine has been called, %d row(s) affected.' => array('Procedūra izsaukta, izmainīts %d ieraksts.', 'Procedūra izsaukta, izmainīti %d ieraksti.', 'Procedūra izsaukta, izmainīti %d ieraksti.'),
'Call' => 'Izsaukt',
'No extension' => 'Nav paplašinājuma',
'None of the supported PHP extensions (%s) are available.' => 'Neviens PHP no atbalstītajiem paplašinājumiem (%s) nav pieejams.',
'Session support must be enabled.' => 'Sesiju atbalstam jābūt ieslēgtam.',
'Session expired, please login again.' => 'Sesijas laiks ir beidzies, piesakies no jauna sistēmā.',
'Text length' => 'Teksta garums',
'Foreign key has been dropped.' => 'Ārejā atslēga dzēsta.',
'Foreign key has been altered.' => 'Ārejā atslēga izmainīta.',
'Foreign key has been created.' => 'Ārejā atslēga izveidota.',
'Foreign key' => 'Ārejā atslēga',
'Target table' => 'Mērķa tabula',
'Change' => 'Mainīt',
'Source' => 'Avots',
'Target' => 'Mērķis',
'Add column' => 'Pievienot lauku',
'Alter' => 'Izmainīt',
'Add foreign key' => 'Pievienot ārējo atslēgu',
'ON DELETE' => 'Pie dzēšanas',
'ON UPDATE' => 'Pie atjaunošanas',
'Index Type' => 'Indeksa tips',
'length' => 'garums',
'View has been dropped.' => 'Skats dzēsts.',
'View has been altered.' => 'Skats izmainīts.',
'View has been created.' => 'Skats izveidots.',
'Alter view' => 'Izmainīt skatu',
'Create view' => 'Izveidot skatu',
'Name' => 'Nosaukums',
'Process list' => 'Procesu saraksts',
'%d process(es) have been killed.' => array('Pabeigts %d process.', 'Pabeigti %d procesi.', 'Pabeigti %d procesi.'),
'Kill' => 'Nobeigt',
'Parameter name' => 'Parametra nosaukums',
'Database schema' => 'Datubāzes shēma',
'Create procedure' => 'Izveidot procedūru',
'Create function' => 'Izveidot funkciju',
'Routine has been dropped.' => 'Procedūru dzēsta.',
'Routine has been altered.' => 'Procedūru izmainīta.',
'Routine has been created.' => 'Procedūru izveidota.',
'Alter function' => 'Mainīt funkciju',
'Alter procedure' => 'Mainīt procedūru',
'Return type' => 'Atgriezt tips',
'Add trigger' => 'Pievienot trigeri',
'Trigger has been dropped.' => 'Trigeris dzēsts.',
'Trigger has been altered.' => 'Trigeris izmainīts.',
'Trigger has been created.' => 'Trigeris izveidots.',
'Alter trigger' => 'Izmainīt trigeri',
'Create trigger' => 'Izveidot trigeri',
'Time' => 'Laiks',
'Event' => 'Notikums',
'%s version: %s through PHP extension %s' => 'Versija %s: %s ar PHP paplašinājumu %s',
'%d row(s)' => array('%d rinda', '%d rindas', '%d rindu'),
'Remove' => 'Noņemt',
'Are you sure?' => 'Vai Tu esi pārliecināts?',
'Privileges' => 'Tiesības',
'Create user' => 'Izveidot lietotāju',
'User has been dropped.' => 'Lietotājs dzests.',
'User has been altered.' => 'Lietotājs izmainīts.',
'User has been created.' => 'Lietotājs izveidots.',
'Hashed' => 'Sajaukts',
'Column' => 'Lauks',
'Routine' => 'Procedūra',
'Grant' => 'Atļaut',
'Revoke' => 'Aizliegt',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST metodes pieprasījums apjoms par lielu. Atsūtiet mazāka apjoma pieprasījumu kā konfigurācijas %s.',
'Logged as: %s' => 'Ielogojies kā: %s',
'Move up' => 'Pārvietot uz augšu',
'Move down' => 'Pārvietot uz leju',
'Functions' => 'Funkcijas',
'Aggregation' => 'Agregācija',
'Export' => 'Eksports',
'Output' => 'Izejas dati',
'open' => 'atvērt',
'save' => 'saglabāt',
'Format' => 'Formāts',
'Tables' => 'Tabulas',
'Data' => 'Dati',
'Event has been dropped.' => 'Notikums dzēsts.',
'Event has been altered.' => 'Notikums izmainīts.',
'Event has been created.' => 'Notikums izveidots.',
'Alter event' => 'Izmainīt notikumu',
'Create event' => 'Izveidot notikumu',
'At given time' => 'Norāditā laikā',
'Every' => 'Katru',
'Events' => 'Notikumi',
'Schedule' => 'Grafiks',
'Start' => 'Sākums',
'End' => 'Beigas',
'Status' => 'Statuss',
'On completion preserve' => 'Beigās saglabāt',
'Tables and views' => 'Tabulas un skati',
'Data Length' => 'Datu apjoms',
'Index Length' => 'Indeksu izmērs',
'Data Free' => 'Brīvā vieta',
'Collation' => 'Kolācija',
'Analyze' => 'Analizēt',
'Optimize' => 'Optimizēt',
'Check' => 'Pārbaudīt',
'Repair' => 'Salabot',
'Truncate' => 'Iztīrīt',
'Tables have been truncated.' => 'Tabulas iztīrītas.',
'Rows' => 'Rindas',
',' => ' ',
'0123456789' => '0123456789',
'Tables have been moved.' => 'Tabulas pārvietotas.',
'Move to other database' => 'Pārvietot uz citu datubāzi',
'Move' => 'Pārvietot',
'Engine' => 'Dzinējs',
'Save and continue edit' => 'Saglabāt un turpināt rediģēt',
'original' => 'oriģināls',
'%d item(s) have been affected.' => array('Izmainīts %d ieraksts.', 'Izmainīti %d ieraksti.', 'Izmainīti %d ieraksti.'),
'Whole result' => 'Viss rezultāts',
'Tables have been dropped.' => 'Tabulas dzēstas.',
'Clone' => 'Klonēt',
'Partition by' => 'Sadalīt pēc',
'Partitions' => 'Partīcijas',
'Partition name' => 'Partīcijas nosaukums',
'Values' => 'Vērtības',
'%d row(s) have been imported.' => array('Importēta %d rinda.', 'Importētas %d rindas.', 'Importētas %d rindas.'),
'Import' => 'Imports',
'Stop on error' => 'Astāties kļūdas gadījumā',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Sasniegts maksimālais lauku skaita ierobežojums. Palieliniet %s.',
'anywhere' => 'jebkurā vietā',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$5.$3.$1',
'[yyyy]-mm-dd' => 'dd.mm.[gggg]',
'History' => 'Vēsture',
'Variables' => 'Mainīgie',
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'Lauku tipiem jābūt vienādiem, rezultējošā laukā jābut indeksa datiem.',
'Relations' => 'Relācijas',
'Run file' => 'Izpildīt failu',
'Clear' => 'Notīrīt',
'Maximum allowed file size is %sB.' => 'Faila maksimālais izmērs — %sB.',
'Numbers' => 'Skaitļi',
'Date and time' => 'Datums un laiks',
'Strings' => 'Virknes',
'Binary' => 'Binārie',
'Lists' => 'Saraksti',
'Editor' => 'Redaktors',
'E-mail' => 'Epasts',
'From' => 'No',
'Subject' => 'Tēma',
'Send' => 'Sūtīt',
'%d e-mail(s) have been sent.' => array('Nosūtīts %d epasts.', 'Nosūtīti %d epasti.', 'Nosūtīti %d epasti.'),
'Webserver file %s' => 'Fails %s uz servera',
'File does not exist.' => 'Fails neeksistē.',
'%d in total' => 'Kopā %d',
'Permanent login' => 'Atcerēties mani',
'Databases have been dropped.' => 'Datubāzes dzēstas.',
'Search data in tables' => 'Meklēt tabulās',
'Schema' => 'Shēma',
'Alter schema' => 'Izmainīt shēmu',
'Create schema' => 'Jauna shēma',
'Schema has been dropped.' => 'Shēma dzēsta.',
'Schema has been created.' => 'Izveidota jauna shēma.',
'Schema has been altered.' => 'Shēma izmainīta.',
'Sequences' => 'Virknes',
'Create sequence' => 'Izveidot virkni',
'Alter sequence' => 'Izmainīt virkni',
'Sequence has been dropped.' => 'Virkne dzēsta.',
'Sequence has been created.' => 'Izveidota virkne.',
'Sequence has been altered.' => 'Virkne izmainīta.',
'User types' => 'Lietotāju tipi',
'Create type' => 'Izveidot tipu',
'Alter type' => 'Izmainīt tipu',
'Type has been dropped.' => 'Tips dzēsts.',
'Type has been created.' => 'Tips izveidots.',
'Ctrl+click on a value to modify it.' => 'Lai izmainītu vērtību, izmanto Ctrl + peles klikšķi.',
'Use edit link to modify this value.' => 'Izmainīt vērtību var tikai ar saiti "Izmainīt".',
'last' => 'pēdējā',
'From server' => 'No servera',
'System' => 'Sistēma',
'Select data' => 'Izvēlēties datus',
'Show structure' => 'Parādīt struktūru',
'empty' => 'tukšs',
'Network' => 'Tīkls',
'Geometry' => 'Ģeometrija',
'File exists.' => 'Fails eksistē.',
'Attachments' => 'Pielikumi',
'%d query(s) executed OK.' => array('%d pieprasījums veiksmīgs.', '%d pieprasījumi veiksmīgi.', '%d pieprasījumi veiksmīgi.'),
'Show only errors' => 'Rādīt tikai kļūdas',
'Refresh' => 'Atjaunot',
'Invalid schema.' => 'Nederīga shēma.',
'Please use one of the extensions %s.' => 'Izmainojiet kādu no paplašinājumiem %s.',
'now' => 'tagad',
'ltr' => 'ltr',
'Tables have been copied.' => 'Tabulas nokopētas.',
'Copy' => 'kopēt',
'Permanent link' => 'Pastāvīga saite',
'Edit all' => 'Rediģēt visus',
'HH:MM:SS' => 'HH:MM:SS',
'Tables have been optimized.' => 'Tabulas optimizētas.',
'Materialized view' => 'Matrializēts skats',
'Vacuum' => 'Vakums',
'Selected' => 'Izvēlētie',
'File must be in UTF-8 encoding.' => 'Failam jābūt UTF-8 kodējumam.',
'Modify' => 'Izmainīt',
'Loading' => 'Ielāde',
'Load more data' => 'Ielādēt vēl datus',
'ATTACH queries are not supported.' => 'ATTACH-pieprasījumi nav atbalstīti.',
'%d / ' => '%d / ',
'Limit rows' => 'Rindu limits',
'Default value' => 'Noklusētā vērtība',
'Full table scan' => 'Pilna tabulas analīze',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Pieteikšanās mēģinājumu skaits par lielu. Mēginiet pēc %d minūtes.', 'Pieteikšanās mēģinājumu skaits par lielu. Mēginiet pēc %d minūtēm.', 'Pieteikšanās mēģinājumu skaits par lielu. Mēginiet pēc %d minūtēm.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master-parole nav derīga. <a href="https://www.adminer.org/en/extension/"%s>Implementējiet</a> metodi %s, lai padarīgu šo par ierastu metodi.',
'If you did not send this request from Adminer then close this page.' => 'Ja nesūtījāt šo pieprasījumu no Adminer, tad aizveriet pārlūka logu.',
'You can upload a big SQL file via FTP and import it from server.' => 'Varat ielādēt lielu SQL failu uz servera un tad importēt to.',
'Size' => 'Izmērs',
'Compute' => 'Izskaitļot',
'You are offline.' => 'Jūs est bezsasaistē.',
'You have no privileges to update this table.' => 'jums nav pieejas labot šo tabulu.',
'Saving' => 'Saglabāšana',
'yes' => 'Jā',
'no' => 'Nē',
'Drop %s?' => 'Dzēst %s?',
'overwrite' => 'pārrakstīt',
'DB' => 'DB',
'Warnings' => 'Brīdinājumi',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer neatbalsta pieeju bez paroles, <a href="https://www.adminer.org/en/password/"%s>vairāk informācijas šeit</a>.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Paldies, ka izmantoji Adminer, vai vēlies veikt <a href="https://www.adminer.org/en/donation/">ziedojumu</a>.',
'The action will be performed after successful login with the same credentials.' => 'Darbība tiks pabeigta pēc derīgas pieteikšanās sistēmā.',
'Connecting to privileged ports is not allowed.' => 'Pieeja priviliģētiem portiem nav atļauta.',
'There is a space in the input password which might be the cause.' => 'Parole satur atstarpi, kas varētu būt lieka.',
'Unknown error.' => 'Nezināma kļūda.',
'Database does not support password.' => 'Datubāze neatbalsta paroli.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistem',
@@ -82,7 +84,6 @@ $translations = array(
'Data' => 'Data',
'Database' => 'Pangkalan data',
'database' => 'pangkalan data',
'Use' => 'Guna',
'Select database' => 'Pilih pangkalan data',
'Invalid database.' => 'Pangkalan data tidak sah.',
@@ -198,7 +199,7 @@ $translations = array(
'Alter indexes' => 'Ubah indeks',
'Add next' => 'Tambah yang seterusnya',
'Index Type' => 'Jenis Indeks',
'Column (length)' => 'Kolum (kepanjangan)',
'length' => 'kepanjangan',
'Foreign keys' => 'Kunci asing',
'Foreign key' => 'Kunci asing',

View File

@@ -1,8 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Inloggen',
'Logout successful.' => 'Uitloggen geslaagd.',
'Invalid credentials.' => 'Ongeldige logingegevens.',
'Login' => 'Aanmelden',
'Logout successful.' => 'Successvol afgemeld.',
'Invalid credentials.' => 'Ongeldige gebruikersgegevens.',
'Server' => 'Server',
'Username' => 'Gebruikersnaam',
'Password' => 'Wachtwoord',
@@ -31,8 +33,7 @@ $translations = array(
'Alter database' => 'Database aanpassen',
'Create database' => 'Database aanmaken',
'SQL command' => 'SQL opdracht',
'Logout' => 'Uitloggen',
'database' => 'database',
'Logout' => 'Afmelden',
'Use' => 'Gebruik',
'No tables.' => 'Geen tabellen.',
'select' => 'kies',
@@ -41,7 +42,7 @@ $translations = array(
'Item%s has been inserted.' => 'Item%s toegevoegd.',
'Edit' => 'Bewerk',
'Insert' => 'Toevoegen',
'Save and insert next' => 'Opslaan, daarna toevoegen',
'Save and insert next' => 'Opslaan en volgende toevoegen',
'Delete' => 'Verwijderen',
'Database' => 'Database',
'Routines' => 'Procedures',
@@ -60,7 +61,7 @@ $translations = array(
'Action' => 'Acties',
'edit' => 'bewerk',
'Page' => 'Pagina',
'Query executed OK, %d row(s) affected.' => array('Query uitgevoerd, %d rij geraakt.', 'Query uitgevoerd, %d rijen beïnvloed.'),
'Query executed OK, %d row(s) affected.' => array('Query uitgevoerd, %d rij aangepast.', 'Query uitgevoerd, %d rijen aangepast.'),
'Error in query' => 'Fout in query',
'Execute' => 'Uitvoeren',
'Table' => 'Tabel',
@@ -81,7 +82,7 @@ $translations = array(
'No extension' => 'Geen extensie',
'None of the supported PHP extensions (%s) are available.' => 'Geen geldige PHP extensies beschikbaar (%s).',
'Session support must be enabled.' => 'Sessies moeten geactiveerd zijn.',
'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw in te loggen.',
'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw aan te melden.',
'Text length' => 'Tekst lengte',
'Foreign key has been dropped.' => 'Foreign key verwijderd.',
'Foreign key has been altered.' => 'Foreign key aangepast.',
@@ -97,7 +98,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Index type',
'Column (length)' => 'Kolom (lengte)',
'length' => 'lengte',
'View has been dropped.' => 'View verwijderd.',
'View has been altered.' => 'View aangepast.',
'View has been created.' => 'View aangemaakt.',
@@ -265,4 +266,39 @@ $translations = array(
'Permanent link' => 'Permanente link',
'Edit all' => 'Alles bewerken',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => 'Verwijder %s?',
'Tables have been optimized.' => 'Tabellen zijn geoptimaliseerd.',
'Materialized view' => 'Materialized view',
'Vacuum' => 'Vacuum',
'Selected' => 'Geselecteerd',
'overwrite' => 'overschrijven',
'DB' => 'DB',
'File must be in UTF-8 encoding.' => 'Het bestand moet met UTF-8 encodering zijn opgeslagen.',
'Modify' => 'Aanpassen',
'Load more data' => 'Meer data inladen',
'Loading' => 'Aan het laden',
'ATTACH queries are not supported.' => 'ATTACH queries worden niet ondersteund',
'Warnings' => 'Waarschuwingen',
'%d / ' => '%d / ',
'Limit rows' => 'Rijen beperken',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer ondersteunt geen toegang tot databases zonder wachtwoord, <a href="https://www.adminer.org/en/password/"%s>meer informatie</a>.',
'Default value' => 'Standaardwaarde',
'Full table scan' => 'Full table scan',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuut.', 'Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuten.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master wachtwoord verlopen. <a href="https://www.adminer.org/en/extension/"%s>Implementeer</a> de %s methode om het permanent te maken.',
'The action will be performed after successful login with the same credentials.' => 'Deze actie zal uitgevoerd worden na het succesvol aanmelden met dezelfde gebruikersgegevens',
'Connecting to privileged ports is not allowed.' => 'Verbindingen naar geprivilegieerde poorten is niet toegestaan.',
'There is a space in the input password which might be the cause.' => 'Er staat een spatie in het wachtwoord, wat misschien de oorzaak is.',
'If you did not send this request from Adminer then close this page.' => 'Als u deze actie niet via Adminer hebt gedaan, gelieve deze pagina dan te sluiten.',
'You can upload a big SQL file via FTP and import it from server.' => 'U kan een groot SQL-bestand uploaden via FTP en het importeren via de server.',
'Size' => 'Grootte',
'Compute' => 'Bereken',
'You are offline.' => 'U bent offline.',
'You have no privileges to update this table.' => 'U bent niet gemachtigd om deze tabel aan te passen.',
'Saving' => 'Opslaan',
'Unknown error.' => 'Onbekende fout',
'Database does not support password.' => 'Database ondersteunt het wachtwoord niet.',
'Disable %s or enable %s or %s extensions.' => 'Schakel %s uit or schakel extensies %s of %s in.',
'yes' => 'ja',
'no' => 'neen',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'System' => 'System',
'Server' => 'Server',
@@ -64,7 +66,6 @@ $translations = array(
'Format' => 'Format',
'Data' => 'Data',
'Database' => 'Database',
'database' => 'database',
'Use' => 'Bruk',
'Select database' => 'Velg database',
'Invalid database.' => 'Ugyldig database.',
@@ -165,7 +166,7 @@ $translations = array(
'Alter indexes' => 'Endre indekser',
'Add next' => 'Legg til neste',
'Index Type' => 'Indekstype',
'Column (length)' => 'Kolonne (lengde)',
'length' => 'lengde',
'Foreign keys' => 'Fremmednøkler',
'Foreign key' => 'Fremmednøkkel',
'Foreign key has been dropped.' => 'Fremmednøkkelen er slettet.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Rodzaj bazy',
@@ -81,7 +83,6 @@ $translations = array(
'Data' => 'Dane',
'Database' => 'Baza danych',
'database' => 'baza danych',
'Use' => 'Wybierz',
'Select database' => 'Wybierz bazę danych',
'Invalid database.' => 'Nie znaleziono bazy danych.',
@@ -197,7 +198,7 @@ $translations = array(
'Alter indexes' => 'Zmień indeksy',
'Add next' => 'Dodaj następny',
'Index Type' => 'Typ indeksu',
'Column (length)' => 'Kolumna (długość)',
'length' => 'długość',
'Foreign keys' => 'Klucze obce',
'Foreign key' => 'Klucz obcy',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Entrar',
'Logout successful.' => 'Saída bem sucedida.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Criar Base de dados',
'SQL command' => 'Comando SQL',
'Logout' => 'Sair',
'database' => 'base de dados',
'Use' => 'Usar',
'No tables.' => 'Não existem tabelas.',
'select' => 'selecionar',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Coluna (tamanho)',
'length' => 'tamanho',
'View has been dropped.' => 'A Visão foi apagada.',
'View has been altered.' => 'A Visão foi alterada.',
'View has been created.' => 'A Visão foi criada.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Entrar',
'Logout successful.' => 'Sessão terminada com sucesso.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Criar Base de dados',
'SQL command' => 'Comando SQL',
'Logout' => 'Terminar sessão',
'database' => 'base de dados',
'Use' => 'Usar',
'No tables.' => 'Não existem tabelas.',
'select' => 'registos',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'coluna (tamanho)',
'length' => 'tamanho',
'View has been dropped.' => 'Vista eliminada.',
'View has been altered.' => 'Vista modificada.',
'View has been created.' => 'Vista criada.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Intră',
'Logout successful.' => 'Ați ieșit cu succes.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Crează baza de date',
'SQL command' => 'SQL query',
'Logout' => 'Ieșire',
'database' => 'baza de date',
'Use' => 'Alege',
'No tables.' => 'În baza de date nu sunt tabele.',
'select' => 'selectează',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'La ștergere',
'ON UPDATE' => 'La modificare',
'Index Type' => 'Tipul indexului',
'Column (length)' => 'Coloană (lungimea)',
'length' => 'lungimea',
'View has been dropped.' => 'Reprezentarea a fost ștearsă.',
'View has been altered.' => 'Reprezentarea a fost modificată.',
'View has been created.' => 'Reprezentarea a fost creată.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Войти',
'Logout successful.' => 'Вы успешно покинули систему.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'Создать базу данных',
'SQL command' => 'SQL-запрос',
'Logout' => 'Выйти',
'database' => 'база данных',
'Use' => 'Выбрать',
'No tables.' => 'В базе данных нет таблиц.',
'select' => 'выбрать',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'При стирании',
'ON UPDATE' => 'При обновлении',
'Index Type' => 'Тип индекса',
'Column (length)' => 'Поле (длина)',
'length' => 'длина',
'View has been dropped.' => 'Представление было удалено.',
'View has been altered.' => 'Представление было изменено.',
'View has been created.' => 'Представление было создано.',
@@ -300,4 +301,5 @@ $translations = array(
'There is a space in the input password which might be the cause.' => 'В введеном пароле есть пробел, это может быть причиною.',
'Unknown error.' => 'Неизвестная ошибка.',
'Database does not support password.' => 'База данных не поддерживает пароль.',
'Disable %s or enable %s or %s extensions.' => 'Отключите %s или включите расширения %s или %s.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'Prihlásiť sa',
'Logout successful.' => 'Odhlásenie prebehlo v poriadku.',
@@ -32,7 +34,6 @@ $translations = array(
'Create database' => 'Vytvoriť databázu',
'SQL command' => 'SQL príkaz',
'Logout' => 'Odhlásiť',
'database' => 'databáza',
'Use' => 'Vybrať',
'No tables.' => 'Žiadne tabuľky.',
'select' => 'vypísať',
@@ -70,7 +71,7 @@ $translations = array(
'Unable to select the table' => 'Tabuľku sa nepodarilo vypísať',
'Invalid CSRF token. Send the form again.' => 'Neplatný token CSRF. Odošlite formulár znova.',
'Comment' => 'Komentár',
'Default values' => 'Východzie hodnoty',
'Default values' => 'Predvolené hodnoty',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtov'),
'No commands to execute.' => 'Žiadne príkazy na vykonanie.',
'Unable to upload a file.' => 'Súbor sa nepodarilo nahrať.',
@@ -94,10 +95,10 @@ $translations = array(
'Add column' => 'Pridať stĺpec',
'Alter' => 'Zmeniť',
'Add foreign key' => 'Pridať cudzí kľúč',
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'ON DELETE' => 'Pri zmazaní',
'ON UPDATE' => 'Pri aktualizácii',
'Index Type' => 'Typ indexu',
'Column (length)' => 'Stĺpec (dĺžka)',
'length' => 'dĺžka',
'View has been dropped.' => 'Pohľad bol odstránený.',
'View has been altered.' => 'Pohľad bol zmenený.',
'View has been created.' => 'Pohľad bol vytvorený.',
@@ -265,4 +266,40 @@ $translations = array(
'Permanent link' => 'Permanentný odkaz',
'Edit all' => 'Upraviť všetko',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => 'Odstrániť %s?',
'Tables have been optimized.' => 'Tabuľky boli optimalizované.',
'Materialized view' => 'Materializovaný pohľad',
'Vacuum' => 'Vyčistiť',
'Selected' => 'Označené',
'overwrite' => 'prepísať',
'DB' => 'DB',
'File must be in UTF-8 encoding.' => 'Súbor musí byť v kódovaní UTF-8.',
'Modify' => 'Zmeniť',
'Load more data' => 'Načítať ďalšie dáta',
'Loading' => 'Načítava sa',
'ATTACH queries are not supported.' => 'Dotazy ATTACH nie sú podporované.',
'Warnings' => 'Varovania',
'%d / ' => '%d / ',
'Limit rows' => 'Limit riadkov',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nepodporuje prístup k databáze bez hesla, <a href="https://www.adminer.org/cs/password/"%s>viac informácií</a>.',
'Default value' => 'Predvolená hodnota',
'Full table scan' => 'Prechod celej tabuľky',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Príliš veľa pokusov o prihlásenie, skúste to znova za %d minutu.', 'Príliš veľa pokusov o prihlásenie, skúste to znova za %d minuty.', 'Príliš veľa pokusov o prihlásenie, skúste to znova za %d minút.'),
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Vďaka za používanie Admineru, <a href="https://www.adminer.org/cs/donation/">prispejte</a> na vývoj.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Platnosť hlavného hesla vypršala. <a href="https://www.adminer.org/cs/extension/"%s>Implementujte</a> metodu %s, aby platilo natrvalo.',
'The action will be performed after successful login with the same credentials.' => 'Akcia sa vykoná po úspešnom prihlásení s rovnakými prihlasovacími údajmi.',
'Connecting to privileged ports is not allowed.' => 'Pripojenie k privilegovaným portom nie je povolené.',
'There is a space in the input password which might be the cause.' => 'V zadanom hesle je medzera, ktorá môže byť príčinou.',
'If you did not send this request from Adminer then close this page.' => 'Pokiaľ ste tento požiadavok neodoslali z Adminera, zatvorte túto stránku.',
'You can upload a big SQL file via FTP and import it from server.' => 'Veľký SQL soubor môžete nahrať pomocou FTP a importovať ho zo servera.',
'Size' => 'Veľkosť',
'Compute' => 'Spočítať',
'You are offline.' => 'Ste offline.',
'You have no privileges to update this table.' => 'Nemáte oprávnenie na aktualizáciu tejto tabuľky.',
'Saving' => 'Ukladá sa',
'Unknown error.' => 'Neznáma chyba.',
'Database does not support password.' => 'Databáza nepodporuje heslo.',
'Disable %s or enable %s or %s extensions.' => 'Zakážte %s alebo povoľte rozšírenie %s alebo %s.',
'yes' => 'áno',
'no' => 'nie',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistem',
@@ -72,7 +74,6 @@ $translations = array(
'Data' => 'Podatki',
'Database' => 'Baza',
'database' => 'baza',
'Use' => 'Uporabi',
'Select database' => 'Izberi bazo',
'Invalid database.' => 'Neveljavna baza.',
@@ -178,7 +179,7 @@ $translations = array(
'Alter indexes' => 'Spremeni indekse',
'Add next' => 'Dodaj naslednjega',
'Index Type' => 'Tip indeksa',
'Column (length)' => 'Stolpec (dolžina)',
'length' => 'dolžina',
'Foreign keys' => 'Tuji ključi',
'Foreign key' => 'Tuj ključ',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Систем',
@@ -73,7 +75,6 @@ $translations = array(
'Data' => 'Податци',
'Database' => 'База података',
'database' => 'база података',
'Use' => 'Користи',
'Select database' => 'Изаберите базу',
'Invalid database.' => 'Неисправна база података.',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Уреди индексе',
'Add next' => 'Додај следећи',
'Index Type' => 'Тип индекса',
'Column (length)' => 'Колона (дужина)',
'length' => 'дужина',
'Foreign keys' => 'Страни кључеви',
'Foreign key' => 'Страни кључ',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'System',
@@ -89,7 +91,6 @@ $translations = array(
'Data' => 'Data',
'Database' => 'Databas',
'database' => 'databas',
'DB' => 'DB',
'Use' => 'Använd',
'Select database' => 'Välj databas',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => 'Ändra index',
'Add next' => 'Lägg till nästa',
'Index Type' => 'Indextyp',
'Column (length)' => 'Kolumn (längd)',
'length' => 'längd',
'Foreign keys' => 'Främmande nycklar',
'Foreign key' => 'Främmande nyckel',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'நுழை',
'Logout successful.' => 'வெற்றிக‌ர‌மாய் வெளியேறியாயிற்று.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'த‌க‌வ‌ல்த‌ள‌த்தை உருவாக்கு',
'SQL command' => 'SQL க‌ட்ட‌ளை',
'Logout' => 'வெளியேறு',
'database' => 'த‌க‌வ‌ல்த‌ள‌ம்',
'Use' => 'உப‌யோகி',
'No tables.' => 'அட்ட‌வ‌ணை இல்லை.',
'select' => 'தேர்வு செய்',
@@ -94,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'அக‌வ‌ரிசை வ‌கை (Index Type)',
'Column (length)' => 'நெடுவ‌ரிசை (நீள‌ம்)',
'length' => 'நீள‌ம்',
'View has been dropped.' => 'தோற்ற‌ம் நீக்க‌ப்ப‌ட்ட‌து.',
'View has been altered.' => 'தோற்றம் மாற்றப்ப‌ட்ட‌து.',
'View has been created.' => 'தோற்ற‌ம் உருவாக்க‌ப்ப‌ட்ட‌து.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Login' => 'เข้าสู่ระบบ',
'Logout successful.' => 'ออกจากระบบเรียบร้อยแล้ว.',
@@ -31,7 +33,6 @@ $translations = array(
'Create database' => 'สร้างฐานข้อมูล',
'SQL command' => 'คำสั่ง SQL',
'Logout' => 'ออกจากระบบ',
'database' => 'ฐานข้อมูล',
'Use' => 'ใช้งาน',
'No tables.' => 'ไม่พบตาราง.',
'select' => 'เลือก',
@@ -96,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'ชนิดของดัชนี',
'Column (length)' => 'คอลัมน์ (ความยาว)',
'length' => 'ความยาว',
'View has been dropped.' => 'วิวถูกลบแล้ว.',
'View has been altered.' => 'วิวถูกเปลี่ยนแปลงแล้ว.',
'View has been created.' => 'วิวถูกสร้างแล้ว.',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Sistem',
@@ -84,7 +86,6 @@ $translations = array(
'Data' => 'Veri',
'Database' => 'Veri Tabanı',
'database' => 'veri tabanı',
'DB' => 'DB',
'Use' => 'Kullan',
'Select database' => 'Veri tabanı seç',
@@ -201,7 +202,7 @@ $translations = array(
'Alter indexes' => 'İndeksleri değiştir',
'Add next' => 'Bundan sonra ekle',
'Index Type' => 'İndex Türü',
'Column (length)' => 'Kolon (uzunluğu)',
'length' => 'uzunluğu',
'Foreign keys' => 'Dış anahtarlar',
'Foreign key' => 'Dış anahtar',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Система Бази Даних',
@@ -73,7 +75,6 @@ $translations = array(
'Data' => 'Дані',
'Database' => 'База даних',
'database' => 'база даних',
'Use' => 'Обрати',
'Select database' => 'Обрати базу даних',
'Invalid database.' => 'Погана база даних.',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Змінити індексування',
'Add next' => 'Додати ще',
'Index Type' => 'Тип індексу',
'Column (length)' => 'Стовпець (довжина)',
'length' => 'довжина',
'Foreign keys' => 'Зовнішні ключі',
'Foreign key' => 'Зовнішній ключ',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Hệ thống',
@@ -76,7 +78,6 @@ $translations = array(
'Data' => 'Dữ liệu',
'Database' => 'Cơ sở dữ liệu',
'database' => 'cơ sở dữ liệu',
'Use' => 'Sử dụng',
'Select database' => 'Chọn CSDL',
'Invalid database.' => 'CSDL sai.',
@@ -188,7 +189,7 @@ $translations = array(
'Alter indexes' => 'Sửa chỉ mục',
'Add next' => 'Thêm tiếp',
'Index Type' => 'Loại chỉ mục',
'Column (length)' => 'Cột (độ dài)',
'length' => 'độ dài',
'Foreign keys' => 'Các khoá ngoại',
'Foreign key' => 'Khoá ngoại',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => 'Xx',
@@ -89,7 +91,6 @@ $translations = array(
'Data' => 'Xx',
'Database' => 'Xx',
'database' => 'xx',
'DB' => 'XX',
'Use' => 'Xx',
'Select database' => 'Xx',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => 'Xx',
'Add next' => 'Xx',
'Index Type' => 'Xx',
'Column (length)' => 'Xx',
'length' => 'xx',
'Foreign keys' => 'Xx',
'Foreign key' => 'Xx',
@@ -346,4 +347,12 @@ $translations = array(
'Type has been dropped.' => 'Xx.',
'Type has been created.' => 'Xx.',
'Alter type' => 'Xx',
// Table check constraints
'Checks' => 'Xx',
'Create check' => 'Xx',
'Alter check' => 'Xx',
'Check has been created.' => 'Xx.',
'Check has been altered.' => 'Xx.',
'Check has been dropped.' => 'Xx.',
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => '資料庫系統',
@@ -89,7 +91,6 @@ $translations = array(
'Data' => '資料',
'Database' => '資料庫',
'database' => '資料庫',
'DB' => '資料庫',
'Use' => '使用',
'Select database' => '選擇資料庫',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => '修改索引',
'Add next' => '新增下一筆',
'Index Type' => '索引類型',
'Column (length)' => '欄位(長度',
'length' => '長度',
'Foreign keys' => '外來鍵',
'Foreign key' => '外來鍵',

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'System' => '系统',
@@ -89,7 +91,6 @@ $translations = array(
'Data' => '数据',
'Database' => '数据库',
'database' => '数据库',
'DB' => '数据库',
'Use' => '使用',
'Select database' => '选择数据库',

View File

@@ -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,

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
page_header(lang('Privileges'));
echo '<p class="links"><a href="' . h(ME) . 'user=">' . lang('Create user') . "</a>";
@@ -14,15 +16,15 @@ echo "<form action=''><p>\n";
hidden_fields_get();
echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n";
echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n");
echo "<table cellspacing='0'>\n";
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th></thead>\n";
while ($row = $result->fetch_assoc()) {
echo '<tr' . odd() . '><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
echo '<tr><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
}
if (!$grant || DB != "") {
echo "<tr" . odd() . "><td><input name='user' autocapitalize='off'><td><input name='host' value='localhost' autocapitalize='off'><td><input type='submit' value='" . lang('Edit') . "'>\n";
echo "<tr><td><input name='user' autocapitalize='off'><td><input name='host' value='localhost' autocapitalize='off'><td><input type='submit' value='" . lang('Edit') . "'>\n";
}
echo "</table>\n";

View File

@@ -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"];
@@ -39,12 +41,12 @@ $routine_languages = routine_languages();
<?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) . "\n" : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<div class="scrollable">
<table cellspacing="0" class="nowrap">
<table class="nowrap">
<?php
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>

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
if (support("kill")) {
if ($_POST && !$error) {
$killed = 0;
@@ -16,13 +18,12 @@ page_header(lang('Process list'), $error);
<form action="" method="post">
<div class="scrollable">
<table cellspacing="0" class="nowrap checkable">
<table class="nowrap checkable odds">
<?php
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
// HTML valid because there is always at least one process
$i = -1;
foreach (process_list() as $i => $row) {
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" . odd() . ">" . (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)
);
}

View File

@@ -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>"
;
}
}
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$row = $_POST;
if ($_POST && !$error) {
@@ -26,8 +28,7 @@ if (!$row) {
?>
<form action="" method="post">
<p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php echo script("focus(qs('#name'));"); ?>
<p><input name="name" autofocus value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php
if ($_GET["ns"] != "") {

View File

@@ -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"] == ($sql == "pgsql" ? "table" : "InnoDB")
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);

View File

@@ -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
@@ -224,14 +227,17 @@ if (is_ajax()) {
$set = null;
if (isset($rights["insert"]) || !support("table")) {
$set = "";
$params = array();
foreach ((array) $_GET["where"] as $val) {
if ($foreign_keys[$val["col"]] && count($foreign_keys[$val["col"]]) == 1 && ($val["op"] == "="
|| (!$val["op"] && !preg_match('~[_%]~', $val["val"])) // LIKE in Editor
)) {
$set .= "&set" . urlencode("[" . bracket_escape($val["col"]) . "]") . "=" . urlencode($val["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
) {
$params["set" . "[" . bracket_escape($val["col"]) . "]"] = $val["val"];
}
}
$set = $params ? "&" . http_build_query($params) : "";
}
$adminer->selectLinks($table_status, $set);
@@ -286,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
}
@@ -310,7 +316,7 @@ if (!$columns && support("table")) {
$backward_keys = $adminer->backwardKeys($TABLE, $table_name);
echo "<div class='scrollable'>";
echo "<table id='table' cellspacing='0' class='nowrap checkable'>";
echo "<table id='table' class='nowrap checkable odds'>";
echo script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});");
echo "<thead><tr>" . (!$group && $select
? ""
@@ -324,7 +330,7 @@ if (!$columns && support("table")) {
if (!isset($unselected[$key])) {
$val = $_GET["columns"][key($select)];
$field = $fields[$select ? ($val ? $val["col"] : current($select)) : $key];
$name = ($field ? $adminer->fieldName($field, $rank) : ($val["fun"] ? "*" : $key));
$name = ($field ? $adminer->fieldName($field, $rank) : ($val["fun"] ? "*" : h($key)));
if ($name != "") {
$rank++;
$names[$key] = $name;
@@ -359,9 +365,6 @@ if (!$columns && support("table")) {
echo ($backward_keys ? "<th>" . lang('Relations') : "") . "</thead>\n";
if (is_ajax()) {
if ($limit % 2 == 1 && $page % 2 == 1) {
odd();
}
ob_end_clean();
}
@@ -377,14 +380,14 @@ 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));
}
echo "<tr" . odd() . ">" . (!$group && $select ? "" : "<td>"
echo "<tr>" . (!$group && $select ? "" : "<td>"
. checkbox("check[]", substr($unique_idf, 1), in_array(substr($unique_idf, 1), (array) $_POST["check"]))
. ($is_group || information_schema(DB) ? "" : " <a href='" . h(ME . "edit=" . urlencode($TABLE) . $unique_idf) . "' class='edit'>" . lang('edit') . "</a>")
);
@@ -434,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) {
@@ -444,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"
;
}
}
@@ -470,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
@@ -501,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 ? "" : "");
@@ -527,7 +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()) {
@@ -568,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') . "'>";

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$SEQUENCE = $_GET["sequence"];
$row = $_POST;

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
if (!$error && $_POST["export"]) {
dump_headers("sql");
$adminer->dumpTable("", "");
@@ -32,8 +34,8 @@ if (!$error && $_POST) {
}
if (is_string($query)) { // get_file() returns error as number, fread() as false
if (function_exists('memory_get_usage')) {
@ini_set("memory_limit", max(ini_bytes("memory_limit"), 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
if (function_exists('memory_get_usage') && ($memory_limit = ini_bytes("memory_limit")) != "-1") {
@ini_set("memory_limit", max($memory_limit, 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
}
if ($query != "" && strlen($query) < 1e6) { // don't add big queries
@@ -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,13 +83,21 @@ if (!$error && $_POST) {
$offset = $pos + strlen($found);
if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES
$c_style_escapes = $driver->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
$pattern = ($found == '/*' ? '\*/'
: ($found == '[' ? ']'
: (preg_match('~^-- |^#~', $found) ? "\n"
: preg_quote($found) . ($c_style_escapes ? "|\\\\." : "")
)));
while (preg_match("($pattern|\$)s", $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
$s = $match[0][0];
if (!$s && $fp && !feof($fp)) {
$query .= fread($fp, 1e5);
} else {
$offset = $match[0][1] + strlen($s);
if ($s[0] != "\\") {
if (!$s || $s[0] != "\\") {
break;
}
}
@@ -97,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";
@@ -133,7 +143,7 @@ if (!$error && $_POST) {
$time = " <span class='time'>(" . format_time($start) . ")</span>"
. (strlen($q) < 1000 ? " <a href='" . h(ME) . "sql=" . urlencode(trim($q)) . "'>" . lang('Edit') . "</a>" : "") // 1000 - maximum length of encoded URL in IE is 2083 characters
;
$affected = $connection->affected_rows; // getting warnigns overwrites this
$affected = $connection->affected_rows; // getting warnings overwrites this
$warnings = ($_POST["only_errors"] ? "" : $driver->warnings());
$warnings_id = "warnings-$commands";
if ($warnings) {
@@ -174,7 +184,7 @@ if (!$error && $_POST) {
}
echo ($warnings ? "<div id='$warnings_id' class='hidden'>\n$warnings</div>\n" : "");
if ($explain) {
echo "<div id='$explain_id' class='hidden'>\n";
echo "<div id='$explain_id' class='hidden explain'>\n";
select($explain, $connection2, $orgtables);
echo "</div>\n";
}
@@ -255,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"
;

View File

@@ -1,5 +1,5 @@
/** @author Ondrej Valka, http://valka.info */
body { color: #000; background: #fff; font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; width: -moz-fit-content; width: fit-content; }
body { color: #000; background: #fff; font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; min-width: fit-content; }
a { color: blue; text-decoration: none; }
a:visited { color: navy; }
a:link:hover, a:visited:hover { color: red; text-decoration: underline; }
@@ -22,14 +22,18 @@ 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; }
input.wayoff { left: -1000px; position: absolute; }
.block { display: block; }
.version { color: #777; font-size: 67%; }
.version { color: #777; font-size: 62%; }
.js .hidden, .nojs .jsonly { display: none; }
.js .column { position: absolute; background: #ddf; padding: .27em 1ex .3em 0; margin-top: -.27em; }
.nowrap td, .nowrap th, td.nowrap, p.nowrap { white-space: pre; }
@@ -43,7 +47,7 @@ input.wayoff { left: -1000px; position: absolute; }
.date { color: #7F007F; }
.enum { color: #007F7F; }
.binary { color: red; }
.odd td { background: #F5F5F5; }
.odds tbody tr:nth-child(2n) td { background: #F5F5F5; }
.js .checkable .checked td, .js .checkable .checked th { background: #ddf; }
.time { color: silver; font-size: 70%; }
.function { text-align: right; }
@@ -54,9 +58,10 @@ input.wayoff { left: -1000px; position: absolute; }
.view { font-style: italic; }
.active { font-weight: bold; }
.sqlarea { width: 98%; }
.explain { white-space: pre; }
.icon { width: 18px; height: 18px; background-color: navy; }
.icon:hover { background-color: red; }
.size { width: 6ex; }
.size { width: 7ex; }
.help { cursor: help; }
.footer { position: sticky; bottom: 0; margin-right: -20px; border-top: 20px solid rgba(255, 255, 255, .7); border-image: linear-gradient(rgba(255, 255, 255, .2), #fff) 100% 0; }
.footer > div { background: #fff; padding: 0 0 .5em; }
@@ -65,18 +70,18 @@ input.wayoff { left: -1000px; position: absolute; }
.logout { margin-top: .5em; position: absolute; top: 0; right: 0; }
.loadmore { margin-left: 1ex; }
/* .edit used in designs */
#menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; }
#menu { position: absolute; margin: 10px 0 0; top: 2em; left: 0; width: 19em; }
#menu p, #logins, #tables { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; }
#logins li, #tables li { list-style: none; }
#dbs { overflow: hidden; }
#logins, #tables { white-space: nowrap; overflow: auto; }
#logins, #tables { white-space: nowrap; overflow: hidden; }
#logins a, #tables a, #tables span { background: #fff; }
#content { margin: 2em 0 0 21em; padding: 10px 20px 20px 0; }
#lang { position: absolute; top: 0; left: 0; line-height: 1.8em; padding: .3em 1em; }
#lang { position: absolute; top: -2.6em; left: 0; padding: .3em 1em; }
#breadcrumb { white-space: nowrap; position: absolute; top: 0; left: 21em; background: #eee; height: 2em; line-height: 1.8em; padding: 0 1em; margin: 0 0 0 -18px; }
#h1 { color: #777; text-decoration: none; font-style: italic; }
#version { font-size: 67%; color: red; }
#schema { margin-left: 60px; position: relative; -moz-user-select: none; -webkit-user-select: none; }
#version { color: red; }
#schema { margin-left: 60px; position: relative; user-select: none; -webkit-user-select: none; }
#schema .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; }
#schema .references { position: absolute; }
#help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; }
@@ -89,12 +94,14 @@ input.wayoff { left: -1000px; position: absolute; }
.rtl .pages { left: auto; right: 21em; }
.rtl input.wayoff { left: auto; right: -1000px; }
.rtl #lang, .rtl #menu { left: auto; right: 0; }
.rtl pre, .rtl code { direction: ltr; }
@media all and (max-device-width: 880px) {
@media all and (max-width: 880px) {
.pages { left: auto; }
.logout { position: static; padding: 0 1em 1em; }
#menu { position: static; width: auto; }
#content { margin-left: 10px; }
#lang { position: static; border-top: 1px solid #999; }
#lang { position: static; }
#breadcrumb { left: auto; }
.rtl .pages { right: auto; }
.rtl #content { margin-right: 10px; }

View File

@@ -16,17 +16,22 @@ function bodyLoad(version, maria) {
if (maria) {
for (var i = 1; i < obj.length; i++) {
obj[i] = obj[i]
.replace(/\.html/, '/')
.replace(/-type-syntax/, '-data-types')
.replace('.html', '/')
.replace('-type-syntax', '-data-types')
.replace(/numeric-(data-types)/, '$1-$&')
.replace(/#statvar_.*/, '#$$1')
.replace(/replication-options-(master|binary-log)\//, 'replication-and-binary-log-system-variables/')
.replace('server-options/', 'server-system-variables/')
.replace('innodb-parameters/', 'innodb-system-variables/')
.replace(/#(statvar|sysvar|option_mysqld)_(.*)/, '#$2')
.replace(/#sysvar_(.*)/, '#$1')
;
}
}
}
obj[key] = (maria ? obj[key].replace(/dev\.mysql\.com\/doc\/mysql\/en\//, 'mariadb.com/kb/en/library/') : obj[key]) // MariaDB
.replace(/\/doc\/mysql/, '/doc/refman/' + version) // MySQL
.replace(/\/docs\/current/, '/docs/' + version) // PostgreSQL
obj[key] = (maria ? obj[key].replace('dev.mysql.com/doc/mysql', 'mariadb.com/kb') : obj[key]) // MariaDB
.replace('/doc/mysql', '/doc/refman/' + version) // MySQL
.replace('/docs/current', '/docs/' + version) // PostgreSQL
;
}
}
@@ -103,6 +108,13 @@ var dbPrevious = {};
* @this HTMLSelectElement
*/
function dbMouseDown(event) {
// Firefox: mouse-down event does not contain pressed key information for OPTION.
// Chrome: mouse-down event has inherited key information from SELECT.
// So we ignore the event for OPTION to work Ctrl+click correctly everywhere.
if (event.target.tagName == "OPTION") {
return;
}
dbCtrl = isCtrl(event);
if (dbPrevious[this.name] == undefined) {
dbPrevious[this.name] = this.value;
@@ -145,7 +157,7 @@ function selectFieldChange() {
for (var i=0; i < selects.length; i++) {
var select = selects[i];
var col = selectValue(select);
var match = /^(where.+)col\]/.exec(select.name);
var match = /^(where.+)col]/.exec(select.name);
if (match) {
var op = selectValue(form[match[1] + 'op]']);
var val = form[match[1] + 'val]'].value;
@@ -155,7 +167,7 @@ function selectFieldChange() {
ok = false;
}
}
if ((match = /^(columns.+)fun\]/.exec(select.name))) {
if ((match = /^(columns.+)fun]/.exec(select.name))) {
if (/^(avg|count|count distinct|group_concat|max|min|sum)$/.test(col)) {
group = true;
}
@@ -226,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
});
}
@@ -273,8 +289,9 @@ function editingClick(event) {
*/
function editingInput(event) {
var el = getTarget(event);
if (/\[default\]$/.test(el.name)) {
el.previousSibling.checked = true;
if (/\[default]$/.test(el.name)) {
el.previousElementSibling.checked = true;
el.previousElementSibling.selectedIndex = Math.max(el.previousElementSibling.selectedIndex, 1);
}
}
@@ -343,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;
@@ -406,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));
@@ -488,6 +507,16 @@ function columnShow(checked, column) {
}
}
/** Show or hide index column options
* @param boolean
*/
function indexOptionsShow(checked) {
var options = qsa('.idxopts');
for (var i=0; i < options.length; i++) {
alterClass(options[i], 'hidden', !checked);
}
}
/** Display partition options
* @this HTMLSelectElement
*/
@@ -531,7 +560,7 @@ function dumpClick(event) {
var el = parentTag(getTarget(event), 'label');
if (el) {
el = qs('input', el);
var match = /(.+)\[\]$/.exec(el.name);
var match = /(.+)\[]$/.exec(el.name);
if (match) {
checkboxClick.call(el, event);
formUncheck('check-' + match[1]);
@@ -549,7 +578,7 @@ function foreignAddRow() {
this.onchange = function () { };
var selects = qsa('select', row);
for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/\]/, '1$&');
selects[i].name = selects[i].name.replace(/\d+]/, '1$&');
selects[i].selectedIndex = 0;
}
parentTag(this, 'table').appendChild(row);
@@ -585,7 +614,7 @@ function indexesChangeColumn(prefix) {
for (var tag in { 'select': 1, 'input': 1 }) {
var columns = qsa(tag, parentTag(this, 'td'));
for (var i=0; i < columns.length; i++) {
if (/\[columns\]/.test(columns[i].name)) {
if (/\[columns]/.test(columns[i].name)) {
var value = selectValue(columns[i]);
if (value) {
names.push(value);
@@ -593,7 +622,7 @@ function indexesChangeColumn(prefix) {
}
}
}
this.form[this.name.replace(/\].*/, '][name]')].value = prefix + names.join('_');
this.form[this.name.replace(/].*/, '][name]')].value = prefix + names.join('_');
}
/** Add column for index
@@ -602,7 +631,7 @@ function indexesChangeColumn(prefix) {
*/
function indexesAddColumn(prefix) {
var field = this;
var select = field.form[field.name.replace(/\].*/, '][type]')];
var select = field.form[field.name.replace(/].*/, '][type]')];
if (!select.selectedIndex) {
while (selectValue(select) != "INDEX" && select.selectedIndex < select.options.length) {
select.selectedIndex++;
@@ -613,14 +642,14 @@ function indexesAddColumn(prefix) {
var selects = qsa('select', column);
for (var i = 0; i < selects.length; i++) {
select = selects[i];
select.name = select.name.replace(/\]\[\d+/, '$&1');
select.name = select.name.replace(/]\[\d+/, '$&1');
select.selectedIndex = 0;
}
field.onchange = partial(indexesChangeColumn, prefix);
var inputs = qsa('input', column);
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
input.name = input.name.replace(/\]\[\d+/, '$&1');
input.name = input.name.replace(/]\[\d+/, '$&1');
if (input.type != 'checkbox') {
input.value = '';
}
@@ -670,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;
@@ -689,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) {

View File

@@ -139,7 +139,7 @@ function selectValue(select) {
/** Verify if element has a specified tag name
* @param HTMLElement
* @param string regular expression
* @return bool
* @return boolean
*/
function isTag(el, tag) {
var re = new RegExp('^(' + tag + ')$', 'i');
@@ -333,7 +333,7 @@ function setHtml(id, html) {
*/
function nodePosition(el) {
var pos = 0;
while (el = el.previousSibling) {
while ((el = el.previousSibling)) {
pos++;
}
return pos;
@@ -366,7 +366,7 @@ function menuOver(event) {
* @this HTMLElement
*/
function menuOut() {
this.style.overflow = 'auto';
this.style.overflow = 'hidden';
}
@@ -708,9 +708,13 @@ function selectClick(event, text, warning) {
td.innerHTML = original;
}
};
var pos = event.rangeOffset;
var value = (td.firstChild && td.firstChild.alt) || td.textContent || td.innerText;
input.style.width = Math.max(td.clientWidth - 14, 20) + 'px'; // 14 = 2 * (td.border + td.padding + input.border)
let pos = event.rangeOffset;
let value = (td.firstChild && td.firstChild.alt) || td.textContent || td.innerText;
const tdStyle = window.getComputedStyle(td, null);
input.style.width = Math.max(td.clientWidth - parseFloat(tdStyle.paddingLeft) - parseFloat(tdStyle.paddingRight), 20) + 'px';
if (text) {
var rows = 1;
value.replace(/\n/g, function () {
@@ -880,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);
}

Some files were not shown because too many files have changed in this diff Show More