Source for file Mysql.php

Documentation is available at Mysql.php

  1. <?php
  2. /*
  3.  *  $Id: Mysql.php 1730 2007-06-18 18:27:11Z zYne $
  4.  *
  5.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * This software consists of voluntary contributions made by many individuals
  18.  * and is licensed under the LGPL. For more information, see
  19.  * <http://www.phpdoctrine.com>.
  20.  */
  21. Doctrine::autoload('Doctrine_DataDict');
  22. /**
  23.  * @package     Doctrine
  24.  * @subpackage  Doctrine_DataDict
  25.  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
  26.  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
  27.  * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  28.  * @version     $Revision: 1730 $
  29.  * @category    Object Relational Mapping
  30.  * @link        www.phpdoctrine.com
  31.  * @since       1.0
  32.  */
  33. {
  34.     protected $keywords = array(
  35.                           'ADD''ALL''ALTER',
  36.                           'ANALYZE''AND''AS',
  37.                           'ASC''ASENSITIVE''BEFORE',
  38.                           'BETWEEN''BIGINT''BINARY',
  39.                           'BLOB''BOTH''BY',
  40.                           'CALL''CASCADE''CASE',
  41.                           'CHANGE''CHAR''CHARACTER',
  42.                           'CHECK''COLLATE''COLUMN',
  43.                           'CONDITION''CONNECTION''CONSTRAINT',
  44.                           'CONTINUE''CONVERT''CREATE',
  45.                           'CROSS''CURRENT_DATE''CURRENT_TIME',
  46.                           'CURRENT_TIMESTAMP''CURRENT_USER''CURSOR',
  47.                           'DATABASE''DATABASES''DAY_HOUR',
  48.                           'DAY_MICROSECOND''DAY_MINUTE''DAY_SECOND',
  49.                           'DEC''DECIMAL''DECLARE',
  50.                           'DEFAULT''DELAYED''DELETE',
  51.                           'DESC''DESCRIBE''DETERMINISTIC',
  52.                           'DISTINCT''DISTINCTROW''DIV',
  53.                           'DOUBLE''DROP''DUAL',
  54.                           'EACH''ELSE''ELSEIF',
  55.                           'ENCLOSED''ESCAPED''EXISTS',
  56.                           'EXIT''EXPLAIN''FALSE',
  57.                           'FETCH''FLOAT''FLOAT4',
  58.                           'FLOAT8''FOR''FORCE',
  59.                           'FOREIGN''FROM''FULLTEXT',
  60.                           'GRANT''GROUP''HAVING',
  61.                           'HIGH_PRIORITY''HOUR_MICROSECOND''HOUR_MINUTE',
  62.                           'HOUR_SECOND''IF''IGNORE',
  63.                           'IN''INDEX''INFILE',
  64.                           'INNER''INOUT''INSENSITIVE',
  65.                           'INSERT''INT''INT1',
  66.                           'INT2''INT3''INT4',
  67.                           'INT8''INTEGER''INTERVAL',
  68.                           'INTO''IS''ITERATE',
  69.                           'JOIN''KEY''KEYS',
  70.                           'KILL''LEADING''LEAVE',
  71.                           'LEFT''LIKE''LIMIT',
  72.                           'LINES''LOAD''LOCALTIME',
  73.                           'LOCALTIMESTAMP''LOCK''LONG',
  74.                           'LONGBLOB''LONGTEXT''LOOP',
  75.                           'LOW_PRIORITY''MATCH''MEDIUMBLOB',
  76.                           'MEDIUMINT''MEDIUMTEXT''MIDDLEINT',
  77.                           'MINUTE_MICROSECOND''MINUTE_SECOND''MOD',
  78.                           'MODIFIES''NATURAL''NOT',
  79.                           'NO_WRITE_TO_BINLOG''NULL''NUMERIC',
  80.                           'ON''OPTIMIZE''OPTION',
  81.                           'OPTIONALLY''OR''ORDER',
  82.                           'OUT''OUTER''OUTFILE',
  83.                           'PRECISION''PRIMARY''PROCEDURE',
  84.                           'PURGE''RAID0''READ',
  85.                           'READS''REAL''REFERENCES',
  86.                           'REGEXP''RELEASE''RENAME',
  87.                           'REPEAT''REPLACE''REQUIRE',
  88.                           'RESTRICT''RETURN''REVOKE',
  89.                           'RIGHT''RLIKE''SCHEMA',
  90.                           'SCHEMAS''SECOND_MICROSECOND''SELECT',
  91.                           'SENSITIVE''SEPARATOR''SET',
  92.                           'SHOW''SMALLINT''SONAME',
  93.                           'SPATIAL''SPECIFIC''SQL',
  94.                           'SQLEXCEPTION''SQLSTATE''SQLWARNING',
  95.                           'SQL_BIG_RESULT''SQL_CALC_FOUND_ROWS''SQL_SMALL_RESULT',
  96.                           'SSL''STARTING''STRAIGHT_JOIN',
  97.                           'TABLE''TERMINATED''THEN',
  98.                           'TINYBLOB''TINYINT''TINYTEXT',
  99.                           'TO''TRAILING''TRIGGER',
  100.                           'TRUE''UNDO''UNION',
  101.                           'UNIQUE''UNLOCK''UNSIGNED',
  102.                           'UPDATE''USAGE''USE',
  103.                           'USING''UTC_DATE''UTC_TIME',
  104.                           'UTC_TIMESTAMP''VALUES''VARBINARY',
  105.                           'VARCHAR''VARCHARACTER''VARYING',
  106.                           'WHEN''WHERE''WHILE',
  107.                           'WITH''WRITE''X509',
  108.                           'XOR''YEAR_MONTH''ZEROFILL'
  109.                           );
  110.  
  111.     /**
  112.      * Obtain DBMS specific SQL code portion needed to declare an text type
  113.      * field to be used in statements like CREATE TABLE.
  114.      *
  115.      * @param array $field  associative array with the name of the properties
  116.      *       of the field being declared as array indexes. Currently, the types
  117.      *       of supported field properties are as follows:
  118.      *
  119.      *       length
  120.      *           Integer value that determines the maximum length of the text
  121.      *           field. If this argument is missing the field should be
  122.      *           declared to have the longest length allowed by the DBMS.
  123.      *
  124.      *       default
  125.      *           Text value to be used as default for this field.
  126.      *
  127.      *       notnull
  128.      *           Boolean flag that indicates whether this field is constrained
  129.      *           to not be set to null.
  130.      *
  131.      * @return string  DBMS specific SQL code portion that should be used to
  132.      *       declare the specified field.
  133.      */
  134.     public function getNativeDeclaration($field)
  135.     {
  136.         if isset($field['type'])) {
  137.             throw new Doctrine_DataDict_Exception('Missing column type.');
  138.         }
  139.  
  140.         switch ($field['type']{
  141.             case 'char':
  142.                 $length (empty($field['length'])) $field['length'false;
  143.  
  144.                 return $length 'CHAR('.$length.')' 'CHAR(255)';
  145.             case 'varchar':
  146.             case 'array':
  147.             case 'object':
  148.             case 'string':
  149.             case 'gzip':
  150.                 if isset($field['length'])) {
  151.                     if (array_key_exists('default'$field)) {
  152.                         $field['length'$this->conn->varchar_max_length;
  153.                     else {
  154.                         $field['length'false;
  155.                     }
  156.                 }
  157.  
  158.                 $length ($field['length'<= $this->conn->varchar_max_length$field['length'false;
  159.                 $fixed  (isset($field['fixed'])) $field['fixed'false;
  160.  
  161.                 return $fixed ($length 'CHAR(' $length ')' 'CHAR(255)')
  162.                     : ($length 'VARCHAR(' $length ')' 'TEXT');
  163.             case 'clob':
  164.                 if (!empty($field['length'])) {
  165.                     $length $field['length'];
  166.                     if ($length <= 255{
  167.                         return 'TINYTEXT';
  168.                     elseif ($length <= 65532{
  169.                         return 'TEXT';
  170.                     elseif ($length <= 16777215{
  171.                         return 'MEDIUMTEXT';
  172.                     }
  173.                 }
  174.                 return 'LONGTEXT';
  175.             case 'blob':
  176.                 if (!empty($field['length'])) {
  177.                     $length $field['length'];
  178.                     if ($length <= 255{
  179.                         return 'TINYBLOB';
  180.                     elseif ($length <= 65532{
  181.                         return 'BLOB';
  182.                     elseif ($length <= 16777215{
  183.                         return 'MEDIUMBLOB';
  184.                     }
  185.                 }
  186.                 return 'LONGBLOB';
  187.             case 'integer':
  188.             case 'int':
  189.             case 'enum':
  190.                 if (!empty($field['length'])) {
  191.                     $length $field['length'];
  192.                     if ($length <= 1{
  193.                         return 'TINYINT';
  194.                     elseif ($length == 2{
  195.                         return 'SMALLINT';
  196.                     elseif ($length == 3{
  197.                         return 'MEDIUMINT';
  198.                     elseif ($length == 4{
  199.                         return 'INT';
  200.                     elseif ($length 4{
  201.                         return 'BIGINT';
  202.                     }
  203.                 }
  204.                 return 'INT';
  205.             case 'boolean':
  206.                 return 'TINYINT(1)';
  207.             case 'date':
  208.                 return 'DATE';
  209.             case 'time':
  210.                 return 'TIME';
  211.             case 'timestamp':
  212.                 return 'DATETIME';
  213.             case 'float':
  214.             case 'double':
  215.                 return 'DOUBLE';
  216.             case 'decimal':
  217.                 $length !empty($field['length']$field['length'18;
  218.                 $scale !empty($field['scale']$field['scale'$this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
  219.                 return 'DECIMAL('.$length.','.$scale.')';
  220.         }
  221.         throw new Doctrine_DataDict_Exception('Unknown field type \'' $field['type'.  '\'.');
  222.     }
  223.     /**
  224.      * Maps a native array description of a field to a MDB2 datatype and length
  225.      *
  226.      * @param array  $field native field description
  227.      * @return array containing the various possible types, length, sign, fixed
  228.      */
  229.     public function getPortableDeclaration(array $field)
  230.     {
  231.         $dbType strtolower($field['type']);
  232.         $dbType strtok($dbType'(), ');
  233.         if ($dbType == 'national'{
  234.             $dbType strtok('(), ');
  235.         }
  236.         if (isset($field['length'])) {
  237.             $length $field['length'];
  238.             $decimal '';
  239.         else {
  240.             $length strtok('(), ');
  241.             $decimal strtok('(), ');
  242.         }
  243.         $type array();
  244.         $unsigned $fixed null;
  245.  
  246.         if isset($field['name'])) {
  247.             $field['name''';
  248.         }
  249.  
  250.         $values null;
  251.  
  252.         switch ($dbType{
  253.             case 'tinyint':
  254.                 $type['integer';
  255.                 $type['boolean';
  256.                 if (preg_match('/^(is|has)/'$field['name'])) {
  257.                     $type array_reverse($type);
  258.                 }
  259.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  260.                 $length 1;
  261.             break;
  262.             case 'smallint':
  263.                 $type['integer';
  264.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  265.                 $length 2;
  266.             break;
  267.             case 'mediumint':
  268.                 $type['integer';
  269.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  270.                 $length 3;
  271.             break;
  272.             case 'int':
  273.             case 'integer':
  274.                 $type['integer';
  275.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  276.                 $length 4;
  277.             break;
  278.             case 'bigint':
  279.                 $type['integer';
  280.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  281.                 $length 8;
  282.             break;
  283.             case 'tinytext':
  284.             case 'mediumtext':
  285.             case 'longtext':
  286.             case 'text':
  287.             case 'text':
  288.             case 'varchar':
  289.                 $fixed false;
  290.             case 'string':
  291.             case 'char':
  292.                 $type['string';
  293.                 if ($length == '1'{
  294.                     $type['boolean';
  295.                     if (preg_match('/^(is|has)/'$field['name'])) {
  296.                         $type array_reverse($type);
  297.                     }
  298.                 elseif (strstr($dbType'text')) {
  299.                     $type['clob';
  300.                     if ($decimal == 'binary'{
  301.                         $type['blob';
  302.                     }
  303.                 }
  304.                 if ($fixed !== false{
  305.                     $fixed true;
  306.                 }
  307.             break;
  308.             case 'enum':
  309.                 $type['enum';
  310.                 preg_match_all('/\'.+\'/U'$field['type']$matches);
  311.                 $length 0;
  312.                 $fixed false;
  313.                 if (is_array($matches)) {
  314.                     foreach ($matches[0as $value{
  315.                         $length max($lengthstrlen($value)-2);
  316.                     }
  317.                     if ($length == '1' && count($matches[0]== 2{
  318.                         $type['boolean';
  319.                         if (preg_match('/^(is|has)/'$field['name'])) {
  320.                             $type array_reverse($type);
  321.                         }
  322.                     else {
  323.                         $values $matches[0];
  324.                     }
  325.                 }
  326.                 $type['integer';
  327.             case 'set':
  328.                 $fixed false;
  329.                 $type['text';
  330.                 $type['integer';
  331.             break;
  332.             case 'date':
  333.                 $type['date';
  334.                 $length null;
  335.             break;
  336.             case 'datetime':
  337.             case 'timestamp':
  338.                 $type['timestamp';
  339.                 $length null;
  340.             break;
  341.             case 'time':
  342.                 $type['time';
  343.                 $length null;
  344.             break;
  345.             case 'float':
  346.             case 'double':
  347.             case 'real':
  348.                 $type['float';
  349.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  350.             break;
  351.             case 'unknown':
  352.             case 'decimal':
  353.             case 'numeric':
  354.                 $type['decimal';
  355.                 $unsigned preg_match('/ unsigned/i'$field['type']);
  356.             break;
  357.             case 'tinyblob':
  358.             case 'mediumblob':
  359.             case 'longblob':
  360.             case 'blob':
  361.                 $type['blob';
  362.                 $length null;
  363.             break;
  364.             case 'year':
  365.                 $type['integer';
  366.                 $type['date';
  367.                 $length null;
  368.             break;
  369.             default:
  370.                 throw new Doctrine_DataDict_Exception('unknown database attribute type: ' $dbType);
  371.         }
  372.  
  373.         $length ((int) $length == 0null : (int) $length;
  374.  
  375.         if ($values === null{
  376.             return array('type' => $type'length' => $length'unsigned' => $unsigned'fixed' => $fixed);
  377.         else {
  378.             return array('type' => $type'length' => $length'unsigned' => $unsigned'fixed' => $fixed'values' => $values);
  379.         }
  380.     }
  381.     /**
  382.      * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
  383.      * of a field declaration to be used in statements like CREATE TABLE.
  384.      *
  385.      * @param string $charset   name of the charset
  386.      * @return string  DBMS specific SQL code portion needed to set the CHARACTER SET
  387.      *                  of a field declaration.
  388.      */
  389.     public function getCharsetFieldDeclaration($charset)
  390.     {
  391.         return 'CHARACTER SET ' $charset;
  392.     }
  393.     /**
  394.      * Obtain DBMS specific SQL code portion needed to set the COLLATION
  395.      * of a field declaration to be used in statements like CREATE TABLE.
  396.      *
  397.      * @param string $collation   name of the collation
  398.      * @return string  DBMS specific SQL code portion needed to set the COLLATION
  399.      *                  of a field declaration.
  400.      */
  401.     public function getCollationFieldDeclaration($collation)
  402.     {
  403.         return 'COLLATE ' $collation;
  404.     }
  405.     /**
  406.      * Obtain DBMS specific SQL code portion needed to declare an integer type
  407.      * field to be used in statements like CREATE TABLE.
  408.      *
  409.      * @param string  $name   name the field to be declared.
  410.      * @param string  $field  associative array with the name of the properties
  411.      *                         of the field being declared as array indexes.
  412.      *                         Currently, the types of supported field
  413.      *                         properties are as follows:
  414.      *
  415.      *                        unsigned
  416.      *                         Boolean flag that indicates whether the field
  417.      *                         should be declared as unsigned integer if
  418.      *                         possible.
  419.      *
  420.      *                        default
  421.      *                         Integer value to be used as default for this
  422.      *                         field.
  423.      *
  424.      *                        notnull
  425.      *                         Boolean flag that indicates whether this field is
  426.      *                         constrained to not be set to null.
  427.      * @return string  DBMS specific SQL code portion that should be used to
  428.      *                  declare the specified field.
  429.      */
  430.     public function getIntegerDeclaration($name$field)
  431.     {
  432.         $default $autoinc '';
  433.         if (!empty($field['autoincrement'])) {
  434.             $autoinc ' AUTO_INCREMENT';
  435.         elseif (array_key_exists('default'$field)) {
  436.             if ($field['default'=== ''{
  437.                 $field['default'empty($field['notnull']null 0;
  438.             }
  439.             $default ' DEFAULT '.$this->conn->quote($field['default']);
  440.         }
  441.         /**
  442.         elseif (empty($field['notnull'])) {
  443.             $default = ' DEFAULT NULL';
  444.         }
  445.         */
  446.  
  447.         $notnull  (isset($field['notnull'])  && $field['notnull'])  ' NOT NULL' '';
  448.         $unsigned (isset($field['unsigned']&& $field['unsigned']' UNSIGNED' '';
  449.  
  450.         $name $this->conn->quoteIdentifier($nametrue);
  451.  
  452.         return $name ' ' $this->getNativeDeclaration($field$unsigned $default $notnull $autoinc;
  453.     }
  454. }