ExportSql.class.php 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897
  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
  7. * @subpackage SQL
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. /* Get the export interface */
  13. require_once 'libraries/plugins/ExportPlugin.class.php';
  14. /**
  15. * Handles the export for the SQL class
  16. *
  17. * @package PhpMyAdmin-Export
  18. * @subpackage SQL
  19. */
  20. class ExportSql extends ExportPlugin
  21. {
  22. /**
  23. * Constructor
  24. */
  25. public function __construct()
  26. {
  27. $this->setProperties();
  28. // Avoids undefined variables, use NULL so isset() returns false
  29. if (! isset($GLOBALS['sql_backquotes'])) {
  30. $GLOBALS['sql_backquotes'] = null;
  31. }
  32. }
  33. /**
  34. * Sets the export SQL properties
  35. *
  36. * @return void
  37. */
  38. protected function setProperties()
  39. {
  40. global $plugin_param;
  41. $hide_sql = false;
  42. $hide_structure = false;
  43. if ($plugin_param['export_type'] == 'table'
  44. && ! $plugin_param['single_table']
  45. ) {
  46. $hide_structure = true;
  47. $hide_sql = true;
  48. }
  49. if (! $hide_sql) {
  50. $props = 'libraries/properties/';
  51. include_once "$props/plugins/ExportPluginProperties.class.php";
  52. include_once "$props/options/groups/OptionsPropertyRootGroup.class.php";
  53. include_once "$props/options/groups/OptionsPropertyMainGroup.class.php";
  54. include_once "$props/options/groups/OptionsPropertySubgroup.class.php";
  55. include_once "$props/options/items/BoolPropertyItem.class.php";
  56. include_once "$props/options/items/MessageOnlyPropertyItem.class.php";
  57. include_once "$props/options/items/RadioPropertyItem.class.php";
  58. include_once "$props/options/items/SelectPropertyItem.class.php";
  59. include_once "$props/options/items/TextPropertyItem.class.php";
  60. $exportPluginProperties = new ExportPluginProperties();
  61. $exportPluginProperties->setText('SQL');
  62. $exportPluginProperties->setExtension('sql');
  63. $exportPluginProperties->setMimeType('text/x-sql');
  64. $exportPluginProperties->setOptionsText(__('Options'));
  65. // create the root group that will be the options field for
  66. // $exportPluginProperties
  67. // this will be shown as "Format specific options"
  68. $exportSpecificOptions = new OptionsPropertyRootGroup();
  69. $exportSpecificOptions->setName("Format Specific Options");
  70. // general options main group
  71. $generalOptions = new OptionsPropertyMainGroup();
  72. $generalOptions->setName("general_opts");
  73. // comments
  74. $subgroup = new OptionsPropertySubgroup();
  75. $subgroup->setName("include_comments");
  76. $leaf = new BoolPropertyItem();
  77. $leaf->setName('include_comments');
  78. $leaf->setText(
  79. __(
  80. 'Display comments <i>(includes info such as export'
  81. . ' timestamp, PHP version, and server version)</i>'
  82. )
  83. );
  84. $subgroup->setSubgroupHeader($leaf);
  85. $leaf = new TextPropertyItem();
  86. $leaf->setName('header_comment');
  87. $leaf->setText(
  88. __('Additional custom header comment (\n splits lines):')
  89. );
  90. $subgroup->addProperty($leaf);
  91. $leaf = new BoolPropertyItem();
  92. $leaf->setName('dates');
  93. $leaf->setText(
  94. __(
  95. 'Include a timestamp of when databases were created, last'
  96. . ' updated, and last checked'
  97. )
  98. );
  99. $subgroup->addProperty($leaf);
  100. if (! empty($GLOBALS['cfgRelation']['relation'])) {
  101. $leaf = new BoolPropertyItem();
  102. $leaf->setName('relation');
  103. $leaf->setText(__('Display foreign key relationships'));
  104. $subgroup->addProperty($leaf);
  105. }
  106. if (! empty($GLOBALS['cfgRelation']['mimework'])) {
  107. $leaf = new BoolPropertyItem();
  108. $leaf->setName('mime');
  109. $leaf->setText(__('Display MIME types'));
  110. $subgroup->addProperty($leaf);
  111. }
  112. $generalOptions->addProperty($subgroup);
  113. // enclose in a transaction
  114. $leaf = new BoolPropertyItem();
  115. $leaf->setName("use_transaction");
  116. $leaf->setText(__('Enclose export in a transaction'));
  117. $leaf->setDoc(
  118. array(
  119. 'programs',
  120. 'mysqldump',
  121. 'option_mysqldump_single-transaction'
  122. )
  123. );
  124. $generalOptions->addProperty($leaf);
  125. // disable foreign key checks
  126. $leaf = new BoolPropertyItem();
  127. $leaf->setName("disable_fk");
  128. $leaf->setText(__('Disable foreign key checks'));
  129. $leaf->setDoc(
  130. array(
  131. 'manual_MySQL_Database_Administration',
  132. 'server-system-variables',
  133. 'sysvar_foreign_key_checks'
  134. )
  135. );
  136. $generalOptions->addProperty($leaf);
  137. // compatibility maximization
  138. $compats = PMA_DBI_getCompatibilities();
  139. if (count($compats) > 0) {
  140. $values = array();
  141. foreach ($compats as $val) {
  142. $values[$val] = $val;
  143. }
  144. $leaf = new SelectPropertyItem();
  145. $leaf->setName("compatibility");
  146. $leaf->setText(
  147. __(
  148. 'Database system or older MySQL server to maximize output'
  149. . ' compatibility with:'
  150. )
  151. );
  152. $leaf->setValues($values);
  153. $leaf->setDoc(
  154. array(
  155. 'manual_MySQL_Database_Administration',
  156. 'Server_SQL_mode'
  157. )
  158. );
  159. $generalOptions->addProperty($leaf);
  160. unset($values);
  161. }
  162. // server export options
  163. if ($plugin_param['export_type'] == 'server') {
  164. $leaf = new BoolPropertyItem();
  165. $leaf->setName("drop_database");
  166. $leaf->setText(
  167. sprintf(__('Add %s statement'), '<code>DROP DATABASE</code>')
  168. );
  169. $generalOptions->addProperty($leaf);
  170. }
  171. // what to dump (structure/data/both)
  172. $subgroup = new OptionsPropertySubgroup();
  173. $subgroup->setName("dump_table");
  174. $subgroup->setText("Dump table");
  175. $leaf = new RadioPropertyItem();
  176. $leaf->setName('structure_or_data');
  177. $leaf->setValues(
  178. array(
  179. 'structure' => __('structure'),
  180. 'data' => __('data'),
  181. 'structure_and_data' => __('structure and data')
  182. )
  183. );
  184. $subgroup->setSubgroupHeader($leaf);
  185. $generalOptions->addProperty($subgroup);
  186. // add the main group to the root group
  187. $exportSpecificOptions->addProperty($generalOptions);
  188. // structure options main group
  189. if (! $hide_structure) {
  190. $structureOptions = new OptionsPropertyMainGroup();
  191. $structureOptions->setName("structure");
  192. $structureOptions->setText(__('Object creation options'));
  193. $structureOptions->setForce('data');
  194. // begin SQL Statements
  195. $subgroup = new OptionsPropertySubgroup();
  196. $leaf = new MessageOnlyPropertyItem();
  197. $leaf->setName('add_statements');
  198. $leaf->setText(__('Add statements:'));
  199. $subgroup->setSubgroupHeader($leaf);
  200. if ($plugin_param['export_type'] != 'table') {
  201. $leaf = new BoolPropertyItem();
  202. $leaf->setName('create_database');
  203. $create_clause = '<code>CREATE DATABASE / USE</code>';
  204. $leaf->setText(sprintf(__('Add %s statement'), $create_clause));
  205. $subgroup->addProperty($leaf);
  206. }
  207. if ($plugin_param['export_type'] == 'table') {
  208. if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) {
  209. $drop_clause = '<code>DROP VIEW</code>';
  210. } else {
  211. $drop_clause = '<code>DROP TABLE</code>';
  212. }
  213. } else {
  214. if (PMA_DRIZZLE) {
  215. $drop_clause = '<code>DROP TABLE</code>';
  216. } else {
  217. $drop_clause = '<code>DROP TABLE / VIEW / PROCEDURE'
  218. . ' / FUNCTION</code>';
  219. if (PMA_MYSQL_INT_VERSION > 50100) {
  220. $drop_clause .= '<code> / EVENT</code>';
  221. }
  222. }
  223. }
  224. $leaf = new BoolPropertyItem();
  225. $leaf->setName('drop_table');
  226. $leaf->setText(sprintf(__('Add %s statement'), $drop_clause));
  227. $subgroup->addProperty($leaf);
  228. // Drizzle doesn't support procedures and functions
  229. if (! PMA_DRIZZLE) {
  230. $leaf = new BoolPropertyItem();
  231. $leaf->setName('procedure_function');
  232. $leaf->setText(
  233. sprintf(
  234. __('Add %s statement'),
  235. '<code>CREATE PROCEDURE / FUNCTION'
  236. . (PMA_MYSQL_INT_VERSION > 50100
  237. ? ' / EVENT</code>' : '</code>')
  238. )
  239. );
  240. $subgroup->addProperty($leaf);
  241. }
  242. // begin CREATE TABLE statements
  243. $subgroup_create_table = new OptionsPropertySubgroup();
  244. $leaf = new BoolPropertyItem();
  245. $leaf->setName('create_table_statements');
  246. $leaf->setText(__('<code>CREATE TABLE</code> options:'));
  247. $subgroup_create_table->setSubgroupHeader($leaf);
  248. $leaf = new BoolPropertyItem();
  249. $leaf->setName('if_not_exists');
  250. $leaf->setText('<code>IF NOT EXISTS</code>');
  251. $subgroup_create_table->addProperty($leaf);
  252. $leaf = new BoolPropertyItem();
  253. $leaf->setName('auto_increment');
  254. $leaf->setText('<code>AUTO_INCREMENT</code>');
  255. $subgroup_create_table->addProperty($leaf);
  256. $subgroup->addProperty($subgroup_create_table);
  257. $structureOptions->addProperty($subgroup);
  258. $leaf = new BoolPropertyItem();
  259. $leaf->setName("backquotes");
  260. $leaf->setText(
  261. __(
  262. 'Enclose table and column names with backquotes '
  263. . '<i>(Protects column and table names formed with'
  264. . ' special characters or keywords)</i>'
  265. )
  266. );
  267. $structureOptions->addProperty($leaf);
  268. // add the main group to the root group
  269. $exportSpecificOptions->addProperty($structureOptions);
  270. }
  271. // begin Data options
  272. $dataOptions = new OptionsPropertyMainGroup();
  273. $dataOptions->setName("data");
  274. $dataOptions->setText(__('Data creation options'));
  275. $dataOptions->setForce('structure');
  276. $leaf = new BoolPropertyItem();
  277. $leaf->setName("truncate");
  278. $leaf->setText(__('Truncate table before insert'));
  279. $dataOptions->addProperty($leaf);
  280. // begin SQL Statements
  281. $subgroup = new OptionsPropertySubgroup();
  282. $leaf = new MessageOnlyPropertyItem();
  283. $leaf->setText(__('Instead of <code>INSERT</code> statements, use:'));
  284. $subgroup->setSubgroupHeader($leaf);
  285. // Not supported in Drizzle
  286. if (! PMA_DRIZZLE) {
  287. $leaf = new BoolPropertyItem();
  288. $leaf->setName("delayed");
  289. $leaf->setText(__('<code>INSERT DELAYED</code> statements'));
  290. $leaf->setDoc(
  291. array(
  292. 'manual_MySQL_Database_Administration',
  293. 'insert_delayed'
  294. )
  295. );
  296. $subgroup->addProperty($leaf);
  297. }
  298. $leaf = new BoolPropertyItem();
  299. $leaf->setName("ignore");
  300. $leaf->setText(__('<code>INSERT IGNORE</code> statements'));
  301. $leaf->setDoc(
  302. array(
  303. 'manual_MySQL_Database_Administration',
  304. 'insert'
  305. )
  306. );
  307. $subgroup->addProperty($leaf);
  308. $dataOptions->addProperty($subgroup);
  309. // Function to use when dumping dat
  310. $leaf = new SelectPropertyItem();
  311. $leaf->setName("type");
  312. $leaf->setText(__('Function to use when dumping data:'));
  313. $leaf->setValues(
  314. array(
  315. 'INSERT' => 'INSERT',
  316. 'UPDATE' => 'UPDATE',
  317. 'REPLACE' => 'REPLACE'
  318. )
  319. );
  320. $dataOptions->addProperty($leaf);
  321. /* Syntax to use when inserting data */
  322. $subgroup = new OptionsPropertySubgroup();
  323. $leaf = new MessageOnlyPropertyItem();
  324. $leaf->setText(__('Syntax to use when inserting data:'));
  325. $subgroup->setSubgroupHeader($leaf);
  326. $leaf = new RadioPropertyItem();
  327. $leaf->setName("insert_syntax");
  328. $leaf->setText(__('<code>INSERT IGNORE</code> statements'));
  329. $leaf->setValues(
  330. array(
  331. 'complete' => __(
  332. 'include column names in every <code>INSERT</code> statement'
  333. . ' <br /> &nbsp; &nbsp; &nbsp; Example: <code>INSERT INTO'
  334. . ' tbl_name (col_A,col_B,col_C) VALUES (1,2,3)</code>'
  335. ),
  336. 'extended' => __(
  337. 'insert multiple rows in every <code>INSERT</code> statement'
  338. . '<br /> &nbsp; &nbsp; &nbsp; Example: <code>INSERT INTO'
  339. . ' tbl_name VALUES (1,2,3), (4,5,6), (7,8,9)</code>'
  340. ),
  341. 'both' => __(
  342. 'both of the above<br /> &nbsp; &nbsp; &nbsp; Example:'
  343. . ' <code>INSERT INTO tbl_name (col_A,col_B) VALUES (1,2,3),'
  344. . ' (4,5,6), (7,8,9)</code>'
  345. ),
  346. 'none' => __(
  347. 'neither of the above<br /> &nbsp; &nbsp; &nbsp; Example:'
  348. . ' <code>INSERT INTO tbl_name VALUES (1,2,3)</code>'
  349. )
  350. )
  351. );
  352. $subgroup->addProperty($leaf);
  353. $dataOptions->addProperty($subgroup);
  354. // Max length of query
  355. $leaf = new TextPropertyItem();
  356. $leaf->setName("max_query_size");
  357. $leaf->setText(__('Maximal length of created query'));
  358. $dataOptions->addProperty($leaf);
  359. // Dump binary columns in hexadecimal
  360. $leaf = new BoolPropertyItem();
  361. $leaf->setName("hex_for_blob");
  362. $leaf->setText(
  363. __(
  364. 'Dump binary columns in hexadecimal notation'
  365. . ' <i>(for example, "abc" becomes 0x616263)</i>'
  366. )
  367. );
  368. $dataOptions->addProperty($leaf);
  369. // Drizzle works only with UTC timezone
  370. if (! PMA_DRIZZLE) {
  371. // Dump time in UTC
  372. $leaf = new BoolPropertyItem();
  373. $leaf->setName("utc_time");
  374. $leaf->setText(
  375. __(
  376. 'Dump TIMESTAMP columns in UTC <i>(enables TIMESTAMP columns'
  377. . ' to be dumped and reloaded between servers in different'
  378. . ' time zones)</i>'
  379. )
  380. );
  381. $dataOptions->addProperty($leaf);
  382. }
  383. // add the main group to the root group
  384. $exportSpecificOptions->addProperty($dataOptions);
  385. // set the options for the export plugin property item
  386. $exportPluginProperties->setOptions($exportSpecificOptions);
  387. $this->properties = $exportPluginProperties;
  388. }
  389. }
  390. /**
  391. * This method is called when any PluginManager to which the observer
  392. * is attached calls PluginManager::notify()
  393. *
  394. * @param SplSubject $subject The PluginManager notifying the observer
  395. * of an update.
  396. *
  397. * @return void
  398. */
  399. public function update (SplSubject $subject)
  400. {
  401. }
  402. /**
  403. * Exports routines (procedures and functions)
  404. *
  405. * @param string $db Database
  406. *
  407. * @return bool Whether it succeeded
  408. */
  409. public function exportRoutines($db)
  410. {
  411. global $crlf;
  412. $text = '';
  413. $delimiter = '$$';
  414. $procedure_names = PMA_DBI_get_procedures_or_functions($db, 'PROCEDURE');
  415. $function_names = PMA_DBI_get_procedures_or_functions($db, 'FUNCTION');
  416. if ($procedure_names || $function_names) {
  417. $text .= $crlf
  418. . 'DELIMITER ' . $delimiter . $crlf;
  419. }
  420. if ($procedure_names) {
  421. $text .=
  422. $this->_exportComment()
  423. . $this->_exportComment(__('Procedures'))
  424. . $this->_exportComment();
  425. foreach ($procedure_names as $procedure_name) {
  426. if (! empty($GLOBALS['sql_drop_table'])) {
  427. $text .= 'DROP PROCEDURE IF EXISTS '
  428. . PMA_Util::backquote($procedure_name)
  429. . $delimiter . $crlf;
  430. }
  431. $text .= PMA_DBI_get_definition($db, 'PROCEDURE', $procedure_name)
  432. . $delimiter . $crlf . $crlf;
  433. }
  434. }
  435. if ($function_names) {
  436. $text .=
  437. $this->_exportComment()
  438. . $this->_exportComment(__('Functions'))
  439. . $this->_exportComment();
  440. foreach ($function_names as $function_name) {
  441. if (! empty($GLOBALS['sql_drop_table'])) {
  442. $text .= 'DROP FUNCTION IF EXISTS '
  443. . PMA_Util::backquote($function_name)
  444. . $delimiter . $crlf;
  445. }
  446. $text .= PMA_DBI_get_definition($db, 'FUNCTION', $function_name)
  447. . $delimiter . $crlf . $crlf;
  448. }
  449. }
  450. if ($procedure_names || $function_names) {
  451. $text .= 'DELIMITER ;' . $crlf;
  452. }
  453. if (! empty($text)) {
  454. return PMA_exportOutputHandler($text);
  455. } else {
  456. return false;
  457. }
  458. }
  459. /**
  460. * Possibly outputs comment
  461. *
  462. * @param string $text Text of comment
  463. *
  464. * @return string The formatted comment
  465. */
  466. private function _exportComment($text = '')
  467. {
  468. if (isset($GLOBALS['sql_include_comments'])
  469. && $GLOBALS['sql_include_comments']
  470. ) {
  471. // see http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-comments.html
  472. if (empty($text)) {
  473. return '--' . $GLOBALS['crlf'];
  474. } else {
  475. $lines = preg_split("/\\r\\n|\\r|\\n/", $text);
  476. $result = array();
  477. foreach ($lines as $line) {
  478. $result[] = '-- ' . $line . $GLOBALS['crlf'];
  479. }
  480. return implode('', $result);
  481. }
  482. } else {
  483. return '';
  484. }
  485. }
  486. /**
  487. * Possibly outputs CRLF
  488. *
  489. * @return string $crlf or nothing
  490. */
  491. private function _possibleCRLF()
  492. {
  493. if (isset($GLOBALS['sql_include_comments'])
  494. && $GLOBALS['sql_include_comments']
  495. ) {
  496. return $GLOBALS['crlf'];
  497. } else {
  498. return '';
  499. }
  500. }
  501. /**
  502. * Outputs export footer
  503. *
  504. * @return bool Whether it succeeded
  505. */
  506. public function exportFooter()
  507. {
  508. global $crlf, $mysql_charset_map;
  509. $foot = '';
  510. if (isset($GLOBALS['sql_disable_fk'])) {
  511. $foot .= 'SET FOREIGN_KEY_CHECKS=1;' . $crlf;
  512. }
  513. if (isset($GLOBALS['sql_use_transaction'])) {
  514. $foot .= 'COMMIT;' . $crlf;
  515. }
  516. // restore connection settings
  517. $charset_of_file = isset($GLOBALS['charset_of_file'])
  518. ? $GLOBALS['charset_of_file'] : '';
  519. if (! empty($GLOBALS['asfile'])
  520. && isset($mysql_charset_map[$charset_of_file])
  521. && ! PMA_DRIZZLE
  522. ) {
  523. $foot .= $crlf
  524. . '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;'
  525. . $crlf
  526. . '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;'
  527. . $crlf
  528. . '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;'
  529. . $crlf;
  530. }
  531. /* Restore timezone */
  532. if (isset($GLOBALS['sql_utc_time']) && $GLOBALS['sql_utc_time']) {
  533. PMA_DBI_query('SET time_zone = "' . $GLOBALS['old_tz'] . '"');
  534. }
  535. return PMA_exportOutputHandler($foot);
  536. }
  537. /**
  538. * Outputs export header. It is the first method to be called, so all
  539. * the required variables are initialized here.
  540. *
  541. * @return bool Whether it succeeded
  542. */
  543. public function exportHeader()
  544. {
  545. global $crlf, $cfg;
  546. global $mysql_charset_map;
  547. if (isset($GLOBALS['sql_compatibility'])) {
  548. $tmp_compat = $GLOBALS['sql_compatibility'];
  549. if ($tmp_compat == 'NONE') {
  550. $tmp_compat = '';
  551. }
  552. PMA_DBI_try_query('SET SQL_MODE="' . $tmp_compat . '"');
  553. unset($tmp_compat);
  554. }
  555. $head = $this->_exportComment('phpMyAdmin SQL Dump')
  556. . $this->_exportComment('version ' . PMA_VERSION)
  557. . $this->_exportComment('https://www.phpmyadmin.net')
  558. . $this->_exportComment();
  559. $host_string = __('Host') . ': ' . $cfg['Server']['host'];
  560. if (! empty($cfg['Server']['port'])) {
  561. $host_string .= ':' . $cfg['Server']['port'];
  562. }
  563. $head .= $this->_exportComment($host_string);
  564. $head .=
  565. $this->_exportComment(
  566. __('Generation Time') . ': '
  567. . PMA_Util::localisedDate()
  568. )
  569. . $this->_exportComment(
  570. __('Server version') . ': ' . PMA_MYSQL_STR_VERSION
  571. )
  572. . $this->_exportComment(__('PHP Version') . ': ' . phpversion())
  573. . $this->_possibleCRLF();
  574. if (isset($GLOBALS['sql_header_comment'])
  575. && ! empty($GLOBALS['sql_header_comment'])
  576. ) {
  577. // '\n' is not a newline (like "\n" would be), it's the characters
  578. // backslash and n, as explained on the export interface
  579. $lines = explode('\n', $GLOBALS['sql_header_comment']);
  580. $head .= $this->_exportComment();
  581. foreach ($lines as $one_line) {
  582. $head .= $this->_exportComment($one_line);
  583. }
  584. $head .= $this->_exportComment();
  585. }
  586. if (isset($GLOBALS['sql_disable_fk'])) {
  587. $head .= 'SET FOREIGN_KEY_CHECKS=0;' . $crlf;
  588. }
  589. // We want exported AUTO_INCREMENT columns to have still same value,
  590. // do this only for recent MySQL exports
  591. if ((! isset($GLOBALS['sql_compatibility'])
  592. || $GLOBALS['sql_compatibility'] == 'NONE')
  593. && ! PMA_DRIZZLE
  594. ) {
  595. $head .= 'SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";' . $crlf;
  596. }
  597. if (isset($GLOBALS['sql_use_transaction'])) {
  598. $head .= 'SET AUTOCOMMIT = 0;' . $crlf
  599. . 'START TRANSACTION;' . $crlf;
  600. }
  601. /* Change timezone if we should export timestamps in UTC */
  602. if (isset($GLOBALS['sql_utc_time']) && $GLOBALS['sql_utc_time']) {
  603. $head .= 'SET time_zone = "+00:00";' . $crlf;
  604. $GLOBALS['old_tz'] = PMA_DBI_fetch_value('SELECT @@session.time_zone');
  605. PMA_DBI_query('SET time_zone = "+00:00"');
  606. }
  607. $head .= $this->_possibleCRLF();
  608. if (! empty($GLOBALS['asfile']) && ! PMA_DRIZZLE) {
  609. // we are saving as file, therefore we provide charset information
  610. // so that a utility like the mysql client can interpret
  611. // the file correctly
  612. if (isset($GLOBALS['charset_of_file'])
  613. && isset($mysql_charset_map[$GLOBALS['charset_of_file']])
  614. ) {
  615. // we got a charset from the export dialog
  616. $set_names = $mysql_charset_map[$GLOBALS['charset_of_file']];
  617. } else {
  618. // by default we use the connection charset
  619. $set_names = $mysql_charset_map['utf-8'];
  620. }
  621. $head .= $crlf
  622. . '/*!40101 SET @OLD_CHARACTER_SET_CLIENT='
  623. . '@@CHARACTER_SET_CLIENT */;' . $crlf
  624. . '/*!40101 SET @OLD_CHARACTER_SET_RESULTS='
  625. . '@@CHARACTER_SET_RESULTS */;' . $crlf
  626. . '/*!40101 SET @OLD_COLLATION_CONNECTION='
  627. . '@@COLLATION_CONNECTION */;'. $crlf
  628. . '/*!40101 SET NAMES ' . $set_names . ' */;' . $crlf . $crlf;
  629. }
  630. return PMA_exportOutputHandler($head);
  631. }
  632. /**
  633. * Outputs CREATE DATABASE statement
  634. *
  635. * @param string $db Database name
  636. *
  637. * @return bool Whether it succeeded
  638. */
  639. public function exportDBCreate($db)
  640. {
  641. global $crlf;
  642. if (isset($GLOBALS['sql_compatibility'])) {
  643. $compat = $GLOBALS['sql_compatibility'];
  644. } else {
  645. $compat = 'NONE';
  646. }
  647. if (isset($GLOBALS['sql_drop_database'])) {
  648. if (! PMA_exportOutputHandler(
  649. 'DROP DATABASE '
  650. . (isset($GLOBALS['sql_backquotes'])
  651. ? PMA_Util::backquoteCompat($db, $compat) : $db)
  652. . ';' . $crlf
  653. )) {
  654. return false;
  655. }
  656. }
  657. if (isset($GLOBALS['sql_create_database'])) {
  658. $create_query = 'CREATE DATABASE IF NOT EXISTS '
  659. . (isset($GLOBALS['sql_backquotes'])
  660. ? PMA_Util::backquoteCompat($db, $compat) : $db);
  661. $collation = PMA_getDbCollation($db);
  662. if (PMA_DRIZZLE) {
  663. $create_query .= ' COLLATE ' . $collation;
  664. } else {
  665. if (strpos($collation, '_')) {
  666. $create_query .= ' DEFAULT CHARACTER SET '
  667. . substr($collation, 0, strpos($collation, '_'))
  668. . ' COLLATE ' . $collation;
  669. } else {
  670. $create_query .= ' DEFAULT CHARACTER SET ' . $collation;
  671. }
  672. }
  673. $create_query .= ';' . $crlf;
  674. if (! PMA_exportOutputHandler($create_query)) {
  675. return false;
  676. }
  677. if (isset($GLOBALS['sql_backquotes'])
  678. && ((isset($GLOBALS['sql_compatibility'])
  679. && $GLOBALS['sql_compatibility'] == 'NONE')
  680. || PMA_DRIZZLE)
  681. ) {
  682. $result = PMA_exportOutputHandler(
  683. 'USE ' . PMA_Util::backquoteCompat($db, $compat)
  684. . ';' . $crlf
  685. );
  686. } else {
  687. $result = PMA_exportOutputHandler('USE ' . $db . ';' . $crlf);
  688. }
  689. return $result;
  690. } else {
  691. return true;
  692. }
  693. }
  694. /**
  695. * Outputs database header
  696. *
  697. * @param string $db Database name
  698. *
  699. * @return bool Whether it succeeded
  700. */
  701. public function exportDBHeader($db)
  702. {
  703. if (isset($GLOBALS['sql_compatibility'])) {
  704. $compat = $GLOBALS['sql_compatibility'];
  705. } else {
  706. $compat = 'NONE';
  707. }
  708. $head = $this->_exportComment()
  709. . $this->_exportComment(
  710. __('Database') . ': '
  711. . (isset($GLOBALS['sql_backquotes'])
  712. ? PMA_Util::backquoteCompat($db, $compat)
  713. : '\'' . $db . '\'')
  714. )
  715. . $this->_exportComment();
  716. return PMA_exportOutputHandler($head);
  717. }
  718. /**
  719. * Outputs database footer
  720. *
  721. * @param string $db Database name
  722. *
  723. * @return bool Whether it succeeded
  724. */
  725. public function exportDBFooter($db)
  726. {
  727. global $crlf;
  728. $result = true;
  729. if (isset($GLOBALS['sql_constraints'])) {
  730. $result = PMA_exportOutputHandler($GLOBALS['sql_constraints']);
  731. unset($GLOBALS['sql_constraints']);
  732. }
  733. if (($GLOBALS['sql_structure_or_data'] == 'structure'
  734. || $GLOBALS['sql_structure_or_data'] == 'structure_and_data')
  735. && isset($GLOBALS['sql_procedure_function'])
  736. ) {
  737. $text = '';
  738. $delimiter = '$$';
  739. if (PMA_MYSQL_INT_VERSION > 50100) {
  740. $event_names = PMA_DBI_fetch_result(
  741. 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE'
  742. . ' EVENT_SCHEMA= \''
  743. . PMA_Util::sqlAddSlashes($db, true)
  744. . '\';'
  745. );
  746. } else {
  747. $event_names = array();
  748. }
  749. if ($event_names) {
  750. $text .= $crlf
  751. . 'DELIMITER ' . $delimiter . $crlf;
  752. $text .=
  753. $this->_exportComment()
  754. . $this->_exportComment(__('Events'))
  755. . $this->_exportComment();
  756. foreach ($event_names as $event_name) {
  757. if (! empty($GLOBALS['sql_drop_table'])) {
  758. $text .= 'DROP EVENT '
  759. . PMA_Util::backquote($event_name)
  760. . $delimiter . $crlf;
  761. }
  762. $text .= PMA_DBI_get_definition($db, 'EVENT', $event_name)
  763. . $delimiter . $crlf . $crlf;
  764. }
  765. $text .= 'DELIMITER ;' . $crlf;
  766. }
  767. if (! empty($text)) {
  768. $result = PMA_exportOutputHandler($text);
  769. }
  770. }
  771. return $result;
  772. }
  773. /**
  774. * Returns a stand-in CREATE definition to resolve view dependencies
  775. *
  776. * @param string $db the database name
  777. * @param string $view the view name
  778. * @param string $crlf the end of line sequence
  779. *
  780. * @return string resulting definition
  781. */
  782. public function getTableDefStandIn($db, $view, $crlf)
  783. {
  784. $create_query = '';
  785. if (! empty($GLOBALS['sql_drop_table'])) {
  786. $create_query .= 'DROP VIEW IF EXISTS '
  787. . PMA_Util::backquote($view)
  788. . ';' . $crlf;
  789. }
  790. $create_query .= 'CREATE TABLE ';
  791. if (isset($GLOBALS['sql_if_not_exists'])
  792. && $GLOBALS['sql_if_not_exists']
  793. ) {
  794. $create_query .= 'IF NOT EXISTS ';
  795. }
  796. $create_query .= PMA_Util::backquote($view) . ' (' . $crlf;
  797. $tmp = array();
  798. $columns = PMA_DBI_get_columns_full($db, $view);
  799. foreach ($columns as $column_name => $definition) {
  800. $tmp[] = PMA_Util::backquote($column_name) . ' ' .
  801. $definition['Type'] . $crlf;
  802. }
  803. $create_query .= implode(',', $tmp) . ');';
  804. return($create_query);
  805. }
  806. /**
  807. * Returns $table's CREATE definition
  808. *
  809. * @param string $db the database name
  810. * @param string $table the table name
  811. * @param string $crlf the end of line sequence
  812. * @param string $error_url the url to go back in case of error
  813. * @param bool $show_dates whether to include creation/update/check
  814. * dates
  815. * @param bool $add_semicolon whether to add semicolon and end-of-line at
  816. * the end
  817. * @param bool $view whether we're handling a view
  818. *
  819. * @return string resulting schema
  820. */
  821. public function getTableDef(
  822. $db,
  823. $table,
  824. $crlf,
  825. $error_url,
  826. $show_dates = false,
  827. $add_semicolon = true,
  828. $view = false
  829. ) {
  830. global $sql_drop_table, $sql_backquotes, $sql_constraints,
  831. $sql_constraints_query, $sql_drop_foreign_keys;
  832. $schema_create = '';
  833. $auto_increment = '';
  834. $new_crlf = $crlf;
  835. if (isset($GLOBALS['sql_compatibility'])) {
  836. $compat = $GLOBALS['sql_compatibility'];
  837. } else {
  838. $compat = 'NONE';
  839. }
  840. // need to use PMA_DBI_QUERY_STORE with PMA_DBI_num_rows() in mysqli
  841. $result = PMA_DBI_query(
  842. 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($db)
  843. . ' LIKE \'' . PMA_Util::sqlAddSlashes($table, true) . '\'',
  844. null,
  845. PMA_DBI_QUERY_STORE
  846. );
  847. if ($result != false) {
  848. if (PMA_DBI_num_rows($result) > 0) {
  849. $tmpres = PMA_DBI_fetch_assoc($result);
  850. if (PMA_DRIZZLE && $show_dates) {
  851. // Drizzle doesn't give Create_time and Update_time in
  852. // SHOW TABLE STATUS, add it
  853. $sql ="SELECT
  854. TABLE_CREATION_TIME AS Create_time,
  855. TABLE_UPDATE_TIME AS Update_time
  856. FROM data_dictionary.TABLES
  857. WHERE TABLE_SCHEMA = '"
  858. . PMA_Util::sqlAddSlashes($db) . "'
  859. AND TABLE_NAME = '"
  860. . PMA_Util::sqlAddSlashes($table) . "'";
  861. $tmpres = array_merge(PMA_DBI_fetch_single_row($sql), $tmpres);
  862. }
  863. // Here we optionally add the AUTO_INCREMENT next value,
  864. // but starting with MySQL 5.0.24, the clause is already included
  865. // in SHOW CREATE TABLE so we'll remove it below
  866. // It's required for Drizzle because SHOW CREATE TABLE uses
  867. // the value from table's creation time
  868. if (isset($GLOBALS['sql_auto_increment'])
  869. && ! empty($tmpres['Auto_increment'])
  870. ) {
  871. $auto_increment .= ' AUTO_INCREMENT='
  872. . $tmpres['Auto_increment'] . ' ';
  873. }
  874. if ($show_dates
  875. && isset($tmpres['Create_time'])
  876. && ! empty($tmpres['Create_time'])
  877. ) {
  878. $schema_create .= $this->_exportComment(
  879. __('Creation') . ': '
  880. . PMA_Util::localisedDate(
  881. strtotime($tmpres['Create_time'])
  882. )
  883. );
  884. $new_crlf = $this->_exportComment() . $crlf;
  885. }
  886. if ($show_dates
  887. && isset($tmpres['Update_time'])
  888. && ! empty($tmpres['Update_time'])
  889. ) {
  890. $schema_create .= $this->_exportComment(
  891. __('Last update') . ': '
  892. . PMA_Util::localisedDate(
  893. strtotime($tmpres['Update_time'])
  894. )
  895. );
  896. $new_crlf = $this->_exportComment() . $crlf;
  897. }
  898. if ($show_dates
  899. && isset($tmpres['Check_time'])
  900. && ! empty($tmpres['Check_time'])
  901. ) {
  902. $schema_create .= $this->_exportComment(
  903. __('Last check') . ': '
  904. . PMA_Util::localisedDate(
  905. strtotime($tmpres['Check_time'])
  906. )
  907. );
  908. $new_crlf = $this->_exportComment() . $crlf;
  909. }
  910. }
  911. PMA_DBI_free_result($result);
  912. }
  913. $schema_create .= $new_crlf;
  914. // no need to generate a DROP VIEW here, it was done earlier
  915. if (! empty($sql_drop_table) && ! PMA_Table::isView($db, $table)) {
  916. $schema_create .= 'DROP TABLE IF EXISTS '
  917. . PMA_Util::backquote($table, $sql_backquotes) . ';'
  918. . $crlf;
  919. }
  920. // Complete table dump,
  921. // Whether to quote table and column names or not
  922. // Drizzle always quotes names
  923. if (! PMA_DRIZZLE) {
  924. if ($sql_backquotes) {
  925. PMA_DBI_query('SET SQL_QUOTE_SHOW_CREATE = 1');
  926. } else {
  927. PMA_DBI_query('SET SQL_QUOTE_SHOW_CREATE = 0');
  928. }
  929. }
  930. // I don't see the reason why this unbuffered query could cause problems,
  931. // because SHOW CREATE TABLE returns only one row, and we free the
  932. // results below. Nonetheless, we got 2 user reports about this
  933. // (see bug 1562533) so I removed the unbuffered mode.
  934. // $result = PMA_DBI_query('SHOW CREATE TABLE ' . backquote($db)
  935. // . '.' . backquote($table), null, PMA_DBI_QUERY_UNBUFFERED);
  936. //
  937. // Note: SHOW CREATE TABLE, at least in MySQL 5.1.23, does not
  938. // produce a displayable result for the default value of a BIT
  939. // column, nor does the mysqldump command. See MySQL bug 35796
  940. $result = PMA_DBI_try_query(
  941. 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
  942. . PMA_Util::backquote($table)
  943. );
  944. // an error can happen, for example the table is crashed
  945. $tmp_error = PMA_DBI_getError();
  946. if ($tmp_error) {
  947. return $this->_exportComment(__('in use') . '(' . $tmp_error . ')');
  948. }
  949. if ($result != false && ($row = PMA_DBI_fetch_row($result))) {
  950. $create_query = $row[1];
  951. unset($row);
  952. // Convert end of line chars to one that we want (note that MySQL
  953. // doesn't return query it will accept in all cases)
  954. if (strpos($create_query, "(\r\n ")) {
  955. $create_query = str_replace("\r\n", $crlf, $create_query);
  956. } elseif (strpos($create_query, "(\n ")) {
  957. $create_query = str_replace("\n", $crlf, $create_query);
  958. } elseif (strpos($create_query, "(\r ")) {
  959. $create_query = str_replace("\r", $crlf, $create_query);
  960. }
  961. /*
  962. * Drop database name from VIEW creation.
  963. *
  964. * This is a bit tricky, but we need to issue SHOW CREATE TABLE with
  965. * database name, but we don't want name to show up in CREATE VIEW
  966. * statement.
  967. */
  968. if ($view) {
  969. $create_query = preg_replace(
  970. '/' . PMA_Util::backquote($db) . '\./',
  971. '',
  972. $create_query
  973. );
  974. }
  975. // Should we use IF NOT EXISTS?
  976. // It always must be OFF for MSSQL compatibility mode
  977. if (isset($GLOBALS['sql_if_not_exists']) && $compat != 'MSSQL') {
  978. $create_query = preg_replace(
  979. '/^CREATE TABLE/',
  980. 'CREATE TABLE IF NOT EXISTS',
  981. $create_query
  982. );
  983. }
  984. // In MSSQL
  985. // 1. DATE field doesn't exists, we will use DATETIME instead
  986. // 2. UNSIGNED attribute doesn't exist
  987. // 3. No length on INT, TINYINT, SMALLINT, BIGINT and no precision on
  988. // FLOAT fields
  989. // 4. No KEY and INDEX inside CREATE TABLE
  990. // 5. DOUBLE field doesn't exists, we will use FLOAT instead
  991. if ($compat == 'MSSQL') {
  992. // first we need to replace all lines ended with '" DATE ...,\n'
  993. // last preg_replace preserve us from situation with date text
  994. // inside DEFAULT field value
  995. $create_query = preg_replace(
  996. "/\" date DEFAULT NULL(,)?\n/",
  997. '" datetime DEFAULT NULL$1' . "\n",
  998. $create_query
  999. );
  1000. $create_query = preg_replace(
  1001. "/\" date NOT NULL(,)?\n/",
  1002. '" datetime NOT NULL$1' . "\n",
  1003. $create_query
  1004. );
  1005. $create_query = preg_replace(
  1006. '/" date NOT NULL DEFAULT \'([^\'])/',
  1007. '" datetime NOT NULL DEFAULT \'$1',
  1008. $create_query
  1009. );
  1010. // next we need to replace all lines ended with ') UNSIGNED ...,'
  1011. // last preg_replace preserve us from situation with unsigned text
  1012. // inside DEFAULT field value
  1013. $create_query = preg_replace(
  1014. "/\) unsigned NOT NULL(,)?\n/",
  1015. ') NOT NULL$1' . "\n",
  1016. $create_query
  1017. );
  1018. $create_query = preg_replace(
  1019. "/\) unsigned DEFAULT NULL(,)?\n/",
  1020. ') DEFAULT NULL$1' . "\n",
  1021. $create_query
  1022. );
  1023. $create_query = preg_replace(
  1024. '/\) unsigned NOT NULL DEFAULT \'([^\'])/',
  1025. ') NOT NULL DEFAULT \'$1',
  1026. $create_query
  1027. );
  1028. // we need to replace all lines ended with
  1029. // '" INT|TINYINT([0-9]{1,}) ...,' last preg_replace preserve us
  1030. // from situation with int([0-9]{1,}) text inside DEFAULT field
  1031. // value
  1032. $create_query = preg_replace(
  1033. '/" (int|tinyint|smallint|bigint)\([0-9]+\) DEFAULT NULL(,)?\n/',
  1034. '" $1 DEFAULT NULL$2' . "\n",
  1035. $create_query
  1036. );
  1037. $create_query = preg_replace(
  1038. '/" (int|tinyint|smallint|bigint)\([0-9]+\) NOT NULL(,)?\n/',
  1039. '" $1 NOT NULL$2' . "\n",
  1040. $create_query
  1041. );
  1042. $create_query = preg_replace(
  1043. '/" (int|tinyint|smallint|bigint)\([0-9]+\) NOT NULL DEFAULT \'([^\'])/',
  1044. '" $1 NOT NULL DEFAULT \'$2',
  1045. $create_query
  1046. );
  1047. // we need to replace all lines ended with
  1048. // '" FLOAT|DOUBLE([0-9,]{1,}) ...,'
  1049. // last preg_replace preserve us from situation with
  1050. // float([0-9,]{1,}) text inside DEFAULT field value
  1051. $create_query = preg_replace(
  1052. '/" (float|double)(\([0-9]+,[0-9,]+\))? DEFAULT NULL(,)?\n/',
  1053. '" float DEFAULT NULL$3' . "\n",
  1054. $create_query
  1055. );
  1056. $create_query = preg_replace(
  1057. '/" (float|double)(\([0-9,]+,[0-9,]+\))? NOT NULL(,)?\n/',
  1058. '" float NOT NULL$3' . "\n",
  1059. $create_query
  1060. );
  1061. $create_query = preg_replace(
  1062. '/" (float|double)(\([0-9,]+,[0-9,]+\))? NOT NULL DEFAULT \'([^\'])/',
  1063. '" float NOT NULL DEFAULT \'$3',
  1064. $create_query
  1065. );
  1066. // @todo remove indexes from CREATE TABLE
  1067. }
  1068. // Drizzle (checked on 2011.03.13) returns ROW_FORMAT surrounded
  1069. // with quotes, which is not accepted by parser
  1070. if (PMA_DRIZZLE) {
  1071. $create_query = preg_replace(
  1072. '/ROW_FORMAT=\'(\S+)\'/',
  1073. 'ROW_FORMAT=$1',
  1074. $create_query
  1075. );
  1076. }
  1077. // are there any constraints to cut out?
  1078. if (preg_match('@CONSTRAINT|FOREIGN[\s]+KEY@', $create_query)) {
  1079. // Split the query into lines, so we can easily handle it.
  1080. // We know lines are separated by $crlf (done few lines above).
  1081. $sql_lines = explode($crlf, $create_query);
  1082. $sql_count = count($sql_lines);
  1083. // lets find first line with constraints
  1084. for ($i = 0; $i < $sql_count; $i++) {
  1085. if (preg_match(
  1086. '@^[\s]*(CONSTRAINT|FOREIGN[\s]+KEY)@',
  1087. $sql_lines[$i]
  1088. )) {
  1089. break;
  1090. }
  1091. }
  1092. // If we really found a constraint
  1093. if ($i != $sql_count) {
  1094. // remove, from the end of create statement
  1095. $sql_lines[$i - 1] = preg_replace(
  1096. '@,$@',
  1097. '',
  1098. $sql_lines[$i - 1]
  1099. );
  1100. // prepare variable for constraints
  1101. if (! isset($sql_constraints)) {
  1102. if (isset($GLOBALS['no_constraints_comments'])) {
  1103. $sql_constraints = '';
  1104. } else {
  1105. $sql_constraints = $crlf
  1106. . $this->_exportComment()
  1107. . $this->_exportComment(
  1108. __('Constraints for dumped tables')
  1109. )
  1110. . $this->_exportComment();
  1111. }
  1112. }
  1113. // comments for current table
  1114. if (! isset($GLOBALS['no_constraints_comments'])) {
  1115. $sql_constraints .= $crlf
  1116. . $this->_exportComment()
  1117. . $this->_exportComment(
  1118. __('Constraints for table')
  1119. . ' '
  1120. . PMA_Util::backquoteCompat($table, $compat)
  1121. )
  1122. . $this->_exportComment();
  1123. }
  1124. // let's do the work
  1125. $sql_constraints_query .= 'ALTER TABLE '
  1126. . PMA_Util::backquoteCompat($table, $compat)
  1127. . $crlf;
  1128. $sql_constraints .= 'ALTER TABLE '
  1129. . PMA_Util::backquoteCompat($table, $compat)
  1130. . $crlf;
  1131. $sql_drop_foreign_keys .= 'ALTER TABLE '
  1132. . PMA_Util::backquoteCompat($db, $compat) . '.'
  1133. . PMA_Util::backquoteCompat($table, $compat)
  1134. . $crlf;
  1135. $first = true;
  1136. for ($j = $i; $j < $sql_count; $j++) {
  1137. if (preg_match(
  1138. '@CONSTRAINT|FOREIGN[\s]+KEY@',
  1139. $sql_lines[$j]
  1140. )) {
  1141. if (! $first) {
  1142. $sql_constraints .= $crlf;
  1143. }
  1144. if (strpos($sql_lines[$j], 'CONSTRAINT') === false) {
  1145. $tmp_str = preg_replace(
  1146. '/(FOREIGN[\s]+KEY)/',
  1147. 'ADD \1',
  1148. $sql_lines[$j]
  1149. );
  1150. $sql_constraints_query .= $tmp_str;
  1151. $sql_constraints .= $tmp_str;
  1152. } else {
  1153. $tmp_str = preg_replace(
  1154. '/(CONSTRAINT)/',
  1155. 'ADD \1',
  1156. $sql_lines[$j]
  1157. );
  1158. $sql_constraints_query .= $tmp_str;
  1159. $sql_constraints .= $tmp_str;
  1160. preg_match(
  1161. '/(CONSTRAINT)([\s])([\S]*)([\s])/',
  1162. $sql_lines[$j],
  1163. $matches
  1164. );
  1165. if (! $first) {
  1166. $sql_drop_foreign_keys .= ', ';
  1167. }
  1168. $sql_drop_foreign_keys .= 'DROP FOREIGN KEY '
  1169. . $matches[3];
  1170. }
  1171. $first = false;
  1172. } else {
  1173. break;
  1174. }
  1175. }
  1176. $sql_constraints .= ';' . $crlf;
  1177. $sql_constraints_query .= ';';
  1178. $create_query = implode(
  1179. $crlf,
  1180. array_slice($sql_lines, 0, $i)
  1181. )
  1182. . $crlf
  1183. . implode(
  1184. $crlf,
  1185. array_slice($sql_lines, $j, $sql_count - 1)
  1186. );
  1187. unset($sql_lines);
  1188. }
  1189. }
  1190. $schema_create .= $create_query;
  1191. }
  1192. // remove a possible "AUTO_INCREMENT = value" clause
  1193. // that could be there starting with MySQL 5.0.24
  1194. // in Drizzle it's useless as it contains the value given at table
  1195. // creation time
  1196. $schema_create = preg_replace(
  1197. '/AUTO_INCREMENT\s*=\s*([0-9])+/',
  1198. '',
  1199. $schema_create
  1200. );
  1201. $schema_create .= ($compat != 'MSSQL') ? $auto_increment : '';
  1202. PMA_DBI_free_result($result);
  1203. return $schema_create . ($add_semicolon ? ';' . $crlf : '');
  1204. } // end of the 'getTableDef()' function
  1205. /**
  1206. * Returns $table's comments, relations etc.
  1207. *
  1208. * @param string $db database name
  1209. * @param string $table table name
  1210. * @param string $crlf end of line sequence
  1211. * @param bool $do_relation whether to include relation comments
  1212. * @param bool $do_mime whether to include mime comments
  1213. *
  1214. * @return string resulting comments
  1215. */
  1216. private function _getTableComments(
  1217. $db,
  1218. $table,
  1219. $crlf,
  1220. $do_relation = false,
  1221. $do_mime = false
  1222. ) {
  1223. global $cfgRelation, $sql_backquotes;
  1224. $schema_create = '';
  1225. // Check if we can use Relations
  1226. if ($do_relation && ! empty($cfgRelation['relation'])) {
  1227. // Find which tables are related with the current one and write it in
  1228. // an array
  1229. $res_rel = PMA_getForeigners($db, $table);
  1230. if ($res_rel && count($res_rel) > 0) {
  1231. $have_rel = true;
  1232. } else {
  1233. $have_rel = false;
  1234. }
  1235. } else {
  1236. $have_rel = false;
  1237. } // end if
  1238. if ($do_mime && $cfgRelation['mimework']) {
  1239. if (! ($mime_map = PMA_getMIME($db, $table, true))) {
  1240. unset($mime_map);
  1241. }
  1242. }
  1243. if (isset($mime_map) && count($mime_map) > 0) {
  1244. $schema_create .= $this->_possibleCRLF()
  1245. . $this->_exportComment()
  1246. . $this->_exportComment(
  1247. __('MIME TYPES FOR TABLE'). ' '
  1248. . PMA_Util::backquote($table, $sql_backquotes) . ':'
  1249. );
  1250. @reset($mime_map);
  1251. foreach ($mime_map AS $mime_field => $mime) {
  1252. $schema_create .=
  1253. $this->_exportComment(
  1254. ' '
  1255. . PMA_Util::backquote($mime_field, $sql_backquotes)
  1256. )
  1257. . $this->_exportComment(
  1258. ' '
  1259. . PMA_Util::backquote(
  1260. $mime['mimetype'],
  1261. $sql_backquotes
  1262. )
  1263. );
  1264. }
  1265. $schema_create .= $this->_exportComment();
  1266. }
  1267. if ($have_rel) {
  1268. $schema_create .= $this->_possibleCRLF()
  1269. . $this->_exportComment()
  1270. . $this->_exportComment(
  1271. __('RELATIONS FOR TABLE') . ' '
  1272. . PMA_Util::backquote($table, $sql_backquotes)
  1273. . ':'
  1274. );
  1275. foreach ($res_rel AS $rel_field => $rel) {
  1276. $schema_create .=
  1277. $this->_exportComment(
  1278. ' '
  1279. . PMA_Util::backquote($rel_field, $sql_backquotes)
  1280. )
  1281. . $this->_exportComment(
  1282. ' '
  1283. . PMA_Util::backquote(
  1284. $rel['foreign_table'],
  1285. $sql_backquotes
  1286. )
  1287. . ' -> '
  1288. . PMA_Util::backquote(
  1289. $rel['foreign_field'],
  1290. $sql_backquotes
  1291. )
  1292. );
  1293. }
  1294. $schema_create .= $this->_exportComment();
  1295. }
  1296. return $schema_create;
  1297. } // end of the '_getTableComments()' function
  1298. /**
  1299. * Outputs table's structure
  1300. *
  1301. * @param string $db database name
  1302. * @param string $table table name
  1303. * @param string $crlf the end of line sequence
  1304. * @param string $error_url the url to go back in case of error
  1305. * @param string $export_mode 'create_table','triggers','create_view',
  1306. * 'stand_in'
  1307. * @param string $export_type 'server', 'database', 'table'
  1308. * @param bool $relation whether to include relation comments
  1309. * @param bool $comments whether to include the pmadb-style column
  1310. * comments as comments in the structure; this is
  1311. * deprecated but the parameter is left here
  1312. * because export.php calls exportStructure()
  1313. * also for other export types which use this
  1314. * parameter
  1315. * @param bool $mime whether to include mime comments
  1316. * @param bool $dates whether to include creation/update/check dates
  1317. *
  1318. * @return bool Whether it succeeded
  1319. */
  1320. public function exportStructure(
  1321. $db,
  1322. $table,
  1323. $crlf,
  1324. $error_url,
  1325. $export_mode,
  1326. $export_type,
  1327. $relation = false,
  1328. $comments = false,
  1329. $mime = false,
  1330. $dates = false
  1331. ) {
  1332. if (isset($GLOBALS['sql_compatibility'])) {
  1333. $compat = $GLOBALS['sql_compatibility'];
  1334. } else {
  1335. $compat = 'NONE';
  1336. }
  1337. $formatted_table_name = (isset($GLOBALS['sql_backquotes']))
  1338. ? PMA_Util::backquoteCompat($table, $compat)
  1339. : '\'' . $table . '\'';
  1340. $dump = $this->_possibleCRLF()
  1341. . $this->_exportComment(str_repeat('-', 56))
  1342. . $this->_possibleCRLF()
  1343. . $this->_exportComment();
  1344. switch($export_mode) {
  1345. case 'create_table':
  1346. $dump .= $this->_exportComment(
  1347. __('Table structure for table') . ' '. $formatted_table_name
  1348. );
  1349. $dump .= $this->_exportComment();
  1350. $dump .= $this->getTableDef($db, $table, $crlf, $error_url, $dates);
  1351. $dump .= $this->_getTableComments($db, $table, $crlf, $relation, $mime);
  1352. break;
  1353. case 'triggers':
  1354. $dump = '';
  1355. $triggers = PMA_DBI_get_triggers($db, $table);
  1356. if ($triggers) {
  1357. $dump .= $this->_possibleCRLF()
  1358. . $this->_exportComment()
  1359. . $this->_exportComment(
  1360. __('Triggers') . ' ' . $formatted_table_name
  1361. )
  1362. . $this->_exportComment();
  1363. $delimiter = '//';
  1364. foreach ($triggers as $trigger) {
  1365. $dump .= $trigger['drop'] . ';' . $crlf;
  1366. $dump .= 'DELIMITER ' . $delimiter . $crlf;
  1367. $dump .= $trigger['create'];
  1368. $dump .= 'DELIMITER ;' . $crlf;
  1369. }
  1370. }
  1371. break;
  1372. case 'create_view':
  1373. $dump .=
  1374. $this->_exportComment(
  1375. __('Structure for view')
  1376. . ' '
  1377. . $formatted_table_name
  1378. )
  1379. . $this->_exportComment();
  1380. // delete the stand-in table previously created (if any)
  1381. if ($export_type != 'table') {
  1382. $dump .= 'DROP TABLE IF EXISTS '
  1383. . PMA_Util::backquote($table) . ';' . $crlf;
  1384. }
  1385. $dump .= $this->getTableDef(
  1386. $db, $table, $crlf, $error_url, $dates, true, true
  1387. );
  1388. break;
  1389. case 'stand_in':
  1390. $dump .=
  1391. $this->_exportComment(
  1392. __('Stand-in structure for view') . ' ' . $formatted_table_name
  1393. )
  1394. . $this->_exportComment();
  1395. // export a stand-in definition to resolve view dependencies
  1396. $dump .= $this->getTableDefStandIn($db, $table, $crlf);
  1397. } // end switch
  1398. // this one is built by getTableDef() to use in table copy/move
  1399. // but not in the case of export
  1400. unset($GLOBALS['sql_constraints_query']);
  1401. return PMA_exportOutputHandler($dump);
  1402. }
  1403. /**
  1404. * Outputs the content of a table in SQL format
  1405. *
  1406. * @param string $db database name
  1407. * @param string $table table name
  1408. * @param string $crlf the end of line sequence
  1409. * @param string $error_url the url to go back in case of error
  1410. * @param string $sql_query SQL query for obtaining data
  1411. *
  1412. * @return bool Whether it succeeded
  1413. */
  1414. public function exportData($db, $table, $crlf, $error_url, $sql_query)
  1415. {
  1416. global $current_row, $sql_backquotes;
  1417. if (isset($GLOBALS['sql_compatibility'])) {
  1418. $compat = $GLOBALS['sql_compatibility'];
  1419. } else {
  1420. $compat = 'NONE';
  1421. }
  1422. $formatted_table_name = (isset($GLOBALS['sql_backquotes']))
  1423. ? PMA_Util::backquoteCompat($table, $compat)
  1424. : '\'' . $table . '\'';
  1425. // Do not export data for a VIEW
  1426. // (For a VIEW, this is called only when exporting a single VIEW)
  1427. if (PMA_Table::isView($db, $table)) {
  1428. $head = $this->_possibleCRLF()
  1429. . $this->_exportComment()
  1430. . $this->_exportComment('VIEW ' . ' ' . $formatted_table_name)
  1431. . $this->_exportComment(__('Data') . ': ' . __('None'))
  1432. . $this->_exportComment()
  1433. . $this->_possibleCRLF();
  1434. if (! PMA_exportOutputHandler($head)) {
  1435. return false;
  1436. }
  1437. return true;
  1438. }
  1439. // analyze the query to get the true column names, not the aliases
  1440. // (this fixes an undefined index, also if Complete inserts
  1441. // are used, we did not get the true column name in case of aliases)
  1442. $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($sql_query));
  1443. $result = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
  1444. // a possible error: the table has crashed
  1445. $tmp_error = PMA_DBI_getError();
  1446. if ($tmp_error) {
  1447. return PMA_exportOutputHandler(
  1448. $this->_exportComment(
  1449. __('Error reading data:') . ' (' . $tmp_error . ')'
  1450. )
  1451. );
  1452. }
  1453. if ($result != false) {
  1454. $fields_cnt = PMA_DBI_num_fields($result);
  1455. // Get field information
  1456. $fields_meta = PMA_DBI_get_fields_meta($result);
  1457. $field_flags = array();
  1458. for ($j = 0; $j < $fields_cnt; $j++) {
  1459. $field_flags[$j] = PMA_DBI_field_flags($result, $j);
  1460. }
  1461. for ($j = 0; $j < $fields_cnt; $j++) {
  1462. if (isset($analyzed_sql[0]['select_expr'][$j]['column'])) {
  1463. $field_set[$j] = PMA_Util::backquoteCompat(
  1464. $analyzed_sql[0]['select_expr'][$j]['column'],
  1465. $compat,
  1466. $sql_backquotes
  1467. );
  1468. } else {
  1469. $field_set[$j] = PMA_Util::backquoteCompat(
  1470. $fields_meta[$j]->name,
  1471. $compat,
  1472. $sql_backquotes
  1473. );
  1474. }
  1475. }
  1476. if (isset($GLOBALS['sql_type'])
  1477. && $GLOBALS['sql_type'] == 'UPDATE'
  1478. ) {
  1479. // update
  1480. $schema_insert = 'UPDATE ';
  1481. if (isset($GLOBALS['sql_ignore'])) {
  1482. $schema_insert .= 'IGNORE ';
  1483. }
  1484. // avoid EOL blank
  1485. $schema_insert .= PMA_Util::backquoteCompat(
  1486. $table,
  1487. $compat,
  1488. $sql_backquotes
  1489. ) . ' SET';
  1490. } else {
  1491. // insert or replace
  1492. if (isset($GLOBALS['sql_type'])
  1493. && $GLOBALS['sql_type'] == 'REPLACE'
  1494. ) {
  1495. $sql_command = 'REPLACE';
  1496. } else {
  1497. $sql_command = 'INSERT';
  1498. }
  1499. // delayed inserts?
  1500. if (isset($GLOBALS['sql_delayed'])) {
  1501. $insert_delayed = ' DELAYED';
  1502. } else {
  1503. $insert_delayed = '';
  1504. }
  1505. // insert ignore?
  1506. if (isset($GLOBALS['sql_type'])
  1507. && $GLOBALS['sql_type'] == 'INSERT'
  1508. && isset($GLOBALS['sql_ignore'])
  1509. ) {
  1510. $insert_delayed .= ' IGNORE';
  1511. }
  1512. //truncate table before insert
  1513. if (isset($GLOBALS['sql_truncate'])
  1514. && $GLOBALS['sql_truncate']
  1515. && $sql_command == 'INSERT'
  1516. ) {
  1517. $truncate = 'TRUNCATE TABLE '
  1518. . PMA_Util::backquoteCompat(
  1519. $table,
  1520. $compat,
  1521. $sql_backquotes
  1522. ) . ";";
  1523. $truncatehead = $this->_possibleCRLF()
  1524. . $this->_exportComment()
  1525. . $this->_exportComment(
  1526. __('Truncate table before insert') . ' '
  1527. . $formatted_table_name
  1528. )
  1529. . $this->_exportComment()
  1530. . $crlf;
  1531. PMA_exportOutputHandler($truncatehead);
  1532. PMA_exportOutputHandler($truncate);
  1533. } else {
  1534. $truncate = '';
  1535. }
  1536. // scheme for inserting fields
  1537. if ($GLOBALS['sql_insert_syntax'] == 'complete'
  1538. || $GLOBALS['sql_insert_syntax'] == 'both'
  1539. ) {
  1540. $fields = implode(', ', $field_set);
  1541. $schema_insert = $sql_command . $insert_delayed .' INTO '
  1542. . PMA_Util::backquoteCompat(
  1543. $table,
  1544. $compat,
  1545. $sql_backquotes
  1546. )
  1547. // avoid EOL blank
  1548. . ' (' . $fields . ') VALUES';
  1549. } else {
  1550. $schema_insert = $sql_command . $insert_delayed .' INTO '
  1551. . PMA_Util::backquoteCompat(
  1552. $table,
  1553. $compat,
  1554. $sql_backquotes
  1555. )
  1556. . ' VALUES';
  1557. }
  1558. }
  1559. //\x08\\x09, not required
  1560. $search = array("\x00", "\x0a", "\x0d", "\x1a");
  1561. $replace = array('\0', '\n', '\r', '\Z');
  1562. $current_row = 0;
  1563. $query_size = 0;
  1564. if (($GLOBALS['sql_insert_syntax'] == 'extended'
  1565. || $GLOBALS['sql_insert_syntax'] == 'both')
  1566. && (! isset($GLOBALS['sql_type'])
  1567. || $GLOBALS['sql_type'] != 'UPDATE')
  1568. ) {
  1569. $separator = ',';
  1570. $schema_insert .= $crlf;
  1571. } else {
  1572. $separator = ';';
  1573. }
  1574. while ($row = PMA_DBI_fetch_row($result)) {
  1575. if ($current_row == 0) {
  1576. $head = $this->_possibleCRLF()
  1577. . $this->_exportComment()
  1578. . $this->_exportComment(
  1579. __('Dumping data for table') . ' '
  1580. . $formatted_table_name
  1581. )
  1582. . $this->_exportComment()
  1583. . $crlf;
  1584. if (! PMA_exportOutputHandler($head)) {
  1585. return false;
  1586. }
  1587. }
  1588. // We need to SET IDENTITY_INSERT ON for MSSQL
  1589. if (isset($GLOBALS['sql_compatibility'])
  1590. && $GLOBALS['sql_compatibility'] == 'MSSQL'
  1591. && $current_row == 0
  1592. ) {
  1593. if (! PMA_exportOutputHandler(
  1594. 'SET IDENTITY_INSERT '
  1595. . PMA_Util::backquoteCompat(
  1596. $table,
  1597. $compat
  1598. )
  1599. . ' ON ;'.$crlf
  1600. )) {
  1601. return false;
  1602. }
  1603. }
  1604. $current_row++;
  1605. for ($j = 0; $j < $fields_cnt; $j++) {
  1606. // NULL
  1607. if (! isset($row[$j]) || is_null($row[$j])) {
  1608. $values[] = 'NULL';
  1609. } elseif ($fields_meta[$j]->numeric
  1610. && $fields_meta[$j]->type != 'timestamp'
  1611. && ! $fields_meta[$j]->blob
  1612. ) {
  1613. // a number
  1614. // timestamp is numeric on some MySQL 4.1, BLOBs are
  1615. // sometimes numeric
  1616. $values[] = $row[$j];
  1617. } elseif (stristr($field_flags[$j], 'BINARY')
  1618. && $fields_meta[$j]->blob
  1619. && isset($GLOBALS['sql_hex_for_blob'])
  1620. ) {
  1621. // a true BLOB
  1622. // - mysqldump only generates hex data when the --hex-blob
  1623. // option is used, for fields having the binary attribute
  1624. // no hex is generated
  1625. // - a TEXT field returns type blob but a real blob
  1626. // returns also the 'binary' flag
  1627. // empty blobs need to be different, but '0' is also empty
  1628. // :-(
  1629. if (empty($row[$j]) && $row[$j] != '0') {
  1630. $values[] = '\'\'';
  1631. } else {
  1632. $values[] = '0x' . bin2hex($row[$j]);
  1633. }
  1634. } elseif ($fields_meta[$j]->type == 'bit') {
  1635. // detection of 'bit' works only on mysqli extension
  1636. $values[] = "b'" . PMA_Util::sqlAddSlashes(
  1637. PMA_Util::printableBitValue(
  1638. $row[$j], $fields_meta[$j]->length
  1639. )
  1640. )
  1641. . "'";
  1642. } else {
  1643. // something else -> treat as a string
  1644. $values[] = '\''
  1645. . str_replace(
  1646. $search, $replace,
  1647. PMA_Util::sqlAddSlashes($row[$j])
  1648. )
  1649. . '\'';
  1650. } // end if
  1651. } // end for
  1652. // should we make update?
  1653. if (isset($GLOBALS['sql_type'])
  1654. && $GLOBALS['sql_type'] == 'UPDATE'
  1655. ) {
  1656. $insert_line = $schema_insert;
  1657. for ($i = 0; $i < $fields_cnt; $i++) {
  1658. if (0 == $i) {
  1659. $insert_line .= ' ';
  1660. }
  1661. if ($i > 0) {
  1662. // avoid EOL blank
  1663. $insert_line .= ',';
  1664. }
  1665. $insert_line .= $field_set[$i] . ' = ' . $values[$i];
  1666. }
  1667. list($tmp_unique_condition, $tmp_clause_is_unique)
  1668. = PMA_Util::getUniqueCondition(
  1669. $result,
  1670. $fields_cnt,
  1671. $fields_meta,
  1672. $row
  1673. );
  1674. $insert_line .= ' WHERE ' . $tmp_unique_condition;
  1675. unset($tmp_unique_condition, $tmp_clause_is_unique);
  1676. } else {
  1677. // Extended inserts case
  1678. if ($GLOBALS['sql_insert_syntax'] == 'extended'
  1679. || $GLOBALS['sql_insert_syntax'] == 'both'
  1680. ) {
  1681. if ($current_row == 1) {
  1682. $insert_line = $schema_insert . '('
  1683. . implode(', ', $values) . ')';
  1684. } else {
  1685. $insert_line = '(' . implode(', ', $values) . ')';
  1686. $sql_max_size = $GLOBALS['sql_max_query_size'];
  1687. if (isset($sql_max_size)
  1688. && $sql_max_size > 0
  1689. && $query_size + strlen($insert_line) > $sql_max_size
  1690. ) {
  1691. if (! PMA_exportOutputHandler(';' . $crlf)) {
  1692. return false;
  1693. }
  1694. $query_size = 0;
  1695. $current_row = 1;
  1696. $insert_line = $schema_insert . $insert_line;
  1697. }
  1698. }
  1699. $query_size += strlen($insert_line);
  1700. // Other inserts case
  1701. } else {
  1702. $insert_line = $schema_insert
  1703. . '('
  1704. . implode(', ', $values)
  1705. . ')';
  1706. }
  1707. }
  1708. unset($values);
  1709. if (! PMA_exportOutputHandler(
  1710. ($current_row == 1 ? '' : $separator . $crlf)
  1711. . $insert_line
  1712. )) {
  1713. return false;
  1714. }
  1715. } // end while
  1716. if ($current_row > 0) {
  1717. if (! PMA_exportOutputHandler(';' . $crlf)) {
  1718. return false;
  1719. }
  1720. }
  1721. // We need to SET IDENTITY_INSERT OFF for MSSQL
  1722. if (isset($GLOBALS['sql_compatibility'])
  1723. && $GLOBALS['sql_compatibility'] == 'MSSQL'
  1724. && $current_row > 0
  1725. ) {
  1726. $outputSucceeded = PMA_exportOutputHandler(
  1727. $crlf . 'SET IDENTITY_INSERT '
  1728. . PMA_Util::backquoteCompat($table, $compat)
  1729. . ' OFF;' . $crlf
  1730. );
  1731. if (! $outputSucceeded) {
  1732. return false;
  1733. }
  1734. }
  1735. } // end if ($result != false)
  1736. PMA_DBI_free_result($result);
  1737. return true;
  1738. } // end of the 'exportData()' function
  1739. }