Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  /*
   3  @version   v5.20.16  12-Jan-2020
   4  @copyright (c) 2000-2013 John Lim. All rights reserved.
   5  @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
   6    Released under both BSD license and Lesser GPL library license.
   7    Whenever there is any discrepancy between the two licenses,
   8    the BSD license will take precedence.
   9    Set tabs to 4 for best viewing.
  10  
  11    Latest version is available at http://adodb.org/
  12  
  13    Sybase driver contributed by Toni (toni.tunkkari@finebyte.com)
  14  
  15    - MSSQL date patch applied.
  16  
  17    Date patch by Toni 15 Feb 2002
  18  */
  19  
  20   // security - hide paths
  21  if (!defined('ADODB_DIR')) die();
  22  
  23  class ADODB_sybase extends ADOConnection {
  24  	 var $databaseType = "sybase";
  25  	 var $dataProvider = 'sybase';
  26  	 var $replaceQuote = "''"; // string to use to replace quotes
  27  	 var $fmtDate = "'Y-m-d'";
  28  	 var $fmtTimeStamp = "'Y-m-d H:i:s'";
  29  	 var $hasInsertID = true;
  30  	 var $hasAffectedRows = true;
  31    	 var $metaTablesSQL="select name from sysobjects where type='U' or type='V'";
  32  	 // see http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
  33  	 var $metaColumnsSQL = "SELECT c.column_name, c.column_type, c.width FROM syscolumn c, systable t WHERE t.table_name='%s' AND c.table_id=t.table_id AND t.table_type='BASE'";
  34  	 /*
  35  	 "select c.name,t.name,c.length from
  36  	 syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id
  37  	 where o.name='%s'";
  38  	 */
  39  	 var $concat_operator = '+';
  40  	 var $arrayClass = 'ADORecordSet_array_sybase';
  41  	 var $sysDate = 'GetDate()';
  42  	 var $leftOuter = '*=';
  43  	 var $rightOuter = '=*';
  44  
  45  	 var $port;
  46  
  47  	function __construct()
  48  	 {
  49  	 }
  50  
  51  	 // might require begintrans -- committrans
  52  	function _insertid()
  53  	 {
  54  	 	 return $this->GetOne('select @@identity');
  55  	 }
  56  	   // might require begintrans -- committrans
  57  	function _affectedrows()
  58  	 {
  59  	 	 return $this->GetOne('select @@rowcount');
  60  	 }
  61  
  62  
  63  	function BeginTrans()
  64  	 {
  65  
  66  	 	 if ($this->transOff) return true;
  67  	 	 $this->transCnt += 1;
  68  
  69  	 	 $this->Execute('BEGIN TRAN');
  70  	 	 return true;
  71  	 }
  72  
  73  	function CommitTrans($ok=true)
  74  	 {
  75  	 	 if ($this->transOff) return true;
  76  
  77  	 	 if (!$ok) return $this->RollbackTrans();
  78  
  79  	 	 $this->transCnt -= 1;
  80  	 	 $this->Execute('COMMIT TRAN');
  81  	 	 return true;
  82  	 }
  83  
  84  	function RollbackTrans()
  85  	 {
  86  	 	 if ($this->transOff) return true;
  87  	 	 $this->transCnt -= 1;
  88  	 	 $this->Execute('ROLLBACK TRAN');
  89  	 	 return true;
  90  	 }
  91  
  92  	 // http://www.isug.com/Sybase_FAQ/ASE/section6.1.html#6.1.4
  93  	function RowLock($tables,$where,$col='top 1 null as ignore')
  94  	 {
  95  	 	 if (!$this->_hastrans) $this->BeginTrans();
  96  	 	 $tables = str_replace(',',' HOLDLOCK,',$tables);
  97  	 	 return $this->GetOne("select $col from $tables HOLDLOCK where $where");
  98  
  99  	 }
 100  
 101  	function SelectDB($dbName)
 102  	 {
 103  	 	 $this->database = $dbName;
 104  	 	 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
 105  	 	 if ($this->_connectionID) {
 106  	 	 	 return @sybase_select_db($dbName);
 107  	 	 }
 108  	 	 else return false;
 109  	 }
 110  
 111  	 /*	 Returns: the last error message from previous database operation
 112  	 	 Note: This function is NOT available for Microsoft SQL Server.	 */
 113  
 114  
 115  	function ErrorMsg()
 116  	 {
 117  	 	 if ($this->_logsql) return $this->_errorMsg;
 118  	 	 if (function_exists('sybase_get_last_message'))
 119  	 	 	 $this->_errorMsg = sybase_get_last_message();
 120  	 	 else {
 121  	 	 	 $this->_errorMsg = 'SYBASE error messages not supported on this platform';
 122  	 	 }
 123  
 124  	 	 return $this->_errorMsg;
 125  	 }
 126  
 127  	 // returns true or false
 128  	function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
 129  	 {
 130  	 	 if (!function_exists('sybase_connect')) return null;
 131  
 132  	 	 // Sybase connection on custom port
 133  	 	 if ($this->port) {
 134  	 	 	 $argHostname .= ':' . $this->port;
 135  	 	 }
 136  
 137  	 	 if ($this->charSet) {
 138  	 	 	 $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword, $this->charSet);
 139  	 	 } else {
 140  	 	 	 $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword);
 141  	 	 }
 142  
 143  	 	 if ($this->_connectionID === false) return false;
 144  	 	 if ($argDatabasename) return $this->SelectDB($argDatabasename);
 145  	 	 return true;
 146  	 }
 147  
 148  	 // returns true or false
 149  	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 150  	 {
 151  	 	 if (!function_exists('sybase_connect')) return null;
 152  
 153  	 	 // Sybase connection on custom port
 154  	 	 if ($this->port) {
 155  	 	 	 $argHostname .= ':' . $this->port;
 156  	 	 }
 157  
 158  	 	 if ($this->charSet) {
 159  	 	 	 $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword, $this->charSet);
 160  	 	 } else {
 161  	 	 	 $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword);
 162  	 	 }
 163  
 164  	 	 if ($this->_connectionID === false) return false;
 165  	 	 if ($argDatabasename) return $this->SelectDB($argDatabasename);
 166  	 	 return true;
 167  	 }
 168  
 169  	 // returns query ID if successful, otherwise false
 170  	function _query($sql,$inputarr=false)
 171  	 {
 172  	 global $ADODB_COUNTRECS;
 173  
 174  	 	 if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
 175  	 	 	 return sybase_unbuffered_query($sql,$this->_connectionID);
 176  	 	 else
 177  	 	 	 return sybase_query($sql,$this->_connectionID);
 178  	 }
 179  
 180  	 // See http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12
 181  	function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
 182  	 {
 183  	 	 if ($secs2cache > 0) {// we do not cache rowcount, so we have to load entire recordset
 184  	 	 	 $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
 185  	 	 	 return $rs;
 186  	 	 }
 187  
 188  	 	 $nrows = (integer) $nrows;
 189  	 	 $offset = (integer) $offset;
 190  
 191  	 	 $cnt = ($nrows >= 0) ? $nrows : 999999999;
 192  	 	 if ($offset > 0 && $cnt) $cnt += $offset;
 193  
 194  	 	 $this->Execute("set rowcount $cnt");
 195  	 	 $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,0);
 196  	 	 $this->Execute("set rowcount 0");
 197  
 198  	 	 return $rs;
 199  	 }
 200  
 201  	 // returns true or false
 202  	function _close()
 203  	 {
 204  	 	 return @sybase_close($this->_connectionID);
 205  	 }
 206  
 207  	static function UnixDate($v)
 208  	 {
 209  	 	 return ADORecordSet_array_sybase::UnixDate($v);
 210  	 }
 211  
 212  	static function UnixTimeStamp($v)
 213  	 {
 214  	 	 return ADORecordSet_array_sybase::UnixTimeStamp($v);
 215  	 }
 216  
 217  
 218  
 219  	 # Added 2003-10-05 by Chris Phillipson
 220  	 # Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=16756?target=%25N%15_12018_START_RESTART_N%25
 221  	 # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
 222  	 // Format date column in sql string given an input format that understands Y M D
 223  	function SQLDate($fmt, $col=false)
 224  	 {
 225  	 	 if (!$col) $col = $this->sysTimeStamp;
 226  	 	 $s = '';
 227  
 228  	 	 $len = strlen($fmt);
 229  	 	 for ($i=0; $i < $len; $i++) {
 230  	 	 	 if ($s) $s .= '+';
 231  	 	 	 $ch = $fmt[$i];
 232  	 	 	 switch($ch) {
 233  	 	 	 case 'Y':
 234  	 	 	 case 'y':
 235  	 	 	 	 $s .= "datename(yy,$col)";
 236  	 	 	 	 break;
 237  	 	 	 case 'M':
 238  	 	 	 	 $s .= "convert(char(3),$col,0)";
 239  	 	 	 	 break;
 240  	 	 	 case 'm':
 241  	 	 	 	 $s .= "str_replace(str(month($col),2),' ','0')";
 242  	 	 	 	 break;
 243  	 	 	 case 'Q':
 244  	 	 	 case 'q':
 245  	 	 	 	 $s .= "datename(qq,$col)";
 246  	 	 	 	 break;
 247  	 	 	 case 'D':
 248  	 	 	 case 'd':
 249  	 	 	 	 $s .= "str_replace(str(datepart(dd,$col),2),' ','0')";
 250  	 	 	 	 break;
 251  	 	 	 case 'h':
 252  	 	 	 	 $s .= "substring(convert(char(14),$col,0),13,2)";
 253  	 	 	 	 break;
 254  
 255  	 	 	 case 'H':
 256  	 	 	 	 $s .= "str_replace(str(datepart(hh,$col),2),' ','0')";
 257  	 	 	 	 break;
 258  
 259  	 	 	 case 'i':
 260  	 	 	 	 $s .= "str_replace(str(datepart(mi,$col),2),' ','0')";
 261  	 	 	 	 break;
 262  	 	 	 case 's':
 263  	 	 	 	 $s .= "str_replace(str(datepart(ss,$col),2),' ','0')";
 264  	 	 	 	 break;
 265  	 	 	 case 'a':
 266  	 	 	 case 'A':
 267  	 	 	 	 $s .= "substring(convert(char(19),$col,0),18,2)";
 268  	 	 	 	 break;
 269  
 270  	 	 	 default:
 271  	 	 	 	 if ($ch == '\\') {
 272  	 	 	 	 	 $i++;
 273  	 	 	 	 	 $ch = substr($fmt,$i,1);
 274  	 	 	 	 }
 275  	 	 	 	 $s .= $this->qstr($ch);
 276  	 	 	 	 break;
 277  	 	 	 }
 278  	 	 }
 279  	 	 return $s;
 280  	 }
 281  
 282  	 # Added 2003-10-07 by Chris Phillipson
 283  	 # Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
 284  	 # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
 285  	function MetaPrimaryKeys($table, $owner = false)
 286  	 {
 287  	 	 $sql = "SELECT c.column_name " .
 288  	 	 	    "FROM syscolumn c, systable t " .
 289  	 	 	    "WHERE t.table_name='$table' AND c.table_id=t.table_id " .
 290  	 	 	    "AND t.table_type='BASE' " .
 291  	 	 	    "AND c.pkey = 'Y' " .
 292  	 	 	    "ORDER BY c.column_id";
 293  
 294  	 	 $a = $this->GetCol($sql);
 295  	 	 if ($a && sizeof($a)>0) return $a;
 296  	 	 return false;
 297  	 }
 298  }
 299  
 300  /*--------------------------------------------------------------------------------------
 301  	  Class Name: Recordset
 302  --------------------------------------------------------------------------------------*/
 303  global $ADODB_sybase_mths;
 304  $ADODB_sybase_mths = array(
 305  	 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
 306  	 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
 307  
 308  class ADORecordset_sybase extends ADORecordSet {
 309  
 310  	 var $databaseType = "sybase";
 311  	 var $canSeek = true;
 312  	 // _mths works only in non-localised system
 313  	 var  $_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
 314  
 315  	function __construct($id,$mode=false)
 316  	 {
 317  	 	 if ($mode === false) {
 318  	 	 	 global $ADODB_FETCH_MODE;
 319  	 	 	 $mode = $ADODB_FETCH_MODE;
 320  	 	 }
 321  	 	 if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
 322  	 	 else $this->fetchMode = $mode;
 323  	 	 parent::__construct($id,$mode);
 324  	 }
 325  
 326  	 /*	 Returns: an object containing field information.
 327  	 	 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
 328  	 	 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
 329  	 	 fetchField() is retrieved.	 */
 330  	function FetchField($fieldOffset = -1)
 331  	 {
 332  	 	 if ($fieldOffset != -1) {
 333  	 	 	 $o = @sybase_fetch_field($this->_queryID, $fieldOffset);
 334  	 	 }
 335  	 	 else if ($fieldOffset == -1) {	 /*	 The $fieldOffset argument is not provided thus its -1 	 */
 336  	 	 	 $o = @sybase_fetch_field($this->_queryID);
 337  	 	 }
 338  	 	 // older versions of PHP did not support type, only numeric
 339  	 	 if ($o && !isset($o->type)) $o->type = ($o->numeric) ? 'float' : 'varchar';
 340  	 	 return $o;
 341  	 }
 342  
 343  	function _initrs()
 344  	 {
 345  	 global $ADODB_COUNTRECS;
 346  	 	 $this->_numOfRows = ($ADODB_COUNTRECS)? @sybase_num_rows($this->_queryID):-1;
 347  	 	 $this->_numOfFields = @sybase_num_fields($this->_queryID);
 348  	 }
 349  
 350  	function _seek($row)
 351  	 {
 352  	 	 return @sybase_data_seek($this->_queryID, $row);
 353  	 }
 354  
 355  	function _fetch($ignore_fields=false)
 356  	 {
 357  	 	 if ($this->fetchMode == ADODB_FETCH_NUM) {
 358  	 	 	 $this->fields = @sybase_fetch_row($this->_queryID);
 359  	 	 } else if ($this->fetchMode == ADODB_FETCH_ASSOC) {
 360  	 	 	 $this->fields = @sybase_fetch_assoc($this->_queryID);
 361  
 362  	 	 	 if (is_array($this->fields)) {
 363  	 	 	 	 $this->fields = $this->GetRowAssoc();
 364  	 	 	 	 return true;
 365  	 	 	 }
 366  	 	 	 return false;
 367  	 	 }  else {
 368  	 	 	 $this->fields = @sybase_fetch_array($this->_queryID);
 369  	 	 }
 370  	 	 if ( is_array($this->fields)) {
 371  	 	 	 return true;
 372  	 	 }
 373  
 374  	 	 return false;
 375  	 }
 376  
 377  	 /*	 close() only needs to be called if you are worried about using too much memory while your script
 378  	 	 is running. All associated result memory for the specified result identifier will automatically be freed.	 */
 379  	function _close() {
 380  	 	 return @sybase_free_result($this->_queryID);
 381  	 }
 382  
 383  	 // sybase/mssql uses a default date like Dec 30 2000 12:00AM
 384  	static function UnixDate($v)
 385  	 {
 386  	 	 return ADORecordSet_array_sybase::UnixDate($v);
 387  	 }
 388  
 389  	static function UnixTimeStamp($v)
 390  	 {
 391  	 	 return ADORecordSet_array_sybase::UnixTimeStamp($v);
 392  	 }
 393  }
 394  
 395  class ADORecordSet_array_sybase extends ADORecordSet_array {
 396  	function __construct($id=-1)
 397  	 {
 398  	 	 parent::__construct($id);
 399  	 }
 400  
 401  	 	 // sybase/mssql uses a default date like Dec 30 2000 12:00AM
 402  	static function UnixDate($v)
 403  	 {
 404  	 global $ADODB_sybase_mths;
 405  
 406  	 	 //Dec 30 2000 12:00AM
 407  	 	 if (!preg_match( "/([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})/"
 408  	 	 	 ,$v, $rr)) return parent::UnixDate($v);
 409  
 410  	 	 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
 411  
 412  	 	 $themth = substr(strtoupper($rr[1]),0,3);
 413  	 	 $themth = $ADODB_sybase_mths[$themth];
 414  	 	 if ($themth <= 0) return false;
 415  	 	 // h-m-s-MM-DD-YY
 416  	 	 return  adodb_mktime(0,0,0,$themth,$rr[2],$rr[3]);
 417  	 }
 418  
 419  	static function UnixTimeStamp($v)
 420  	 {
 421  	 global $ADODB_sybase_mths;
 422  	 	 //11.02.2001 Toni Tunkkari toni.tunkkari@finebyte.com
 423  	 	 //Changed [0-9] to [0-9 ] in day conversion
 424  	 	 if (!preg_match( "/([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})/"
 425  	 	 	 ,$v, $rr)) return parent::UnixTimeStamp($v);
 426  	 	 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
 427  
 428  	 	 $themth = substr(strtoupper($rr[1]),0,3);
 429  	 	 $themth = $ADODB_sybase_mths[$themth];
 430  	 	 if ($themth <= 0) return false;
 431  
 432  	 	 switch (strtoupper($rr[6])) {
 433  	 	 case 'P':
 434  	 	 	 if ($rr[4]<12) $rr[4] += 12;
 435  	 	 	 break;
 436  	 	 case 'A':
 437  	 	 	 if ($rr[4]==12) $rr[4] = 0;
 438  	 	 	 break;
 439  	 	 default:
 440  	 	 	 break;
 441  	 	 }
 442  	 	 // h-m-s-MM-DD-YY
 443  	 	 return  adodb_mktime($rr[4],$rr[5],0,$themth,$rr[2],$rr[3]);
 444  	 }
 445  }