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

Source for file mssql.php

Documentation is available at mssql.php

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  7. // | Stig. S. Bakken, Lukas Smith, Frank M. Kromann                       |
  8. // | All rights reserved.                                                 |
  9. // +----------------------------------------------------------------------+
  10. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  11. // | API as well as database abstraction for PHP applications.            |
  12. // | This LICENSE is in the BSD license style.                            |
  13. // |                                                                      |
  14. // | Redistribution and use in source and binary forms, with or without   |
  15. // | modification, are permitted provided that the following conditions   |
  16. // | are met:                                                             |
  17. // |                                                                      |
  18. // | Redistributions of source code must retain the above copyright       |
  19. // | notice, this list of conditions and the following disclaimer.        |
  20. // |                                                                      |
  21. // | Redistributions in binary form must reproduce the above copyright    |
  22. // | notice, this list of conditions and the following disclaimer in the  |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // |                                                                      |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission.                                                  |
  29. // |                                                                      |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Frank M. Kromann <frank@kromann.info>                        |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id: mssql.php,v 1.6.4.30 2004/04/10 07:57:16 lsmith Exp $
  47. //
  48.  
  49. require_once('MDB/Common.php');
  50.  
  51. /**
  52.  * MDB MSSQL Server driver
  53.  *
  54.  * Notes:
  55.  * - Until at least version 6.5, the only kind of table changes that the
  56.  *   ALTER TABLE SQL statement of Microsoft SQL server supports is new field
  57.      and constraint additions.
  58.  *
  59.  * - The driver alterTable method does not implement table or column renaming,
  60.  *   column definitions changes or column dropping. In the future versions of
  61.  *   this driver those capabilities may be emulated using other SQL statements
  62.  *   to recreate the tables with a new definition.
  63.  *
  64.  *   MDB_Manager_mssql::getTableFieldDefinition() is still alpha quality
  65.  *
  66.  * @package MDB
  67.  * @category Database
  68.  * @author  Frank M. Kromann <frank@kromann.info>
  69.  */
  70. class MDB_mssql extends MDB_Common
  71. {
  72.     // {{{ properties
  73.  
  74.     var $connection = 0;
  75.     var $connected_host;
  76.     var $connected_user;
  77.     var $connected_password;
  78.     var $connected_port;
  79.     var $opened_persistent = '';
  80.  
  81.     var $escape_quotes = "'";
  82.  
  83.     var $highest_fetched_row = array();
  84.     var $columns = array();
  85.  
  86.     // }}}
  87.     // {{{ constructor
  88.  
  89.     /**
  90.     * Constructor
  91.     */
  92.     function MDB_mssql()
  93.     {
  94.         $this->MDB_Common();
  95.         $this->phptype 'mssql';
  96.         $this->dbsyntax 'mssql';
  97.  
  98.         $this->supported['Sequences'= 1;
  99.         $this->supported['Indexes'= 1;
  100.         $this->supported['AffectedRows'= 1;
  101.         $this->supported['Transactions'= 1;
  102.         $this->supported['Summaryfunctions'= 1;
  103.         $this->supported['OrderByText'= 0;
  104.         $this->supported['CurrId'= 0;
  105.         $this->supported['SelectRowRanges'= 1;
  106.         $this->supported['LOBs'= 1;
  107.         $this->supported['Replace'= 1;
  108.         $this->supported['SubSelects'= 1;
  109.  
  110.         $this->errorcode_map = array(
  111.             207   => MDB_ERROR_NOSUCHFIELD,
  112.             208   => MDB_ERROR_NOSUCHTABLE,
  113.             245   => MDB_ERROR_INVALID_NUMBER,
  114.             515   => MDB_ERROR_CONSTRAINT_NOT_NULL,
  115.             547   => MDB_ERROR_CONSTRAINT,
  116.             1205  => MDB_ERROR_DEADLOCK,
  117.             2627  => MDB_ERROR_CONSTRAINT,
  118.             2714  => MDB_ERROR_ALREADY_EXISTS,
  119.             3701  => MDB_ERROR_NOSUCHTABLE,
  120.             8134  => MDB_ERROR_DIVZERO,
  121.         );
  122.     }
  123.  
  124.     // }}}
  125.     // {{{ errorNative()
  126.  
  127.     /**
  128.      * Get the native error code of the last error (if any) that
  129.      * occured on the current connection.
  130.      *
  131.      * @access public
  132.      *
  133.      * @return int native FrontBase error code
  134.      */
  135.     function errorNative()
  136.     {
  137.        $res @mssql_query('select @@ERROR as ErrorCode'$this->connection);
  138.        if ($res{
  139.            $row @mssql_fetch_row($res);
  140.            if (is_array($row&& $row[0> 0{
  141.                return $row[0];
  142.            }
  143.        }
  144.        return NULL;
  145.     }
  146.  
  147.     // }}}
  148.     // {{{ mssqlRaiseError()
  149.  
  150.     /**
  151.      * This method is used to communicate an error and invoke error
  152.      * callbacks etc.  Basically a wrapper for MDB::raiseError
  153.      * that checks for native error msgs.
  154.      *
  155.      * @param string  $message userinfo message
  156.      * @param integer $errno error code
  157.      * @return object PEAR error object
  158.      * @access public
  159.      * @see PEAR_Error
  160.      */
  161.     function mssqlRaiseError($errno = NULL$message = NULL)
  162.     {
  163.         if ($errno == NULL{
  164.             $errno $this->errorNative();
  165.         }
  166.         $error @mssql_get_last_message();
  167.         return $this->raiseError($this->errorCode()NULLNULL,
  168.             $message$error);
  169.     }
  170.  
  171.     // }}}
  172.     // {{{ quoteIdentifier()
  173.  
  174.     /**
  175.      * Quote a string so it can be safely used as a table / column name
  176.      *
  177.      * Quoting style depends on which database driver is being used.
  178.      *
  179.      * @param string $str  identifier name to be quoted
  180.      *
  181.      * @return string  quoted identifier string
  182.      *
  183.      * @since 1.6.0
  184.      * @access public
  185.      */
  186.     function quoteIdentifier($str)
  187.     {
  188.         return '[' str_replace(']'']]'$str']';
  189.     }
  190.  
  191.     // }}}
  192.     // {{{ autoCommit()
  193.  
  194.     /**
  195.      * Define whether database changes done on the database be automatically
  196.      * committed. This function may also implicitly start or end a transaction.
  197.      *
  198.      * @param boolean $auto_commit    flag that indicates whether the database
  199.      *                                 changes should be committed right after
  200.      *                                 executing every query statement. If this
  201.      *                                 argument is 0 a transaction implicitly
  202.      *                                 started. Otherwise, if a transaction is
  203.      *                                 in progress it is ended by committing any
  204.      *                                 database changes that were pending.
  205.      *
  206.      * @access public
  207.      *
  208.      * @return mixed MDB_OK on success, a MDB error on failure
  209.      */
  210.     function autoCommit($auto_commit)
  211.     {
  212.         $this->debug("AutoCommit: ".($auto_commit "On" "Off"));
  213.         if (!isset($this->supported['Transactions'])) {
  214.             return($this->raiseError(MDB_ERROR_UNSUPPORTEDNULLNULL,
  215.                 'Auto-commit transactions: transactions are not in use'));
  216.         }
  217.         if ($this->auto_commit == $auto_commit{
  218.             return(MDB_OK);
  219.         }
  220.         if ($this->connection{
  221.             if ($auto_commit{
  222.                 $result $this->query('COMMIT TRANSACTION');
  223.             else {
  224.                 $result $this->query('BEGIN TRANSACTION');
  225.             }
  226.             if (MDB::isError($result)) {
  227.                 return($result);
  228.             }
  229.         }
  230.         $this->auto_commit $auto_commit;
  231.         $this->in_transaction !$auto_commit;
  232.         return(MDB_OK);
  233.     }
  234.  
  235.     // }}}
  236.     // {{{ commit()
  237.  
  238.     /**
  239.      * Commit the database changes done during a transaction that is in
  240.      * progress. This function may only be called when auto-committing is
  241.      * disabled, otherwise it will fail. Therefore, a new transaction is
  242.      * implicitly started after committing the pending changes.
  243.      *
  244.      * @access public
  245.      *
  246.      * @return mixed MDB_OK on success, a MDB error on failure
  247.      */
  248.     function commit()
  249.     {
  250.         $this->debug("Commit Transaction");
  251.         if (!isset($this->supported['Transactions'])) {
  252.             return($this->raiseError(MDB_ERROR_UNSUPPORTEDNULLNULL,
  253.                 'Commit transactions: transactions are not in use'));
  254.         }
  255.         if ($this->auto_commit{
  256.             return($this->raiseError(MDB_ERRORNULLNULL,
  257.             'Commit transactions: transaction changes are being auto commited'));
  258.         }
  259.         $result $this->query('COMMIT TRANSACTION');
  260.         if (MDB::isError($result)) {
  261.             return($result);
  262.         }
  263.         return($this->query('BEGIN TRANSACTION'));
  264.     }
  265.  
  266.     // }}}
  267.     // {{{ rollback()
  268.  
  269.     /**
  270.      * Cancel any database changes done during a transaction that is in
  271.      * progress. This function may only be called when auto-committing is
  272.      * disabled, otherwise it will fail. Therefore, a new transaction is
  273.      * implicitly started after canceling the pending changes.
  274.      *
  275.      * @access public
  276.      *
  277.      * @return mixed MDB_OK on success, a MDB error on failure
  278.      */
  279.     function rollback()
  280.     {
  281.         $this->debug("Rollback Transaction");
  282.         if (!isset($this->supported['Transactions'])) {
  283.             return($this->raiseError(MDB_ERROR_UNSUPPORTEDNULLNULL,
  284.                 'Rollback transactions: transactions are not in use'));
  285.         }
  286.         if ($this->auto_commit{
  287.             return($this->raiseError(MDB_ERRORNULLNULL,
  288.                 'Rollback transactions: transactions can not be rolled back when changes are auto commited'));
  289.         }
  290.         $result $this->query('ROLLBACK TRANSACTION');
  291.         if (MDB::isError($result)) {
  292.             return($result);
  293.         }
  294.         return($this->query('BEGIN TRANSACTION'));
  295.     }
  296.  
  297.     function _doQuery($query)
  298.     {
  299.         $this->current_row $this->affected_rows = -1;
  300.         return(@mssql_query($query$this->connection));
  301.     }
  302.  
  303.     // }}}
  304.     // {{{ connect()
  305.  
  306.     /**
  307.      * Connect to the database
  308.      *
  309.      * @return TRUE on success, MDB_Error on failure
  310.      ***/
  311.     function connect()
  312.     {
  313.         $port (isset($this->port$this->port '');
  314.         if($this->connection != 0{
  315.             if (!strcmp($this->connected_host$this->host)
  316.                 && !strcmp($this->connected_user$this->user)
  317.                 && !strcmp($this->connected_password$this->password)
  318.                 && !strcmp($this->connected_port$port)
  319.                 && $this->opened_persistent == $this->options['persistent'])
  320.             {
  321.                 return(MDB_OK);
  322.             }
  323.             @mssql_close($this->connection);
  324.             $this->connection = 0;
  325.             $this->affected_rows = -1;
  326.         }
  327.  
  328.         if(!PEAR::loadExtension($this->phptype)) {
  329.             return(PEAR::raiseError(NULLMDB_ERROR_NOT_FOUND,
  330.                 NULLNULL'extension '.$this->phptype.' is not compiled into PHP',
  331.                 'MDB_Error'TRUE));
  332.         }
  333.  
  334.         $function ($this->options['persistent''mssql_pconnect' 'mssql_connect');
  335.         if (!function_exists($function)) {
  336.             return($this->raiseError(MDB_ERROR_UNSUPPORTED));
  337.         }
  338.  
  339.         @ini_set('track_errors'TRUE);
  340.         $this->connection = @$function(
  341.             $this->host.(!strcmp($port,'''' ':'.$port),
  342.             $this->user$this->password);
  343.         @ini_restore('track_errors');
  344.         if ($this->connection <= 0{
  345.             return($this->raiseError(MDB_ERROR_CONNECT_FAILEDNULLNULL,
  346.                 $php_errormsg));
  347.         }
  348.  
  349.         if(isset($this->supported['Transactions']&& !$this->auto_commit
  350.             && !$this->_doQuery("BEGIN TRANSACTION"))
  351.         {
  352.             @mssql_close($this->connection);
  353.             $this->connection = 0;
  354.             $this->affected_rows = -1;
  355.             return($this->raiseError("Connect: Could not begin the initial transaction"));
  356.         }
  357.         $this->connected_host = $this->host;
  358.         $this->connected_user = $this->user;
  359.         $this->connected_password = $this->password;
  360.         $this->connected_port = $port;
  361.         $this->selected_database $this->database_name;
  362.         $this->opened_persistent = $this->getoption('persistent');
  363.         return(MDB_OK);
  364.     }
  365.  
  366.     // }}}
  367.     // {{{ _close()
  368.     /**
  369.      * all the RDBMS specific things needed close a DB connection
  370.      *
  371.      * @return boolean 
  372.      * @access private
  373.      ***/
  374.     function _close()
  375.     {
  376.         if ($this->connection != 0{
  377.             if (isset($this->supported['Transactions']&& !$this->auto_commit{
  378.                 $result $this->_doQuery("ROLLBACK TRANSACTION");
  379.             }
  380.             @mssql_close($this->connection);
  381.             $this->connection = 0;
  382.             $this->affected_rows $this->current_row = -1;
  383.  
  384.             if (isset($result&& MDB::isError($result)) {
  385.                 return($result);
  386.             }
  387.             unset($GLOBALS['_MDB_databases'][$this->database]);
  388.             return(TRUE);
  389.         }
  390.         return(FALSE);
  391.     }
  392.  
  393.     function standaloneQuery($query)
  394.     {
  395.         if(!PEAR::loadExtension($this->phptype)) {
  396.             return(PEAR::raiseError(NULLMDB_ERROR_NOT_FOUND,
  397.                 NULLNULL'extension '.$this->phptype.' is not compiled into PHP',
  398.                 'MDB_Error'TRUE));
  399.         }
  400.         $connection @mssql_connect($this->host,$this->user,$this->password);
  401.         if($connection == 0{
  402.             return($this->mssqlRaiseError(NULL"Query: Could not connect to the Microsoft SQL server"));
  403.         }
  404.         $result @mssql_query($query$connection);
  405.         if(!$result{
  406.             return($this->mssqlRaiseError(NULL"Query: Could not query a Microsoft SQL server"));
  407.         }
  408.         @mssql_close($connection);
  409.         return(MDB_OK);
  410.     }
  411.  
  412.     // }}}
  413.     // {{{ query()
  414.  
  415.     /**
  416.      * Send a query to the database and return any results
  417.      *
  418.      * @access public
  419.      *
  420.      * @param string  $query  the SQL query
  421.      * @param mixed   $types  array that contains the types of the columns in
  422.      *                         the result set
  423.      *
  424.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  425.      */
  426.     function query($query$types = NULL)
  427.     {
  428.         $this->debug("Query: $query");
  429.         if ($this->database_name{
  430.             $ismanip MDB::isManip($query);
  431.             $this->last_query $query;
  432.             $first $this->first_selected_row;
  433.             $limit $this->selected_row_limit;
  434.             $this->first_selected_row $this->selected_row_limit = 0;
  435.  
  436.             $last_connection $this->connection;
  437.             $result $this->connect();
  438.             if (MDB::isError($result)) {
  439.                 return($result);
  440.             }
  441.             if($limit > 0{
  442.                 $fetch $first $limit;
  443.                 if (!$ismanip{
  444.                     $query str_replace('SELECT'"SELECT TOP $fetch"$query);
  445.                 }
  446.             }
  447.             if$last_connection != $this->connection
  448.                 || !strcmp($this->selected_database'')
  449.                 || strcmp($this->selected_database$this->database_name))
  450.             {
  451.                 if(!@mssql_select_db($this->database_name$this->connection)) {
  452.                     return($this->mssqlRaiseError());
  453.                 }
  454.             }
  455.             if ($result $this->_doQuery($query)) {
  456.                 if ($ismanip{
  457.                     $this->affected_rows @mssql_rows_affected($this->connection);
  458.                     return(MDB_OK);
  459.                 else {
  460.                     $result_value intval($result);
  461.                     if($first > 0 || $limit > 0{
  462.                         $this->limits[$result_value= array($first$limit);
  463.                     }
  464.                     $this->highest_fetched_row[$result_value= -1;
  465.                     if ($types != NULL{
  466.                         if (!is_array($types)) {
  467.                             $types = array($types);
  468.                         }
  469.                         $err $this->setResultTypes($result$types);
  470.                         if (MDB::isError($err)) {
  471.                             $this->freeResult($result);
  472.                             return($err);
  473.                         }
  474.                     }
  475.                     return($result);
  476.                 }
  477.             }
  478.         }
  479.  
  480.         return($this->mssqlRaiseError());
  481.     }
  482.  
  483.     // }}}
  484.     // {{{ getColumnNames()
  485.  
  486.     /**
  487.      * Retrieve the names of columns returned by the DBMS in a query result.
  488.      *
  489.      * @param resource   $result    result identifier
  490.      * @return mixed                an associative array variable
  491.      *                               that will hold the names of columns. The
  492.      *                               indexes of the array are the column names
  493.      *                               mapped to lower case and the values are the
  494.      *                               respective numbers of the columns starting
  495.      *                               from 0. Some DBMS may not return any
  496.      *                               columns when the result set does not
  497.      *                               contain any rows.
  498.      *
  499.      *                               a MDB error on failure
  500.      * @access public
  501.      */
  502.     function getColumnNames($result)
  503.     {
  504.         $result_value intval($result);
  505.         if (!isset($this->highest_fetched_row[$result_value])) {
  506.             return($this->raiseError(MDB_ERROR_INVALIDNULLNULL,
  507.                 'Get column names: it was specified an inexisting result set'));
  508.         }
  509.         if (!isset($this->columns[$result_value])) {
  510.             $this->columns[$result_value= array();
  511.             $columns @mssql_num_fields($result);
  512.             for($column = 0; $column $columns$column++{
  513.                 $field_name @mssql_field_name($result$column);
  514.                 if ($this->options['optimize'== 'portability'{
  515.                     $field_name strtolower($field_name);
  516.                 }
  517.                 $this->columns[$result_value][$field_name$column;
  518.             }
  519.         }
  520.         return($this->columns[$result_value]);
  521.     }
  522.  
  523.     // }}}
  524.     // {{{ numCols()
  525.  
  526.     /**
  527.      * Count the number of columns returned by the DBMS in a query result.
  528.      *
  529.      * @param resource    $result        result identifier
  530.      * @access public
  531.      * @return mixed integer value with the number of columns, a MDB error
  532.      *                        on failure
  533.      */
  534.     function numCols($result)
  535.     {
  536.         if (!isset($this->highest_fetched_row[intval($result)])) {
  537.             return($this->raiseError(MDB_ERROR_INVALIDNULLNULL,
  538.                 'numCols: it was specified an inexisting result set'));
  539.         }
  540.         return(@mssql_num_fields($result));
  541.     }
  542.  
  543.     // }}}
  544.     // {{{ endOfResult()
  545.  
  546.     /**
  547.     * check if the end of the result set has been reached
  548.     *
  549.     * @param resource    $result result identifier
  550.     * @return mixed TRUE or FALSE on sucess, a MDB error on failure
  551.     * @access public
  552.     */
  553.     function endOfResult($result)
  554.     {
  555.         $result_value intval($result);
  556.         if (!isset($this->highest_fetched_row[$result_value])) {
  557.             return($this->raiseError(MDB_ERRORNULLNULL,
  558.                 'End of result: attempted to check the end of an unknown result'));
  559.         }
  560.         return($this->highest_fetched_row[$result_value>= $this->numRows($result)-1);
  561.     }
  562.  
  563.     // }}}
  564.     // {{{ fetch()
  565.  
  566.     /**
  567.     * fetch value from a result set
  568.     *
  569.     * @param resource    $result result identifier
  570.     * @param int    $row    number of the row where the data can be found
  571.     * @param int    $field    field number where the data can be found
  572.     * @return mixed string on success, a MDB error on failure
  573.     * @access public
  574.     */
  575.     function fetch($result$row$field)
  576.     {
  577.         $result_value intval($result);
  578.         $this->highest_fetched_row[$result_valuemax($this->highest_fetched_row[$result_value]$row);
  579.         if (isset($this->limits[$result_value])) {
  580.             $row += $this->limits[$result_value][0];
  581.         }
  582.         $res @mssql_result($result$row$field);
  583.         if ($res === FALSE && $res != NULL{
  584.             return($this->mssqlRaiseError());
  585.         }
  586.         return($res);
  587.     }
  588.  
  589.     // }}}
  590.     // {{{ fetchClob()
  591.  
  592.     /**
  593.     * fetch a clob value from a result set
  594.     *
  595.     * @param resource    $result result identifier
  596.     * @param int    $row    number of the row where the data can be found
  597.     * @param int    $field    field number where the data can be found
  598.     * @return mixed content of the specified data cell, a MDB error on failure,
  599.     *                a MDB error on failure
  600.     * @access public
  601.     */
  602.     function fetchClob($result$row$field)
  603.     {
  604.         return($this->fetchLob($result$row$field));
  605.     }
  606.  
  607.     // }}}
  608.     // {{{ fetchBlob()
  609.  
  610.     /**
  611.     * fetch a blob value from a result set
  612.     *
  613.     * @param resource    $result result identifier
  614.     * @param int    $row    number of the row where the data can be found
  615.     * @param int    $field    field number where the data can be found
  616.     * @return mixed content of the specified data cell, a MDB error on failure
  617.     * @access public
  618.     */
  619.     function fetchBlob($result$row$field)
  620.     {
  621.         return($this->fetchLob($result$row$field));
  622.     }
  623.  
  624.     // }}}
  625.     // {{{ convertResult()
  626.  
  627.     /**
  628.     * convert a value to a RDBMS indepdenant MDB type
  629.     *
  630.     * @param mixed  $value   value to be converted
  631.     * @param int    $type    constant that specifies which type to convert to
  632.     * @return mixed converted value
  633.     * @access public
  634.     */
  635.     function convertResult($value$type)
  636.     {
  637.         switch($type{
  638.             case MDB_TYPE_BOOLEAN:
  639.                 return ($value == '1'? TRUE : FALSE;
  640.             case MDB_TYPE_DATE:
  641.                 if(strlen($value> 10{
  642.                     $value=substr($value,0,10);
  643.                 }
  644.                 return($value);
  645.             case MDB_TYPE_TIME:
  646.                 if(strlen($value> 8{
  647.                     $value=substr($value,11,8);
  648.                 }
  649.                 return($value);
  650.             case MDB_TYPE_TIMESTAMP:
  651.                 return($value);
  652.             default:
  653.                 return($this->_baseConvertResult($value,$type));
  654.         }
  655.     }
  656.  
  657.     // }}}
  658.     // {{{ numRows()
  659.  
  660.     /**
  661.     * returns the number of rows in a result object
  662.     *
  663.     * @param ressource $result a valid result ressouce pointer
  664.     * @return mixed MDB_Error or the number of rows
  665.     * @access public
  666.     */
  667.     function numRows($result)
  668.     {
  669.         $result_value intval($result);
  670.         $rows @mssql_num_rows($result);
  671.         if (isset($this->limits[$result_value])) {
  672.             $rows -= $this->limits[$result_value][0];
  673.             if ($rows < 0$rows = 0;
  674.         }
  675.         return($rows);
  676.     }
  677.  
  678.     // }}}
  679.     // {{{ freeResult()
  680.  
  681.     /**
  682.      * Free the internal resources associated with $result.
  683.      *
  684.      * @param $result result identifier
  685.      * @return boolean TRUE on success, FALSE if $result is invalid
  686.      * @access public
  687.      */
  688.     function freeResult($result)
  689.     {
  690.         $result_value intval($result);
  691.         if(isset($this->fetched_row[$result_value])) {
  692.             unset($this->fetched_row[$result_value]);
  693.         }
  694.         if(isset($this->highest_fetched_row[$result_value])) {
  695.             unset($this->highest_fetched_row[$result_value]);
  696.         }
  697.         if(isset($this->columns[$result_value])) {
  698.             unset($this->columns[$result_value]);
  699.         }
  700.         if(isset($this->result_types[$result_value])) {
  701.             unset($this->result_types[$result_value]);
  702.         }
  703.         return(@mssql_free_result($result));
  704.     }
  705.  
  706.     // }}}
  707.     // {{{ getIntegerDeclaration()
  708.  
  709.     /**
  710.      * Obtain DBMS specific SQL code portion needed to declare an integer type
  711.      * field to be used in statements like CREATE TABLE.
  712.      *
  713.      * @param string  $name   name the field to be declared.
  714.      * @param string  $field  associative array with the name of the properties
  715.      *                         of the field being declared as array indexes.
  716.      *                         Currently, the types of supported field
  717.      *                         properties are as follows:
  718.      *
  719.      *                        unsigned
  720.      *                         Boolean flag that indicates whether the field
  721.      *                         should be declared as unsigned integer if
  722.      *                         possible.
  723.      *
  724.      *                        default
  725.      *                         Integer value to be used as default for this
  726.      *                         field.
  727.      *
  728.      *                        notnull
  729.      *                         Boolean flag that indicates whether this field is
  730.      *                         constrained to not be set to NULL.
  731.      * @return string  DBMS specific SQL code portion that should be used to
  732.      *                  declare the specified field.
  733.      * @access public
  734.      */
  735.     function getIntegerDeclaration($name$field)
  736.     {
  737.         if (isset($field['unsigned'])) {
  738.             $this->warnings[= "unsigned integer field \"$name\" is being
  739.                 declared as signed integer";
  740.         }
  741.         return("$name INT".(isset($field["default"]" DEFAULT ".$field["default""").(isset($field["notnull"]" NOT NULL" " NULL"));
  742.     }
  743.  
  744.     // }}}
  745.     // {{{ getTextDeclaration()
  746.  
  747.     /**
  748.      * Obtain DBMS specific SQL code portion needed to declare an text type
  749.      * field to be used in statements like CREATE TABLE.
  750.      *
  751.      * @param string $name name the field to be declared.
  752.      * @param string $field associative array with the name of the properties
  753.      *        of the field being declared as array indexes. Currently, the types
  754.      *        of supported field properties are as follows:
  755.      *
  756.      *        length
  757.      *            Integer value that determines the maximum length of the text
  758.      *            field. If this argument is missing the field should be
  759.      *            declared to have the longest length allowed by the DBMS.
  760.      *
  761.      *        default
  762.      *            Text value to be used as default for this field.
  763.      *
  764.      *        notnull
  765.      *            Boolean flag that indicates whether this field is constrained
  766.      *            to not be set to NULL.
  767.      * @return string DBMS specific SQL code portion that should be used to
  768.      *        declare the specified field.
  769.      * @access public
  770.      */
  771.     function getTextDeclaration($name$field)
  772.     {
  773.         return((isset($field["length"]? "$name VARCHAR (".$field["length"].")" : "$name TEXT").(isset($field["default"]" DEFAULT ".$this->GetTextValue($field["default"]"").(isset($field["notnull"]" NOT NULL" " NULL"));
  774.     }
  775.  
  776.     // }}}
  777.     // {{{ getClobDeclaration()
  778.  
  779.     /**
  780.      * Obtain DBMS specific SQL code portion needed to declare an character
  781.      * large object type field to be used in statements like CREATE TABLE.
  782.      *
  783.      * @param string  $name   name the field to be declared.
  784.      * @param string  $field  associative array with the name of the
  785.      *                         properties of the field being declared as array
  786.      *                         indexes. Currently, the types of supported field
  787.      *                         properties are as follows:
  788.      *
  789.      *                        length
  790.      *                         Integer value that determines the maximum length
  791.      *                         of the large object field. If this argument is
  792.      *                         missing the field should be declared to have the
  793.      *                         longest length allowed by the DBMS.
  794.      *
  795.      *                        notnull
  796.      *                         Boolean flag that indicates whether this field
  797.      *                         is constrained to not be set to NULL.
  798.      * @return string  DBMS specific SQL code portion that should be used to
  799.      *                  declare the specified field.
  800.      * @access public
  801.      */
  802.     function getClobDeclaration($name$field)
  803.     {
  804.         if (isset($field["length"])) {
  805.             $length $field["length"];
  806.             if ($length <= 8000{
  807.                 $type = "VARCHAR($length)";
  808.             else {
  809.                 $type "TEXT";
  810.             }
  811.         else {
  812.             $type "TEXT";
  813.         }
  814.         return("$name $type".(isset($field["notnull"]" NOT NULL" " NULL"));
  815.     }
  816.  
  817.     // }}}
  818.     // {{{ getBlobDeclaration()
  819.  
  820.     /**
  821.      * Obtain DBMS specific SQL code portion needed to declare an binary large
  822.      * object type field to be used in statements like CREATE TABLE.
  823.      *
  824.      * @param string  $name   name the field to be declared.
  825.      * @param string  $field  associative array with the name of the properties
  826.      *                         of the field being declared as array indexes.
  827.      *                         Currently, the types of supported field
  828.      *                         properties are as follows:
  829.      *
  830.      *                        length
  831.      *                         Integer value that determines the maximum length
  832.      *                         of the large object field. If this argument is
  833.      *                         missing the field should be declared to have the
  834.      *                         longest length allowed by the DBMS.
  835.      *
  836.      *                        notnull
  837.      *                         Boolean flag that indicates whether this field is
  838.      *                         constrained to not be set to NULL.
  839.      * @return string  DBMS specific SQL code portion that should be used to
  840.      *                  declare the specified field.
  841.      * @access public
  842.      */
  843.     function getBlobDeclaration($name$field)
  844.     {
  845.         if(isset($field["length"])) {
  846.             $length $field["length"];
  847.             if($length <= 8000{
  848.                 $type = "VARBINARY($length)";
  849.             else {
  850.                 $type "IMAGE";
  851.             }
  852.         else {
  853.             $type "IMAGE";
  854.         }
  855.         return("$name $type".(isset($field["notnull"]" NOT NULL" " NULL"));
  856.     }
  857.  
  858.     // }}}
  859.     // {{{ getBooleanDeclaration()
  860.  
  861.     /**
  862.      * Obtain DBMS specific SQL code portion needed to declare a boolean type
  863.      * field to be used in statements like CREATE TABLE.
  864.      *
  865.      * @param string $name name the field to be declared.
  866.      * @param string $field associative array with the name of the properties
  867.      *        of the field being declared as array indexes. Currently, the types
  868.      *        of supported field properties are as follows:
  869.      *
  870.      *        default
  871.      *            Boolean value to be used as default for this field.
  872.      *
  873.      *        notnullL
  874.      *            Boolean flag that indicates whether this field is constrained
  875.      *            to not be set to NULL.
  876.      * @return string DBMS specific SQL code portion that should be used to
  877.      *        declare the specified field.
  878.      * @access public
  879.      */
  880.     function getBooleanDeclaration($name$field)
  881.     {
  882.         return("$name BIT".(isset($field["default"]" DEFAULT ".$field["default""").(isset($field["notnull"]" NOT NULL" " NULL"));
  883.     }
  884.  
  885.     // }}}
  886.     // {{{ getDateDeclaration()
  887.  
  888.     /**
  889.      * Obtain DBMS specific SQL code portion needed to declare an date type
  890.      * field to be used in statements like CREATE TABLE.
  891.      *
  892.      * @param string  $name   name the field to be declared.
  893.      * @param string  $field  associative array with the name of the properties
  894.      *                         of the field being declared as array indexes.
  895.      *                         Currently, the types of supported field properties
  896.      *                         are as follows:
  897.      *
  898.      *                        default
  899.      *                         Date value to be used as default for this field.
  900.      *
  901.      *                        notnull
  902.      *                         Boolean flag that indicates whether this field is
  903.      *                         constrained to not be set to NULL.
  904.      * @return string  DBMS specific SQL code portion that should be used to
  905.      *                  declare the specified field.
  906.      * @access public
  907.      */
  908.     function getDateDeclaration($name$field)
  909.     {
  910.         return("$name CHAR (".strlen("YYYY-MM-DD").")".(isset($field["default"]" DEFAULT ".$this->getDateValue($field["default"]"").(isset($field["notnull"]" NOT NULL" " NULL"));
  911.     }
  912.  
  913.     // }}}
  914.     // {{{ getTimestampDeclaration()
  915.  
  916.     /**
  917.      * Obtain DBMS specific SQL code portion needed to declare an timestamp
  918.      * type field to be used in statements like CREATE TABLE.
  919.      *
  920.      * @param string  $name   name the field to be declared.
  921.      * @param string  $field  associative array with the name of the properties
  922.      *                         of the field being declared as array indexes.
  923.      *                         Currently, the types of supported field
  924.      *                         properties are as follows:
  925.      *
  926.      *                        default
  927.      *                         Time stamp value to be used as default for this
  928.      *                         field.
  929.      *
  930.      *                        notnull
  931.      *                         Boolean flag that indicates whether this field is
  932.      *                         constrained to not be set to NULL.
  933.      * @return string  DBMS specific SQL code portion that should be used to
  934.      *                  declare the specified field.
  935.      * @access public
  936.      */
  937.     function getTimestampDeclaration($name$field)
  938.     {
  939.         return("$name CHAR (".strlen("YYYY-MM-DD HH:MM:SS").")".(isset($field["default"]" DEFAULT ".$this->getTimestampValue($field["default"]"").(isset($field["notnull"]" NOT NULL" " NULL"));
  940.     }
  941.  
  942.     // }}}
  943.     // {{{ getTimeDeclaration()
  944.  
  945.     /**
  946.      * Obtain DBMS specific SQL code portion needed to declare an time type
  947.      * field to be used in statements like CREATE TABLE.
  948.      *
  949.      * @param string  $name   name the field to be declared.
  950.      * @param string  $field  associative array with the name of the properties
  951.      *                         of the field being declared as array indexes.
  952.      *                         Currently, the types of supported field
  953.      *                         properties are as follows:
  954.      *
  955.      *                        default
  956.      *                         Time value to be used as default for this field.
  957.      *
  958.      *                        notnull
  959.      *                         Boolean flag that indicates whether this field is
  960.      *                         constrained to not be set to NULL.
  961.      * @return string  DBMS specific SQL code portion that should be used to
  962.      *                  declare the specified field.
  963.      * @access public
  964.      */
  965.     function getTimeDeclaration($name$field)
  966.     {
  967.         return("$name CHAR (".strlen("HH:MM:SS").")".(isset($field["default"]" DEFAULT ".$this->getTimeValue($field["default"]"").(isset($field["notnull"]" NOT NULL" " NULL"));
  968.     }
  969.  
  970.     // }}}
  971.     // {{{ getFloatDeclaration()
  972.  
  973.     /**
  974.      * Obtain DBMS specific SQL code portion needed to declare an float type
  975.      * field to be used in statements like CREATE TABLE.
  976.      *
  977.      * @param string  $name   name the field to be declared.
  978.      * @param string  $field  associative array with the name of the properties
  979.      *                         of the field being declared as array indexes.
  980.      *                         Currently, the types of supported field
  981.      *                         properties are as follows:
  982.      *
  983.      *                        default
  984.      *                         Integer value to be used as default for this
  985.      *                         field.
  986.      *
  987.      *                        notnull
  988.      *                         Boolean flag that indicates whether this field is
  989.      *                         constrained to not be set to NULL.
  990.      * @return string  DBMS specific SQL code portion that should be used to
  991.      *                  declare the specified field.
  992.      * @access public
  993.      */
  994.     function getFloatDeclaration($name$field)
  995.     {
  996.         return("$name FLOAT".(isset($field["default"]" DEFAULT ".$field["default""").(isset($field["notnull"]" NOT NULL" " NULL"));
  997.     }
  998.  
  999.     // }}}
  1000.     // {{{ getDecimalDeclaration()
  1001.  
  1002.     /**
  1003.      * Obtain DBMS specific SQL code portion needed to declare an decimal type
  1004.      * field to be used in statements like CREATE TABLE.
  1005.      *
  1006.      * @param string  $name   name the field to be declared.
  1007.      * @param string  $field  associative array with the name of the properties
  1008.      *                         of the field being declared as array indexes.
  1009.      *                         Currently, the types of supported field
  1010.      *                         properties are as follows:
  1011.      *
  1012.      *                        default
  1013.      *                         Integer value to be used as default for this
  1014.      *                         field.
  1015.      *
  1016.      *                        notnull
  1017.      *                         Boolean flag that indicates whether this field is
  1018.      *                         constrained to not be set to NULL.
  1019.      * @return string  DBMS specific SQL code portion that should be used to
  1020.      *                  declare the specified field.
  1021.      * @access public
  1022.      */
  1023.     function getDecimalDeclaration($name$field)
  1024.     {
  1025.         return("$name DECIMAL(18,".$this->decimal_places.")".(isset($field["default"]" DEFAULT ".$this->getDecimalValue($field["default"]"").(isset($field["notnull"]" NOT NULL" " NULL"));
  1026.     }
  1027.  
  1028.     // }}}
  1029.     // {{{ getClobValue()
  1030.  
  1031.     /**
  1032.      * Convert a text value into a DBMS specific format that is suitable to
  1033.      * compose query statements.
  1034.      *
  1035.      * @param resource  $prepared_query query handle from prepare()
  1036.      * @param           $parameter 
  1037.      * @param           $clob 
  1038.      * @return string  text string that represents the given argument value in
  1039.      *                  a DBMS specific format.
  1040.      * @access public
  1041.      */
  1042.     function getClobValue($prepared_query$parameter$clob)
  1043.     {
  1044.         $value="'";
  1045.         while(!$this->endOfLob($clob)) {
  1046.             if (MDB::isError($result $this->readLob($clob$data$this->options['lob_buffer_length']))) {
  1047.                 return($result);
  1048.             }
  1049.             $value .= $this->_quote($data);
  1050.         }
  1051.         $value .= "'";
  1052.         return($value);
  1053.     }
  1054.  
  1055.     // }}}
  1056.     // {{{ freeClobValue()
  1057.  
  1058.     /**
  1059.      * free a character large object
  1060.      *
  1061.      * @param resource  $prepared_query query handle from prepare()
  1062.      * @param string    $clob 
  1063.      * @return MDB_OK 
  1064.      * @access public
  1065.      */
  1066.     function freeClobValue($prepared_query$clob)
  1067.     {
  1068.         unset($this->lobs[$clob]);
  1069.         return(MDB_OK);
  1070.     }
  1071.  
  1072.     // }}}
  1073.     // {{{ getBlobValue()
  1074.  
  1075.     /**
  1076.      * Convert a text value into a DBMS specific format that is suitable to
  1077.      * compose query statements.
  1078.      *
  1079.      * @param resource  $prepared_query query handle from prepare()
  1080.      * @param           $parameter 
  1081.      * @param           $blob 
  1082.      * @return string  text string that represents the given argument value in
  1083.      *                  a DBMS specific format.
  1084.      * @access public
  1085.      */
  1086.     function getBlobValue($prepared_query$parameter$blob)
  1087.     {
  1088.         $value "0x";
  1089.         while(!$this->endOfLob($blob))
  1090.         {
  1091.             if (MDB::isError($result $this->readLob($blob$data$this->options['lob_buffer_length']))) {
  1092.                 return($result);
  1093.             }
  1094.             $value.= Bin2Hex($data);
  1095.         }
  1096.         return($value);
  1097.     }
  1098.  
  1099.     // }}}
  1100.     // {{{ freeBlobValue()
  1101.  
  1102.     /**
  1103.      * free a binary large object
  1104.      *
  1105.      * @param resource  $prepared_query query handle from prepare()
  1106.      * @param string    $blob 
  1107.      * @return MDB_OK 
  1108.      * @access public
  1109.      */
  1110.     function freeBlobValue($prepared_query$blob)
  1111.     {
  1112.         unset($this->lobs[$blob]);
  1113.         return(MDB_OK);
  1114.     }
  1115.  
  1116.     // }}}
  1117.     // {{{ getBooleanValue()
  1118.  
  1119.     /**
  1120.      * Convert a text value into a DBMS specific format that is suitable to
  1121.      * compose query statements.
  1122.      *
  1123.      * @param string $value text string value that is intended to be converted.
  1124.      * @return string text string that represents the given argument value in
  1125.      *        a DBMS specific format.
  1126.      * @access public
  1127.      */
  1128.     function getBooleanValue($value)
  1129.     {
  1130.         return(($value === NULL'NULL' $value);
  1131.     }
  1132.  
  1133.     // }}}
  1134.     // {{{ getFloatValue()
  1135.  
  1136.     /**
  1137.      * Convert a text value into a DBMS specific format that is suitable to
  1138.      * compose query statements.
  1139.      *
  1140.      * @param string  $value text string value that is intended to be converted.
  1141.      * @return string  text string that represents the given argument value in
  1142.      *                  a DBMS specific format.
  1143.      * @access public
  1144.      */
  1145.     function getFloatValue($value)
  1146.     {
  1147.         return(($value === NULL'NULL' $value);
  1148.     }
  1149.  
  1150.     // }}}
  1151.     // {{{ getDecimalValue()
  1152.  
  1153.     /**
  1154.      * Convert a text value into a DBMS specific format that is suitable to
  1155.      * compose query statements.
  1156.      *
  1157.      * @param string  $value text string value that is intended to be converted.
  1158.      * @return string  text string that represents the given argument value in
  1159.      *                  a DBMS specific format.
  1160.      * @access public
  1161.      */
  1162.     function getDecimalValue($value)
  1163.     {
  1164.         return(($value === NULL'NULL' $value);
  1165.     }
  1166.  
  1167.     // }}}
  1168.     // {{{ nextId()
  1169.  
  1170.     /**
  1171.      * returns the next free id of a sequence
  1172.      *
  1173.      * @param string  $seq_name name of the sequence
  1174.      * @param boolean $ondemand when true the seqence is
  1175.      *                           automatic created, if it
  1176.      *                           not exists
  1177.      *
  1178.      * @return mixed MDB_Error or id
  1179.      * @access public
  1180.      */
  1181.     function nextId($seq_name$ondemand = TRUE)
  1182.     {
  1183.         $sequence_name $this->getSequenceName($seq_name);
  1184.         $this->expectError(MDB_ERROR_NOSUCHTABLE);
  1185.         $result $this->query("INSERT INTO $sequence_name DEFAULT VALUES");
  1186.         $this->popExpect();
  1187.         if ($ondemand && MDB::isError($result&&
  1188.             $result->getCode(== MDB_ERROR_NOSUCHTABLE)
  1189.         {
  1190.             // Since we are creating the sequence on demand
  1191.             // we know the first id = 1 so initialize the
  1192.             // sequence at 2
  1193.             $result $this->createSequence($seq_name2);
  1194.             if (MDB::isError($result)) {
  1195.                 return($this->raiseError(MDB_ERRORNULLNULL,
  1196.                     'Next ID: on demand sequence could not be created'));
  1197.             else {
  1198.                 // First ID of a newly created sequence is 1
  1199.                 return(1);
  1200.             }
  1201.         }
  1202.         $value $this->queryOne("SELECT @@IDENTITY FROM $sequence_name"'integer');
  1203.         if (MDB::isError($value)) {
  1204.             return($value);
  1205.         }
  1206.         $result $this->query("DELETE FROM $sequence_name WHERE ".$this->options['sequence_col_name']." < $value");
  1207.         if (MDB::isError($result)) {
  1208.             $this->warnings['nextID: could not delete previous sequence table values';
  1209.         }
  1210.         return($value);
  1211.     }
  1212.  
  1213.     // }}}
  1214.     // {{{ fetchInto()
  1215.  
  1216.     /**
  1217.      * Fetch a row and insert the data into an existing array.
  1218.      *
  1219.      * @param resource  $result     result identifier
  1220.      * @param int       $fetchmode  how the array data should be indexed
  1221.      * @param int       $rownum     the row number to fetch
  1222.      * @return int data array on success, a MDB error on failure
  1223.      * @access public
  1224.      */
  1225.     function fetchInto($result$fetchmode = MDB_FETCHMODE_DEFAULT$rownum = NULL)
  1226.     {
  1227.         $result_value intval($result);
  1228.         if (is_null($rownum)) {
  1229.             ++$this->highest_fetched_row[$result_value];
  1230.         else {
  1231.             $this->highest_fetched_row[$result_value=
  1232.                 max($this->highest_fetched_row[$result_value]$rownum);
  1233.             if (isset($this->limits[$result_value])) {
  1234.                 $rownum $rownum $this->limits[$result_value][0];
  1235.             }
  1236.             if (!@mssql_data_seek($result$rownum)) {
  1237.                 return(NULL);
  1238.             }
  1239.         }
  1240.         if ($fetchmode == MDB_FETCHMODE_DEFAULT{
  1241.             $fetchmode $this->fetchmode;
  1242.         }
  1243.         if ($fetchmode MDB_FETCHMODE_ASSOC{
  1244.             $row @mssql_fetch_assoc($result);
  1245.             if (is_array($row&& $this->options['optimize'== 'portability'{
  1246.                 $row array_change_key_case($rowCASE_LOWER);
  1247.             }
  1248.         else {
  1249.             $row @mssql_fetch_row($result);
  1250.         }
  1251.         if (!$row{
  1252.             if($this->options['autofree']{
  1253.                 $this->freeResult($result);
  1254.             }
  1255.             return(NULL);
  1256.         }
  1257.         if (isset($this->result_types[$result_value])) {
  1258.             $row $this->convertResultRow($result$row);
  1259.         }
  1260.         return($row);
  1261.     }
  1262.  
  1263.     // }}}
  1264.     // {{{ tableInfo()
  1265.  
  1266.   /**
  1267.      * Returns information about a table or a result set
  1268.      *
  1269.      * NOTE: doesn't support table name and flags if called from a db_result
  1270.      *
  1271.      * @param  mixed $resource SQL Server result identifier or table name
  1272.      * @param  int $mode A valid tableInfo mode (MDB_TABLEINFO_ORDERTABLE or
  1273.      *                    MDB_TABLEINFO_ORDER)
  1274.      *
  1275.      * @return array An array with all the information
  1276.      */
  1277.     function tableInfo($result$mode = NULL)
  1278.     {
  1279.  
  1280.         $count = 0;
  1281.         $id    = 0;
  1282.         $res   = array();
  1283.  
  1284.         /*
  1285.          * depending on $mode, metadata returns the following values:
  1286.          *
  1287.          * - mode is false (default):
  1288.          * $result[]:
  1289.          *   [0]['table']  table name
  1290.          *   [0]['name']   field name
  1291.          *   [0]['type']   field type
  1292.          *   [0]['len']    field length
  1293.          *   [0]['flags']  field flags
  1294.          *
  1295.          * - mode is MDB_TABLEINFO_ORDER
  1296.          * $result[]:
  1297.          *   ["num_fields"] number of metadata records
  1298.          *   [0]['table']  table name
  1299.          *   [0]['name']   field name
  1300.          *   [0]['type']   field type
  1301.          *   [0]['len']    field length
  1302.          *   [0]['flags']  field flags
  1303.          *   ['order'][field name]  index of field named "field name"
  1304.          *   The last one is used, if you have a field name, but no index.
  1305.          *   Test:  if (isset($result['meta']['myfield'])) { ...
  1306.          *
  1307.          * - mode is MDB_TABLEINFO_ORDERTABLE
  1308.          *    the same as above. but additionally
  1309.          *   ["ordertable"][table name][field name] index of field
  1310.          *      named "field name"
  1311.          *
  1312.          *      this is, because if you have fields from different
  1313.          *      tables with the same field name * they override each
  1314.          *      other with MDB_TABLEINFO_ORDER
  1315.          *
  1316.          *      you can combine MDB_TABLEINFO_ORDER and
  1317.          *      MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |
  1318.          *      MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL
  1319.          */
  1320.  
  1321.         // if $result is a string, then we want information about a
  1322.         // table without a resultset
  1323.  
  1324.         if (is_string($result)) {
  1325.             if (!@mssql_select_db($this->database_name$this->connection)) {
  1326.                 return $this->mssqlRaiseError();
  1327.             }
  1328.             $id @mssql_query("SELECT * FROM $result"$this->connection);
  1329.             if (empty($id)) {
  1330.                 return($this->mssqlRaiseError());
  1331.             }
  1332.         else // else we want information about a resultset
  1333.             $id $result;
  1334.             if (empty($id)) {
  1335.                 return($this->mssqlRaiseError());
  1336.             }
  1337.         }
  1338.  
  1339.         $count @mssql_num_fields($id);
  1340.  
  1341.         // made this IF due to performance (one if is faster than $count if's)
  1342.         if (empty($mode)) {
  1343.  
  1344.             for ($i=0; $i<$count$i++{
  1345.                 $res[$i]['table'(is_string($result)) $result '';
  1346.                 $res[$i]['name']  @mssql_field_name($id$i);
  1347.                 $res[$i]['type']  @mssql_field_type($id$i);
  1348.                 $res[$i]['len']   @mssql_field_length($id$i);
  1349.                 // We only support flags for tables
  1350.                 $res[$i]['flags'is_string($result$this->_mssql_field_flags($result$res[$i]['name']'';
  1351.             }
  1352.  
  1353.         else // full
  1354.             $res['num_fields']$count;
  1355.  
  1356.             for ($i=0; $i<$count$i++{
  1357.                 $res[$i]['table'(is_string($result)) $result '';
  1358.                 $res[$i]['name']  @mssql_field_name($id$i);
  1359.                 $res[$i]['type']  @mssql_field_type($id$i);
  1360.                 $res[$i]['len']   @mssql_field_length($id$i);
  1361.                 // We only support flags for tables
  1362.                 $res[$i]['flags'is_string($result$this->_mssql_field_flags($result$res[$i]['name']'';
  1363.                 if ($mode MDB_TABLEINFO_ORDER{
  1364.                     $res['order'][$res[$i]['name']] $i;
  1365.                 }
  1366.                 if ($mode MDB_TABLEINFO_ORDERTABLE{
  1367.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  1368.                 }
  1369.             }
  1370.         }
  1371.  
  1372.         // free the result only if we were called on a table
  1373.         if (is_string($result)) {
  1374.             @mssql_free_result($id);
  1375.         }
  1376.         return($res);
  1377.     }
  1378.  
  1379.     // }}}
  1380.     // {{{ _mssql_field_flags()
  1381.     /**
  1382.     * Get the flags for a field, currently only supports "isnullable" and "primary_key"
  1383.     *
  1384.     * @param string The table name
  1385.     * @param string The field
  1386.     * @access private
  1387.     */
  1388.     function _mssql_field_flags($table$column)
  1389.     {
  1390.         static $current_table = NULL;
  1391.         static $flags;
  1392.         // At the first call we discover the flags for all fields
  1393.         if ($table != $current_table{
  1394.             $flags = array();
  1395.             // find nullable fields
  1396.             $q_nulls = "SELECT syscolumns.name, syscolumns.isnullable
  1397.                         FROM sysobjects
  1398.                         INNER JOIN syscolumns ON sysobjects.id = syscolumns.id
  1399.                         WHERE sysobjects.name ='$table' AND syscolumns.isnullable = 1";
  1400.             $res $this->query($q_nullsNULLFALSE);
  1401.             $res $this->fetchAll($resMDB_FETCHMODE_ASSOC);
  1402.             foreach ($res as $data{
  1403.                 if ($data['isnullable'== 1{
  1404.                     $flags[$data['name']]['isnullable';
  1405.                 }
  1406.             }
  1407.             // find primary keys
  1408.             $res2 $this->query("EXEC SP_PKEYS[$table]"NULLFALSE);
  1409.             $res2 $this->fetchAll($resMDB_FETCHMODE_ASSOC);
  1410.             foreach ($res2 as $data{
  1411.                 if (!empty($data['COLUMN_NAME'])) {
  1412.                     $flags[$data['COLUMN_NAME']]['primary_key';
  1413.                 }
  1414.             }
  1415.             $current_table $table;
  1416.         }
  1417.         if (isset($flags[$column])) {
  1418.             return(implode(','$flags[$column]));
  1419.         }
  1420.         return('');
  1421.     }
  1422.     // }}}
  1423. }
  1424.  
  1425. ?>

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