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

Source for file sybase.php

Documentation is available at sybase.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Sterling Hughes <sterling@php.net>                          |
  17. // | Maintainer: Daniel Convissor <danielc@php.net>                       |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: sybase.php,v 1.50 2004/03/05 01:46:53 danielc Exp $
  21.  
  22.  
  23. // TODO
  24. //    - This driver may fail with multiple connections under the same
  25. //      user/pass/host and different databases
  26.  
  27.  
  28. require_once 'DB/common.php';
  29.  
  30. /**
  31.  * Database independent query interface definition for PHP's Sybase
  32.  * extension.
  33.  *
  34.  * @package  DB
  35.  * @version  $Id: sybase.php,v 1.50 2004/03/05 01:46:53 danielc Exp $
  36.  * @category Database
  37.  * @author   Sterling Hughes <sterling@php.net>
  38.  * @author
  39.  */
  40. class DB_sybase extends DB_common
  41. {
  42.     // {{{ properties
  43.  
  44.     var $connection;
  45.     var $phptype$dbsyntax;
  46.     var $prepare_tokens = array();
  47.     var $prepare_types = array();
  48.     var $transaction_opcount = 0;
  49.     var $autocommit = true;
  50.  
  51.     // }}}
  52.     // {{{ constructor
  53.  
  54.     /**
  55.      * DB_sybase constructor.
  56.      *
  57.      * @access public
  58.      */
  59.     function DB_sybase()
  60.     {
  61.         $this->DB_common();
  62.         $this->phptype = 'sybase';
  63.         $this->dbsyntax = 'sybase';
  64.         $this->features = array(
  65.             'prepare' => false,
  66.             'pconnect' => true,
  67.             'transactions' => false,
  68.             'limit' => 'emulate'
  69.         );
  70.         $this->errorcode_map = array(
  71.         );
  72.     }
  73.  
  74.     // }}}
  75.     // {{{ connect()
  76.  
  77.     /**
  78.      * Connect to a database and log in as the specified user.
  79.      *
  80.      * @param $dsn the data source name (see DB::parseDSN for syntax)
  81.      * @param $persistent (optional) whether the connection should
  82.      *         be persistent
  83.      * @access public
  84.      * @return int DB_OK on success, a DB error on failure
  85.      */
  86.     function connect($dsninfo$persistent = false)
  87.     {
  88.         if (!DB::assertExtension('sybase'&&
  89.             !DB::assertExtension('sybase_ct'))
  90.         {
  91.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  92.         }
  93.  
  94.         $this->dsn $dsninfo;
  95.  
  96.         $interface $dsninfo['hostspec'$dsninfo['hostspec''localhost';
  97.         $connect_function $persistent 'sybase_pconnect' 'sybase_connect';
  98.  
  99.         if ($interface && $dsninfo['username'&& $dsninfo['password']{
  100.             $conn @$connect_function($interface$dsninfo['username'],
  101.                                        $dsninfo['password']);
  102.         elseif ($interface && $dsninfo['username']{
  103.             /*
  104.              * Using false for pw as a workaround to avoid segfault.
  105.              * See PEAR bug 631
  106.              */
  107.             $conn @$connect_function($interface$dsninfo['username'],
  108.                                        false);
  109.         else {
  110.             $conn = false;
  111.         }
  112.  
  113.         if (!$conn{
  114.             return $this->raiseError(DB_ERROR_CONNECT_FAILED);
  115.         }
  116.  
  117.         if ($dsninfo['database']{
  118.             if (!@sybase_select_db($dsninfo['database']$conn)) {
  119.                 return $this->raiseError(DB_ERROR_NODBSELECTEDnull,
  120.                                          nullnull@sybase_get_last_message());
  121.             }
  122.             $this->_db $dsninfo['database'];
  123.         }
  124.  
  125.         $this->connection = $conn;
  126.         return DB_OK;
  127.     }
  128.  
  129.     // }}}
  130.     // {{{ disconnect()
  131.  
  132.     /**
  133.      * Log out and disconnect from the database.
  134.      *
  135.      * @access public
  136.      *
  137.      * @return bool true on success, false if not connected.
  138.      */
  139.     function disconnect()
  140.     {
  141.         $ret @sybase_close($this->connection);
  142.         $this->connection = null;
  143.         return $ret;
  144.     }
  145.  
  146.     // }}}
  147.     // {{{ errorNative()
  148.  
  149.     /**
  150.      * Get the last server error messge (if any)
  151.      *
  152.      * @return string sybase last error message
  153.      */
  154.     function errorNative()
  155.     {
  156.         return @sybase_get_last_message();
  157.     }
  158.  
  159.     // }}}
  160.     // {{{ errorCode()
  161.  
  162.     /**
  163.      * Determine PEAR::DB error code from the database's text error message.
  164.      *
  165.      * @param  string  $errormsg  error message returned from the database
  166.      * @return integer  an error number from a DB error constant
  167.      */
  168.     function errorCode($errormsg)
  169.     {
  170.         static $error_regexps;
  171.         if (!isset($error_regexps)) {
  172.             $error_regexps = array(
  173.                 '/Incorrect syntax near/'
  174.                     => DB_ERROR_SYNTAX,
  175.                 '/^Unclosed quote before the character string [\"\'].*[\"\']\./'
  176.                     => DB_ERROR_SYNTAX,
  177.                 '/Implicit conversion from datatype [\"\'].+[\"\'] to [\"\'].+[\"\'] is not allowed\./'
  178.                     => DB_ERROR_INVALID_NUMBER,
  179.                 '/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./'
  180.                     => DB_ERROR_NOSUCHTABLE,
  181.                 '/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./'
  182.                     => DB_ERROR_ACCESS_VIOLATION,
  183.                 '/^.+ permission denied on object .+, database .+, owner .+/'
  184.                     => DB_ERROR_ACCESS_VIOLATION,
  185.                 '/^.* permission denied, database .+, owner .+/'
  186.                     => DB_ERROR_ACCESS_VIOLATION,
  187.                 '/[^.*] not found\./'
  188.                     => DB_ERROR_NOSUCHTABLE,
  189.                 '/There is already an object named/'
  190.                     => DB_ERROR_ALREADY_EXISTS,
  191.                 '/Invalid column name/'
  192.                     => DB_ERROR_NOSUCHFIELD,
  193.                 '/does not allow null values/'
  194.                     => DB_ERROR_CONSTRAINT_NOT_NULL,
  195.                 '/Command has been aborted/'
  196.                     => DB_ERROR_CONSTRAINT,
  197.             );
  198.         }
  199.  
  200.         foreach ($error_regexps as $regexp => $code{
  201.             if (preg_match($regexp$errormsg)) {
  202.                 return $code;
  203.             }
  204.         }
  205.         return DB_ERROR;
  206.     }
  207.  
  208.     // }}}
  209.     // {{{ sybaseRaiseError()
  210.  
  211.     /**
  212.      * Gather information about an error, then use that info to create a
  213.      * DB error object and finally return that object.
  214.      *
  215.      * @param  integer  $errno  PEAR error number (usually a DB constant) if
  216.      *                           manually raising an error
  217.      * @return object  DB error object
  218.      * @see errorNative()
  219.      * @see errorCode()
  220.      * @see DB_common::raiseError()
  221.      */
  222.     function sybaseRaiseError($errno = null)
  223.     {
  224.         $native $this->errorNative();
  225.         if ($errno === null{
  226.             $errno $this->errorCode($native);
  227.         }
  228.         return $this->raiseError($errnonullnullnull$native);
  229.     }
  230.  
  231.     // }}}
  232.     // {{{ simpleQuery()
  233.  
  234.     /**
  235.      * Send a query to Sybase and return the results as a Sybase resource
  236.      * identifier.
  237.      *
  238.      * @param the SQL query
  239.      *
  240.      * @access public
  241.      *
  242.      * @return mixed returns a valid Sybase result for successful SELECT
  243.      *  queries, DB_OK for other successful queries.  A DB error is
  244.      *  returned on failure.
  245.      */
  246.     function simpleQuery($query)
  247.     {
  248.         $ismanip DB::isManip($query);
  249.         $this->last_query = $query;
  250.         if (!@sybase_select_db($this->_db$this->connection)) {
  251.             return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
  252.         }
  253.         $query $this->modifyQuery($query);
  254.         if (!$this->autocommit && $ismanip{
  255.             if ($this->transaction_opcount == 0{
  256.                 $result @sybase_query('BEGIN TRANSACTION'$this->connection);
  257.                 if (!$result{
  258.                     return $this->sybaseRaiseError();
  259.                 }
  260.             }
  261.             $this->transaction_opcount++;
  262.         }
  263.         $result @sybase_query($query$this->connection);
  264.         if (!$result{
  265.             return $this->sybaseRaiseError();
  266.         }
  267.         if (is_resource($result)) {
  268.             $numrows $this->numRows($result);
  269.             if (is_object($numrows)) {
  270.                 return $numrows;
  271.             }
  272.             $this->num_rows[(int)$result$numrows;
  273.             return $result;
  274.         }
  275.         // Determine which queries that should return data, and which
  276.         // should return an error code only.
  277.         return $ismanip DB_OK : $result;
  278.     }
  279.  
  280.     // }}}
  281.     // {{{ nextResult()
  282.  
  283.     /**
  284.      * Move the internal sybase result pointer to the next available result
  285.      *
  286.      * @param valid sybase result resource
  287.      *
  288.      * @access public
  289.      *
  290.      * @return true if a result is available otherwise return false
  291.      */
  292.     function nextResult($result)
  293.     {
  294.         return false;
  295.     }
  296.  
  297.     // }}}
  298.     // {{{ fetchInto()
  299.  
  300.     /**
  301.      * Fetch a row and insert the data into an existing array.
  302.      *
  303.      * Formating of the array and the data therein are configurable.
  304.      * See DB_result::fetchInto() for more information.
  305.      *
  306.      * @param resource $result    query result identifier
  307.      * @param array    $arr       (reference) array where data from the row
  308.      *                             should be placed
  309.      * @param int      $fetchmode how the resulting array should be indexed
  310.      * @param int      $rownum    the row number to fetch
  311.      *
  312.      * @return mixed DB_OK on success, null when end of result set is
  313.      *                reached or on failure
  314.      *
  315.      * @see DB_result::fetchInto()
  316.      * @access private
  317.      */
  318.     function fetchInto($result&$arr$fetchmode$rownum=null)
  319.     {
  320.         if ($rownum !== null{
  321.             if (!@sybase_data_seek($result$rownum)) {
  322.                 return null;
  323.             }
  324.         }
  325.         if ($fetchmode DB_FETCHMODE_ASSOC{
  326.             if (function_exists('sybase_fetch_assoc')) {
  327.                 $arr @sybase_fetch_assoc($result);
  328.             else {
  329.                 if ($arr @sybase_fetch_array($result)) {
  330.                     foreach ($arr as $key => $value{
  331.                         if (is_int($key)) {
  332.                             unset($arr[$key]);
  333.                         }
  334.                     }
  335.                 }
  336.             }
  337.             if ($this->options['portability'DB_PORTABILITY_LOWERCASE && $arr{
  338.                 $arr array_change_key_case($arrCASE_LOWER);
  339.             }
  340.         else {
  341.             $arr @sybase_fetch_row($result);
  342.         }
  343.         if (!$arr{
  344.             // reported not work as seems that sybase_get_last_message()
  345.             // always return a message here
  346.             //if ($errmsg = @sybase_get_last_message()) {
  347.             //    return $this->sybaseRaiseError($errmsg);
  348.             //} else {
  349.                 return null;
  350.             //}
  351.         }
  352.         if ($this->options['portability'DB_PORTABILITY_RTRIM{
  353.             $this->_rtrimArrayValues($arr);
  354.         }
  355.         if ($this->options['portability'DB_PORTABILITY_NULL_TO_EMPTY{
  356.             $this->_convertNullArrayValuesToEmpty($arr);
  357.         }
  358.         return DB_OK;
  359.     }
  360.  
  361.     // }}}
  362.     // {{{ freeResult()
  363.  
  364.     /**
  365.      * Free the internal resources associated with $result.
  366.      *
  367.      * @param $result Sybase result identifier
  368.      *
  369.      * @access public
  370.      *
  371.      * @return bool true on success, false if $result is invalid
  372.      */
  373.     function freeResult($result)
  374.     {
  375.         unset($this->num_rows[(int)$result]);
  376.         return @sybase_free_result($result);
  377.     }
  378.  
  379.     // }}}
  380.     // {{{ numCols()
  381.  
  382.     /**
  383.      * Get the number of columns in a result set.
  384.      *
  385.      * @param $result Sybase result identifier
  386.      *
  387.      * @access public
  388.      *
  389.      * @return int the number of columns per row in $result
  390.      */
  391.     function numCols($result)
  392.     {
  393.         $cols @sybase_num_fields($result);
  394.         if (!$cols{
  395.             return $this->sybaseRaiseError();
  396.         }
  397.         return $cols;
  398.     }
  399.  
  400.     // }}}
  401.     // {{{ numRows()
  402.  
  403.     /**
  404.      * Get the number of rows in a result set.
  405.      *
  406.      * @param $result Sybase result identifier
  407.      *
  408.      * @access public
  409.      *
  410.      * @return int the number of rows in $result
  411.      */
  412.     function numRows($result)
  413.     {
  414.         $rows @sybase_num_rows($result);
  415.         if ($rows === false{
  416.             return $this->sybaseRaiseError();
  417.         }
  418.         return $rows;
  419.     }
  420.  
  421.     // }}}
  422.     // {{{ affectedRows()
  423.  
  424.     /**
  425.      * Gets the number of rows affected by the data manipulation
  426.      * query.  For other queries, this function returns 0.
  427.      *
  428.      * @return number of rows affected by the last query
  429.      */
  430.     function affectedRows()
  431.     {
  432.         if (DB::isManip($this->last_query)) {
  433.             $result @sybase_affected_rows($this->connection);
  434.         else {
  435.             $result = 0;
  436.         }
  437.         return $result;
  438.      }
  439.  
  440.     // }}}
  441.     // {{{ nextId()
  442.  
  443.     /**
  444.      * Returns the next free id in a sequence
  445.      *
  446.      * @param string  $seq_name  name of the sequence
  447.      * @param boolean $ondemand  when true, the seqence is automatically
  448.      *                            created if it does not exist
  449.      *
  450.      * @return int  the next id number in the sequence.  DB_Error if problem.
  451.      *
  452.      * @internal
  453.      * @see DB_common::nextID()
  454.      * @access public
  455.      */
  456.     function nextId($seq_name$ondemand = true)
  457.     {
  458.         $seqname $this->getSequenceName($seq_name);
  459.         if (!@sybase_select_db($this->_db$this->connection)) {
  460.             return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
  461.         }
  462.         $repeat = 0;
  463.         do {
  464.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  465.             $result $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
  466.             $this->popErrorHandling();
  467.             if ($ondemand && DB::isError($result&&
  468.                 ($result->getCode(== DB_ERROR || $result->getCode(== DB_ERROR_NOSUCHTABLE))
  469.             {
  470.                 $repeat = 1;
  471.                 $result $this->createSequence($seq_name);
  472.                 if (DB::isError($result)) {
  473.                     return $this->raiseError($result);
  474.                 }
  475.             elseif (!DB::isError($result)) {
  476.                 $result =$this->query("SELECT @@IDENTITY FROM $seqname");
  477.                 $repeat = 0;
  478.             else {
  479.                 $repeat = false;
  480.             }
  481.         while ($repeat);
  482.         if (DB::isError($result)) {
  483.             return $this->raiseError($result);
  484.         }
  485.         $result $result->fetchRow(DB_FETCHMODE_ORDERED);
  486.         return $result[0];
  487.     }
  488.  
  489.     /**
  490.      * Creates a new sequence
  491.      *
  492.      * @param string $seq_name  name of the new sequence
  493.      *
  494.      * @return int  DB_OK on success.  A DB_Error object is returned if
  495.      *               problems arise.
  496.      *
  497.      * @internal
  498.      * @see DB_common::createSequence()
  499.      * @access public
  500.      */
  501.     function createSequence($seq_name)
  502.     {
  503.         $seqname $this->getSequenceName($seq_name);
  504.         return $this->query("CREATE TABLE $seqname ".
  505.                             '(id numeric(10,0) IDENTITY NOT NULL ,' .
  506.                             'vapor int NULL)');
  507.     }
  508.  
  509.     // }}}
  510.     // {{{ dropSequence()
  511.  
  512.     /**
  513.      * Deletes a sequence
  514.      *
  515.      * @param string $seq_name  name of the sequence to be deleted
  516.      *
  517.      * @return int  DB_OK on success.  DB_Error if problems.
  518.      *
  519.      * @internal
  520.      * @see DB_common::dropSequence()
  521.      * @access public
  522.      */
  523.     function dropSequence($seq_name)
  524.     {
  525.         $seqname $this->getSequenceName($seq_name);
  526.         return $this->query("DROP TABLE $seqname");
  527.     }
  528.  
  529.     // }}}
  530.     // {{{ getSpecialQuery()
  531.  
  532.     /**
  533.      * Returns the query needed to get some backend info
  534.      * @param string $type What kind of info you want to retrieve
  535.      * @return string The SQL query string
  536.      */
  537.     function getSpecialQuery($type)
  538.     {
  539.         switch ($type{
  540.             case 'tables':
  541.                 return "select name from sysobjects where type = 'U' order by name";
  542.             case 'views':
  543.                 return "select name from sysobjects where type = 'V'";
  544.             default:
  545.                 return null;
  546.         }
  547.     }
  548.  
  549.     // }}}
  550.     // {{{ autoCommit()
  551.  
  552.     /**
  553.      * Enable/disable automatic commits
  554.      */
  555.     function autoCommit($onoff = false)
  556.     {
  557.         // XXX if $this->transaction_opcount > 0, we should probably
  558.         // issue a warning here.
  559.         $this->autocommit = $onoff ? true : false;
  560.         return DB_OK;
  561.     }
  562.  
  563.     // }}}
  564.     // {{{ commit()
  565.  
  566.     /**
  567.      * Commit the current transaction.
  568.      */
  569.     function commit()
  570.     {
  571.         if ($this->transaction_opcount > 0{
  572.             if (!@sybase_select_db($this->_db$this->connection)) {
  573.                 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
  574.             }
  575.             $result @sybase_query('COMMIT'$this->connection);
  576.             $this->transaction_opcount = 0;
  577.             if (!$result{
  578.                 return $this->sybaseRaiseError();
  579.             }
  580.         }
  581.         return DB_OK;
  582.     }
  583.  
  584.     // }}}
  585.     // {{{ rollback()
  586.  
  587.     /**
  588.      * Roll back (undo) the current transaction.
  589.      */
  590.     function rollback()
  591.     {
  592.         if ($this->transaction_opcount > 0{
  593.             if (!@sybase_select_db($this->_db$this->connection)) {
  594.                 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
  595.             }
  596.             $result @sybase_query('ROLLBACK'$this->connection);
  597.             $this->transaction_opcount = 0;
  598.             if (!$result{
  599.                 return $this->sybaseRaiseError();
  600.             }
  601.         }
  602.         return DB_OK;
  603.     }
  604.  
  605.     // }}}
  606.     // {{{ tableInfo()
  607.  
  608.     /**
  609.      * Returns information about a table or a result set.
  610.      *
  611.      * NOTE: only supports 'table' and 'flags' if <var>$result</var>
  612.      * is a table name.
  613.      *
  614.      * @param object|string $result  DB_result object from a query or a
  615.      *                                 string containing the name of a table
  616.      * @param int            $mode    a valid tableInfo mode
  617.      * @return array  an associative array with the information requested
  618.      *                 or an error object if something is wrong
  619.      * @access public
  620.      * @internal
  621.      * @since 1.6.0
  622.      * @see DB_common::tableInfo()
  623.      */
  624.     function tableInfo($result$mode = null)
  625.     {
  626.         if (isset($result->result)) {
  627.             /*
  628.              * Probably received a result object.
  629.              * Extract the result resource identifier.
  630.              */
  631.             $id $result->result;
  632.             $got_string = false;
  633.         elseif (is_string($result)) {
  634.             /*
  635.              * Probably received a table name.
  636.              * Create a result resource identifier.
  637.              */
  638.             if (!@sybase_select_db($this->_db$this->connection)) {
  639.                 return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
  640.             }
  641.             $id @sybase_query("SELECT * FROM $result WHERE 1=0",
  642.                                 $this->connection);
  643.             $got_string = true;
  644.         else {
  645.             /*
  646.              * Probably received a result resource identifier.
  647.              * Copy it.
  648.              * Depricated.  Here for compatibility only.
  649.              */
  650.             $id $result;
  651.             $got_string = false;
  652.         }
  653.  
  654.         if (!is_resource($id)) {
  655.             return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA);
  656.         }
  657.  
  658.         if ($this->options['portability'DB_PORTABILITY_LOWERCASE{
  659.             $case_func 'strtolower';
  660.         else {
  661.             $case_func 'strval';
  662.         }
  663.  
  664.         $count @sybase_num_fields($id);
  665.  
  666.         // made this IF due to performance (one if is faster than $count if's)
  667.         if (!$mode{
  668.  
  669.             for ($i=0; $i<$count$i++{
  670.                 $f @sybase_fetch_field($id$i);
  671.  
  672.                 // column_source is often blank
  673.                 if ($got_string{
  674.                     $res[$i]['table'$case_func($result);
  675.                 else {
  676.                     $res[$i]['table'$case_func($f->column_source);
  677.                 }
  678.                 $res[$i]['name']  $case_func($f->name);
  679.                 $res[$i]['type']  $f->type;
  680.                 $res[$i]['len']   $f->max_length;
  681.                 if ($res[$i]['table']{
  682.                     $res[$i]['flags'$this->_sybase_field_flags(
  683.                             $res[$i]['table']$res[$i]['name']);
  684.                 else {
  685.                     $res[$i]['flags''';
  686.                 }
  687.             }
  688.  
  689.         else {
  690.             // get full info
  691.  
  692.             $res['num_fields'$count;
  693.  
  694.             for ($i=0; $i<$count$i++{
  695.                 $f @sybase_fetch_field($id$i);
  696.  
  697.                 // column_source is often blank
  698.                 if ($got_string{
  699.                     $res[$i]['table'$case_func($result);
  700.                 else {
  701.                     $res[$i]['table'$case_func($f->column_source);
  702.                 }
  703.                 $res[$i]['name']  $case_func($f->name);
  704.                 $res[$i]['type']  $f->type;
  705.                 $res[$i]['len']   $f->max_length;
  706.                 if ($res[$i]['table']{
  707.                     $res[$i]['flags'$this->_sybase_field_flags(
  708.                             $res[$i]['table']$res[$i]['name']);
  709.                 else {
  710.                     $res[$i]['flags''';
  711.                 }
  712.  
  713.                 if ($mode DB_TABLEINFO_ORDER{
  714.                     $res['order'][$res[$i]['name']] $i;
  715.                 }
  716.                 if ($mode DB_TABLEINFO_ORDERTABLE{
  717.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] $i;
  718.                 }
  719.             }
  720.         }
  721.  
  722.         // free the result only if we were called on a table
  723.         if ($got_string{
  724.             @sybase_free_result($id);
  725.         }
  726.         return $res;
  727.     }
  728.  
  729.     // }}}
  730.     // {{{ _sybase_field_flags()
  731.  
  732.     /**
  733.      * Get the flags for a field.
  734.      *
  735.      * Currently supports:
  736.      *  + <samp>unique_key</samp>    (unique index, unique check or primary_key)
  737.      *  + <samp>multiple_key</samp>  (multi-key index)
  738.      *
  739.      * @param string  $table   table name
  740.      * @param string  $column  field name
  741.      * @return string  space delimited string of flags.  Empty string if none.
  742.      * @access private
  743.      */
  744.     function _sybase_field_flags($table$column)
  745.     {
  746.         static $tableName = null;
  747.         static $flags = array();
  748.  
  749.         if ($table != $tableName{
  750.             $flags = array();
  751.             $tableName $table;
  752.  
  753.             // get unique/primary keys
  754.             $res $this->getAll("sp_helpindex $table"DB_FETCHMODE_ASSOC);
  755.  
  756.             if (!isset($res[0]['index_description'])) {
  757.                 return '';
  758.             }
  759.  
  760.             foreach ($res as $val{
  761.                 $keys explode(', 'trim($val['index_keys']));
  762.  
  763.                 if (sizeof($keys> 1{
  764.                     foreach ($keys as $key{
  765.                         $this->_add_flag($flags[$key]'multiple_key');
  766.                     }
  767.                 }
  768.  
  769.                 if (strpos($val['index_description']'unique')) {
  770.                     foreach ($keys as $key{
  771.                         $this->_add_flag($flags[$key]'unique_key');
  772.                     }
  773.                 }
  774.             }
  775.  
  776.         }
  777.  
  778.         if (array_key_exists($column$flags)) {
  779.             return(implode(' '$flags[$column]));
  780.         }
  781.  
  782.         return '';
  783.     }
  784.  
  785.     // }}}
  786.     // {{{ _add_flag()
  787.  
  788.     /**
  789.      * Adds a string to the flags array if the flag is not yet in there
  790.      * - if there is no flag present the array is created.
  791.      *
  792.      * @param array  $array  reference of flags array to add a value to
  793.      * @param mixed  $value  value to add to the flag array
  794.      * @access private
  795.      */
  796.     function _add_flag(&$array$value)
  797.     {
  798.         if (!is_array($array)) {
  799.             $array = array($value);
  800.         elseif (!in_array($value$array)) {
  801.             array_push($array$value);
  802.         }
  803.     }
  804.  
  805.     // }}}
  806.     // {{{ quoteIdentifier()
  807.  
  808.     /**
  809.      * Quote a string so it can be safely used as a table / column name
  810.      *
  811.      * Quoting style depends on which database driver is being used.
  812.      *
  813.      * @param string $str  identifier name to be quoted
  814.      *
  815.      * @return string  quoted identifier string
  816.      *
  817.      * @since 1.6.0
  818.      * @access public
  819.      */
  820.     function quoteIdentifier($str)
  821.     {
  822.         return '[' str_replace(']'']]'$str']';
  823.     }
  824.  
  825.     // }}}
  826.  
  827. }
  828.  
  829. /*
  830.  * Local variables:
  831.  * tab-width: 4
  832.  * c-basic-offset: 4
  833.  * End:
  834.  */
  835.  
  836. ?>

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