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