root/releases/elgg0.8rc2/lib/adodb/adodb-connection.inc.php

Revision 269, 60.7 kB (checked in by ben, 3 years ago)

--

  • Property svn:eol-style set to native
Line 
1 <?php
2 /**
3  * @version V3.40 7 April 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). 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  *
8  * Set tabs to 4 for best viewing.
9  *
10  * Latest version is available at http://php.weblogs.com
11  *
12  */
13
14     
15     function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
16     {
17         /* print "Errorno ($fn errno=$errno m=$errmsg) "; */
18         
19         $thisConnection->_transOK = false;
20         if ($thisConnection->_oldRaiseFn) {
21             $fn = $thisConnection->_oldRaiseFn;
22             $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
23         }
24     }
25     
26     
27     /**
28      * Connection object. For connecting to databases, and executing queries.
29      */
30     class ADOConnection {
31     /*  */
32     /*  PUBLIC VARS  */
33     /*  */
34     var $dataProvider = 'native';
35     var $databaseType = '';     /* / RDBMS currently in use, eg. odbc, mysql, mssql                 */
36     var $database = '';         /* / Name of database to be used.   */
37     var $host = '';         /* / The hostname of the database server    */
38     var $user = '';         /* / The username which is used to connect to the database server.  */
39     var $password = '';     /* / Password for the username. For security, we no longer store it. */
40     var $debug = false;     /* / if set to true will output sql statements */
41     var $maxblobsize = 256000/* / maximum size of blobs or large text fields -- some databases die otherwise like foxpro */
42     var $concat_operator = '+'; /* / default concat operator -- change to || for Oracle/Interbase     */
43     var $fmtDate = "'Y-m-d'";   /* / used by DBDate() as the default date format used by the database */
44     var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; /* / used by DBTimeStamp as the default timestamp fmt. */
45     var $true = '1';            /* / string that represents TRUE for a database */
46     var $false = '0';           /* / string that represents FALSE for a database */
47     var $replaceQuote = "\\'"/* / string to use to replace quotes */
48     var $charSet=false;     /* / character set to use - only for interbase */
49     var $metaTablesSQL = '';
50     /* -- */
51     var $hasInsertID = false;       /* / supports autoincrement ID? */
52     var $hasAffectedRows = false;   /* / supports affected rows for update/delete? */
53     var $hasTop = false;            /* / support mssql/access SELECT TOP 10 * FROM TABLE */
54     var $hasLimit = false;          /* / support pgsql/mysql SELECT * FROM TABLE LIMIT 10 */
55     var $readOnly = false;          /* / this is a readonly database - used by phpLens */
56     var $hasMoveFirst = false/* / has ability to run MoveFirst(), scrolling backwards */
57     var $hasGenID = false;      /* / can generate sequences using GenID(); */
58     var $hasTransactions = true; /* / has transactions */
59     /* -- */
60     var $genID = 0;         /* / sequence id used by GenID(); */
61     var $raiseErrorFn = false/* / error function to call */
62     var $upperCase = false; /* / uppercase function to call for searching/where */
63     var $isoDates = false; /* / accepts dates in ISO format */
64     var $cacheSecs = 3600; /* / cache for 1 hour */
65     var $sysDate = false; /* / name of function that returns the current date */
66     var $sysTimeStamp = false; /* / name of function that returns the current timestamp */
67     var $arrayClass = 'ADORecordSet_array'; /* / name of class used to generate array recordsets, which are pre-downloaded recordsets */
68     
69     var $noNullStrings = false; /* / oracle specific stuff - if true ensures that '' is converted to ' ' */
70     var $numCacheHits = 0;
71     var $numCacheMisses = 0;
72     var $pageExecuteCountRows = true;
73     var $uniqueSort = false; /* / indicates that all fields in order by must be unique */
74     var $leftOuter = false; /* / operator to use for left outer join in WHERE clause */
75     var $rightOuter = false; /* / operator to use for right outer join in WHERE clause */
76     var $ansiOuter = false; /* / whether ansi outer join syntax supported */
77     var $autoRollback = false; /*  autoRollback on PConnect(). */
78     var $poorAffectedRows = false; /*  affectedRows not working or unreliable */
79     
80     var $fnExecute = false;
81     var $fnCacheExecute = false;
82     var $blobEncodeType = false; /*  false=not required, 'I'=encode to integer, 'C'=encode to char */
83     var $dbxDriver = false;
84     
85      /*  */
86      /*  PRIVATE VARS */
87      /*  */
88     var $_oldRaiseFn false;
89     var $_transOK = null;
90     var $_connectionID = false; /* / The returned link identifier whenever a successful database connection is made.    */
91     var $_errorMsg = '';    /* / A variable which was used to keep the returned last error message.  The value will */
92                                 /* / then returned by the errorMsg() function     */
93                         
94     var $_queryID = false/* / This variable keeps the last created result link identifier */
95     
96     var $_isPersistentConnection = false;   /* / A boolean variable to state whether its a persistent connection or normal connection.  */
97     var $_bindInputArray = false; /* / set to true if ADOConnection.Execute() permits binding of array parameters. */
98     var $autoCommit = true; /* / do not modify this yourself - actually private */
99     var $transOff = 0/* / temporarily disable transactions */
100     var $transCnt = 0/* / count of nested transactions */
101     
102     var $fetchMode=false;
103     
104     /**
105      * Constructor
106      */
107     function ADOConnection()
108     {
109         die('Virtual Class -- cannot instantiate');
110     }
111     
112     /**
113         Get server version info...
114         
115         @returns An array with 2 elements: $arr['string'] is the description string,
116             and $arr[version] is the version (also a string).
117     */
118     function ServerInfo()
119     {
120         return array('description' => '', 'version' => '');
121     }
122     
123     function _findvers($str)
124     {
125         if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) return $arr[1];
126         else return '';
127     }
128     
129     /**
130     * All error messages go through this bottleneck function.
131     * You can define your own handler by defining the function name in ADODB_OUTP.
132     */
133     function outp($msg,$newline=true)
134     {
135     global $HTTP_SERVER_VARS;
136     
137         if (defined('ADODB_OUTP')) {
138             $fn = ADODB_OUTP;
139             $fn($msg,$newline);
140             return;
141         }
142         
143         if ($newline) $msg .= "<br />\n";
144         
145         if (isset($HTTP_SERVER_VARS['HTTP_USER_AGENT'])) echo $msg;
146         else echo strip_tags($msg);
147         flush();
148     }
149     
150     /**
151      * Connect to database
152      *
153      * @param [argHostname]        Host to connect to
154      * @param [argUsername]        Userid to login
155      * @param [argPassword]        Associated password
156      * @param [argDatabaseName]    database
157      * @param [forceNew]        force new connection
158      *
159      * @return true or false
160      */     
161     function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false)
162     {
163         if ($argHostname != "") $this->host = $argHostname;
164         if ($argUsername != "") $this->user = $argUsername;
165         if ($argPassword != "") $this->password = $argPassword; /*  not stored for security reasons */
166         if ($argDatabaseName != "") $this->database = $argDatabaseName;
167         
168         $this->_isPersistentConnection = false;   
169         if ($fn = $this->raiseErrorFn) {
170             if ($forceNew) {
171                 if ($this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true;
172             } else {
173                  if ($this->_connect($this->host, $this->user, $this->password, $this->database)) return true;
174             }
175             $err = $this->ErrorMsg();
176             if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
177             $fn($this->databaseType,'CONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
178         } else {
179             if ($forceNew) {
180                 if ($this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true;
181             } else {
182                 if ($this->_connect($this->host, $this->user, $this->password, $this->database)) return true;
183             }
184         }
185         if ($this->debug) ADOConnection::outp( $this->host.': '.$this->ErrorMsg());
186         
187         return false;
188     }   
189     
190      function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
191      {
192          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
193      }
194     
195     
196     /**
197      * Always force a new connection to database - currently only works with oracle
198      *
199      * @param [argHostname]        Host to connect to
200      * @param [argUsername]        Userid to login
201      * @param [argPassword]        Associated password
202      * @param [argDatabaseName]    database
203      *
204      * @return true or false
205      */     
206     function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
207     {
208         return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true);
209     }
210     
211     /**
212      * Establish persistent connect to database
213      *
214      * @param [argHostname]        Host to connect to
215      * @param [argUsername]        Userid to login
216      * @param [argPassword]        Associated password
217      * @param [argDatabaseName]    database
218      *
219      * @return return true or false
220      */   
221     function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
222     {
223         if (defined('ADODB_NEVER_PERSIST'))
224             return $this->Connect($argHostname,$argUsername,$argPassword,$argDatabaseName);
225         
226         if ($argHostname != "") $this->host = $argHostname;
227         if ($argUsername != "") $this->user = $argUsername;
228         if ($argPassword != "") $this->password = $argPassword;
229         if ($argDatabaseName != "") $this->database = $argDatabaseName;
230             
231         $this->_isPersistentConnection = true;
232         
233         if ($fn = $this->raiseErrorFn) {
234             if ($this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;
235             $err = $this->ErrorMsg();
236             if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
237             $fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
238         } else
239             if ($this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;
240
241         if ($this->debug) ADOConnection::outp( $this->host.': '.$this->ErrorMsg());
242         
243         return false;
244     }
245
246     /*  Format date column in sql string given an input format that understands Y M D */
247     function SQLDate($fmt, $col=false)
248     {   
249         if (!$col) $col = $this->sysDate;
250         return $col; /*  child class implement */
251     }
252     
253     /**
254      * Should prepare the sql statement and return the stmt resource.
255      * For databases that do not support this, we return the $sql. To ensure
256      * compatibility with databases that do not support prepare:
257      *
258      *   $stmt = $db->Prepare("insert into table (id, name) values (?,?)");
259      *   $db->Execute($stmt,array(1,'Jill')) or die('insert failed');
260      *   $db->Execute($stmt,array(2,'Joe')) or die('insert failed');
261      *
262      * @param sql   SQL to send to database
263      *
264      * @return return FALSE, or the prepared statement, or the original sql if
265      *          if the database does not support prepare.
266      *
267      */   
268     function Prepare($sql)
269     {
270         return $sql;
271     }
272
273     /**
274      * Some databases, eg. mssql require a different function for preparing
275      * stored procedures. So we cannot use Prepare().
276      *
277      * Should prepare the stored procedure  and return the stmt resource.
278      * For databases that do not support this, we return the $sql. To ensure
279      * compatibility with databases that do not support prepare:
280      *
281      * @param sql   SQL to send to database
282      *
283      * @return return FALSE, or the prepared statement, or the original sql if
284      *          if the database does not support prepare.
285      *
286      */   
287     function PrepareSP($sql)
288     {
289         return $this->Prepare($sql);
290     }
291     
292     /**
293     * PEAR DB Compat
294     */
295     function Quote($s)
296     {
297         return $this->qstr($s,false);
298     }
299
300     
301     /**
302     * PEAR DB Compat - do not use internally.
303     */
304     function ErrorNative()
305     {
306         return $this->ErrorNo();
307     }
308
309     
310    /**
311     * PEAR DB Compat - do not use internally.
312     */
313     function nextId($seq_name)
314     {
315         return $this->GenID($seq_name);
316     }
317
318     /**
319     *   Lock a row, will escalate and lock the table if row locking not supported
320     *   will normally free the lock at the end of the transaction
321     *
322     *  @param $table    name of table to lock
323     *  @param $where    where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
324     */
325     function RowLock($table,$where)
326     {
327         return false;
328     }
329     
330     function CommitLock($table)
331     {
332         return $this->CommitTrans();
333     }
334     
335     function RollbackLock($table)
336     {
337         return $this->RollbackTrans();
338     }
339     
340     /**
341     * PEAR DB Compat - do not use internally.
342     *
343     * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical
344     *   for easy porting :-)
345     *
346     * @param mode   The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
347     * @returns      The previous fetch mode
348     */
349     function SetFetchMode($mode)
350     {   
351         $old = $this->fetchMode;
352         $this->fetchMode = $mode;
353         
354         if ($old === false) {
355         global $ADODB_FETCH_MODE;
356             return $ADODB_FETCH_MODE;
357         }
358         return $old;
359     }
360     
361
362     /**
363     * PEAR DB Compat - do not use internally.
364     */
365     function &Query($sql, $inputarr=false)
366     {
367         $rs = &$this->Execute($sql, $inputarr);
368         if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
369         return $rs;
370     }
371
372     
373     /**
374     * PEAR DB Compat - do not use internally
375     */
376     function &LimitQuery($sql, $offset, $count)
377     {
378         $rs = &$this->SelectLimit($sql, $count, $offset); /*  swap  */
379         if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
380         return $rs;
381     }
382
383     
384     /**
385     * PEAR DB Compat - do not use internally
386     */
387     function Disconnect()
388     {
389         return $this->Close();
390     }
391
392     /*
393     Usage in oracle
394         $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
395         $db->Parameter($stmt,$id,'myid');
396         $db->Parameter($stmt,$group,'group',64);
397         $db->Execute();
398         
399         @param $stmt Statement returned by Prepare() or PrepareSP().
400         @param $var PHP variable to bind to
401         @param $name Name of stored procedure variable name to bind to.
402         @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
403         @param [$maxLen] Holds an maximum length of the variable.
404         @param [$type] The data type of $var. Legal values depend on driver.
405
406     */
407     function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
408     {
409         return false;
410     }
411     
412     /**
413         Improved method of initiating a transaction. Used together with CompleteTrans().
414         Advantages include:
415         
416         a. StartTrans/CompleteTrans is nestable, unlike BeginTrans/CommitTrans/RollbackTrans.
417            Only the outermost block is treated as a transaction.<br />
418         b. CompleteTrans auto-detects SQL errors, and will rollback on errors, commit otherwise.<br />
419         c. All BeginTrans/CommitTrans/RollbackTrans inside a StartTrans/CompleteTrans block
420            are disabled, making it backward compatible.
421     */
422     function StartTrans($errfn = 'ADODB_TransMonitor')
423     {
424         
425         if ($this->transOff > 0) {
426             $this->transOff += 1;
427             return;
428         }
429         
430         $this->_oldRaiseFn = $this->raiseErrorFn;
431         $this->raiseErrorFn = $errfn;
432         $this->_transOK = true;
433         
434         if ($this->debug && $this->transCnt > 0) ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
435         $this->BeginTrans();
436         $this->transOff = 1;
437     }
438     
439     /**
440         Used together with StartTrans() to end a transaction. Monitors connection
441         for sql errors, and will commit or rollback as appropriate.
442         
443         @autoComplete if true, monitor sql errors and commit and rollback as appropriate,
444         and if set to false force rollback even if no SQL error detected.
445         @returns true on commit, false on rollback.
446     */
447     function CompleteTrans($autoComplete = true)
448     {
449         if ($this->transOff > 1) {
450             $this->transOff -= 1;
451             return true;
452         }
453         $this->raiseErrorFn = $this->_oldRaiseFn;
454         
455         $this->transOff = 0;
456         if ($this->_transOK && $autoComplete) $this->CommitTrans();
457         else $this->RollbackTrans();
458         
459         return $this->_transOK;
460     }
461     
462     /*
463         At the end of a StartTrans/CompleteTrans block, perform a rollback.
464     */
465     function FailTrans()
466     {
467         if ($this->debug && $this->transOff == 0) {
468             ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
469         }
470         $this->_transOK = false;
471     }
472     /**
473      * Execute SQL
474      *
475      * @param sql        SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
476      * @param [inputarr]    holds the input data to bind to. Null elements will be set to null.
477      * @param [arg3]    reserved for john lim for future use
478      * @return         RecordSet or false
479      */
480     function &Execute($sql,$inputarr=false,$arg3=false)
481     {
482         if ($this->fnExecute) {
483             $fn = $this->fnExecute;
484             $fn($this,$sql,$inputarr);
485         }
486         if (!$this->_bindInputArray && $inputarr) {
487             $sqlarr = explode('?',$sql);
488             $sql = '';
489             $i = 0;
490             foreach($inputarr as $v) {
491
492                 $sql .= $sqlarr[$i];
493                 /*  from Ron Baldwin <ron.baldwin@sourceprose.com> */
494                 /*  Only quote string types     */
495                 if (gettype($v) == 'string')
496                     $sql .= $this->qstr($v);
497                 else if ($v === null)
498                     $sql .= 'NULL';
499                 else
500                     $sql .= $v;
501                 $i += 1;
502     
503             }
504             $sql .= $sqlarr[$i];
505             if ($i+1 != sizeof($sqlarr))   
506                 ADOConnection::outp( "Input Array does not match ?: ".htmlspecialchars($sql));
507             $inputarr = false;
508         }
509         /*  debug version of query */
510         if ($this->debug) {
511         global $HTTP_S