ImportSql.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * SQL import plugin for phpMyAdmin
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin\Plugins\Import;
  7. use PhpMyAdmin\DatabaseInterface;
  8. use PhpMyAdmin\File;
  9. use PhpMyAdmin\Plugins\ImportPlugin;
  10. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
  11. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
  12. use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
  13. use PhpMyAdmin\Properties\Options\Items\SelectPropertyItem;
  14. use PhpMyAdmin\Properties\Plugins\ImportPluginProperties;
  15. use PhpMyAdmin\SqlParser\Utils\BufferedQuery;
  16. use function count;
  17. use function implode;
  18. use function mb_strlen;
  19. use function preg_replace;
  20. /**
  21. * Handles the import for the SQL format
  22. */
  23. class ImportSql extends ImportPlugin
  24. {
  25. public function __construct()
  26. {
  27. parent::__construct();
  28. $this->setProperties();
  29. }
  30. /**
  31. * Sets the import plugin properties.
  32. * Called in the constructor.
  33. *
  34. * @return void
  35. */
  36. protected function setProperties()
  37. {
  38. global $dbi;
  39. $importPluginProperties = new ImportPluginProperties();
  40. $importPluginProperties->setText('SQL');
  41. $importPluginProperties->setExtension('sql');
  42. $importPluginProperties->setOptionsText(__('Options'));
  43. $compats = $dbi->getCompatibilities();
  44. if (count($compats) > 0) {
  45. $values = [];
  46. foreach ($compats as $val) {
  47. $values[$val] = $val;
  48. }
  49. // create the root group that will be the options field for
  50. // $importPluginProperties
  51. // this will be shown as "Format specific options"
  52. $importSpecificOptions = new OptionsPropertyRootGroup(
  53. 'Format Specific Options'
  54. );
  55. // general options main group
  56. $generalOptions = new OptionsPropertyMainGroup('general_opts');
  57. // create primary items and add them to the group
  58. $leaf = new SelectPropertyItem(
  59. 'compatibility',
  60. __('SQL compatibility mode:')
  61. );
  62. $leaf->setValues($values);
  63. $leaf->setDoc(
  64. [
  65. 'manual_MySQL_Database_Administration',
  66. 'Server_SQL_mode',
  67. ]
  68. );
  69. $generalOptions->addProperty($leaf);
  70. $leaf = new BoolPropertyItem(
  71. 'no_auto_value_on_zero',
  72. __('Do not use <code>AUTO_INCREMENT</code> for zero values')
  73. );
  74. $leaf->setDoc(
  75. [
  76. 'manual_MySQL_Database_Administration',
  77. 'Server_SQL_mode',
  78. 'sqlmode_no_auto_value_on_zero',
  79. ]
  80. );
  81. $generalOptions->addProperty($leaf);
  82. // add the main group to the root group
  83. $importSpecificOptions->addProperty($generalOptions);
  84. // set the options for the import plugin property item
  85. $importPluginProperties->setOptions($importSpecificOptions);
  86. }
  87. $this->properties = $importPluginProperties;
  88. }
  89. /**
  90. * Handles the whole import logic
  91. *
  92. * @param array $sql_data 2-element array with sql data
  93. *
  94. * @return void
  95. */
  96. public function doImport(?File $importHandle = null, array &$sql_data = [])
  97. {
  98. global $error, $timeout_passed, $dbi;
  99. // Handle compatibility options.
  100. $this->setSQLMode($dbi, $_REQUEST);
  101. $bq = new BufferedQuery();
  102. if (isset($_POST['sql_delimiter'])) {
  103. $bq->setDelimiter($_POST['sql_delimiter']);
  104. }
  105. /**
  106. * Will be set in Import::getNextChunk().
  107. *
  108. * @global bool $GLOBALS ['finished']
  109. */
  110. $GLOBALS['finished'] = false;
  111. while (! $error && (! $timeout_passed)) {
  112. // Getting the first statement, the remaining data and the last
  113. // delimiter.
  114. $statement = $bq->extract();
  115. // If there is no full statement, we are looking for more data.
  116. if (empty($statement)) {
  117. // Importing new data.
  118. $newData = $this->import->getNextChunk($importHandle);
  119. // Subtract data we didn't handle yet and stop processing.
  120. if ($newData === false) {
  121. $GLOBALS['offset'] -= mb_strlen($bq->query);
  122. break;
  123. }
  124. // Checking if the input buffer has finished.
  125. if ($newData === true) {
  126. $GLOBALS['finished'] = true;
  127. break;
  128. }
  129. // Convert CR (but not CRLF) to LF otherwise all queries may
  130. // not get executed on some platforms.
  131. $bq->query .= preg_replace("/\r($|[^\n])/", "\n$1", $newData);
  132. continue;
  133. }
  134. // Executing the query.
  135. $this->import->runQuery($statement, $statement, $sql_data);
  136. }
  137. // Extracting remaining statements.
  138. while (! $error && ! $timeout_passed && ! empty($bq->query)) {
  139. $statement = $bq->extract(true);
  140. if (empty($statement)) {
  141. continue;
  142. }
  143. $this->import->runQuery($statement, $statement, $sql_data);
  144. }
  145. // Finishing.
  146. $this->import->runQuery('', '', $sql_data);
  147. }
  148. /**
  149. * Handle compatibility options
  150. *
  151. * @param DatabaseInterface $dbi Database interface
  152. * @param array $request Request array
  153. *
  154. * @return void
  155. */
  156. private function setSQLMode($dbi, array $request)
  157. {
  158. $sql_modes = [];
  159. if (isset($request['sql_compatibility'])
  160. && $request['sql_compatibility'] !== 'NONE'
  161. ) {
  162. $sql_modes[] = $request['sql_compatibility'];
  163. }
  164. if (isset($request['sql_no_auto_value_on_zero'])) {
  165. $sql_modes[] = 'NO_AUTO_VALUE_ON_ZERO';
  166. }
  167. if (count($sql_modes) <= 0) {
  168. return;
  169. }
  170. $dbi->tryQuery(
  171. 'SET SQL_MODE="' . implode(',', $sql_modes) . '"'
  172. );
  173. }
  174. }