[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/MDB/ -> mssql.php (source)

   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 a 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(), NULL, NULL,
 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_UNSUPPORTED, NULL, NULL,
 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_UNSUPPORTED, NULL, NULL,
 253                  'Commit transactions: transactions are not in use'));
 254          }
 255          if ($this->auto_commit) {
 256              return($this->raiseError(MDB_ERROR, NULL, NULL,
 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_UNSUPPORTED, NULL, NULL,
 284                  'Rollback transactions: transactions are not in use'));
 285          }
 286          if ($this->auto_commit) {
 287              return($this->raiseError(MDB_ERROR, NULL, NULL,
 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(NULL, MDB_ERROR_NOT_FOUND,
 330                  NULL, NULL, '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_FAILED, NULL, NULL,
 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(NULL, MDB_ERROR_NOT_FOUND,
 397                  NULL, NULL, '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_INVALID, NULL, NULL,
 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_INVALID, NULL, NULL,
 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_ERROR, NULL, NULL,
 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_value] = max($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_name, 2);
1194              if (MDB::isError($result)) {
1195                  return($this->raiseError(MDB_ERROR, NULL, NULL,
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($row, CASE_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_nulls, NULL, FALSE);
1401              $res = $this->fetchAll($res, MDB_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]", NULL, FALSE);
1409              $res2 = $this->fetchAll($res, MDB_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  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7