Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / adodb / drivers / adodb-sybase.inc.php
blobef6df6be6dc6232dd26f79636dcc984bb6748224
1 <?php
2 /*
3 V4.98 13 Feb 2008 (c) 2000-2008 John Lim. All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence.
7 Set tabs to 4 for best viewing.
9 Latest version is available at http://adodb.sourceforge.net
11 Sybase driver contributed by Toni (toni.tunkkari@finebyte.com)
13 - MSSQL date patch applied.
15 Date patch by Toni 15 Feb 2002
18 // security - hide paths
19 if (!defined('ADODB_DIR')) die();
21 class ADODB_sybase extends ADOConnection {
22 var $databaseType = "sybase";
23 var $dataProvider = 'sybase';
24 var $replaceQuote = "''"; // string to use to replace quotes
25 var $fmtDate = "'Y-m-d'";
26 var $fmtTimeStamp = "'Y-m-d H:i:s'";
27 var $hasInsertID = true;
28 var $hasAffectedRows = true;
29 var $metaTablesSQL="select name from sysobjects where type='U' or type='V'";
30 // see http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
31 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'";
33 "select c.name,t.name,c.length from
34 syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id
35 where o.name='%s'";
37 var $concat_operator = '+';
38 var $arrayClass = 'ADORecordSet_array_sybase';
39 var $sysDate = 'GetDate()';
40 var $leftOuter = '*=';
41 var $rightOuter = '=*';
43 function ADODB_sybase()
47 // might require begintrans -- committrans
48 function _insertid()
50 return $this->GetOne('select @@identity');
52 // might require begintrans -- committrans
53 function _affectedrows()
55 return $this->GetOne('select @@rowcount');
59 function BeginTrans()
62 if ($this->transOff) return true;
63 $this->transCnt += 1;
65 $this->Execute('BEGIN TRAN');
66 return true;
69 function CommitTrans($ok=true)
71 if ($this->transOff) return true;
73 if (!$ok) return $this->RollbackTrans();
75 $this->transCnt -= 1;
76 $this->Execute('COMMIT TRAN');
77 return true;
80 function RollbackTrans()
82 if ($this->transOff) return true;
83 $this->transCnt -= 1;
84 $this->Execute('ROLLBACK TRAN');
85 return true;
88 // http://www.isug.com/Sybase_FAQ/ASE/section6.1.html#6.1.4
89 function RowLock($tables,$where,$flds='top 1 null as ignore')
91 if (!$this->_hastrans) $this->BeginTrans();
92 $tables = str_replace(',',' HOLDLOCK,',$tables);
93 return $this->GetOne("select $flds from $tables HOLDLOCK where $where");
97 function SelectDB($dbName)
99 $this->database = $dbName;
100 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
101 if ($this->_connectionID) {
102 return @sybase_select_db($dbName);
104 else return false;
107 /* Returns: the last error message from previous database operation
108 Note: This function is NOT available for Microsoft SQL Server. */
111 function ErrorMsg()
113 if ($this->_logsql) return $this->_errorMsg;
114 if (function_exists('sybase_get_last_message'))
115 $this->_errorMsg = sybase_get_last_message();
116 else
117 $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : 'SYBASE error messages not supported on this platform';
118 return $this->_errorMsg;
121 // returns true or false
122 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
124 if (!function_exists('sybase_connect')) return null;
126 $this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword);
127 if ($this->_connectionID === false) return false;
128 if ($argDatabasename) return $this->SelectDB($argDatabasename);
129 return true;
131 // returns true or false
132 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
134 if (!function_exists('sybase_connect')) return null;
136 $this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword);
137 if ($this->_connectionID === false) return false;
138 if ($argDatabasename) return $this->SelectDB($argDatabasename);
139 return true;
142 // returns query ID if successful, otherwise false
143 function _query($sql,$inputarr)
145 global $ADODB_COUNTRECS;
147 if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
148 return sybase_unbuffered_query($sql,$this->_connectionID);
149 else
150 return sybase_query($sql,$this->_connectionID);
153 // See http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12
154 function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
156 if ($secs2cache > 0) {// we do not cache rowcount, so we have to load entire recordset
157 $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
158 return $rs;
161 $nrows = (integer) $nrows;
162 $offset = (integer) $offset;
164 $cnt = ($nrows >= 0) ? $nrows : 999999999;
165 if ($offset > 0 && $cnt) $cnt += $offset;
167 $this->Execute("set rowcount $cnt");
168 $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,0);
169 $this->Execute("set rowcount 0");
171 return $rs;
174 // returns true or false
175 function _close()
177 return @sybase_close($this->_connectionID);
180 function UnixDate($v)
182 return ADORecordSet_array_sybase::UnixDate($v);
185 function UnixTimeStamp($v)
187 return ADORecordSet_array_sybase::UnixTimeStamp($v);
192 # Added 2003-10-05 by Chris Phillipson
193 # 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
194 # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
195 // Format date column in sql string given an input format that understands Y M D
196 function SQLDate($fmt, $col=false)
198 if (!$col) $col = $this->sysTimeStamp;
199 $s = '';
201 $len = strlen($fmt);
202 for ($i=0; $i < $len; $i++) {
203 if ($s) $s .= '+';
204 $ch = $fmt[$i];
205 switch($ch) {
206 case 'Y':
207 case 'y':
208 $s .= "datename(yy,$col)";
209 break;
210 case 'M':
211 $s .= "convert(char(3),$col,0)";
212 break;
213 case 'm':
214 $s .= "replace(str(month($col),2),' ','0')";
215 break;
216 case 'Q':
217 case 'q':
218 $s .= "datename(qq,$col)";
219 break;
220 case 'D':
221 case 'd':
222 $s .= "replace(str(datepart(dd,$col),2),' ','0')";
223 break;
224 case 'h':
225 $s .= "substring(convert(char(14),$col,0),13,2)";
226 break;
228 case 'H':
229 $s .= "replace(str(datepart(hh,$col),2),' ','0')";
230 break;
232 case 'i':
233 $s .= "replace(str(datepart(mi,$col),2),' ','0')";
234 break;
235 case 's':
236 $s .= "replace(str(datepart(ss,$col),2),' ','0')";
237 break;
238 case 'a':
239 case 'A':
240 $s .= "substring(convert(char(19),$col,0),18,2)";
241 break;
243 default:
244 if ($ch == '\\') {
245 $i++;
246 $ch = substr($fmt,$i,1);
248 $s .= $this->qstr($ch);
249 break;
252 return $s;
255 # Added 2003-10-07 by Chris Phillipson
256 # 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
257 # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
258 function MetaPrimaryKeys($table)
260 $sql = "SELECT c.column_name " .
261 "FROM syscolumn c, systable t " .
262 "WHERE t.table_name='$table' AND c.table_id=t.table_id " .
263 "AND t.table_type='BASE' " .
264 "AND c.pkey = 'Y' " .
265 "ORDER BY c.column_id";
267 $a = $this->GetCol($sql);
268 if ($a && sizeof($a)>0) return $a;
269 return false;
273 /*--------------------------------------------------------------------------------------
274 Class Name: Recordset
275 --------------------------------------------------------------------------------------*/
276 global $ADODB_sybase_mths;
277 $ADODB_sybase_mths = array(
278 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
279 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
281 class ADORecordset_sybase extends ADORecordSet {
283 var $databaseType = "sybase";
284 var $canSeek = true;
285 // _mths works only in non-localised system
286 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);
288 function ADORecordset_sybase($id,$mode=false)
290 if ($mode === false) {
291 global $ADODB_FETCH_MODE;
292 $mode = $ADODB_FETCH_MODE;
294 if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
295 else $this->fetchMode = $mode;
296 $this->ADORecordSet($id,$mode);
299 /* Returns: an object containing field information.
300 Get column information in the Recordset object. fetchField() can be used in order to obtain information about
301 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
302 fetchField() is retrieved. */
303 function &FetchField($fieldOffset = -1)
305 if ($fieldOffset != -1) {
306 $o = @sybase_fetch_field($this->_queryID, $fieldOffset);
308 else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
309 $o = @sybase_fetch_field($this->_queryID);
311 // older versions of PHP did not support type, only numeric
312 if ($o && !isset($o->type)) $o->type = ($o->numeric) ? 'float' : 'varchar';
313 return $o;
316 function _initrs()
318 global $ADODB_COUNTRECS;
319 $this->_numOfRows = ($ADODB_COUNTRECS)? @sybase_num_rows($this->_queryID):-1;
320 $this->_numOfFields = @sybase_num_fields($this->_queryID);
323 function _seek($row)
325 return @sybase_data_seek($this->_queryID, $row);
328 function _fetch($ignore_fields=false)
330 if ($this->fetchMode == ADODB_FETCH_NUM) {
331 $this->fields = @sybase_fetch_row($this->_queryID);
332 } else if ($this->fetchMode == ADODB_FETCH_ASSOC) {
333 $this->fields = @sybase_fetch_row($this->_queryID);
334 if (is_array($this->fields)) {
335 $this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE);
336 return true;
338 return false;
339 } else {
340 $this->fields = @sybase_fetch_array($this->_queryID);
342 if ( is_array($this->fields)) {
343 return true;
346 return false;
349 /* close() only needs to be called if you are worried about using too much memory while your script
350 is running. All associated result memory for the specified result identifier will automatically be freed. */
351 function _close() {
352 return @sybase_free_result($this->_queryID);
355 // sybase/mssql uses a default date like Dec 30 2000 12:00AM
356 function UnixDate($v)
358 return ADORecordSet_array_sybase::UnixDate($v);
361 function UnixTimeStamp($v)
363 return ADORecordSet_array_sybase::UnixTimeStamp($v);
367 class ADORecordSet_array_sybase extends ADORecordSet_array {
368 function ADORecordSet_array_sybase($id=-1)
370 $this->ADORecordSet_array($id);
373 // sybase/mssql uses a default date like Dec 30 2000 12:00AM
374 function UnixDate($v)
376 global $ADODB_sybase_mths;
378 //Dec 30 2000 12:00AM
379 if (!ereg( "([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})"
380 ,$v, $rr)) return parent::UnixDate($v);
382 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
384 $themth = substr(strtoupper($rr[1]),0,3);
385 $themth = $ADODB_sybase_mths[$themth];
386 if ($themth <= 0) return false;
387 // h-m-s-MM-DD-YY
388 return mktime(0,0,0,$themth,$rr[2],$rr[3]);
391 function UnixTimeStamp($v)
393 global $ADODB_sybase_mths;
394 //11.02.2001 Toni Tunkkari toni.tunkkari@finebyte.com
395 //Changed [0-9] to [0-9 ] in day conversion
396 if (!ereg( "([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})"
397 ,$v, $rr)) return parent::UnixTimeStamp($v);
398 if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
400 $themth = substr(strtoupper($rr[1]),0,3);
401 $themth = $ADODB_sybase_mths[$themth];
402 if ($themth <= 0) return false;
404 switch (strtoupper($rr[6])) {
405 case 'P':
406 if ($rr[4]<12) $rr[4] += 12;
407 break;
408 case 'A':
409 if ($rr[4]==12) $rr[4] = 0;
410 break;
411 default:
412 break;
414 // h-m-s-MM-DD-YY
415 return mktime($rr[4],$rr[5],0,$themth,$rr[2],$rr[3]);