PageRenderTime 62ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/pma/libraries/export/sql.php

https://bitbucket.org/StasPiv/playzone
PHP | 1026 lines | 679 code | 109 blank | 238 comment | 193 complexity | f83e13c662acca9593d612844f64c4df MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0, LGPL-2.1
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Set of functions used to build SQL dumps of tables
  5. *
  6. * @package phpMyAdmin-Export-SQL
  7. * @version $Id: sql.php 12271 2009-03-03 10:12:17Z nijel $
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. /**
  13. *
  14. */
  15. if (isset($plugin_list)) {
  16. $hide_sql = false;
  17. $hide_structure = false;
  18. if ($plugin_param['export_type'] == 'table' && !$plugin_param['single_table']) {
  19. $hide_structure = true;
  20. $hide_sql = true;
  21. }
  22. if (!$hide_sql) {
  23. $plugin_list['sql'] = array(
  24. 'text' => 'strSQL',
  25. 'extension' => 'sql',
  26. 'mime_type' => 'text/x-sql',
  27. 'options' => array(
  28. array('type' => 'text', 'name' => 'header_comment', 'text' => 'strAddHeaderComment'),
  29. array('type' => 'bool', 'name' => 'include_comments', 'text' => 'strComments'),
  30. array('type' => 'bool', 'name' => 'use_transaction', 'text' => 'strEncloseInTransaction'),
  31. array('type' => 'bool', 'name' => 'disable_fk', 'text' => 'strDisableForeignChecks'),
  32. ),
  33. 'options_text' => 'strOptions',
  34. );
  35. $compats = PMA_DBI_getCompatibilities();
  36. if (count($compats) > 0) {
  37. $values = array();
  38. foreach($compats as $val) {
  39. $values[$val] = $val;
  40. }
  41. $plugin_list['sql']['options'][] =
  42. array('type' => 'select', 'name' => 'compatibility', 'text' => 'strSQLCompatibility', 'values' => $values, 'doc' => array('manual_MySQL_Database_Administration', 'Server_SQL_mode'));
  43. unset($values);
  44. }
  45. /* Server export options */
  46. if ($plugin_param['export_type'] == 'server') {
  47. $plugin_list['sql']['options'][] =
  48. array('type' => 'bgroup', 'text' => 'strDatabaseExportOptions');
  49. $plugin_list['sql']['options'][] =
  50. array('type' => 'bool', 'name' => 'drop_database', 'text' => sprintf($GLOBALS['strAddClause'], 'DROP DATABASE'));
  51. $plugin_list['sql']['options'][] =
  52. array('type' => 'egroup');
  53. }
  54. /* Structure options */
  55. if (!$hide_structure) {
  56. $plugin_list['sql']['options'][] =
  57. array('type' => 'bgroup', 'name' => 'structure', 'text' => 'strStructure', 'force' => 'data');
  58. if ($plugin_param['export_type'] == 'table') {
  59. if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) {
  60. $drop_clause = 'DROP VIEW';
  61. } else {
  62. $drop_clause = 'DROP TABLE';
  63. }
  64. } else {
  65. $drop_clause = 'DROP TABLE / VIEW / PROCEDURE / FUNCTION';
  66. if (PMA_MYSQL_INT_VERSION > 50100) {
  67. $drop_clause .= ' / EVENT';
  68. }
  69. }
  70. $plugin_list['sql']['options'][] =
  71. array('type' => 'bool', 'name' => 'drop_table', 'text' => sprintf($GLOBALS['strAddClause'], $drop_clause));
  72. $plugin_list['sql']['options'][] =
  73. array('type' => 'bool', 'name' => 'if_not_exists', 'text' => sprintf($GLOBALS['strAddClause'], 'IF NOT EXISTS'));
  74. $plugin_list['sql']['options'][] =
  75. array('type' => 'bool', 'name' => 'auto_increment', 'text' => 'strAddAutoIncrement');
  76. $plugin_list['sql']['options'][] =
  77. array('type' => 'bool', 'name' => 'backquotes', 'text' => 'strUseBackquotes');
  78. $plugin_list['sql']['options'][] =
  79. array('type' => 'bool', 'name' => 'procedure_function', 'text' => sprintf($GLOBALS['strAddClause'], 'CREATE PROCEDURE / FUNCTION' . (PMA_MYSQL_INT_VERSION > 50100 ? ' / EVENT' : '')));
  80. /* MIME stuff etc. */
  81. $plugin_list['sql']['options'][] =
  82. array('type' => 'bgroup', 'text' => 'strAddIntoComments');
  83. $plugin_list['sql']['options'][] =
  84. array('type' => 'bool', 'name' => 'dates', 'text' => 'strCreationDates');
  85. if (!empty($GLOBALS['cfgRelation']['relation'])) {
  86. $plugin_list['sql']['options'][] =
  87. array('type' => 'bool', 'name' => 'relation', 'text' => 'strRelations');
  88. }
  89. if (!empty($GLOBALS['cfgRelation']['mimework'])) {
  90. $plugin_list['sql']['options'][] =
  91. array('type' => 'bool', 'name' => 'mime', 'text' => 'strMIME_MIMEtype');
  92. }
  93. $plugin_list['sql']['options'][] =
  94. array('type' => 'egroup');
  95. $plugin_list['sql']['options'][] =
  96. array('type' => 'egroup');
  97. }
  98. /* Data */
  99. $plugin_list['sql']['options'][] =
  100. array('type' => 'bgroup', 'name' => 'data', 'text' => 'strData', 'force' => 'structure');
  101. $plugin_list['sql']['options'][] =
  102. array('type' => 'bool', 'name' => 'columns', 'text' => 'strCompleteInserts', 'doc' => array('programs', 'mysqldump', 'option_mysqldump_complete-insert-option'));
  103. $plugin_list['sql']['options'][] =
  104. array('type' => 'bool', 'name' => 'extended', 'text' => 'strExtendedInserts', 'doc' => array('programs', 'mysqldump', 'option_mysqldump_extended-insert-option'));
  105. $plugin_list['sql']['options'][] =
  106. array('type' => 'text', 'name' => 'max_query_size', 'text' => 'strMaximalQueryLength');
  107. $plugin_list['sql']['options'][] =
  108. array('type' => 'bool', 'name' => 'delayed', 'text' => 'strDelayedInserts');
  109. $plugin_list['sql']['options'][] =
  110. array('type' => 'bool', 'name' => 'ignore', 'text' => 'strIgnoreInserts');
  111. $plugin_list['sql']['options'][] =
  112. array('type' => 'bool', 'name' => 'hex_for_blob', 'text' => 'strHexForBLOB');
  113. $plugin_list['sql']['options'][] =
  114. array('type' => 'select', 'name' => 'type', 'text' => 'strSQLExportType', 'values' => array('INSERT' => 'INSERT', 'UPDATE' => 'UPDATE', 'REPLACE' => 'REPLACE'));
  115. $plugin_list['sql']['options'][] =
  116. array('type' => 'egroup');
  117. }
  118. } else {
  119. /**
  120. * Avoids undefined variables, use NULL so isset() returns false
  121. */
  122. if (! isset($sql_backquotes)) {
  123. $sql_backquotes = null;
  124. }
  125. /**
  126. * Outputs comment
  127. *
  128. * @param string Text of comment
  129. *
  130. * @return string The formatted comment
  131. */
  132. function PMA_exportComment($text = '')
  133. {
  134. if ($GLOBALS['sql_include_comments']) {
  135. // see http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-comments.html
  136. return '--' . (empty($text) ? '' : ' ') . $text . $GLOBALS['crlf'];
  137. } else {
  138. return '';
  139. }
  140. }
  141. /**
  142. * Outputs export footer
  143. *
  144. * @return bool Whether it suceeded
  145. *
  146. * @access public
  147. */
  148. function PMA_exportFooter()
  149. {
  150. global $crlf;
  151. global $mysql_charset_map;
  152. $foot = '';
  153. if (isset($GLOBALS['sql_disable_fk'])) {
  154. $foot .= $crlf . 'SET FOREIGN_KEY_CHECKS=1;' . $crlf;
  155. }
  156. if (isset($GLOBALS['sql_use_transaction'])) {
  157. $foot .= $crlf . 'COMMIT;' . $crlf;
  158. }
  159. // restore connection settings
  160. // (not set if $cfg['AllowAnywhereRecoding'] is false)
  161. $charset_of_file = isset($GLOBALS['charset_of_file']) ? $GLOBALS['charset_of_file'] : '';
  162. if (!empty($GLOBALS['asfile']) && isset($mysql_charset_map[$charset_of_file])) {
  163. $foot .= $crlf
  164. . '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;' . $crlf
  165. . '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;' . $crlf
  166. . '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;' . $crlf;
  167. }
  168. return PMA_exportOutputHandler($foot);
  169. }
  170. /**
  171. * Outputs export header
  172. *
  173. * @return bool Whether it suceeded
  174. *
  175. * @access public
  176. */
  177. function PMA_exportHeader()
  178. {
  179. global $crlf;
  180. global $cfg;
  181. global $mysql_charset_map;
  182. if (isset($GLOBALS['sql_compatibility'])) {
  183. $tmp_compat = $GLOBALS['sql_compatibility'];
  184. if ($tmp_compat == 'NONE') {
  185. $tmp_compat = '';
  186. }
  187. PMA_DBI_try_query('SET SQL_MODE="' . $tmp_compat . '"');
  188. unset($tmp_compat);
  189. }
  190. $head = PMA_exportComment('phpMyAdmin SQL Dump')
  191. . PMA_exportComment('version ' . PMA_VERSION)
  192. . PMA_exportComment('http://www.phpmyadmin.net')
  193. . PMA_exportComment();
  194. $head .= empty($cfg['Server']['port']) ? PMA_exportComment($GLOBALS['strHost'] . ': ' . $cfg['Server']['host']) : PMA_exportComment($GLOBALS['strHost'] . ': ' . $cfg['Server']['host'] . ':' . $cfg['Server']['port']);
  195. $head .= PMA_exportComment($GLOBALS['strGenTime']
  196. . ': ' . PMA_localisedDate())
  197. . PMA_exportComment($GLOBALS['strServerVersion'] . ': ' . substr(PMA_MYSQL_INT_VERSION, 0, 1) . '.' . (int) substr(PMA_MYSQL_INT_VERSION, 1, 2) . '.' . (int) substr(PMA_MYSQL_INT_VERSION, 3))
  198. . PMA_exportComment($GLOBALS['strPHPVersion'] . ': ' . phpversion());
  199. if (isset($GLOBALS['sql_header_comment']) && !empty($GLOBALS['sql_header_comment'])) {
  200. // '\n' is not a newline (like "\n" would be), it's the characters
  201. // backslash and n, as explained on the export interface
  202. $lines = explode('\n', $GLOBALS['sql_header_comment']);
  203. $head .= PMA_exportComment();
  204. foreach($lines as $one_line) {
  205. $head .= PMA_exportComment($one_line);
  206. }
  207. $head .= PMA_exportComment();
  208. }
  209. if (isset($GLOBALS['sql_disable_fk'])) {
  210. $head .= $crlf . 'SET FOREIGN_KEY_CHECKS=0;' . $crlf;
  211. }
  212. /* We want exported AUTO_INCREMENT fields to have still same value, do this only for recent MySQL exports */
  213. if (!isset($GLOBALS['sql_compatibility']) || $GLOBALS['sql_compatibility'] == 'NONE') {
  214. $head .= $crlf . 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";' . $crlf;
  215. }
  216. if (isset($GLOBALS['sql_use_transaction'])) {
  217. $head .= $crlf .'SET AUTOCOMMIT=0;' . $crlf
  218. . 'START TRANSACTION;' . $crlf;
  219. }
  220. $head .= $crlf;
  221. if (! empty($GLOBALS['asfile'])) {
  222. // we are saving as file, therefore we provide charset information
  223. // so that a utility like the mysql client can interpret
  224. // the file correctly
  225. if (isset($GLOBALS['charset_of_file']) && isset($mysql_charset_map[$GLOBALS['charset_of_file']])) {
  226. // $cfg['AllowAnywhereRecoding'] was true so we got a charset from
  227. // the export dialog
  228. $set_names = $mysql_charset_map[$GLOBALS['charset_of_file']];
  229. } else {
  230. // by default we use the connection charset
  231. $set_names = $mysql_charset_map[$GLOBALS['charset']];
  232. }
  233. $head .= $crlf
  234. . '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;' . $crlf
  235. . '/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;' . $crlf
  236. . '/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;' . $crlf
  237. . '/*!40101 SET NAMES ' . $set_names . ' */;' . $crlf . $crlf;
  238. }
  239. return PMA_exportOutputHandler($head);
  240. }
  241. /**
  242. * Outputs CREATE DATABASE database
  243. *
  244. * @param string Database name
  245. *
  246. * @return bool Whether it suceeded
  247. *
  248. * @access public
  249. */
  250. function PMA_exportDBCreate($db)
  251. {
  252. global $crlf;
  253. if (isset($GLOBALS['sql_drop_database'])) {
  254. if (!PMA_exportOutputHandler('DROP DATABASE ' . (isset($GLOBALS['sql_backquotes']) ? PMA_backquote($db) : $db) . ';' . $crlf)) {
  255. return FALSE;
  256. }
  257. }
  258. $create_query = 'CREATE DATABASE ' . (isset($GLOBALS['sql_backquotes']) ? PMA_backquote($db) : $db);
  259. $collation = PMA_getDbCollation($db);
  260. if (strpos($collation, '_')) {
  261. $create_query .= ' DEFAULT CHARACTER SET ' . substr($collation, 0, strpos($collation, '_')) . ' COLLATE ' . $collation;
  262. } else {
  263. $create_query .= ' DEFAULT CHARACTER SET ' . $collation;
  264. }
  265. $create_query .= ';' . $crlf;
  266. if (!PMA_exportOutputHandler($create_query)) {
  267. return FALSE;
  268. }
  269. if (isset($GLOBALS['sql_backquotes']) && isset($GLOBALS['sql_compatibility']) && $GLOBALS['sql_compatibility'] == 'NONE') {
  270. return PMA_exportOutputHandler('USE ' . PMA_backquote($db) . ';' . $crlf);
  271. }
  272. return PMA_exportOutputHandler('USE ' . $db . ';' . $crlf);
  273. }
  274. /**
  275. * Outputs database header
  276. *
  277. * @param string Database name
  278. *
  279. * @return bool Whether it suceeded
  280. *
  281. * @access public
  282. */
  283. function PMA_exportDBHeader($db)
  284. {
  285. $head = PMA_exportComment()
  286. . PMA_exportComment($GLOBALS['strDatabase'] . ': ' . (isset($GLOBALS['sql_backquotes']) ? PMA_backquote($db) : '\'' . $db . '\''))
  287. . PMA_exportComment();
  288. return PMA_exportOutputHandler($head);
  289. }
  290. /**
  291. * Outputs database footer
  292. *
  293. * @param string Database name
  294. *
  295. * @return bool Whether it suceeded
  296. *
  297. * @access public
  298. */
  299. function PMA_exportDBFooter($db)
  300. {
  301. global $crlf;
  302. $result = TRUE;
  303. if (isset($GLOBALS['sql_constraints'])) {
  304. $result = PMA_exportOutputHandler($GLOBALS['sql_constraints']);
  305. unset($GLOBALS['sql_constraints']);
  306. }
  307. if (isset($GLOBALS['sql_structure']) && isset($GLOBALS['sql_procedure_function'])) {
  308. $text = '';
  309. $delimiter = '$$';
  310. $procedure_names = PMA_DBI_get_procedures_or_functions($db, 'PROCEDURE');
  311. $function_names = PMA_DBI_get_procedures_or_functions($db, 'FUNCTION');
  312. if (PMA_MYSQL_INT_VERSION > 50100) {
  313. $event_names = PMA_DBI_fetch_result('SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \'' . PMA_sqlAddslashes($db,true) . '\';');
  314. } else {
  315. $event_names = array();
  316. }
  317. if ($procedure_names || $function_names || $event_names) {
  318. $text .= $crlf
  319. . 'DELIMITER ' . $delimiter . $crlf;
  320. }
  321. if ($procedure_names) {
  322. $text .=
  323. PMA_exportComment()
  324. . PMA_exportComment($GLOBALS['strProcedures'])
  325. . PMA_exportComment();
  326. foreach($procedure_names as $procedure_name) {
  327. if (! empty($GLOBALS['sql_drop_table'])) {
  328. $text .= 'DROP PROCEDURE IF EXISTS ' . PMA_backquote($procedure_name) . $delimiter . $crlf;
  329. }
  330. $text .= PMA_DBI_get_definition($db, 'PROCEDURE', $procedure_name) . $delimiter . $crlf . $crlf;
  331. }
  332. }
  333. if ($function_names) {
  334. $text .=
  335. PMA_exportComment()
  336. . PMA_exportComment($GLOBALS['strFunctions'])
  337. . PMA_exportComment();
  338. foreach($function_names as $function_name) {
  339. if (! empty($GLOBALS['sql_drop_table'])) {
  340. $text .= 'DROP FUNCTION IF EXISTS ' . PMA_backquote($function_name) . $delimiter . $crlf;
  341. }
  342. $text .= PMA_DBI_get_definition($db, 'FUNCTION', $function_name) . $delimiter . $crlf . $crlf;
  343. }
  344. }
  345. if ($event_names) {
  346. $text .=
  347. PMA_exportComment()
  348. . PMA_exportComment($GLOBALS['strEvents'])
  349. . PMA_exportComment();
  350. foreach($event_names as $event_name) {
  351. if (! empty($GLOBALS['sql_drop_table'])) {
  352. $text .= 'DROP EVENT ' . PMA_backquote($event_name) . $delimiter . $crlf;
  353. }
  354. $text .= PMA_DBI_get_definition($db, 'EVENT', $event_name) . $delimiter . $crlf . $crlf;
  355. }
  356. }
  357. if ($procedure_names || $function_names || $event_names) {
  358. $text .= 'DELIMITER ;' . $crlf;
  359. }
  360. if (! empty($text)) {
  361. $result = PMA_exportOutputHandler($text);
  362. }
  363. }
  364. return $result;
  365. }
  366. /**
  367. * Returns a stand-in CREATE definition to resolve view dependencies
  368. *
  369. * @param string the database name
  370. * @param string the vew name
  371. * @param string the end of line sequence
  372. *
  373. * @return string resulting definition
  374. *
  375. * @access public
  376. */
  377. function PMA_getTableDefStandIn($db, $view, $crlf) {
  378. $create_query = '';
  379. if (! empty($GLOBALS['sql_drop_table'])) {
  380. $create_query .= 'DROP VIEW IF EXISTS ' . PMA_backquote($view) . ';' . $crlf;
  381. }
  382. $create_query .= 'CREATE TABLE ';
  383. if (isset($GLOBALS['sql_if_not_exists']) && $GLOBALS['sql_if_not_exists']) {
  384. $create_query .= 'IF NOT EXISTS ';
  385. }
  386. $create_query .= PMA_backquote($view) . ' (' . $crlf;
  387. $tmp = array();
  388. $columns = PMA_DBI_get_columns_full($db, $view);
  389. foreach($columns as $column_name => $definition) {
  390. $tmp[] = PMA_backquote($column_name) . ' ' . $definition['Type'] . $crlf;
  391. }
  392. $create_query .= implode(',', $tmp) . ');';
  393. return($create_query);
  394. }
  395. /**
  396. * Returns $table's CREATE definition
  397. *
  398. * @param string the database name
  399. * @param string the table name
  400. * @param string the end of line sequence
  401. * @param string the url to go back in case of error
  402. * @param boolean whether to include creation/update/check dates
  403. * @param boolean whether to add semicolon and end-of-line at the end
  404. * @param boolean whether we're handling view
  405. *
  406. * @return string resulting schema
  407. *
  408. * @global boolean whether to add 'drop' statements or not
  409. * @global boolean whether to use backquotes to allow the use of special
  410. * characters in database, table and fields names or not
  411. *
  412. * @access public
  413. */
  414. function PMA_getTableDef($db, $table, $crlf, $error_url, $show_dates = false, $add_semicolon = true, $view = false)
  415. {
  416. global $sql_drop_table;
  417. global $sql_backquotes;
  418. global $cfgRelation;
  419. global $sql_constraints;
  420. global $sql_constraints_query; // just the text of the query
  421. $schema_create = '';
  422. $auto_increment = '';
  423. $new_crlf = $crlf;
  424. // need to use PMA_DBI_QUERY_STORE with PMA_DBI_num_rows() in mysqli
  425. $result = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table) . '\'', null, PMA_DBI_QUERY_STORE);
  426. if ($result != FALSE) {
  427. if (PMA_DBI_num_rows($result) > 0) {
  428. $tmpres = PMA_DBI_fetch_assoc($result);
  429. // Here we optionally add the AUTO_INCREMENT next value,
  430. // but starting with MySQL 5.0.24, the clause is already included
  431. // in SHOW CREATE TABLE so we'll remove it below
  432. if (isset($GLOBALS['sql_auto_increment']) && !empty($tmpres['Auto_increment'])) {
  433. $auto_increment .= ' AUTO_INCREMENT=' . $tmpres['Auto_increment'] . ' ';
  434. }
  435. if ($show_dates && isset($tmpres['Create_time']) && !empty($tmpres['Create_time'])) {
  436. $schema_create .= PMA_exportComment($GLOBALS['strStatCreateTime'] . ': ' . PMA_localisedDate(strtotime($tmpres['Create_time'])));
  437. $new_crlf = PMA_exportComment() . $crlf;
  438. }
  439. if ($show_dates && isset($tmpres['Update_time']) && !empty($tmpres['Update_time'])) {
  440. $schema_create .= PMA_exportComment($GLOBALS['strStatUpdateTime'] . ': ' . PMA_localisedDate(strtotime($tmpres['Update_time'])));
  441. $new_crlf = PMA_exportComment() . $crlf;
  442. }
  443. if ($show_dates && isset($tmpres['Check_time']) && !empty($tmpres['Check_time'])) {
  444. $schema_create .= PMA_exportComment($GLOBALS['strStatCheckTime'] . ': ' . PMA_localisedDate(strtotime($tmpres['Check_time'])));
  445. $new_crlf = PMA_exportComment() . $crlf;
  446. }
  447. }
  448. PMA_DBI_free_result($result);
  449. }
  450. $schema_create .= $new_crlf;
  451. // no need to generate a DROP VIEW here, it was done earlier
  452. if (! empty($sql_drop_table) && ! PMA_Table::isView($db,$table)) {
  453. $schema_create .= 'DROP TABLE IF EXISTS ' . PMA_backquote($table, $sql_backquotes) . ';' . $crlf;
  454. }
  455. // Steve Alberty's patch for complete table dump,
  456. // Whether to quote table and fields names or not
  457. if ($sql_backquotes) {
  458. PMA_DBI_query('SET SQL_QUOTE_SHOW_CREATE = 1');
  459. } else {
  460. PMA_DBI_query('SET SQL_QUOTE_SHOW_CREATE = 0');
  461. }
  462. // I don't see the reason why this unbuffered query could cause problems,
  463. // because SHOW CREATE TABLE returns only one row, and we free the
  464. // results below. Nonetheless, we got 2 user reports about this
  465. // (see bug 1562533) so I remove the unbuffered mode.
  466. //$result = PMA_DBI_query('SHOW CREATE TABLE ' . PMA_backquote($db) . '.' . PMA_backquote($table), null, PMA_DBI_QUERY_UNBUFFERED);
  467. //
  468. // Note: SHOW CREATE TABLE, at least in MySQL 5.1.23, does not
  469. // produce a displayable result for the default value of a BIT
  470. // field, nor does the mysqldump command. See MySQL bug 35796
  471. $result = PMA_DBI_try_query('SHOW CREATE TABLE ' . PMA_backquote($db) . '.' . PMA_backquote($table));
  472. // an error can happen, for example the table is crashed
  473. $tmp_error = PMA_DBI_getError();
  474. if ($tmp_error) {
  475. return PMA_exportComment($GLOBALS['strInUse'] . '(' . $tmp_error . ')');
  476. }
  477. if ($result != FALSE && ($row = PMA_DBI_fetch_row($result))) {
  478. $create_query = $row[1];
  479. unset($row);
  480. // Convert end of line chars to one that we want (note that MySQL doesn't return query it will accept in all cases)
  481. if (strpos($create_query, "(\r\n ")) {
  482. $create_query = str_replace("\r\n", $crlf, $create_query);
  483. } elseif (strpos($create_query, "(\n ")) {
  484. $create_query = str_replace("\n", $crlf, $create_query);
  485. } elseif (strpos($create_query, "(\r ")) {
  486. $create_query = str_replace("\r", $crlf, $create_query);
  487. }
  488. /*
  489. * Drop database name from VIEW creation.
  490. *
  491. * This is a bit tricky, but we need to issue SHOW CREATE TABLE with
  492. * database name, but we don't want name to show up in CREATE VIEW
  493. * statement.
  494. */
  495. if ($view) {
  496. $create_query = preg_replace('/' . PMA_backquote($db) . '\./', '', $create_query);
  497. }
  498. // Should we use IF NOT EXISTS?
  499. if (isset($GLOBALS['sql_if_not_exists'])) {
  500. $create_query = preg_replace('/^CREATE TABLE/', 'CREATE TABLE IF NOT EXISTS', $create_query);
  501. }
  502. // are there any constraints to cut out?
  503. if (preg_match('@CONSTRAINT|FOREIGN[\s]+KEY@', $create_query)) {
  504. // Split the query into lines, so we can easily handle it. We know lines are separated by $crlf (done few lines above).
  505. $sql_lines = explode($crlf, $create_query);
  506. $sql_count = count($sql_lines);
  507. // lets find first line with constraints
  508. for ($i = 0; $i < $sql_count; $i++) {
  509. if (preg_match('@^[\s]*(CONSTRAINT|FOREIGN[\s]+KEY)@', $sql_lines[$i])) {
  510. break;
  511. }
  512. }
  513. // If we really found a constraint
  514. if ($i != $sql_count) {
  515. // remove , from the end of create statement
  516. $sql_lines[$i - 1] = preg_replace('@,$@', '', $sql_lines[$i - 1]);
  517. // prepare variable for constraints
  518. if (!isset($sql_constraints)) {
  519. if (isset($GLOBALS['no_constraints_comments'])) {
  520. $sql_constraints = '';
  521. } else {
  522. $sql_constraints = $crlf
  523. . PMA_exportComment()
  524. . PMA_exportComment($GLOBALS['strConstraintsForDumped'])
  525. . PMA_exportComment();
  526. }
  527. }
  528. // comments for current table
  529. if (!isset($GLOBALS['no_constraints_comments'])) {
  530. $sql_constraints .= $crlf
  531. . PMA_exportComment()
  532. . PMA_exportComment($GLOBALS['strConstraintsForTable'] . ' ' . PMA_backquote($table))
  533. . PMA_exportComment();
  534. }
  535. // let's do the work
  536. $sql_constraints_query .= 'ALTER TABLE ' . PMA_backquote($table) . $crlf;
  537. $sql_constraints .= 'ALTER TABLE ' . PMA_backquote($table) . $crlf;
  538. $first = TRUE;
  539. for ($j = $i; $j < $sql_count; $j++) {
  540. if (preg_match('@CONSTRAINT|FOREIGN[\s]+KEY@', $sql_lines[$j])) {
  541. if (!$first) {
  542. $sql_constraints .= $crlf;
  543. }
  544. if (strpos($sql_lines[$j], 'CONSTRAINT') === FALSE) {
  545. $str_tmp = preg_replace('/(FOREIGN[\s]+KEY)/', 'ADD \1', $sql_lines[$j]);
  546. $sql_constraints_query .= $str_tmp;
  547. $sql_constraints .= $str_tmp;
  548. } else {
  549. $str_tmp = preg_replace('/(CONSTRAINT)/', 'ADD \1', $sql_lines[$j]);
  550. $sql_constraints_query .= $str_tmp;
  551. $sql_constraints .= $str_tmp;
  552. }
  553. $first = FALSE;
  554. } else {
  555. break;
  556. }
  557. }
  558. $sql_constraints .= ';' . $crlf;
  559. $sql_constraints_query .= ';';
  560. $create_query = implode($crlf, array_slice($sql_lines, 0, $i)) . $crlf . implode($crlf, array_slice($sql_lines, $j, $sql_count - 1));
  561. unset($sql_lines);
  562. }
  563. }
  564. $schema_create .= $create_query;
  565. }
  566. // remove a possible "AUTO_INCREMENT = value" clause
  567. // that could be there starting with MySQL 5.0.24
  568. $schema_create = preg_replace('/AUTO_INCREMENT\s*=\s*([0-9])+/', '', $schema_create);
  569. $schema_create .= $auto_increment;
  570. PMA_DBI_free_result($result);
  571. return $schema_create . ($add_semicolon ? ';' . $crlf : '');
  572. } // end of the 'PMA_getTableDef()' function
  573. /**
  574. * Returns $table's comments, relations etc.
  575. *
  576. * @param string the database name
  577. * @param string the table name
  578. * @param string the end of line sequence
  579. * @param boolean whether to include relation comments
  580. * @param boolean whether to include mime comments
  581. *
  582. * @return string resulting comments
  583. *
  584. * @access public
  585. */
  586. function PMA_getTableComments($db, $table, $crlf, $do_relation = false, $do_mime = false)
  587. {
  588. global $cfgRelation;
  589. global $sql_backquotes;
  590. global $sql_constraints;
  591. $schema_create = '';
  592. // Check if we can use Relations (Mike Beck)
  593. if ($do_relation && !empty($cfgRelation['relation'])) {
  594. // Find which tables are related with the current one and write it in
  595. // an array
  596. $res_rel = PMA_getForeigners($db, $table);
  597. if ($res_rel && count($res_rel) > 0) {
  598. $have_rel = TRUE;
  599. } else {
  600. $have_rel = FALSE;
  601. }
  602. } else {
  603. $have_rel = FALSE;
  604. } // end if
  605. if ($do_mime && $cfgRelation['mimework']) {
  606. if (!($mime_map = PMA_getMIME($db, $table, true))) {
  607. unset($mime_map);
  608. }
  609. }
  610. if (isset($mime_map) && count($mime_map) > 0) {
  611. $schema_create .= $crlf
  612. . PMA_exportComment()
  613. . PMA_exportComment($GLOBALS['strMIMETypesForTable']. ' ' . PMA_backquote($table, $sql_backquotes) . ':');
  614. @reset($mime_map);
  615. foreach ($mime_map AS $mime_field => $mime) {
  616. $schema_create .= PMA_exportComment(' ' . PMA_backquote($mime_field, $sql_backquotes))
  617. . PMA_exportComment(' ' . PMA_backquote($mime['mimetype'], $sql_backquotes));
  618. }
  619. $schema_create .= PMA_exportComment();
  620. }
  621. if ($have_rel) {
  622. $schema_create .= $crlf
  623. . PMA_exportComment()
  624. . PMA_exportComment($GLOBALS['strRelationsForTable']. ' ' . PMA_backquote($table, $sql_backquotes) . ':');
  625. foreach ($res_rel AS $rel_field => $rel) {
  626. $schema_create .= PMA_exportComment(' ' . PMA_backquote($rel_field, $sql_backquotes))
  627. . PMA_exportComment(' ' . PMA_backquote($rel['foreign_table'], $sql_backquotes)
  628. . ' -> ' . PMA_backquote($rel['foreign_field'], $sql_backquotes));
  629. }
  630. $schema_create .= PMA_exportComment();
  631. }
  632. return $schema_create;
  633. } // end of the 'PMA_getTableComments()' function
  634. /**
  635. * Outputs table's structure
  636. *
  637. * @param string the database name
  638. * @param string the table name
  639. * @param string the end of line sequence
  640. * @param string the url to go back in case of error
  641. * @param boolean whether to include relation comments
  642. * @param boolean whether to include the pmadb-style column comments
  643. * as comments in the structure; this is deprecated
  644. * but the parameter is left here because export.php
  645. * calls PMA_exportStructure() also for other export
  646. * types which use this parameter
  647. * @param boolean whether to include mime comments
  648. * @param string 'stand_in', 'create_table', 'create_view'
  649. * @param string 'server', 'database', 'table'
  650. *
  651. * @return bool Whether it suceeded
  652. *
  653. * @access public
  654. */
  655. function PMA_exportStructure($db, $table, $crlf, $error_url, $relation = FALSE, $comments = FALSE, $mime = FALSE, $dates = FALSE, $export_mode, $export_type)
  656. {
  657. $formatted_table_name = (isset($GLOBALS['sql_backquotes']))
  658. ? PMA_backquote($table)
  659. : '\'' . $table . '\'';
  660. $dump = $crlf
  661. . PMA_exportComment(str_repeat('-', 56))
  662. . $crlf
  663. . PMA_exportComment();
  664. switch($export_mode) {
  665. case 'create_table':
  666. $dump .= PMA_exportComment($GLOBALS['strTableStructure'] . ' ' . $formatted_table_name)
  667. . PMA_exportComment();
  668. $dump .= PMA_getTableDef($db, $table, $crlf, $error_url, $dates);
  669. $triggers = PMA_DBI_get_triggers($db, $table);
  670. if ($triggers) {
  671. $dump .= $crlf
  672. . PMA_exportComment()
  673. . PMA_exportComment($GLOBALS['strTriggers'] . ' ' . $formatted_table_name)
  674. . PMA_exportComment();
  675. $delimiter = '//';
  676. foreach ($triggers as $trigger) {
  677. $dump .= $trigger['drop'] . ';' . $crlf;
  678. $dump .= 'DELIMITER ' . $delimiter . $crlf;
  679. $dump .= $trigger['create'];
  680. $dump .= 'DELIMITER ;' . $crlf;
  681. }
  682. }
  683. break;
  684. case 'create_view':
  685. $dump .= PMA_exportComment($GLOBALS['strStructureForView'] . ' ' . $formatted_table_name)
  686. . PMA_exportComment();
  687. // delete the stand-in table previously created (if any)
  688. if ($export_type != 'table') {
  689. $dump .= 'DROP TABLE IF EXISTS ' . PMA_backquote($table) . ';' . $crlf;
  690. }
  691. $dump .= PMA_getTableDef($db, $table, $crlf, $error_url, $dates, true, true);
  692. break;
  693. case 'stand_in':
  694. $dump .= PMA_exportComment($GLOBALS['strStandInStructureForView'] . ' ' . $formatted_table_name)
  695. . PMA_exportComment();
  696. // export a stand-in definition to resolve view dependencies
  697. $dump .= PMA_getTableDefStandIn($db, $table, $crlf);
  698. } // end switch
  699. $dump .= PMA_getTableComments($db, $table, $crlf, $relation, $mime);
  700. // this one is built by PMA_getTableDef() to use in table copy/move
  701. // but not in the case of export
  702. unset($GLOBALS['sql_constraints_query']);
  703. return PMA_exportOutputHandler($dump);
  704. }
  705. /**
  706. * Dispatches between the versions of 'getTableContent' to use depending
  707. * on the php version
  708. *
  709. * @param string the database name
  710. * @param string the table name
  711. * @param string the end of line sequence
  712. * @param string the url to go back in case of error
  713. * @param string SQL query for obtaining data
  714. *
  715. * @return bool Whether it suceeded
  716. *
  717. * @global boolean whether to use backquotes to allow the use of special
  718. * characters in database, table and fields names or not
  719. * @global integer the number of records
  720. * @global integer the current record position
  721. *
  722. * @access public
  723. *
  724. * @see PMA_getTableContentFast(), PMA_getTableContentOld()
  725. *
  726. * @author staybyte
  727. */
  728. function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
  729. {
  730. global $sql_backquotes;
  731. global $rows_cnt;
  732. global $current_row;
  733. $formatted_table_name = (isset($GLOBALS['sql_backquotes']))
  734. ? PMA_backquote($table)
  735. : '\'' . $table . '\'';
  736. // Do not export data for a VIEW
  737. // (For a VIEW, this is called only when exporting a single VIEW)
  738. if (PMA_Table::isView($db, $table)) {
  739. $head = $crlf
  740. . PMA_exportComment()
  741. . PMA_exportComment('VIEW ' . ' ' . $formatted_table_name)
  742. . PMA_exportComment($GLOBALS['strData'] . ': ' . $GLOBALS['strNone'])
  743. . PMA_exportComment()
  744. . $crlf;
  745. if (! PMA_exportOutputHandler($head)) {
  746. return FALSE;
  747. }
  748. return true;
  749. }
  750. // it's not a VIEW
  751. $head = $crlf
  752. . PMA_exportComment()
  753. . PMA_exportComment($GLOBALS['strDumpingData'] . ' ' . $formatted_table_name)
  754. . PMA_exportComment()
  755. . $crlf;
  756. if (! PMA_exportOutputHandler($head)) {
  757. return FALSE;
  758. }
  759. $buffer = '';
  760. // analyze the query to get the true column names, not the aliases
  761. // (this fixes an undefined index, also if Complete inserts
  762. // are used, we did not get the true column name in case of aliases)
  763. $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($sql_query));
  764. $result = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
  765. // a possible error: the table has crashed
  766. $tmp_error = PMA_DBI_getError();
  767. if ($tmp_error) {
  768. return PMA_exportOutputHandler(PMA_exportComment($GLOBALS['strInUse'] . ' (' . $tmp_error . ')'));
  769. }
  770. if ($result != FALSE) {
  771. $fields_cnt = PMA_DBI_num_fields($result);
  772. // Get field information
  773. $fields_meta = PMA_DBI_get_fields_meta($result);
  774. $field_flags = array();
  775. for ($j = 0; $j < $fields_cnt; $j++) {
  776. $field_flags[$j] = PMA_DBI_field_flags($result, $j);
  777. }
  778. for ($j = 0; $j < $fields_cnt; $j++) {
  779. if (isset($analyzed_sql[0]['select_expr'][$j]['column'])) {
  780. $field_set[$j] = PMA_backquote($analyzed_sql[0]['select_expr'][$j]['column'], $sql_backquotes);
  781. } else {
  782. $field_set[$j] = PMA_backquote($fields_meta[$j]->name, $sql_backquotes);
  783. }
  784. }
  785. if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'UPDATE') {
  786. // update
  787. $schema_insert = 'UPDATE ';
  788. if (isset($GLOBALS['sql_ignore'])) {
  789. $schema_insert .= 'IGNORE ';
  790. }
  791. // avoid EOL blank
  792. $schema_insert .= PMA_backquote($table, $sql_backquotes) . ' SET';
  793. } else {
  794. // insert or replace
  795. if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'REPLACE') {
  796. $sql_command = 'REPLACE';
  797. } else {
  798. $sql_command = 'INSERT';
  799. }
  800. // delayed inserts?
  801. if (isset($GLOBALS['sql_delayed'])) {
  802. $insert_delayed = ' DELAYED';
  803. } else {
  804. $insert_delayed = '';
  805. }
  806. // insert ignore?
  807. if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'INSERT' && isset($GLOBALS['sql_ignore'])) {
  808. $insert_delayed .= ' IGNORE';
  809. }
  810. // scheme for inserting fields
  811. if (isset($GLOBALS['sql_columns'])) {
  812. $fields = implode(', ', $field_set);
  813. $schema_insert = $sql_command . $insert_delayed .' INTO ' . PMA_backquote($table, $sql_backquotes)
  814. // avoid EOL blank
  815. . ' (' . $fields . ') VALUES';
  816. } else {
  817. $schema_insert = $sql_command . $insert_delayed .' INTO ' . PMA_backquote($table, $sql_backquotes)
  818. . ' VALUES';
  819. }
  820. }
  821. $search = array("\x00", "\x0a", "\x0d", "\x1a"); //\x08\\x09, not required
  822. $replace = array('\0', '\n', '\r', '\Z');
  823. $current_row = 0;
  824. $query_size = 0;
  825. if (isset($GLOBALS['sql_extended']) && (!isset($GLOBALS['sql_type']) || $GLOBALS['sql_type'] != 'UPDATE')) {
  826. $separator = ',';
  827. $schema_insert .= $crlf;
  828. } else {
  829. $separator = ';';
  830. }
  831. while ($row = PMA_DBI_fetch_row($result)) {
  832. $current_row++;
  833. for ($j = 0; $j < $fields_cnt; $j++) {
  834. // NULL
  835. if (!isset($row[$j]) || is_null($row[$j])) {
  836. $values[] = 'NULL';
  837. // a number
  838. // timestamp is numeric on some MySQL 4.1, BLOBs are sometimes numeric
  839. } elseif ($fields_meta[$j]->numeric && $fields_meta[$j]->type != 'timestamp'
  840. && ! $fields_meta[$j]->blob) {
  841. $values[] = $row[$j];
  842. // a true BLOB
  843. // - mysqldump only generates hex data when the --hex-blob
  844. // option is used, for fields having the binary attribute
  845. // no hex is generated
  846. // - a TEXT field returns type blob but a real blob
  847. // returns also the 'binary' flag
  848. } elseif (stristr($field_flags[$j], 'BINARY')
  849. && $fields_meta[$j]->blob
  850. && isset($GLOBALS['sql_hex_for_blob'])) {
  851. // empty blobs need to be different, but '0' is also empty :-(
  852. if (empty($row[$j]) && $row[$j] != '0') {
  853. $values[] = '\'\'';
  854. } else {
  855. $values[] = '0x' . bin2hex($row[$j]);
  856. }
  857. // detection of 'bit' works only on mysqli extension
  858. } elseif ($fields_meta[$j]->type == 'bit') {
  859. $values[] = "b'" . PMA_sqlAddslashes(PMA_printable_bit_value($row[$j], $fields_meta[$j]->length)) . "'";
  860. // something else -> treat as a string
  861. } else {
  862. $values[] = '\'' . str_replace($search, $replace, PMA_sqlAddslashes($row[$j])) . '\'';
  863. } // end if
  864. } // end for
  865. // should we make update?
  866. if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'UPDATE') {
  867. $insert_line = $schema_insert;
  868. for ($i = 0; $i < $fields_cnt; $i++) {
  869. if (0 == $i) {
  870. $insert_line .= ' ';
  871. }
  872. if ($i > 0) {
  873. // avoid EOL blank
  874. $insert_line .= ',';
  875. }
  876. $insert_line .= $field_set[$i] . ' = ' . $values[$i];
  877. }
  878. $insert_line .= ' WHERE ' . PMA_getUniqueCondition($result, $fields_cnt, $fields_meta, $row);
  879. } else {
  880. // Extended inserts case
  881. if (isset($GLOBALS['sql_extended'])) {
  882. if ($current_row == 1) {
  883. $insert_line = $schema_insert . '(' . implode(', ', $values) . ')';
  884. } else {
  885. $insert_line = '(' . implode(', ', $values) . ')';
  886. if (isset($GLOBALS['sql_max_query_size']) && $GLOBALS['sql_max_query_size'] > 0 && $query_size + strlen($insert_line) > $GLOBALS['sql_max_query_size']) {
  887. if (!PMA_exportOutputHandler(';' . $crlf)) {
  888. return FALSE;
  889. }
  890. $query_size = 0;
  891. $current_row = 1;
  892. $insert_line = $schema_insert . $insert_line;
  893. }
  894. }
  895. $query_size += strlen($insert_line);
  896. }
  897. // Other inserts case
  898. else {
  899. $insert_line = $schema_insert . '(' . implode(', ', $values) . ')';
  900. }
  901. }
  902. unset($values);
  903. if (!PMA_exportOutputHandler(($current_row == 1 ? '' : $separator . $crlf) . $insert_line)) {
  904. return FALSE;
  905. }
  906. } // end while
  907. if ($current_row > 0) {
  908. if (!PMA_exportOutputHandler(';' . $crlf)) {
  909. return FALSE;
  910. }
  911. }
  912. } // end if ($result != FALSE)
  913. PMA_DBI_free_result($result);
  914. return TRUE;
  915. } // end of the 'PMA_exportData()' function
  916. }
  917. ?>