MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file mssql.php

Documentation is available at mssql.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP versions 4 and 5                                                 |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Authors: Frank M. Kromann <frank@kromann.info>                       |
  43. // |          David Coallier <davidc@php.net>                             |
  44. // |          Lorenzo Alberton <l.alberton@quipo.it>                      |
  45. // +----------------------------------------------------------------------+
  46. //
  47. // $Id: mssql.php 327310 2012-08-27 15:16:18Z danielc $
  48. //
  49.  
  50. require_once 'MDB2/Driver/Manager/Common.php';
  51.  
  52. // {{{ class MDB2_Driver_Manager_mssql
  53.  
  54. /**
  55.  * MDB2 MSSQL driver for the management modules
  56.  *
  57.  * @package MDB2
  58.  * @category Database
  59.  * @author  Frank M. Kromann <frank@kromann.info>
  60.  * @author  David Coallier <davidc@php.net>
  61.  * @author  Lorenzo Alberton <l.alberton@quipo.it>
  62.  */
  63. class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common
  64. {
  65.     // {{{ createDatabase()
  66.     /**
  67.      * create a new database
  68.      *
  69.      * @param string $name    name of the database that should be created
  70.      * @param array  $options array with collation info
  71.      *
  72.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  73.      * @access public
  74.      */
  75.     function createDatabase($name$options = array())
  76.     {
  77.         $db $this->getDBInstance();
  78.         if (MDB2::isError($db)) {
  79.             return $db;
  80.         }
  81.  
  82.         $name $db->quoteIdentifier($nametrue);
  83.         $query = "CREATE DATABASE $name";
  84.         if ($db->options['database_device']{
  85.             $query.= ' ON '.$db->options['database_device'];
  86.             $query.= $db->options['database_size''=' .
  87.                      $db->options['database_size''';
  88.         }
  89.         if (!empty($options['collation'])) {
  90.             $query .= ' COLLATE ' $options['collation'];
  91.         }
  92.         return $db->standaloneQuery($querynulltrue);
  93.     }
  94.  
  95.     // }}}
  96.     // {{{ alterDatabase()
  97.  
  98.     /**
  99.      * alter an existing database
  100.      *
  101.      * @param string $name    name of the database that is intended to be changed
  102.      * @param array  $options array with name, collation info
  103.      *
  104.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  105.      * @access public
  106.      */
  107.     function alterDatabase($name$options = array())
  108.     {
  109.         $db $this->getDBInstance();
  110.         if (MDB2::isError($db)) {
  111.             return $db;
  112.         }
  113.  
  114.         $query '';
  115.         if (!empty($options['name'])) {
  116.             $query .= ' MODIFY NAME = ' .$db->quoteIdentifier($options['name']true);
  117.         }
  118.         if (!empty($options['collation'])) {
  119.             $query .= ' COLLATE ' $options['collation'];
  120.         }
  121.         if (!empty($query)) {
  122.             $query 'ALTER DATABASE '$db->quoteIdentifier($nametrue$query;
  123.             return $db->standaloneQuery($querynulltrue);
  124.         }
  125.         return MDB2_OK;
  126.     }
  127.  
  128.     // }}}
  129.     // {{{ dropDatabase()
  130.  
  131.     /**
  132.      * drop an existing database
  133.      *
  134.      * @param string $name name of the database that should be dropped
  135.      *
  136.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  137.      * @access public
  138.      */
  139.     function dropDatabase($name)
  140.     {
  141.         $db $this->getDBInstance();
  142.         if (MDB2::isError($db)) {
  143.             return $db;
  144.         }
  145.  
  146.         $name $db->quoteIdentifier($nametrue);
  147.         return $db->standaloneQuery("DROP DATABASE $name"nulltrue);
  148.     }
  149.  
  150.     // }}}
  151.     // {{{ _getTemporaryTableQuery()
  152.  
  153.     /**
  154.      * Override the parent method.
  155.      *
  156.      * @return string The string required to be placed between "CREATE" and "TABLE"
  157.      *                 to generate a temporary table, if possible.
  158.      */
  159.     function _getTemporaryTableQuery()
  160.     {
  161.         return '';
  162.     }
  163.  
  164.     // }}}
  165.     // {{{ _getAdvancedFKOptions()
  166.  
  167.     /**
  168.      * Return the FOREIGN KEY query section dealing with non-standard options
  169.      * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
  170.      *
  171.      * @param array $definition 
  172.      *
  173.      * @return string 
  174.      * @access protected
  175.      */
  176.     function _getAdvancedFKOptions($definition)
  177.     {
  178.         $query '';
  179.         if (!empty($definition['onupdate'])) {
  180.             $query .= ' ON UPDATE '.$definition['onupdate'];
  181.         }
  182.         if (!empty($definition['ondelete'])) {
  183.             $query .= ' ON DELETE '.$definition['ondelete'];
  184.         }
  185.         return $query;
  186.     }
  187.  
  188.     // }}}
  189.     // {{{ createTable()
  190.  
  191.     /**
  192.      * create a new table
  193.      *
  194.      * @param string $name   Name of the database that should be created
  195.      * @param array  $fields Associative array that contains the definition of each field of the new table
  196.      *                        The indexes of the array entries are the names of the fields of the table an
  197.      *                        the array entry values are associative arrays like those that are meant to be
  198.      *                        passed with the field definitions to get[Type]Declaration() functions.
  199.      *
  200.      *                       Example
  201.      *                         array(
  202.      *
  203.      *                             'id' => array(
  204.      *                                 'type' => 'integer',
  205.      *                                 'unsigned' => 1,
  206.      *                                 'notnull' => 1,
  207.      *                                 'default' => 0,
  208.      *                             ),
  209.      *                             'name' => array(
  210.      *                                 'type' => 'text',
  211.      *                                 'length' => 12,
  212.      *                             ),
  213.      *                             'description' => array(
  214.      *                                 'type' => 'text',
  215.      *                                 'length' => 12,
  216.      *                             )
  217.      *                         );
  218.      * @param array $options An associative array of table options:
  219.      *                           array(
  220.      *                               'comment' => 'Foo',
  221.      *                               'temporary' => true|false,
  222.      *                           );
  223.      *
  224.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  225.      * @access public
  226.      */
  227.     function createTable($name$fields$options = array())
  228.     {
  229.         if (!empty($options['temporary'])) {
  230.             $name '#'.$name;
  231.         }
  232.         return parent::createTable($name$fields$options);
  233.     }
  234.  
  235.     // }}}
  236.     // {{{ truncateTable()
  237.  
  238.     /**
  239.      * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
  240.      * it falls back to a DELETE FROM TABLE query)
  241.      *
  242.      * @param string $name name of the table that should be truncated
  243.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  244.      * @access public
  245.      */
  246.     function truncateTable($name)
  247.     {
  248.         $db $this->getDBInstance();
  249.         if (MDB2::isError($db)) {
  250.             return $db;
  251.         }
  252.  
  253.         $name $db->quoteIdentifier($nametrue);
  254.         $result $db->exec("TRUNCATE TABLE $name");
  255.         if (MDB2::isError($result)) {
  256.             return $result;
  257.         }
  258.         return MDB2_OK;
  259.     }
  260.  
  261.     // }}}
  262.     // {{{ vacuum()
  263.  
  264.     /**
  265.      * Optimize (vacuum) all the tables in the db (or only the specified table)
  266.      * and optionally run ANALYZE.
  267.      *
  268.      * @param string $table table name (all the tables if empty)
  269.      * @param array  $options an array with driver-specific options:
  270.      *                - timeout [int] (in seconds) [mssql-only]
  271.      *                - analyze [boolean] [pgsql and mysql]
  272.      *                - full [boolean] [pgsql-only]
  273.      *                - freeze [boolean] [pgsql-only]
  274.      *
  275.      *  NB: you have to run the NSControl Create utility to enable VACUUM
  276.      *
  277.      * @return mixed MDB2_OK success, a MDB2 error on failure
  278.      * @access public
  279.      */
  280.     function vacuum($table = null$options = array())
  281.     {
  282.         $db $this->getDBInstance();
  283.         if (MDB2::isError($db)) {
  284.             return $db;
  285.         }
  286.         $timeout = isset($options['timeout']? (int)$options['timeout': 300;
  287.  
  288.         $query 'NSControl Create';
  289.         $result $db->exec($query);
  290.         if (MDB2::isError($result)) {
  291.             return $result;
  292.         }
  293.  
  294.         $result $db->exec('EXEC NSVacuum '.$timeout);
  295.         if (MDB2::isError($result)) {
  296.             return $result;
  297.         }
  298.         return MDB2_OK;
  299.     }
  300.  
  301.     // }}}
  302.     // {{{ alterTable()
  303.  
  304.     /**
  305.      * alter an existing table
  306.      *
  307.      * @param string  $name    name of the table that is intended to be changed.
  308.      * @param array   $changes associative array that contains the details of each type
  309.      *                          of change that is intended to be performed. The types of
  310.      *                          changes that are currently supported are defined as follows:
  311.      *
  312.      *                              name
  313.      *
  314.      *                                 New name for the table.
  315.      *
  316.      *                             add
  317.      *
  318.      *                                 Associative array with the names of fields to be added as
  319.      *                                  indexes of the array. The value of each entry of the array
  320.      *                                  should be set to another associative array with the properties
  321.      *                                  of the fields to be added. The properties of the fields should
  322.      *                                  be the same as defined by the MDB2 parser.
  323.      *
  324.      *
  325.      *                             remove
  326.      *
  327.      *                                 Associative array with the names of fields to be removed as indexes
  328.      *                                  of the array. Currently the values assigned to each entry are ignored.
  329.      *                                  An empty array should be used for future compatibility.
  330.      *
  331.      *                             rename
  332.      *
  333.      *                                 Associative array with the names of fields to be renamed as indexes
  334.      *                                  of the array. The value of each entry of the array should be set to
  335.      *                                  another associative array with the entry named name with the new
  336.      *                                  field name and the entry named Declaration that is expected to contain
  337.      *                                  the portion of the field declaration already in DBMS specific SQL code
  338.      *                                  as it is used in the CREATE TABLE statement.
  339.      *
  340.      *                             change
  341.      *
  342.      *                                 Associative array with the names of the fields to be changed as indexes
  343.      *                                  of the array. Keep in mind that if it is intended to change either the
  344.      *                                  name of a field and any other properties, the change array entries
  345.      *                                  should have the new names of the fields as array indexes.
  346.      *
  347.      *                                 The value of each entry of the array should be set to another associative
  348.      *                                  array with the properties of the fields to that are meant to be changed as
  349.      *                                  array entries. These entries should be assigned to the new values of the
  350.      *                                  respective properties. The properties of the fields should be the same
  351.      *                                  as defined by the MDB2 parser.
  352.      *
  353.      *                             Example
  354.      *                                 array(
  355.      *                                     'name' => 'userlist',
  356.      *                                     'add' => array(
  357.      *                                         'quota' => array(
  358.      *                                             'type' => 'integer',
  359.      *                                             'unsigned' => 1
  360.      *                                         )
  361.      *                                     ),
  362.      *                                     'remove' => array(
  363.      *                                         'file_limit' => array(),
  364.      *                                         'time_limit' => array()
  365.      *                                     ),
  366.      *                                     'change' => array(
  367.      *                                         'name' => array(
  368.      *                                             'length' => '20',
  369.      *                                             'definition' => array(
  370.      *                                                 'type' => 'text',
  371.      *                                                 'length' => 20,
  372.      *                                             ),
  373.      *                                         )
  374.      *                                     ),
  375.      *                                     'rename' => array(
  376.      *                                         'sex' => array(
  377.      *                                             'name' => 'gender',
  378.      *                                             'definition' => array(
  379.      *                                                 'type' => 'text',
  380.      *                                                 'length' => 1,
  381.      *                                                 'default' => 'M',
  382.      *                                             ),
  383.      *                                         )
  384.      *                                     )
  385.      *                                 )
  386.      *
  387.      * @param boolean $check   indicates whether the function should just check if the DBMS driver
  388.      *                          can perform the requested table alterations if the value is true or
  389.      *                          actually perform them otherwise.
  390.      *
  391.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  392.      * @access public
  393.      */
  394.     function alterTable($name$changes$check)
  395.     {
  396.         $db $this->getDBInstance();
  397.         if (MDB2::isError($db)) {
  398.             return $db;
  399.         }
  400.         $name_quoted $db->quoteIdentifier($nametrue);
  401.  
  402.         foreach ($changes as $change_name => $change{
  403.             switch ($change_name{
  404.             case 'remove':
  405.             case 'rename':
  406.             case 'add':
  407.             case 'change':
  408.             case 'name':
  409.                 break;
  410.             default:
  411.                 return $db->raiseError(MDB2_ERROR_CANNOT_ALTERnullnull,
  412.                     'change type "'.$change_name.'" not yet supported'__FUNCTION__);
  413.             }
  414.         }
  415.  
  416.         if ($check{
  417.             return MDB2_OK;
  418.         }
  419.  
  420.         $idxname_format $db->getOption('idxname_format');
  421.         $db->setOption('idxname_format''%s');
  422.  
  423.         if (!empty($changes['remove']&& is_array($changes['remove'])) {
  424.             $result $this->_dropConflictingIndices($namearray_keys($changes['remove']));
  425.             if (MDB2::isError($result)) {
  426.                 $db->setOption('idxname_format'$idxname_format);
  427.                 return $result;
  428.             }
  429.             $result $this->_dropConflictingConstraints($namearray_keys($changes['remove']));
  430.             if (MDB2::isError($result)) {
  431.                 $db->setOption('idxname_format'$idxname_format);
  432.                 return $result;
  433.             }
  434.  
  435.             $query '';
  436.             foreach ($changes['remove'as $field_name => $field{
  437.                 if ($query{
  438.                     $query.= ', ';
  439.                 }
  440.                 $field_name $db->quoteIdentifier($field_nametrue);
  441.                 $query.= 'COLUMN ' $field_name;
  442.             }
  443.  
  444.             $result $db->exec("ALTER TABLE $name_quoted DROP $query");
  445.             if (MDB2::isError($result)) {
  446.                 $db->setOption('idxname_format'$idxname_format);
  447.                 return $result;
  448.             }
  449.         }
  450.  
  451.         if (!empty($changes['rename']&& is_array($changes['rename'])) {
  452.             foreach ($changes['rename'as $field_name => $field{
  453.                 $field_name $db->quoteIdentifier($field_nametrue);
  454.                 $result $db->exec("sp_rename '$name_quoted.$field_name', '".$field['name']."', 'COLUMN'");
  455.                 if (MDB2::isError($result)) {
  456.                     $db->setOption('idxname_format'$idxname_format);
  457.                     return $result;
  458.                 }
  459.             }
  460.         }
  461.  
  462.         if (!empty($changes['add']&& is_array($changes['add'])) {
  463.             $query '';
  464.             foreach ($changes['add'as $field_name => $field{
  465.                 if ($query{
  466.                     $query.= ', ';
  467.                 else {
  468.                     $query.= 'ADD ';
  469.                 }
  470.                 $query.= $db->getDeclaration($field['type']$field_name$field);
  471.             }
  472.  
  473.             $result $db->exec("ALTER TABLE $name_quoted $query");
  474.             if (MDB2::isError($result)) {
  475.                 $db->setOption('idxname_format'$idxname_format);
  476.                 return $result;
  477.             }
  478.         }
  479.  
  480.         $dropped_indices     = array();
  481.         $dropped_constraints = array();
  482.  
  483.         if (!empty($changes['change']&& is_array($changes['change'])) {
  484.             $dropped $this->_dropConflictingIndices($namearray_keys($changes['change']));
  485.             if (MDB2::isError($dropped)) {
  486.                 $db->setOption('idxname_format'$idxname_format);
  487.                 return $dropped;
  488.             }
  489.             $dropped_indices array_merge($dropped_indices$dropped);
  490.             $dropped $this->_dropConflictingConstraints($namearray_keys($changes['change']));
  491.             if (MDB2::isError($dropped)) {
  492.                 $db->setOption('idxname_format'$idxname_format);
  493.                 return $dropped;
  494.             }
  495.             $dropped_constraints array_merge($dropped_constraints$dropped);
  496.  
  497.             foreach ($changes['change'as $field_name => $field{
  498.                 //MSSQL doesn't allow multiple ALTER COLUMNs in one query
  499.                 $query 'ALTER COLUMN ';
  500.  
  501.                 //MSSQL doesn't allow changing the DEFAULT value of a field in altering mode
  502.                 if (array_key_exists('default'$field['definition'])) {
  503.                     unset($field['definition']['default']);
  504.                 }
  505.  
  506.                 $query .= $db->getDeclaration($field['definition']['type']$field_name$field['definition']);
  507.                 $result $db->exec("ALTER TABLE $name_quoted $query");
  508.                 if (MDB2::isError($result)) {
  509.                     $db->setOption('idxname_format'$idxname_format);
  510.                     return $result;
  511.                 }
  512.             }
  513.         }
  514.  
  515.         // restore the dropped conflicting indices and constraints
  516.         foreach ($dropped_indices as $index_name => $index{
  517.             $result $this->createIndex($name$index_name$index);
  518.             if (MDB2::isError($result)) {
  519.                 $db->setOption('idxname_format'$idxname_format);
  520.                 return $result;
  521.             }
  522.         }
  523.         foreach ($dropped_constraints as $constraint_name => $constraint{
  524.             $result $this->createConstraint($name$constraint_name$constraint);
  525.             if (MDB2::isError($result)) {
  526.                 $db->setOption('idxname_format'$idxname_format);
  527.                 return $result;
  528.             }
  529.         }
  530.  
  531.         $db->setOption('idxname_format'$idxname_format);
  532.  
  533.         if (!empty($changes['name'])) {
  534.             $new_name $db->quoteIdentifier($changes['name']true);
  535.             $result $db->exec("sp_rename '$name_quoted', '$new_name'");
  536.             if (MDB2::isError($result)) {
  537.                 return $result;
  538.             }
  539.         }
  540.  
  541.         return MDB2_OK;
  542.     }
  543.  
  544.     // }}}
  545.     // {{{ _dropConflictingIndices()
  546.  
  547.     /**
  548.      * Drop the indices that prevent a successful ALTER TABLE action
  549.      *
  550.      * @param string $table  table name
  551.      * @param array  $fields array of names of the fields affected by the change
  552.      *
  553.      * @return array dropped indices definitions
  554.      */
  555.     function _dropConflictingIndices($table$fields)
  556.     {
  557.         $db $this->getDBInstance();
  558.         if (MDB2::isError($db)) {
  559.             return $db;
  560.         }
  561.  
  562.         $dropped = array();
  563.         $index_names $this->listTableIndexes($table);
  564.         if (MDB2::isError($index_names)) {
  565.             return $index_names;
  566.         }
  567.         $db->loadModule('Reverse');
  568.         $indexes = array();
  569.         foreach ($index_names as $index_name{
  570.             $idx_def $db->reverse->getTableIndexDefinition($table$index_name);
  571.             if (!MDB2::isError($idx_def)) {
  572.                 $indexes[$index_name$idx_def;
  573.             }
  574.         }
  575.         foreach ($fields as $field_name{
  576.             foreach ($indexes as $index_name => $index{
  577.                 if (!isset($dropped[$index_name]&& array_key_exists($field_name$index['fields'])) {
  578.                     $dropped[$index_name$index;
  579.                     $result $this->dropIndex($table$index_name);
  580.                     if (MDB2::isError($result)) {
  581.                         return $result;
  582.                     }
  583.                 }
  584.             }
  585.         }
  586.  
  587.         return $dropped;
  588.     }
  589.  
  590.     // }}}
  591.     // {{{ _dropConflictingConstraints()
  592.  
  593.     /**
  594.      * Drop the constraints that prevent a successful ALTER TABLE action
  595.      *
  596.      * @param string $table  table name
  597.      * @param array  $fields array of names of the fields affected by the change
  598.      *
  599.      * @return array dropped constraints definitions
  600.      */
  601.     function _dropConflictingConstraints($table$fields)
  602.     {
  603.         $db $this->getDBInstance();
  604.         if (MDB2::isError($db)) {
  605.             return $db;
  606.         }
  607.  
  608.         $dropped = array();
  609.         $constraint_names $this->listTableConstraints($table);
  610.         if (MDB2::isError($constraint_names)) {
  611.             return $constraint_names;
  612.         }
  613.         $db->loadModule('Reverse');
  614.         $constraints = array();
  615.         foreach ($constraint_names as $constraint_name{
  616.             $cons_def $db->reverse->getTableConstraintDefinition($table$constraint_name);
  617.             if (!MDB2::isError($cons_def)) {
  618.                 $constraints[$constraint_name$cons_def;
  619.             }
  620.         }
  621.         foreach ($fields as $field_name{
  622.             foreach ($constraints as $constraint_name => $constraint{
  623.                 if (!isset($dropped[$constraint_name]&& array_key_exists($field_name$constraint['fields'])) {
  624.                     $dropped[$constraint_name$constraint;
  625.                     $result $this->dropConstraint($table$constraint_name);
  626.                     if (MDB2::isError($result)) {
  627.                         return $result;
  628.                     }
  629.                 }
  630.             }
  631.             // also drop implicit DEFAULT constraints
  632.             $default $this->_getTableFieldDefaultConstraint($table$field_name);
  633.             if (!MDB2::isError($default&& !empty($default)) {
  634.                 $result $this->dropConstraint($table$default);
  635.                 if (MDB2::isError($result)) {
  636.                     return $result;
  637.                 }
  638.             }
  639.         }
  640.  
  641.         return $dropped;
  642.     }
  643.  
  644.     // }}}
  645.     // {{{ _getTableFieldDefaultConstraint()
  646.  
  647.     /**
  648.      * Get the default constraint for a table field
  649.      *
  650.      * @param string $table name of table that should be used in method
  651.      * @param string $field name of field that should be used in method
  652.      *
  653.      * @return mixed name of default constraint on success, a MDB2 error on failure
  654.      * @access private
  655.      */
  656.     function _getTableFieldDefaultConstraint($table$field)
  657.     {
  658.         $db $this->getDBInstance();
  659.         if (MDB2::isError($db)) {
  660.             return $db;
  661.         }
  662.  
  663.         $table $db->quoteIdentifier($tabletrue);
  664.         $field $db->quote($field'text');
  665.         $query = "SELECT OBJECT_NAME(syscolumns.cdefault)
  666.                     FROM syscolumns
  667.                    WHERE syscolumns.id = object_id('$table')
  668.                      AND syscolumns.name = $field
  669.                      AND syscolumns.cdefault <> 0";
  670.         return $db->queryOne($query);
  671.     }
  672.  
  673.     // }}}
  674.     // {{{ listTables()
  675.  
  676.     /**
  677.      * list all tables in the current database
  678.      *
  679.      * @return mixed array of table names on success, a MDB2 error on failure
  680.      * @access public
  681.      */
  682.     function listTables()
  683.     {
  684.         $db $this->getDBInstance();
  685.  
  686.         if (MDB2::isError($db)) {
  687.             return $db;
  688.         }
  689.  
  690.         $query 'EXEC sp_tables @table_type = "\'TABLE\'"';
  691.         $table_names $db->queryCol($querynull2);
  692.         if (MDB2::isError($table_names)) {
  693.             return $table_names;
  694.         }
  695.         $result = array();
  696.         foreach ($table_names as $table_name{
  697.             if (!$this->_fixSequenceName($table_nametrue)) {
  698.                 $result[$table_name;
  699.             }
  700.         }
  701.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  702.             $result array_map(($db->options['field_case'== CASE_LOWER ?
  703.                         'strtolower' 'strtoupper')$result);
  704.         }
  705.         return $result;
  706.     }
  707.  
  708.     // }}}
  709.     // {{{ listTableFields()
  710.  
  711.     /**
  712.      * list all fields in a table in the current database
  713.      *
  714.      * @param string $table name of table that should be used in method
  715.      *
  716.      * @return mixed array of field names on success, a MDB2 error on failure
  717.      * @access public
  718.      */
  719.     function listTableFields($table)
  720.     {
  721.         $db $this->getDBInstance();
  722.         if (MDB2::isError($db)) {
  723.             return $db;
  724.         }
  725.  
  726.         $table $db->quote($table'text');
  727.         $columns $db->queryCol("SELECT c.name
  728.                                     FROM syscolumns c
  729.                                LEFT JOIN sysobjects o ON c.id = o.id
  730.                                    WHERE o.name = $table");
  731.         if (MDB2::isError($columns)) {
  732.             return $columns;
  733.         }
  734.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  735.             $columns array_map(($db->options['field_case'== CASE_LOWER ? 'strtolower' 'strtoupper')$columns);
  736.         }
  737.         return $columns;
  738.     }
  739.  
  740.     // }}}
  741.     // {{{ listTableIndexes()
  742.  
  743.     /**
  744.      * list all indexes in a table
  745.      *
  746.      * @param string $table name of table that should be used in method
  747.      *
  748.      * @return mixed array of index names on success, a MDB2 error on failure
  749.      * @access public
  750.      */
  751.     function listTableIndexes($table)
  752.     {
  753.         $db $this->getDBInstance();
  754.         if (MDB2::isError($db)) {
  755.             return $db;
  756.         }
  757.  
  758.         $key_name 'INDEX_NAME';
  759.         $pk_name 'PK_NAME';
  760.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  761.             if ($db->options['field_case'== CASE_LOWER{
  762.                 $key_name strtolower($key_name);
  763.                 $pk_name  strtolower($pk_name);
  764.             else {
  765.                 $key_name strtoupper($key_name);
  766.                 $pk_name  strtoupper($pk_name);
  767.             }
  768.         }
  769.         $table $db->quote($table'text');
  770.         $query = "EXEC sp_statistics @table_name=$table";
  771.         $indexes $db->queryCol($query'text'$key_name);
  772.         if (MDB2::isError($indexes)) {
  773.             return $indexes;
  774.         }
  775.         $query = "EXEC sp_pkeys @table_name=$table";
  776.         $pk_all $db->queryCol($query'text'$pk_name);
  777.         $result = array();
  778.         foreach ($indexes as $index{
  779.             if (!in_array($index$pk_all&& ($index $this->_fixIndexName($index))) {
  780.                 $result[$index= true;
  781.             }
  782.         }
  783.  
  784.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  785.             $result array_change_key_case($result$db->options['field_case']);
  786.         }
  787.         return array_keys($result);
  788.     }
  789.  
  790.     // }}}
  791.     // {{{ listDatabases()
  792.  
  793.     /**
  794.      * list all databases
  795.      *
  796.      * @return mixed array of database names on success, a MDB2 error on failure
  797.      * @access public
  798.      */
  799.     function listDatabases()
  800.     {
  801.         $db $this->getDBInstance();
  802.         if (MDB2::isError($db)) {
  803.             return $db;
  804.         }
  805.  
  806.         $result $db->queryCol('SELECT name FROM sys.databases');
  807.         if (MDB2::isError($result)) {
  808.             return $result;
  809.         }
  810.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  811.             $result array_map(($db->options['field_case'== CASE_LOWER ? 'strtolower' 'strtoupper')$result);
  812.         }
  813.         return $result;
  814.     }
  815.  
  816.     // }}}
  817.     // {{{ listUsers()
  818.  
  819.     /**
  820.      * list all users
  821.      *
  822.      * @return mixed array of user names on success, a MDB2 error on failure
  823.      * @access public
  824.      */
  825.     function listUsers()
  826.     {
  827.         $db $this->getDBInstance();
  828.         if (MDB2::isError($db)) {
  829.             return $db;
  830.         }
  831.  
  832.         $result $db->queryCol('SELECT DISTINCT loginame FROM master..sysprocesses');
  833.         if (MDB2::isError($result|| empty($result)) {
  834.             return $result;
  835.         }
  836.         foreach (array_keys($resultas $k{
  837.             $result[$ktrim($result[$k]);
  838.         }
  839.         return $result;
  840.     }
  841.  
  842.     // }}}
  843.     // {{{ listFunctions()
  844.  
  845.     /**
  846.      * list all functions in the current database
  847.      *
  848.      * @return mixed array of function names on success, a MDB2 error on failure
  849.      * @access public
  850.      */
  851.     function listFunctions()
  852.     {
  853.         $db $this->getDBInstance();
  854.         if (MDB2::isError($db)) {
  855.             return $db;
  856.         }
  857.  
  858.         $query "SELECT name
  859.                     FROM sysobjects
  860.                    WHERE objectproperty(id, N'IsMSShipped') = 0
  861.                     AND (objectproperty(id, N'IsTableFunction') = 1
  862.                      OR objectproperty(id, N'IsScalarFunction') = 1)";
  863.         /*
  864.         SELECT ROUTINE_NAME
  865.           FROM INFORMATION_SCHEMA.ROUTINES
  866.          WHERE ROUTINE_TYPE = 'FUNCTION'
  867.         */
  868.         $result $db->queryCol($query);
  869.         if (MDB2::isError($result)) {
  870.             return $result;
  871.         }
  872.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  873.             $result array_map(($db->options['field_case'== CASE_LOWER ? 'strtolower' 'strtoupper')$result);
  874.         }
  875.         return $result;
  876.     }
  877.  
  878.     // }}}
  879.     // {{{ listTableTriggers()
  880.  
  881.     /**
  882.      * list all triggers in the database that reference a given table
  883.      *
  884.      * @param string table for which all referenced triggers should be found
  885.      *
  886.      * @return mixed array of trigger names on success,  otherwise, false which
  887.      *                could be a db error if the db is not instantiated or could
  888.      *                be the results of the error that occured during the
  889.      *                querying of the sysobject module.
  890.      * @access public
  891.      */
  892.     function listTableTriggers($table = null)
  893.     {
  894.         $db $this->getDBInstance();
  895.         if (MDB2::isError($db)) {
  896.             return $db;
  897.         }
  898.  
  899.         $table $db->quote($table'text');
  900.         $query "SELECT o.name
  901.                     FROM sysobjects o
  902.                    WHERE xtype = 'TR'
  903.                      AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0";
  904.         if (null !== $table{
  905.             $query .= " AND object_name(parent_obj) = $table";
  906.         }
  907.  
  908.         $result $db->queryCol($query);
  909.         if (MDB2::isError($result)) {
  910.             return $result;
  911.         }
  912.  
  913.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE &&
  914.             $db->options['field_case'== CASE_LOWER)
  915.         {
  916.             $result array_map(($db->options['field_case'== CASE_LOWER ?
  917.                 'strtolower' 'strtoupper')$result);
  918.         }
  919.         return $result;
  920.     }
  921.  
  922.     // }}}
  923.     // {{{ listViews()
  924.  
  925.     /**
  926.      * list all views in the current database
  927.      *
  928.      * @param string database, the current is default
  929.      *
  930.      * @return mixed array of view names on success, a MDB2 error on failure
  931.      * @access public
  932.      */
  933.     function listViews()
  934.     {
  935.         $db $this->getDBInstance();
  936.         if (MDB2::isError($db)) {
  937.             return $db;
  938.         }
  939.  
  940.         $query "SELECT name
  941.                     FROM sysobjects
  942.                    WHERE xtype = 'V'";
  943.         /*
  944.         SELECT *
  945.           FROM sysobjects
  946.          WHERE objectproperty(id, N'IsMSShipped') = 0
  947.            AND objectproperty(id, N'IsView') = 1
  948.         */
  949.  
  950.         $result $db->queryCol($query);
  951.         if (MDB2::isError($result)) {
  952.             return $result;
  953.         }
  954.  
  955.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE &&
  956.             $db->options['field_case'== CASE_LOWER)
  957.         {
  958.             $result array_map(($db->options['field_case'== CASE_LOWER ?
  959.                           'strtolower' 'strtoupper')$result);
  960.         }
  961.         return $result;
  962.     }
  963.  
  964.     // }}}
  965.     // {{{ dropIndex()
  966.  
  967.     /**
  968.      * drop existing index
  969.      *
  970.      * @param string $table name of table that should be used in method
  971.      * @param string $name  name of the index to be dropped
  972.      *
  973.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  974.      * @access public
  975.      */
  976.     function dropIndex($table$name)
  977.     {
  978.         $db $this->getDBInstance();
  979.         if (MDB2::isError($db)) {
  980.             return $db;
  981.         }
  982.  
  983.         $table $db->quoteIdentifier($tabletrue);
  984.         $name $db->quoteIdentifier($db->getIndexName($name)true);
  985.         $result $db->exec("DROP INDEX $table.$name");
  986.         if (MDB2::isError($result)) {
  987.             return $result;
  988.         }
  989.         return MDB2_OK;
  990.     }
  991.  
  992.     // }}}
  993.     // {{{ listTableConstraints()
  994.  
  995.     /**
  996.      * list all constraints in a table
  997.      *
  998.      * @param string $table name of table that should be used in method
  999.      *
  1000.      * @return mixed array of constraint names on success, a MDB2 error on failure
  1001.      * @access public
  1002.      */
  1003.     function listTableConstraints($table)
  1004.     {
  1005.         $db $this->getDBInstance();
  1006.         if (MDB2::isError($db)) {
  1007.             return $db;
  1008.         }
  1009.         $table $db->quote($table'text');
  1010.  
  1011.         $query = "SELECT c.constraint_name
  1012.                     FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
  1013.                    WHERE c.constraint_catalog = DB_NAME()
  1014.                      AND c.table_name = $table";
  1015.         $constraints $db->queryCol($query);
  1016.         if (MDB2::isError($constraints)) {
  1017.             return $constraints;
  1018.         }
  1019.  
  1020.         $result = array();
  1021.         foreach ($constraints as $constraint{
  1022.             $constraint $this->_fixIndexName($constraint);
  1023.             if (!empty($constraint)) {
  1024.                 $result[$constraint= true;
  1025.             }
  1026.         }
  1027.  
  1028.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  1029.             $result array_change_key_case($result$db->options['field_case']);
  1030.         }
  1031.         return array_keys($result);
  1032.     }
  1033.  
  1034.     // }}}
  1035.     // {{{ createSequence()
  1036.  
  1037.     /**
  1038.      * create sequence
  1039.      *
  1040.      * @param string $seq_name name of the sequence to be created
  1041.      * @param string $start    start value of the sequence; default is 1
  1042.      *
  1043.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1044.      * @access public
  1045.      */
  1046.     function createSequence($seq_name$start = 1)
  1047.     {
  1048.         $db $this->getDBInstance();
  1049.         if (MDB2::isError($db)) {
  1050.             return $db;
  1051.         }
  1052.  
  1053.         $sequence_name $db->quoteIdentifier($db->getSequenceName($seq_name)true);
  1054.         $seqcol_name $db->quoteIdentifier($db->options['seqcol_name']true);
  1055.         $query = "CREATE TABLE $sequence_name ($seqcol_name " .
  1056.                  "INT PRIMARY KEY CLUSTERED IDENTITY($start,1) NOT NULL)";
  1057.  
  1058.         $res $db->exec($query);
  1059.         if (MDB2::isError($res)) {
  1060.             return $res;
  1061.         }
  1062.  
  1063.         $query = "SET IDENTITY_INSERT $sequence_name ON ".
  1064.                  "INSERT INTO $sequence_name ($seqcol_name) VALUES ($start)";
  1065.         $res $db->exec($query);
  1066.  
  1067.         if (!MDB2::isError($res)) {
  1068.             return MDB2_OK;
  1069.         }
  1070.  
  1071.         $result $db->exec("DROP TABLE $sequence_name");
  1072.         if (MDB2::isError($result)) {
  1073.             return $db->raiseError($resultnullnull,
  1074.                 'could not drop inconsistent sequence table'__FUNCTION__);
  1075.         }
  1076.  
  1077.         return $db->raiseError($resnullnull,
  1078.             'could not create sequence table'__FUNCTION__);
  1079.     }
  1080.  
  1081.     // }}}
  1082.     // {{{ dropSequence()
  1083.  
  1084.     /**
  1085.      * This function drops an existing sequence
  1086.      *
  1087.      * @param string $seq_name name of the sequence to be dropped
  1088.      *
  1089.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1090.      * @access public
  1091.      */
  1092.     function dropSequence($seq_name)
  1093.     {
  1094.         $db $this->getDBInstance();
  1095.         if (MDB2::isError($db)) {
  1096.             return $db;
  1097.         }
  1098.  
  1099.         $sequence_name $db->quoteIdentifier($db->getSequenceName($seq_name)true);
  1100.         $result $db->exec("DROP TABLE $sequence_name");
  1101.         if (MDB2::isError($result)) {
  1102.             return $result;
  1103.         }
  1104.         return MDB2_OK;
  1105.     }
  1106.  
  1107.     // }}}
  1108.     // {{{ listSequences()
  1109.  
  1110.     /**
  1111.      * list all sequences in the current database
  1112.      *
  1113.      * @return mixed array of sequence names on success, a MDB2 error on failure
  1114.      * @access public
  1115.      */
  1116.     function listSequences()
  1117.     {
  1118.         $db $this->getDBInstance();
  1119.         if (MDB2::isError($db)) {
  1120.             return $db;
  1121.         }
  1122.  
  1123.         $query "SELECT name FROM sysobjects WHERE xtype = 'U'";
  1124.         $table_names $db->queryCol($query);
  1125.         if (MDB2::isError($table_names)) {
  1126.             return $table_names;
  1127.         }
  1128.         $result = array();
  1129.         foreach ($table_names as $table_name{
  1130.             if ($sqn $this->_fixSequenceName($table_nametrue)) {
  1131.                 $result[$sqn;
  1132.             }
  1133.         }
  1134.         if ($db->options['portability'MDB2_PORTABILITY_FIX_CASE{
  1135.             $result array_map(($db->options['field_case'== CASE_LOWER ?
  1136.                           'strtolower' 'strtoupper')$result);
  1137.         }
  1138.         return $result;
  1139.     }
  1140.  
  1141.     // }}}
  1142. }
  1143.  
  1144. // }}}
  1145. ?>

Documentation generated on Mon, 11 Mar 2019 15:51:11 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.