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