Source for file mysqli.php

Documentation is available at mysqli.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Database
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM') or die;
  11.  
  12. /**
  13.  * MySQLi import driver.
  14.  *
  15.  * @package     Joomla.Platform
  16.  * @subpackage  Database
  17.  * @since       11.1
  18.  */
  19. {
  20.     /**
  21.      * Checks if all data and options are in order prior to exporting.
  22.      *
  23.      * @return  JDatabaseImporterMysqli  Method supports chaining.
  24.      *
  25.      * @since   11.1
  26.      * @throws  Exception if an error is encountered.
  27.      */
  28.     public function check()
  29.     {
  30.         // Check if the db connector has been set.
  31.         if (!($this->db instanceof JDatabaseDriverMysqli))
  32.         {
  33.             throw new Exception('JPLATFORM_ERROR_DATABASE_CONNECTOR_WRONG_TYPE');
  34.         }
  35.  
  36.         // Check if the tables have been specified.
  37.         if (empty($this->from))
  38.         {
  39.             throw new Exception('JPLATFORM_ERROR_NO_TABLES_SPECIFIED');
  40.         }
  41.  
  42.         return $this;
  43.     }
  44.  
  45.     /**
  46.      * Get the SQL syntax to add a column.
  47.      *
  48.      * @param   string            $table  The table name.
  49.      * @param   SimpleXMLElement  $field  The XML field definition.
  50.      *
  51.      * @return  string 
  52.      *
  53.      * @since   11.1
  54.      */
  55.     protected function getAddColumnSQL($table, SimpleXMLElement $field)
  56.     {
  57.         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD COLUMN ' . $this->getColumnSQL($field);
  58.     }
  59.  
  60.     /**
  61.      * Get the SQL syntax to add a key.
  62.      *
  63.      * @param   string  $table  The table name.
  64.      * @param   array   $keys   An array of the fields pertaining to this key.
  65.      *
  66.      * @return  string 
  67.      *
  68.      * @since   11.1
  69.      */
  70.     protected function getAddKeySQL($table, $keys)
  71.     {
  72.         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD ' . $this->getKeySQL($keys);
  73.     }
  74.  
  75.     /**
  76.      * Get alters for table if there is a difference.
  77.      *
  78.      * @param   SimpleXMLElement  $structure  The XML structure pf the table.
  79.      *
  80.      * @return  array 
  81.      *
  82.      * @since   11.1
  83.      */
  84.     protected function getAlterTableSQL(SimpleXMLElement $structure)
  85.     {
  86.         $table = $this->getRealTableName($structure['name']);
  87.         $oldFields = $this->db->getTableColumns($table);
  88.         $oldKeys = $this->db->getTableKeys($table);
  89.         $alters = array();
  90.  
  91.         // Get the fields and keys from the XML that we are aiming for.
  92.         $newFields = $structure->xpath('field');
  93.         $newKeys = $structure->xpath('key');
  94.  
  95.         // Loop through each field in the new structure.
  96.         foreach ($newFields as $field)
  97.         {
  98.             $fName = (string) $field['Field'];
  99.  
  100.             if (isset($oldFields[$fName]))
  101.             {
  102.                 // The field exists, check it's the same.
  103.                 $column = $oldFields[$fName];
  104.  
  105.                 // Test whether there is a change.
  106.                 $change = ((string) $field['Type'] != $column->Type) || ((string) $field['Null'] != $column->Null)
  107.                     || ((string) $field['Default'] != $column->Default) || ((string) $field['Extra'] != $column->Extra);
  108.  
  109.                 if ($change)
  110.                 {
  111.                     $alters[] = $this->getChangeColumnSQL($table, $field);
  112.                 }
  113.  
  114.                 // Unset this field so that what we have left are fields that need to be removed.
  115.                 unset($oldFields[$fName]);
  116.             }
  117.             else
  118.             {
  119.                 // The field is new.
  120.                 $alters[] = $this->getAddColumnSQL($table, $field);
  121.             }
  122.         }
  123.  
  124.         // Any columns left are orphans
  125.         foreach ($oldFields as $name => $column)
  126.         {
  127.             // Delete the column.
  128.             $alters[] = $this->getDropColumnSQL($table, $name);
  129.         }
  130.  
  131.         // Get the lookups for the old and new keys.
  132.         $oldLookup = $this->getKeyLookup($oldKeys);
  133.         $newLookup = $this->getKeyLookup($newKeys);
  134.  
  135.         // Loop through each key in the new structure.
  136.         foreach ($newLookup as $name => $keys)
  137.         {
  138.             // Check if there are keys on this field in the existing table.
  139.             if (isset($oldLookup[$name]))
  140.             {
  141.                 $same = true;
  142.                 $newCount = count($newLookup[$name]);
  143.                 $oldCount = count($oldLookup[$name]);
  144.  
  145.                 // There is a key on this field in the old and new tables. Are they the same?
  146.                 if ($newCount == $oldCount)
  147.                 {
  148.                     // Need to loop through each key and do a fine grained check.
  149.                     for ($i = 0; $i < $newCount; $i++)
  150.                     {
  151.                         $same = (((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique)
  152.                             && ((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name)
  153.                             && ((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index)
  154.                             && ((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation)
  155.                             && ((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type));
  156.  
  157.                         /*
  158.                         Debug.
  159.                         echo '<pre>';
  160.                         echo '<br />Non_unique:   '.
  161.                             ((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique ? 'Pass' : 'Fail').' '.
  162.                             (string) $newLookup[$name][$i]['Non_unique'].' vs '.$oldLookup[$name][$i]->Non_unique;
  163.                         echo '<br />Column_name:  '.
  164.                             ((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name ? 'Pass' : 'Fail').' '.
  165.                             (string) $newLookup[$name][$i]['Column_name'].' vs '.$oldLookup[$name][$i]->Column_name;
  166.                         echo '<br />Seq_in_index: '.
  167.                             ((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index ? 'Pass' : 'Fail').' '.
  168.                             (string) $newLookup[$name][$i]['Seq_in_index'].' vs '.$oldLookup[$name][$i]->Seq_in_index;
  169.                         echo '<br />Collation:    '.
  170.                             ((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation ? 'Pass' : 'Fail').' '.
  171.                             (string) $newLookup[$name][$i]['Collation'].' vs '.$oldLookup[$name][$i]->Collation;
  172.                         echo '<br />Index_type:   '.
  173.                             ((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type ? 'Pass' : 'Fail').' '.
  174.                             (string) $newLookup[$name][$i]['Index_type'].' vs '.$oldLookup[$name][$i]->Index_type;
  175.                         echo '<br />Same = '.($same ? 'true' : 'false');
  176.                         echo '</pre>';
  177.                          */
  178.  
  179.                         if (!$same)
  180.                         {
  181.                             // Break out of the loop. No need to check further.
  182.                             break;
  183.                         }
  184.                     }
  185.                 }
  186.                 else
  187.                 {
  188.                     // Count is different, just drop and add.
  189.                     $same = false;
  190.                 }
  191.  
  192.                 if (!$same)
  193.                 {
  194.                     $alters[] = $this->getDropKeySQL($table, $name);
  195.                     $alters[] = $this->getAddKeySQL($table, $keys);
  196.                 }
  197.  
  198.                 // Unset this field so that what we have left are fields that need to be removed.
  199.                 unset($oldLookup[$name]);
  200.             }
  201.             else
  202.             {
  203.                 // This is a new key.
  204.                 $alters[] = $this->getAddKeySQL($table, $keys);
  205.             }
  206.         }
  207.  
  208.         // Any keys left are orphans.
  209.         foreach ($oldLookup as $name => $keys)
  210.         {
  211.             if (strtoupper($name) == 'PRIMARY')
  212.             {
  213.                 $alters[] = $this->getDropPrimaryKeySQL($table);
  214.             }
  215.             else
  216.             {
  217.                 $alters[] = $this->getDropKeySQL($table, $name);
  218.             }
  219.         }
  220.  
  221.         return $alters;
  222.     }
  223.  
  224.     /**
  225.      * Get the syntax to alter a column.
  226.      *
  227.      * @param   string            $table  The name of the database table to alter.
  228.      * @param   SimpleXMLElement  $field  The XML definition for the field.
  229.      *
  230.      * @return  string 
  231.      *
  232.      * @since   11.1
  233.      */
  234.     protected function getChangeColumnSQL($table, SimpleXMLElement $field)
  235.     {
  236.         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' CHANGE COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
  237.             . $this->getColumnSQL($field);
  238.     }
  239.  
  240.     /**
  241.      * Get the SQL syntax for a single column that would be included in a table create or alter statement.
  242.      *
  243.      * @param   SimpleXMLElement  $field  The XML field definition.
  244.      *
  245.      * @return  string 
  246.      *
  247.      * @since   11.1
  248.      */
  249.     protected function getColumnSQL(SimpleXMLElement $field)
  250.     {
  251.         // TODO Incorporate into parent class and use $this.
  252.         $blobs = array('text', 'smalltext', 'mediumtext', 'largetext');
  253.  
  254.         $fName = (string) $field['Field'];
  255.         $fType = (string) $field['Type'];
  256.         $fNull = (string) $field['Null'];
  257.         $fDefault = isset($field['Default']) ? (string) $field['Default'] : null;
  258.         $fExtra = (string) $field['Extra'];
  259.  
  260.         $query = $this->db->quoteName($fName) . ' ' . $fType;
  261.  
  262.         if ($fNull == 'NO')
  263.         {
  264.             if (in_array($fType, $blobs) || $fDefault === null)
  265.             {
  266.                 $query .= ' NOT NULL';
  267.             }
  268.             else
  269.             {
  270.                 // TODO Don't quote numeric values.
  271.                 $query .= ' NOT NULL DEFAULT ' . $this->db->quote($fDefault);
  272.             }
  273.         }
  274.         else
  275.         {
  276.             if ($fDefault === null)
  277.             {
  278.                 $query .= ' DEFAULT NULL';
  279.             }
  280.             else
  281.             {
  282.                 // TODO Don't quote numeric values.
  283.                 $query .= ' DEFAULT ' . $this->db->quote($fDefault);
  284.             }
  285.         }
  286.  
  287.         if ($fExtra)
  288.         {
  289.             $query .= ' ' . strtoupper($fExtra);
  290.         }
  291.  
  292.         return $query;
  293.     }
  294.  
  295.     /**
  296.      * Get the SQL syntax to drop a key.
  297.      *
  298.      * @param   string  $table  The table name.
  299.      * @param   string  $name   The name of the key to drop.
  300.      *
  301.      * @return  string 
  302.      *
  303.      * @since   11.1
  304.      */
  305.     protected function getDropKeySQL($table, $name)
  306.     {
  307.         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP KEY ' . $this->db->quoteName($name);
  308.     }
  309.  
  310.     /**
  311.      * Get the SQL syntax to drop a key.
  312.      *
  313.      * @param   string  $table  The table name.
  314.      *
  315.      * @return  string 
  316.      *
  317.      * @since   11.1
  318.      */
  319.     protected function getDropPrimaryKeySQL($table)
  320.     {
  321.         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP PRIMARY KEY';
  322.     }
  323.  
  324.     /**
  325.      * Get the details list of keys for a table.
  326.      *
  327.      * @param   array  $keys  An array of objects that comprise the keys for the table.
  328.      *
  329.      * @return  array  The lookup array. array({key name} => array(object, ...))
  330.      *
  331.      * @since   11.1
  332.      * @throws  Exception
  333.      */
  334.     protected function getKeyLookup($keys)
  335.     {
  336.         // First pass, create a lookup of the keys.
  337.         $lookup = array();
  338.  
  339.         foreach ($keys as $key)
  340.         {
  341.             if ($key instanceof SimpleXMLElement)
  342.             {
  343.                 $kName = (string) $key['Key_name'];
  344.             }
  345.             else
  346.             {
  347.                 $kName = $key->Key_name;
  348.             }
  349.  
  350.             if (empty($lookup[$kName]))
  351.             {
  352.                 $lookup[$kName] = array();
  353.             }
  354.  
  355.             $lookup[$kName][] = $key;
  356.         }
  357.  
  358.         return $lookup;
  359.     }
  360.  
  361.     /**
  362.      * Get the SQL syntax for a key.
  363.      *
  364.      * @param   array  $columns  An array of SimpleXMLElement objects comprising the key.
  365.      *
  366.      * @return  string 
  367.      *
  368.      * @since   11.1
  369.      */
  370.     protected function getKeySQL($columns)
  371.     {
  372.         // TODO Error checking on array and element types.
  373.  
  374.         $kNonUnique = (string) $columns[0]['Non_unique'];
  375.         $kName = (string) $columns[0]['Key_name'];
  376.         $kColumn = (string) $columns[0]['Column_name'];
  377.  
  378.         $prefix = '';
  379.  
  380.         if ($kName == 'PRIMARY')
  381.         {
  382.             $prefix = 'PRIMARY ';
  383.         }
  384.         elseif ($kNonUnique == 0)
  385.         {
  386.             $prefix = 'UNIQUE ';
  387.         }
  388.  
  389.         $nColumns = count($columns);
  390.         $kColumns = array();
  391.  
  392.         if ($nColumns == 1)
  393.         {
  394.             $kColumns[] = $this->db->quoteName($kColumn);
  395.         }
  396.         else
  397.         {
  398.             foreach ($columns as $column)
  399.             {
  400.                 $kColumns[] = (string) $column['Column_name'];
  401.             }
  402.         }
  403.  
  404.         $query = $prefix . 'KEY ' . ($kName != 'PRIMARY' ? $this->db->quoteName($kName) : '') . ' (' . implode(',', $kColumns) . ')';
  405.  
  406.         return $query;
  407.     }
  408. }

Documentation generated on Tue, 19 Nov 2013 15:09:12 +0100 by phpDocumentor 1.4.3