Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 940 lines (859 sloc) 28.582 kB
3f5b683 Reintegrate sqlite branch
jakubvrana authored
1 <?php
a244367 @vrana Always display all drivers (bug #3097666)
authored
2 $drivers = array("server" => "MySQL") + $drivers;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
3
4 if (!defined("DRIVER")) {
a244367 @vrana Always display all drivers (bug #3097666)
authored
5 $possible_drivers = array("MySQLi", "MySQL", "PDO_MySQL");
3f5b683 Reintegrate sqlite branch
jakubvrana authored
6 define("DRIVER", "server"); // server - backwards compatibility
7 // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
8 if (extension_loaded("mysqli")) {
9 class Min_DB extends MySQLi {
10 var $extension = "MySQLi";
11
12 function Min_DB() {
13 parent::init();
14 }
15
16 function connect($server, $username, $password) {
8455d05 @vrana Comment
authored
17 mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4
3f5b683 Reintegrate sqlite branch
jakubvrana authored
18 list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
93f8157 @vrana Set charset natively to defend against Shift JIS on server
authored
19 $return = @$this->real_connect(
3f5b683 Reintegrate sqlite branch
jakubvrana authored
20 ($server != "" ? $host : ini_get("mysqli.default_host")),
21 ("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
22 ("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
23 null,
24 (is_numeric($port) ? $port : ini_get("mysqli.default_port")),
25 (!is_numeric($port) ? $port : null)
26 );
93f8157 @vrana Set charset natively to defend against Shift JIS on server
authored
27 if ($return) {
28 if (method_exists($this, 'set_charset')) {
29 $this->set_charset("utf8");
30 } else {
31 $this->query("SET NAMES utf8");
32 }
33 }
34 return $return;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
35 }
36
37 function result($query, $field = 0) {
38 $result = $this->query($query);
39 if (!$result) {
40 return false;
41 }
42 $row = $result->fetch_array();
43 return $row[$field];
44 }
45
46 function quote($string) {
47 return "'" . $this->escape_string($string) . "'";
48 }
49 }
50
51 } elseif (extension_loaded("mysql")) {
52 class Min_DB {
53 var
54 $extension = "MySQL", ///< @var string extension name
55 $server_info, ///< @var string server version
56 $affected_rows, ///< @var int number of affected rows
57 $error, ///< @var string last error message
58 $_link, $_result ///< @access private
59 ;
60
61 /** Connect to server
62 * @param string
63 * @param string
64 * @param string
65 * @return bool
66 */
67 function connect($server, $username, $password) {
68 $this->_link = @mysql_connect(
69 ($server != "" ? $server : ini_get("mysql.default_host")),
70 ("$server$username" != "" ? $username : ini_get("mysql.default_user")),
71 ("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
72 true,
73 131072 // CLIENT_MULTI_RESULTS for CALL
74 );
75 if ($this->_link) {
76 $this->server_info = mysql_get_server_info($this->_link);
93f8157 @vrana Set charset natively to defend against Shift JIS on server
authored
77 if (function_exists('mysql_set_charset')) {
78 mysql_set_charset("utf8", $this->_link);
79 } else {
80 $this->query("SET NAMES utf8");
81 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
82 } else {
83 $this->error = mysql_error();
84 }
85 return (bool) $this->_link;
86 }
87
88 /** Quote string to use in SQL
89 * @param string
90 * @return string escaped string enclosed in '
91 */
92 function quote($string) {
93 return "'" . mysql_real_escape_string($string, $this->_link) . "'";
94 }
95
96 /** Select database
97 * @param string
98 * @return bool
99 */
100 function select_db($database) {
101 return mysql_select_db($database, $this->_link);
102 }
103
104 /** Send query
105 * @param string
106 * @param bool
107 * @return mixed bool or Min_Result
108 */
109 function query($query, $unbuffered = false) {
110 $result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
111 if (!$result) {
112 $this->error = mysql_error($this->_link);
113 return false;
114 }
115 if ($result === true) {
116 $this->affected_rows = mysql_affected_rows($this->_link);
117 $this->info = mysql_info($this->_link);
118 return true;
119 }
120 return new Min_Result($result);
121 }
122
123 /** Send query with more resultsets
124 * @param string
125 * @return bool
126 */
127 function multi_query($query) {
128 return $this->_result = $this->query($query);
129 }
130
131 /** Get current resultset
132 * @return Min_Result
133 */
134 function store_result() {
135 return $this->_result;
136 }
137
138 /** Fetch next resultset
139 * @return bool
140 */
141 function next_result() {
142 // MySQL extension doesn't support multiple results
143 return false;
144 }
145
146 /** Get single field from result
147 * @param string
148 * @param int
149 * @return string
150 */
151 function result($query, $field = 0) {
152 $result = $this->query($query);
efd7b90 @vrana Avoid warning
authored
153 if (!$result || !$result->num_rows) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
154 return false;
155 }
156 return mysql_result($result->_result, 0, $field);
157 }
158 }
159
160 class Min_Result {
161 var
162 $num_rows, ///< @var int number of rows in the result
2ebf4d7 @vrana Offset probably required in fetch_field (bug #3100185)
authored
163 $_result, $_offset = 0 ///< @access private
3f5b683 Reintegrate sqlite branch
jakubvrana authored
164 ;
165
166 /** Constructor
167 * @param resource
168 */
169 function Min_Result($result) {
170 $this->_result = $result;
171 $this->num_rows = mysql_num_rows($result);
172 }
173
174 /** Fetch next row as associative array
175 * @return array
176 */
177 function fetch_assoc() {
178 return mysql_fetch_assoc($this->_result);
179 }
180
181 /** Fetch next row as numbered array
182 * @return array
183 */
184 function fetch_row() {
185 return mysql_fetch_row($this->_result);
186 }
187
188 /** Fetch next field
189 * @return object properties: name, type, orgtable, orgname, charsetnr
190 */
191 function fetch_field() {
2ebf4d7 @vrana Offset probably required in fetch_field (bug #3100185)
authored
192 $return = mysql_fetch_field($this->_result, $this->_offset++); // offset required under certain conditions
3f5b683 Reintegrate sqlite branch
jakubvrana authored
193 $return->orgtable = $return->table;
194 $return->orgname = $return->name;
195 $return->charsetnr = ($return->blob ? 63 : 0);
196 return $return;
197 }
198
199 /** Free result set
200 */
201 function __destruct() {
202 mysql_free_result($this->_result); //! not called in PHP 4 which is a problem with mysql.trace_mode
203 }
204 }
205
206 } elseif (extension_loaded("pdo_mysql")) {
207 class Min_DB extends Min_PDO {
208 var $extension = "PDO_MySQL";
209
210 function connect($server, $username, $password) {
5002b89 @vrana Big numbers without E
authored
211 $this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\\d)~', ';port=\\1', $server)), $username, $password);
93f8157 @vrana Set charset natively to defend against Shift JIS on server
authored
212 $this->query("SET NAMES utf8"); // charset in DSN is ignored
3f5b683 Reintegrate sqlite branch
jakubvrana authored
213 return true;
214 }
215
216 function select_db($database) {
217 // database selection is separated from the connection so dbname in DSN can't be used
218 return $this->query("USE " . idf_escape($database));
219 }
220
221 function query($query, $unbuffered = false) {
222 $this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
223 return parent::query($query, $unbuffered);
224 }
225 }
226
227 }
228
229 /** Escape database identifier
230 * @param string
231 * @return string
232 */
233 function idf_escape($idf) {
234 return "`" . str_replace("`", "``", $idf) . "`";
235 }
236
60c7ed9 @vrana MS SQL schema support
authored
237 /** Get escaped table name
238 * @param string
239 * @return string
240 */
241 function table($idf) {
242 return idf_escape($idf);
243 }
244
3f5b683 Reintegrate sqlite branch
jakubvrana authored
245 /** Connect to the database
246 * @return mixed Min_DB or string for error
247 */
248 function connect() {
249 global $adminer;
250 $connection = new Min_DB;
251 $credentials = $adminer->credentials();
252 if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
253 $connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
254 return $connection;
255 }
256 return $connection->error;
257 }
258
259 /** Get cached list of databases
260 * @param bool
261 * @return array
262 */
263 function get_databases($flush = true) {
f332258 @vrana Show databases even with skip_show_database in MySQL 5 (thanks to Rad…
authored
264 global $connection;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
265 // SHOW DATABASES can take a very long time so it is cached
49565e0 @vrana Rename variables to avoid conflict with Adminer 2 sessions and enable…
authored
266 $return = &get_session("dbs");
3f5b683 Reintegrate sqlite branch
jakubvrana authored
267 if (!isset($return)) {
268 if ($flush) {
269 restart_session();
270 ob_flush();
271 flush();
272 }
f332258 @vrana Show databases even with skip_show_database in MySQL 5 (thanks to Rad…
authored
273 $return = get_vals($connection->server_info >= 5 ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" : "SHOW DATABASES"); // SHOW DATABASES can be disabled by skip_show_database
3f5b683 Reintegrate sqlite branch
jakubvrana authored
274 }
275 return $return;
276 }
277
278 /** Formulate SQL query with limit
279 * @param string everything after SELECT
ee3e045 @vrana Separate $where in limit function
authored
280 * @param string including WHERE
3f5b683 Reintegrate sqlite branch
jakubvrana authored
281 * @param int
282 * @param int
99a643b LIMIT separator
jakubvrana authored
283 * @param string
3f5b683 Reintegrate sqlite branch
jakubvrana authored
284 * @return string
285 */
ee3e045 @vrana Separate $where in limit function
authored
286 function limit($query, $where, $limit, $offset = 0, $separator = " ") {
287 return " $query$where" . (isset($limit) ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
3f5b683 Reintegrate sqlite branch
jakubvrana authored
288 }
289
290 /** Formulate SQL modification query with limit 1
291 * @param string everything after UPDATE or DELETE
292 * @return string
293 */
ee3e045 @vrana Separate $where in limit function
authored
294 function limit1($query, $where) {
295 return limit($query, $where, 1);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
296 }
297
298 /** Get database collation
299 * @param string
300 * @param array result of collations()
301 * @return string
302 */
303 function db_collation($db, $collations) {
304 global $connection;
305 $return = null;
306 $create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
307 if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
308 $return = $match[1];
309 } elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
310 // default collation
32f2000 @vrana Respect default collation (bug #3191489)
authored
311 $return = $collations[$match[1]][-1];
3f5b683 Reintegrate sqlite branch
jakubvrana authored
312 }
313 return $return;
314 }
315
316 /** Get supported engines
317 * @return array
318 */
319 function engines() {
320 $return = array();
b0d637b @vrana Avoid fatal errors
authored
321 foreach (get_rows("SHOW ENGINES") as $row) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
322 if (ereg("YES|DEFAULT", $row["Support"])) {
323 $return[] = $row["Engine"];
324 }
325 }
326 return $return;
327 }
328
329 /** Get logged user
330 * @return string
331 */
332 function logged_user() {
333 global $connection;
334 return $connection->result("SELECT USER()");
335 }
336
337 /** Get tables list
338 * @return array
339 */
340 function tables_list() {
341 global $connection;
342 return get_key_vals("SHOW" . ($connection->server_info >= 5 ? " FULL" : "") . " TABLES");
343 }
344
345 /** Count tables in all databases
346 * @param array
347 * @return array array($db => $tables)
348 */
349 function count_tables($databases) {
350 $return = array();
351 foreach ($databases as $db) {
352 $return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db)));
353 }
354 return $return;
355 }
356
357 /** Get table status
358 * @param string
359 * @return array
360 */
361 function table_status($name = "") {
362 $return = array();
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
363 foreach (get_rows("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_")) : "")) as $row) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
364 if ($row["Engine"] == "InnoDB") {
365 // ignore internal comment, unnecessary since MySQL 5.1.21
366 $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
367 }
368 if (!isset($row["Rows"])) {
369 $row["Comment"] = "";
370 }
371 if ($name != "") {
372 return $row;
373 }
374 $return[$row["Name"]] = $row;
375 }
376 return $return;
377 }
378
da6f1f8 @vrana Driver specific view detection
authored
379 /** Find out whether the identifier is view
380 * @param array
381 * @return bool
382 */
383 function is_view($table_status) {
384 return !isset($table_status["Rows"]);
385 }
386
3f5b683 Reintegrate sqlite branch
jakubvrana authored
387 /** Check if table supports foreign keys
388 * @param array result of table_status
389 * @return bool
390 */
391 function fk_support($table_status) {
392 return ($table_status["Engine"] == "InnoDB");
393 }
394
395 /** Get information about fields
396 * @param string
397 * @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
398 */
f425601 @vrana Hide hidden columns in PostgreSQL (thanks to Pavel Stehule)
authored
399 function fields($table) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
400 $return = array();
b0d637b @vrana Avoid fatal errors
authored
401 foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) {
402 preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
403 $return[$row["Field"]] = array(
404 "field" => $row["Field"],
405 "full_type" => $row["Type"],
406 "type" => $match[1],
407 "length" => $match[2],
408 "unsigned" => ltrim($match[3] . $match[4]),
409 "default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
410 "null" => ($row["Null"] == "YES"),
411 "auto_increment" => ($row["Extra"] == "auto_increment"),
412 "on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
413 "collation" => $row["Collation"],
414 "privileges" => array_flip(explode(",", $row["Privileges"])),
415 "comment" => $row["Comment"],
416 "primary" => ($row["Key"] == "PRI"),
417 );
3f5b683 Reintegrate sqlite branch
jakubvrana authored
418 }
419 return $return;
420 }
421
422 /** Get table indexes
423 * @param string
424 * @param string Min_DB to use
425 * @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
426 */
427 function indexes($table, $connection2 = null) {
428 global $connection;
429 if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
430 $connection2 = $connection;
431 }
432 $return = array();
b0d637b @vrana Avoid fatal errors
authored
433 foreach (get_rows("SHOW INDEX FROM " . table($table), $connection2) as $row) {
434 $return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
435 $return[$row["Key_name"]]["columns"][] = $row["Column_name"];
436 $return[$row["Key_name"]]["lengths"][] = $row["Sub_part"];
3f5b683 Reintegrate sqlite branch
jakubvrana authored
437 }
438 return $return;
439 }
440
441 /** Get foreign keys in table
442 * @param string
443 * @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
444 */
445 function foreign_keys($table) {
446 global $connection, $on_actions;
447 static $pattern = '`(?:[^`]|``)+`';
448 $return = array();
60c7ed9 @vrana MS SQL schema support
authored
449 $create_table = $connection->result("SHOW CREATE TABLE " . table($table), 1);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
450 if ($create_table) {
451 preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
452 foreach ($matches as $match) {
453 preg_match_all("~$pattern~", $match[2], $source);
454 preg_match_all("~$pattern~", $match[5], $target);
455 $return[idf_unescape($match[1])] = array(
456 "db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
457 "table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
458 "source" => array_map('idf_unescape', $source[0]),
459 "target" => array_map('idf_unescape', $target[0]),
460 "on_delete" => $match[6],
461 "on_update" => $match[7],
462 );
463 }
464 }
465 return $return;
466 }
467
468 /** Get view SELECT
469 * @param string
470 * @return array array("select" => )
471 */
472 function view($name) {
473 global $connection;
60c7ed9 @vrana MS SQL schema support
authored
474 return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\\s+AS\\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1)));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
475 }
476
477 /** Get sorted grouped list of collations
478 * @return array
479 */
480 function collations() {
481 $return = array();
b0d637b @vrana Avoid fatal errors
authored
482 foreach (get_rows("SHOW COLLATION") as $row) {
32f2000 @vrana Respect default collation (bug #3191489)
authored
483 if ($row["Default"]) {
484 $return[$row["Charset"]][-1] = $row["Collation"];
485 } else {
486 $return[$row["Charset"]][] = $row["Collation"];
487 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
488 }
489 ksort($return);
490 foreach ($return as $key => $val) {
32f2000 @vrana Respect default collation (bug #3191489)
authored
491 asort($return[$key]);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
492 }
493 return $return;
494 }
495
496 /** Find out if database is information_schema
497 * @param string
498 * @return bool
499 */
500 function information_schema($db) {
501 global $connection;
502 return ($connection->server_info >= 5 && $db == "information_schema");
503 }
504
505 /** Get escaped error message
506 * @return string
507 */
508 function error() {
509 global $connection;
510 return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
511 }
512
513 /** Return expression for binary comparison
514 * @param string
515 * @return string
516 */
517 function exact_value($val) {
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
518 return q($val) . " COLLATE utf8_bin";
3f5b683 Reintegrate sqlite branch
jakubvrana authored
519 }
520
edb6401 Driver specific create and drop database
jakubvrana authored
521 /** Create database
522 * @param string
523 * @return string
524 */
525 function create_database($db, $collation) {
49565e0 @vrana Rename variables to avoid conflict with Adminer 2 sessions and enable…
authored
526 set_session("dbs", null);
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
527 return queries("CREATE DATABASE " . idf_escape($db) . ($collation ? " COLLATE " . q($collation) : ""));
edb6401 Driver specific create and drop database
jakubvrana authored
528 }
529
530 /** Drop databases
531 * @param array
532 * @return bool
533 */
534 function drop_databases($databases) {
49565e0 @vrana Rename variables to avoid conflict with Adminer 2 sessions and enable…
authored
535 set_session("dbs", null);
dc45301 @vrana Typo
authored
536 return apply_queries("DROP DATABASE", $databases, 'idf_escape');
edb6401 Driver specific create and drop database
jakubvrana authored
537 }
538
3f5b683 Reintegrate sqlite branch
jakubvrana authored
539 /** Rename database from DB
540 * @param string new name
541 * @return string
542 * @return bool
543 */
544 function rename_database($name, $collation) {
edb6401 Driver specific create and drop database
jakubvrana authored
545 if (create_database($name, $collation)) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
546 //! move triggers
515325a @vrana Rename tables by single command
authored
547 $rename = array();
548 foreach (tables_list() as $table => $type) {
549 $rename[] = table($table) . " TO " . idf_escape($name) . "." . table($table);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
550 }
515325a @vrana Rename tables by single command
authored
551 if (!$rename || queries("RENAME TABLE " . implode(", ", $rename))) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
552 queries("DROP DATABASE " . idf_escape(DB));
515325a @vrana Rename tables by single command
authored
553 return true;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
554 }
555 }
515325a @vrana Rename tables by single command
authored
556 return false;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
557 }
558
559 /** Generate modifier for auto increment column
560 * @return string
561 */
562 function auto_increment() {
563 $auto_increment_index = " PRIMARY KEY";
564 // don't overwrite primary key by auto_increment
565 if ($_GET["create"] != "" && $_POST["auto_increment_col"]) {
566 foreach (indexes($_GET["create"]) as $index) {
567 if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
568 $auto_increment_index = "";
569 break;
570 }
571 if ($index["type"] == "PRIMARY") {
572 $auto_increment_index = " UNIQUE";
573 }
574 }
575 }
576 return " AUTO_INCREMENT$auto_increment_index";
577 }
578
579 /** Run commands to create or alter table
580 * @param string "" to create
581 * @param string new name
582 * @param array of array($orig, $process_field, $after)
583 * @param array of strings
584 * @param string
585 * @param string
586 * @param string
587 * @param int
588 * @param string
589 * @return bool
590 */
591 function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
592 $alter = array();
593 foreach ($fields as $field) {
594 $alter[] = ($field[1]
7f3ccd3 @vrana Utilize single parameter implode
authored
595 ? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? " $field[2]" : "")
3f5b683 Reintegrate sqlite branch
jakubvrana authored
596 : "DROP " . idf_escape($field[0])
597 );
598 }
599 $alter = array_merge($alter, $foreign);
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
600 $status = "COMMENT=" . q($comment)
601 . ($engine ? " ENGINE=" . q($engine) : "")
602 . ($collation ? " COLLATE " . q($collation) : "")
3f5b683 Reintegrate sqlite branch
jakubvrana authored
603 . ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
604 . $partitioning
605 ;
606 if ($table == "") {
60c7ed9 @vrana MS SQL schema support
authored
607 return queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n) $status");
3f5b683 Reintegrate sqlite branch
jakubvrana authored
608 }
609 if ($table != $name) {
60c7ed9 @vrana MS SQL schema support
authored
610 $alter[] = "RENAME TO " . table($name);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
611 }
612 $alter[] = $status;
60c7ed9 @vrana MS SQL schema support
authored
613 return queries("ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
614 }
615
616 /** Run commands to alter indexes
617 * @param string escaped table name
618 * @param array of array("index type", "(columns definition)") or array("index type", "escaped name", "DROP")
619 * @return bool
620 */
621 function alter_indexes($table, $alter) {
622 foreach ($alter as $key => $val) {
623 $alter[$key] = ($val[2] ? "\nDROP INDEX " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
624 }
60c7ed9 @vrana MS SQL schema support
authored
625 return queries("ALTER TABLE " . table($table) . implode(",", $alter));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
626 }
627
628 /** Run commands to truncate tables
629 * @param array
630 * @return bool
631 */
632 function truncate_tables($tables) {
f9bb1c5 @vrana Introduce apply_queries function
authored
633 return apply_queries("TRUNCATE TABLE", $tables);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
634 }
635
636 /** Drop views
637 * @param array
638 * @return bool
639 */
640 function drop_views($views) {
60c7ed9 @vrana MS SQL schema support
authored
641 return queries("DROP VIEW " . implode(", ", array_map('table', $views)));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
642 }
643
644 /** Drop tables
645 * @param array
646 * @return bool
647 */
648 function drop_tables($tables) {
60c7ed9 @vrana MS SQL schema support
authored
649 return queries("DROP TABLE " . implode(", ", array_map('table', $tables)));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
650 }
651
44d572e @vrana Driver specific move tables
authored
652 /** Move tables to other schema
653 * @param array
741b19b @vrana Copy tables (bug #3158027)
authored
654 * @param array
44d572e @vrana Driver specific move tables
authored
655 * @param string
656 * @return bool
657 */
658 function move_tables($tables, $views, $target) {
659 $rename = array();
660 foreach (array_merge($tables, $views) as $table) { // views will report SQL error
60c7ed9 @vrana MS SQL schema support
authored
661 $rename[] = table($table) . " TO " . idf_escape($target) . "." . table($table);
44d572e @vrana Driver specific move tables
authored
662 }
663 return queries("RENAME TABLE " . implode(", ", $rename));
664 //! move triggers
665 }
666
741b19b @vrana Copy tables (bug #3158027)
authored
667 /** Copy tables to other schema
668 * @param array
669 * @param array
670 * @param string
671 * @return bool
672 */
673 function copy_tables($tables, $views, $target) {
674 foreach ($tables as $table) {
675 $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
676 if (!queries("DROP TABLE IF EXISTS $name")
677 || !queries("CREATE TABLE $name LIKE " . table($table))
678 || !queries("INSERT INTO $name SELECT * FROM " . table($table))
679 ) {
680 return false;
681 }
682 }
683 foreach ($views as $table) {
684 $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
685 $view = view($table);
686 if (!queries("DROP VIEW IF EXISTS $name")
687 || !queries("CREATE VIEW $name AS $view[select]") //! USE to avoid db.table
688 ) {
689 return false;
690 }
691 }
692 return true;
693 }
694
3f5b683 Reintegrate sqlite branch
jakubvrana authored
695 /** Get information about trigger
696 * @param string trigger name
697 * @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
698 */
699 function trigger($name) {
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
700 $rows = get_rows("SHOW TRIGGERS WHERE `Trigger` = " . q($name));
b0d637b @vrana Avoid fatal errors
authored
701 return reset($rows);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
702 }
703
704 /** Get defined triggers
705 * @param string
706 * @return array array($name => array($timing, $event))
707 */
708 function triggers($table) {
709 $return = array();
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
710 foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_"))) as $row) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
711 $return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
712 }
713 return $return;
714 }
715
edb6401 Driver specific create and drop database
jakubvrana authored
716 /** Get trigger options
717 * @return array ("Timing" => array(), "Type" => array())
718 */
f9dd7aa Driver specific trigger options
jakubvrana authored
719 function trigger_options() {
720 return array(
721 "Timing" => array("BEFORE", "AFTER"),
722 // Event is always INSERT, UPDATE, DELETE
723 "Type" => array("FOR EACH ROW"),
724 );
725 }
726
02a172e Driver specific routines
jakubvrana authored
727 /** Get information about stored routine
728 * @param string
729 * @param string FUNCTION or PROCEDURE
730 * @return array ("fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => )
731 */
732 function routine($name, $type) {
733 global $connection, $enum_length, $inout, $types;
9e1d1c3 @vrana Respect unsupported types
authored
734 $aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
735 $type_pattern = "((" . implode("|", array_merge(array_keys($types), $aliases)) . ")(?:\\s*\\(((?:[^'\")]*|$enum_length)+)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s]+)['\"]?)?";
02a172e Driver specific routines
jakubvrana authored
736 $pattern = "\\s*(" . ($type == "FUNCTION" ? "" : implode("|", $inout)) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
737 $create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
738 preg_match("~\\(((?:$pattern\\s*,?)*)\\)" . ($type == "FUNCTION" ? "\\s*RETURNS\\s+$type_pattern" : "") . "\\s*(.*)~is", $create, $match);
739 $fields = array();
740 preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);
741 foreach ($matches as $param) {
742 $name = str_replace("``", "`", $param[2]) . $param[3];
743 $fields[] = array(
744 "field" => $name,
9e1d1c3 @vrana Respect unsupported types
authored
745 "type" => strtolower($param[5]),
02a172e Driver specific routines
jakubvrana authored
746 "length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
747 "unsigned" => strtolower(preg_replace('~\\s+~', ' ', trim("$param[8] $param[7]"))),
748 "full_type" => $param[4],
749 "inout" => strtoupper($param[1]),
750 "collation" => strtolower($param[9]),
751 );
752 }
753 if ($type != "FUNCTION") {
754 return array("fields" => $fields, "definition" => $match[11]);
755 }
756 return array(
757 "fields" => $fields,
758 "returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]),
759 "definition" => $match[17],
760 );
761 }
762
763 function routines() {
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
764 return get_rows("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB));
02a172e Driver specific routines
jakubvrana authored
765 }
766
d0c72ec Driver specific BEGIN
jakubvrana authored
767 /** Begin transaction
768 * @return bool
769 */
770 function begin() {
771 return queries("BEGIN");
772 }
773
341362a Driver specific INSERT INTO
jakubvrana authored
774 /** Insert data into table
775 * @param string
776 * @param array
777 * @return bool
778 */
779 function insert_into($table, $set) {
60c7ed9 @vrana MS SQL schema support
authored
780 return queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")");
341362a Driver specific INSERT INTO
jakubvrana authored
781 }
782
782921b @vrana Finish SQLite
authored
783 /** Insert or update data in the table
784 * @param string
785 * @param array
6e50eb8 @vrana Pass primary key to insert_update function
authored
786 * @param array columns in keys
782921b @vrana Finish SQLite
authored
787 * @return bool
788 */
6e50eb8 @vrana Pass primary key to insert_update function
authored
789 function insert_update($table, $set, $primary) {
782921b @vrana Finish SQLite
authored
790 foreach ($set as $key => $val) {
791 $set[$key] = "$key = $val";
792 }
793 $update = implode(", ", $set);
794 return queries("INSERT INTO " . table($table) . " SET $update ON DUPLICATE KEY UPDATE $update");
795 }
796
29e7f04 @vrana Display auto_increment value of inserted item
authored
797 /** Get last auto increment ID
798 * @return string
799 */
800 function last_id() {
801 global $connection;
802 return $connection->result("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
803 }
804
3f5b683 Reintegrate sqlite branch
jakubvrana authored
805 /** Explain select
806 * @param Min_DB
807 * @param string
808 * @return Min_Result
809 */
810 function explain($connection, $query) {
811 return $connection->query("EXPLAIN $query");
812 }
813
3308856 @vrana User types support for PostgreSQL
authored
814 /** Get user defined types
815 * @return array
816 */
817 function types() {
818 return array();
819 }
820
6420c58 Schema support for PostgreSQL
jakubvrana authored
821 /** Get existing schemas
822 * @return array
823 */
824 function schemas() {
825 return array();
826 }
827
828 /** Get current schema
829 * @return string
830 */
831 function get_schema() {
832 return "";
833 }
834
835 /** Set current schema
836 * @param string
837 * @return bool
838 */
839 function set_schema($schema) {
840 return true;
841 }
842
3f5b683 Reintegrate sqlite branch
jakubvrana authored
843 /** Get SQL command to create table
844 * @param string
fe53964 @vrana Allow disabling auto_increment value export
authored
845 * @param bool
3f5b683 Reintegrate sqlite branch
jakubvrana authored
846 * @return string
847 */
fe53964 @vrana Allow disabling auto_increment value export
authored
848 function create_sql($table, $auto_increment) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
849 global $connection;
fe53964 @vrana Allow disabling auto_increment value export
authored
850 $return = $connection->result("SHOW CREATE TABLE " . table($table), 1);
851 if (!$auto_increment) {
5002b89 @vrana Big numbers without E
authored
852 $return = preg_replace('~ AUTO_INCREMENT=\\d+~', '', $return); //! skip comments
fe53964 @vrana Allow disabling auto_increment value export
authored
853 }
854 return $return;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
855 }
856
782921b @vrana Finish SQLite
authored
857 /** Get SQL command to truncate table
858 * @param string
859 * @return string
860 */
861 function truncate_sql($table) {
862 return "TRUNCATE " . table($table);
863 }
864
58c80e3 Driver specific USE
jakubvrana authored
865 /** Get SQL command to change database
866 * @param string
867 * @return string
868 */
869 function use_sql($database) {
870 return "USE " . idf_escape($database);
871 }
872
cc04be2 Driver specific trigger export
jakubvrana authored
873 /** Get SQL commands to create triggers
874 * @param string
875 * @param string
876 * @return string
877 */
878 function trigger_sql($table, $style) {
879 $return = "";
96544ba @vrana Report errors in get_rows()
authored
880 foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_")), null, "-- ") as $row) {
b0d637b @vrana Avoid fatal errors
authored
881 $return .= "\n" . ($style == 'CREATE+ALTER' ? "DROP TRIGGER IF EXISTS " . idf_escape($row["Trigger"]) . ";;\n" : "")
882 . "CREATE TRIGGER " . idf_escape($row["Trigger"]) . " $row[Timing] $row[Event] ON " . table($row["Table"]) . " FOR EACH ROW\n$row[Statement];;\n";
cc04be2 Driver specific trigger export
jakubvrana authored
883 }
884 return $return;
885 }
886
58c80e3 Driver specific USE
jakubvrana authored
887 /** Get server variables
888 * @return array ($name => $value)
889 */
984d090 SQLite variables
jakubvrana authored
890 function show_variables() {
891 return get_key_vals("SHOW VARIABLES");
892 }
893
58c80e3 Driver specific USE
jakubvrana authored
894 /** Get status variables
895 * @return array ($name => $value)
896 */
984d090 SQLite variables
jakubvrana authored
897 function show_status() {
898 return get_key_vals("SHOW STATUS");
899 }
900
3f5b683 Reintegrate sqlite branch
jakubvrana authored
901 /** Check whether a feature is supported
741b19b @vrana Copy tables (bug #3158027)
authored
902 * @param string "comment", "drop_col", "dump", "event", "partitioning", "routine", "scheme", "sequence", "status", "trigger", "type", "variables", "view", "copy"
3f5b683 Reintegrate sqlite branch
jakubvrana authored
903 * @return bool
904 */
905 function support($feature) {
906 global $connection;
3308856 @vrana User types support for PostgreSQL
authored
907 return !ereg("scheme|sequence|type" . ($connection->server_info < 5.1 ? "|event|partitioning" . ($connection->server_info < 5 ? "|view|routine|trigger" : "") : ""), $feature);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
908 }
909
e672694 @vrana Rename $driver to $jush
authored
910 $jush = "sql"; ///< @var string JUSH identifier
3f5b683 Reintegrate sqlite branch
jakubvrana authored
911 $types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
912 $structured_types = array(); ///< @var array ($description => array($type, ...), ...)
913 foreach (array(
914 lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
915 lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
916 lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
c0cc2a5 BIT data type
jakubvrana authored
917 lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
3f5b683 Reintegrate sqlite branch
jakubvrana authored
918 lang('Lists') => array("enum" => 65535, "set" => 64),
919 ) as $key => $val) {
920 $types += $val;
921 $structured_types[$key] = array_keys($val);
922 }
923 $unsigned = array("unsigned", "zerofill", "unsigned zerofill"); ///< @var array number variants
675ac01 @vrana Ability to search by expression in select (bug #3158017)
authored
924 $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", ""); ///< @var array operators used in select
a52a327 Add date function in select (thanks to paranoiq)
jakubvrana authored
925 $functions = array("char_length", "date", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "upper"); ///< @var array functions used in select
3f5b683 Reintegrate sqlite branch
jakubvrana authored
926 $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
927 $edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
928 array(
929 "char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength
5a73c01 @vrana Treat binary type as hex
authored
930 "binary" => "md5/sha1/hex",
3f5b683 Reintegrate sqlite branch
jakubvrana authored
931 "date|time" => "now",
932 ), array(
933 "int|float|double|decimal" => "+/-",
934 "date" => "+ interval/- interval",
935 "time" => "addtime/subtime",
936 "char|text" => "concat",
937 )
938 );
939 }
Something went wrong with that request. Please try again.