Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 287
mysql_extractor
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 7
3192
0.00% covered (danger)
0.00%
0 / 287
 write_start
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 12
 write_table
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 26
 write_data
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 14
 write_data_mysqli
0.00% covered (danger)
0.00%
0 / 1
210
0.00% covered (danger)
0.00%
0 / 71
 write_data_mysql
0.00% covered (danger)
0.00%
0 / 1
240
0.00% covered (danger)
0.00%
0 / 75
 new_write_table
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 13
 old_write_table
0.00% covered (danger)
0.00%
0 / 1
210
0.00% covered (danger)
0.00%
0 / 76
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class mysql_extractor extends base_extractor
{
    /**
    * {@inheritdoc}
    */
    public function write_start($table_prefix)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        $sql_data = "#\n";
        $sql_data .= "# phpBB Backup Script\n";
        $sql_data .= "# Dump of tables for $table_prefix\n";
        $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
        $sql_data .= "#\n";
        $this->flush($sql_data);
    }
    /**
    * {@inheritdoc}
    */
    public function write_table($table_name)
    {
        static $new_extract;
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        if ($new_extract === null)
        {
            if ($this->db->get_sql_layer() === 'mysqli' || version_compare($this->db->sql_server_info(true), '3.23.20', '>='))
            {
                $new_extract = true;
            }
            else
            {
                $new_extract = false;
            }
        }
        if ($new_extract)
        {
            $this->new_write_table($table_name);
        }
        else
        {
            $this->old_write_table($table_name);
        }
    }
    /**
    * {@inheritdoc}
    */
    public function write_data($table_name)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        if ($this->db->get_sql_layer() === 'mysqli')
        {
            $this->write_data_mysqli($table_name);
        }
        else
        {
            $this->write_data_mysql($table_name);
        }
    }
    /**
    * Extracts data from database table (for MySQLi driver)
    *
    * @param    string    $table_name    name of the database table
    * @return null
    * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
    */
    protected function write_data_mysqli($table_name)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        $sql = "SELECT *
            FROM $table_name";
        $result = mysqli_query($this->db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);
        if ($result != false)
        {
            $fields_cnt = mysqli_num_fields($result);
            // Get field information
            $field = mysqli_fetch_fields($result);
            $field_set = array();
            for ($j = 0; $j < $fields_cnt; $j++)
            {
                $field_set[] = $field[$j]->name;
            }
            $search            = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
            $replace        = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
            $fields            = implode(', ', $field_set);
            $sql_data        = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
            $first_set        = true;
            $query_len        = 0;
            $max_len        = get_usable_memory();
            while ($row = mysqli_fetch_row($result))
            {
                $values    = array();
                if ($first_set)
                {
                    $query = $sql_data . '(';
                }
                else
                {
                    $query  .= ',(';
                }
                for ($j = 0; $j < $fields_cnt; $j++)
                {
                    if (!isset($row[$j]) || is_null($row[$j]))
                    {
                        $values[$j] = 'NULL';
                    }
                    else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
                    {
                        $values[$j] = $row[$j];
                    }
                    else
                    {
                        $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
                    }
                }
                $query .= implode(', ', $values) . ')';
                $query_len += strlen($query);
                if ($query_len > $max_len)
                {
                    $this->flush($query . ";\n\n");
                    $query = '';
                    $query_len = 0;
                    $first_set = true;
                }
                else
                {
                    $first_set = false;
                }
            }
            mysqli_free_result($result);
            // check to make sure we have nothing left to flush
            if (!$first_set && $query)
            {
                $this->flush($query . ";\n\n");
            }
        }
    }
    /**
    * Extracts data from database table (for MySQL driver)
    *
    * @param    string    $table_name    name of the database table
    * @return null
    * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
    */
    protected function write_data_mysql($table_name)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        $sql = "SELECT *
            FROM $table_name";
        $result = mysql_unbuffered_query($sql, $this->db->get_db_connect_id());
        if ($result != false)
        {
            $fields_cnt = mysql_num_fields($result);
            // Get field information
            $field = array();
            for ($i = 0; $i < $fields_cnt; $i++)
            {
                $field[] = mysql_fetch_field($result, $i);
            }
            $field_set = array();
            for ($j = 0; $j < $fields_cnt; $j++)
            {
                $field_set[] = $field[$j]->name;
            }
            $search            = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
            $replace        = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
            $fields            = implode(', ', $field_set);
            $sql_data        = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
            $first_set        = true;
            $query_len        = 0;
            $max_len        = get_usable_memory();
            while ($row = mysql_fetch_row($result))
            {
                $values = array();
                if ($first_set)
                {
                    $query = $sql_data . '(';
                }
                else
                {
                    $query  .= ',(';
                }
                for ($j = 0; $j < $fields_cnt; $j++)
                {
                    if (!isset($row[$j]) || is_null($row[$j]))
                    {
                        $values[$j] = 'NULL';
                    }
                    else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
                    {
                        $values[$j] = $row[$j];
                    }
                    else
                    {
                        $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
                    }
                }
                $query .= implode(', ', $values) . ')';
                $query_len += strlen($query);
                if ($query_len > $max_len)
                {
                    $this->flush($query . ";\n\n");
                    $query = '';
                    $query_len = 0;
                    $first_set = true;
                }
                else
                {
                    $first_set = false;
                }
            }
            mysql_free_result($result);
            // check to make sure we have nothing left to flush
            if (!$first_set && $query)
            {
                $this->flush($query . ";\n\n");
            }
        }
    }
    /**
    * Extracts database table structure (for MySQLi or MySQL 3.23.20+)
    *
    * @param    string    $table_name    name of the database table
    * @return null
    * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
    */
    protected function new_write_table($table_name)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        $sql = 'SHOW CREATE TABLE ' . $table_name;
        $result = $this->db->sql_query($sql);
        $row = $this->db->sql_fetchrow($result);
        $sql_data = '# Table: ' . $table_name . "\n";
        $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
        $this->flush($sql_data . $row['Create Table'] . ";\n\n");
        $this->db->sql_freeresult($result);
    }
    /**
    * Extracts database table structure (for MySQL verisons older than 3.23.20)
    *
    * @param    string    $table_name    name of the database table
    * @return null
    * @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
    */
    protected function old_write_table($table_name)
    {
        if (!$this->is_initialized)
        {
            throw new extractor_not_initialized_exception();
        }
        $sql_data = '# Table: ' . $table_name . "\n";
        $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
        $sql_data .= "CREATE TABLE $table_name(\n";
        $rows = array();
        $sql = "SHOW FIELDS
            FROM $table_name";
        $result = $this->db->sql_query($sql);
        while ($row = $this->db->sql_fetchrow($result))
        {
            $line = '   ' . $row['Field'] . ' ' . $row['Type'];
            if (!is_null($row['Default']))
            {
                $line .= " DEFAULT '{$row['Default']}'";
            }
            if ($row['Null'] != 'YES')
            {
                $line .= ' NOT NULL';
            }
            if ($row['Extra'] != '')
            {
                $line .= ' ' . $row['Extra'];
            }
            $rows[] = $line;
        }
        $this->db->sql_freeresult($result);
        $sql = "SHOW KEYS
            FROM $table_name";
        $result = $this->db->sql_query($sql);
        $index = array();
        while ($row = $this->db->sql_fetchrow($result))
        {
            $kname = $row['Key_name'];
            if ($kname != 'PRIMARY')
            {
                if ($row['Non_unique'] == 0)
                {
                    $kname = "UNIQUE|$kname";
                }
            }
            if ($row['Sub_part'])
            {
                $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
            }
            $index[$kname][] = $row['Column_name'];
        }
        $this->db->sql_freeresult($result);
        foreach ($index as $key => $columns)
        {
            $line = '   ';
            if ($key == 'PRIMARY')
            {
                $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
            }
            else if (strpos($key, 'UNIQUE') === 0)
            {
                $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
            }
            else if (strpos($key, 'FULLTEXT') === 0)
            {
                $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
            }
            else
            {
                $line .= "KEY $key (" . implode(', ', $columns) . ')';
            }
            $rows[] = $line;
        }
        $sql_data .= implode(",\n", $rows);
        $sql_data .= "\n);\n\n";
        $this->flush($sql_data);
    }
}