]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/drivers/adodb-pdo.inc.php
Update adodb to adodb519
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / drivers / adodb-pdo.inc.php
1 <?php
2 /*
3 V5.19  23-Apr-2014  (c) 2000-2014 John Lim (jlim#natsoft.com). 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://adodb.sourceforge.net
10
11   Requires ODBC. Works on Windows and Unix.
12
13         Problems:
14                 Where is float/decimal type in pdo_param_type
15                 LOB handling for CLOB/BLOB differs significantly
16 */
17 // security - hide paths
18 if (!defined('ADODB_DIR')) die();
19
20
21 /*
22 enum pdo_param_type {
23 PDO::PARAM_NULL, 0
24
25 /* int as in long (the php native int type).
26  * If you mark a column as an int, PDO expects get_col to return
27  * a pointer to a long
28 PDO::PARAM_INT, 1
29
30 /* get_col ptr should point to start of the string buffer
31 PDO::PARAM_STR, 2
32
33 /* get_col: when len is 0 ptr should point to a php_stream *,
34  * otherwise it should behave like a string. Indicate a NULL field
35  * value by setting the ptr to NULL
36 PDO::PARAM_LOB, 3
37
38 /* get_col: will expect the ptr to point to a new PDOStatement object handle,
39  * but this isn't wired up yet
40 PDO::PARAM_STMT, 4 /* hierarchical result set
41
42 /* get_col ptr should point to a zend_bool
43 PDO::PARAM_BOOL, 5
44
45
46 /* magic flag to denote a parameter as being input/output
47 PDO::PARAM_INPUT_OUTPUT = 0x80000000
48 };
49 */
50
51 function adodb_pdo_type($t)
52 {
53         switch($t) {
54         case 2: return 'VARCHAR';
55         case 3: return 'BLOB';
56         default: return 'NUMERIC';
57         }
58 }
59
60 /*--------------------------------------------------------------------------------------
61 --------------------------------------------------------------------------------------*/
62
63 ////////////////////////////////////////////////
64
65
66
67
68
69
70 class ADODB_pdo extends ADOConnection {
71         var $databaseType = "pdo";
72         var $dataProvider = "pdo";
73         var $fmtDate = "'Y-m-d'";
74         var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
75         var $replaceQuote = "''"; // string to use to replace quotes
76         var $hasAffectedRows = true;
77         var $_bindInputArray = true;
78         var $_genSeqSQL = "create table %s (id integer)";
79         var $_autocommit = true;
80         var $_haserrorfunctions = true;
81         var $_lastAffectedRows = 0;
82
83         var $_errormsg = false;
84         var $_errorno = false;
85
86         var $dsnType = '';
87         var $stmt = false;
88
89         function ADODB_pdo()
90         {
91         }
92
93         function _UpdatePDO()
94         {
95                 $d = $this->_driver;
96                 $this->fmtDate = $d->fmtDate;
97                 $this->fmtTimeStamp = $d->fmtTimeStamp;
98                 $this->replaceQuote = $d->replaceQuote;
99                 $this->sysDate = $d->sysDate;
100                 $this->sysTimeStamp = $d->sysTimeStamp;
101                 $this->random = $d->random;
102                 $this->concat_operator = $d->concat_operator;
103                 $this->nameQuote = $d->nameQuote;
104
105                 $this->hasGenID = $d->hasGenID;
106                 $this->_genIDSQL = $d->_genIDSQL;
107                 $this->_genSeqSQL = $d->_genSeqSQL;
108                 $this->_dropSeqSQL = $d->_dropSeqSQL;
109
110                 $d->_init($this);
111         }
112
113         function Time()
114         {
115                 if (!empty($this->_driver->_hasdual)) $sql = "select $this->sysTimeStamp from dual";
116                 else $sql = "select $this->sysTimeStamp";
117
118                 $rs = $this->_Execute($sql);
119                 if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
120
121                 return false;
122         }
123
124         // returns true or false
125         function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persist=false)
126         {
127                 $at = strpos($argDSN,':');
128                 $this->dsnType = substr($argDSN,0,$at);
129
130                 if ($argDatabasename) {
131                         $argDSN .= ';dbname='.$argDatabasename;
132                 }
133                 try {
134                         $this->_connectionID = new PDO($argDSN, $argUsername, $argPassword);
135                 } catch (Exception $e) {
136                         $this->_connectionID = false;
137                         $this->_errorno = -1;
138                         //var_dump($e);
139                         $this->_errormsg = 'Connection attempt failed: '.$e->getMessage();
140                         return false;
141                 }
142
143                 if ($this->_connectionID) {
144                         switch(ADODB_ASSOC_CASE){
145                         case 0: $m = PDO::CASE_LOWER; break;
146                         case 1: $m = PDO::CASE_UPPER; break;
147                         default:
148                         case 2: $m = PDO::CASE_NATURAL; break;
149                         }
150
151                         //$this->_connectionID->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT );
152                         $this->_connectionID->setAttribute(PDO::ATTR_CASE,$m);
153
154                         $class = 'ADODB_pdo_'.$this->dsnType;
155                         //$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true);
156                         switch($this->dsnType) {
157                         case 'oci':
158                         case 'mysql':
159                         case 'pgsql':
160                         case 'mssql':
161                         case 'sqlite':
162                                 include_once(ADODB_DIR.'/drivers/adodb-pdo_'.$this->dsnType.'.inc.php');
163                                 break;
164                         }
165                         if (class_exists($class))
166                                 $this->_driver = new $class();
167                         else
168                                 $this->_driver = new ADODB_pdo_base();
169
170                         $this->_driver->_connectionID = $this->_connectionID;
171                         $this->_UpdatePDO();
172                         return true;
173                 }
174                 $this->_driver = new ADODB_pdo_base();
175                 return false;
176         }
177
178         function Concat()
179         {
180                 $args = func_get_args();
181                 if(method_exists($this->_driver, 'Concat'))
182                         return call_user_func_array(array($this->_driver, 'Concat'), $args);
183
184                 if (PHP_VERSION >= 5.3) return call_user_func_array('parent::Concat', $args);
185                 return call_user_func_array(array($this,'parent::Concat'), $args);
186         }
187
188         // returns true or false
189         function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
190         {
191                 return $this->_connect($argDSN, $argUsername, $argPassword, $argDatabasename, true);
192         }
193
194         /*------------------------------------------------------------------------------*/
195
196
197         function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
198         {
199                 $save = $this->_driver->fetchMode;
200                 $this->_driver->fetchMode = $this->fetchMode;
201                 $this->_driver->debug = $this->debug;
202                 $ret = $this->_driver->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
203                 $this->_driver->fetchMode = $save;
204                 return $ret;
205         }
206
207
208         function ServerInfo()
209         {
210                 return $this->_driver->ServerInfo();
211         }
212
213         function MetaTables($ttype=false,$showSchema=false,$mask=false)
214         {
215                 return $this->_driver->MetaTables($ttype,$showSchema,$mask);
216         }
217
218         function MetaColumns($table,$normalize=true)
219         {
220                 return $this->_driver->MetaColumns($table,$normalize);
221         }
222
223         function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
224         {
225                 $obj = $stmt[1];
226                 if ($type) $obj->bindParam($name,$var,$type,$maxLen);
227                 else $obj->bindParam($name, $var);
228         }
229
230         function OffsetDate($dayFraction,$date=false)
231     {
232         return $this->_driver->OffsetDate($dayFraction,$date);
233     }
234
235         function ErrorMsg()
236         {
237                 if ($this->_errormsg !== false) return $this->_errormsg;
238                 if (!empty($this->_stmt)) $arr = $this->_stmt->errorInfo();
239                 else if (!empty($this->_connectionID)) $arr = $this->_connectionID->errorInfo();
240                 else return 'No Connection Established';
241
242
243                 if ($arr) {
244                         if (sizeof($arr)<2) return '';
245                         if ((integer)$arr[0]) return $arr[2];
246                         else return '';
247                 } else return '-1';
248         }
249
250
251         function ErrorNo()
252         {
253                 if ($this->_errorno !== false) return $this->_errorno;
254                 if (!empty($this->_stmt)) $err = $this->_stmt->errorCode();
255                 else if (!empty($this->_connectionID)) {
256                         $arr = $this->_connectionID->errorInfo();
257                         if (isset($arr[0])) $err = $arr[0];
258                         else $err = -1;
259                 } else
260                         return 0;
261
262                 if ($err == '00000') return 0; // allows empty check
263                 return $err;
264         }
265
266         function SetTransactionMode($transaction_mode)
267         {
268                 if(method_exists($this->_driver, 'SetTransactionMode'))
269                         return $this->_driver->SetTransactionMode($transaction_mode);
270
271                 return parent::SetTransactionMode($seqname);
272         }
273
274         function BeginTrans()
275         {
276                 if(method_exists($this->_driver, 'BeginTrans'))
277                         return $this->_driver->BeginTrans();
278
279                 if (!$this->hasTransactions) return false;
280                 if ($this->transOff) return true;
281                 $this->transCnt += 1;
282                 $this->_autocommit = false;
283                 $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,false);
284                 return $this->_connectionID->beginTransaction();
285         }
286
287         function CommitTrans($ok=true)
288         {
289                 if(method_exists($this->_driver, 'CommitTrans'))
290                         return $this->_driver->CommitTrans($ok);
291
292                 if (!$this->hasTransactions) return false;
293                 if ($this->transOff) return true;
294                 if (!$ok) return $this->RollbackTrans();
295                 if ($this->transCnt) $this->transCnt -= 1;
296                 $this->_autocommit = true;
297
298                 $ret = $this->_connectionID->commit();
299                 $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true);
300                 return $ret;
301         }
302
303         function RollbackTrans()
304         {
305                 if(method_exists($this->_driver, 'RollbackTrans'))
306                         return $this->_driver->RollbackTrans();
307
308                 if (!$this->hasTransactions) return false;
309                 if ($this->transOff) return true;
310                 if ($this->transCnt) $this->transCnt -= 1;
311                 $this->_autocommit = true;
312
313                 $ret = $this->_connectionID->rollback();
314                 $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true);
315                 return $ret;
316         }
317
318         function Prepare($sql)
319         {
320                 $this->_stmt = $this->_connectionID->prepare($sql);
321                 if ($this->_stmt) return array($sql,$this->_stmt);
322
323                 return false;
324         }
325
326         function PrepareStmt($sql)
327         {
328                 $stmt = $this->_connectionID->prepare($sql);
329                 if (!$stmt) return false;
330                 $obj = new ADOPDOStatement($stmt,$this);
331                 return $obj;
332         }
333
334         function CreateSequence($seqname='adodbseq',$startID=1)
335         {
336                 if(method_exists($this->_driver, 'CreateSequence'))
337                         return $this->_driver->CreateSequence($seqname, $startID);
338
339                 return parent::CreateSequence($seqname, $startID);
340         }
341
342         function DropSequence($seqname='adodbseq')
343         {
344                 if(method_exists($this->_driver, 'DropSequence'))
345                         return $this->_driver->DropSequence($seqname);
346
347                 return parent::DropSequence($seqname);
348         }
349
350         function GenID($seqname='adodbseq',$startID=1)
351         {
352                 if(method_exists($this->_driver, 'GenID'))
353                         return $this->_driver->GenID($seqname, $startID);
354
355                 return parent::GenID($seqname, $startID);
356         }
357
358
359         /* returns queryID or false */
360         function _query($sql,$inputarr=false)
361         {
362                 if (is_array($sql)) {
363                         $stmt = $sql[1];
364                 } else {
365                         $stmt = $this->_connectionID->prepare($sql);
366                 }
367                 #adodb_backtrace();
368                 #var_dump($this->_bindInputArray);
369                 if ($stmt) {
370                         $this->_driver->debug = $this->debug;
371                         if ($inputarr) $ok = $stmt->execute($inputarr);
372                         else $ok = $stmt->execute();
373                 }
374
375
376                 $this->_errormsg = false;
377                 $this->_errorno = false;
378
379                 if ($ok) {
380                         $this->_stmt = $stmt;
381                         return $stmt;
382                 }
383
384                 if ($stmt) {
385
386                         $arr = $stmt->errorinfo();
387                         if ((integer)$arr[1]) {
388                                 $this->_errormsg = $arr[2];
389                                 $this->_errorno = $arr[1];
390                         }
391
392                 } else {
393                         $this->_errormsg = false;
394                         $this->_errorno = false;
395                 }
396                 return false;
397         }
398
399         // returns true or false
400         function _close()
401         {
402                 $this->_stmt = false;
403                 return true;
404         }
405
406         function _affectedrows()
407         {
408                 return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
409         }
410
411         function _insertid()
412         {
413                 return ($this->_connectionID) ? $this->_connectionID->lastInsertId() : 0;
414         }
415 }
416
417 class ADODB_pdo_base extends ADODB_pdo {
418
419         var $sysDate = "'?'";
420         var $sysTimeStamp = "'?'";
421
422
423         function _init($parentDriver)
424         {
425                 $parentDriver->_bindInputArray = true;
426                 #$parentDriver->_connectionID->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,true);
427         }
428
429         function ServerInfo()
430         {
431                 return ADOConnection::ServerInfo();
432         }
433
434         function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
435         {
436                 $ret = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
437                 return $ret;
438         }
439
440         function MetaTables()
441         {
442                 return false;
443         }
444
445         function MetaColumns()
446         {
447                 return false;
448         }
449 }
450
451 class ADOPDOStatement {
452
453         var $databaseType = "pdo";
454         var $dataProvider = "pdo";
455         var $_stmt;
456         var $_connectionID;
457
458         function ADOPDOStatement($stmt,$connection)
459         {
460                 $this->_stmt = $stmt;
461                 $this->_connectionID = $connection;
462         }
463
464         function Execute($inputArr=false)
465         {
466                 $savestmt = $this->_connectionID->_stmt;
467                 $rs = $this->_connectionID->Execute(array(false,$this->_stmt),$inputArr);
468                 $this->_connectionID->_stmt = $savestmt;
469                 return $rs;
470         }
471
472         function InParameter(&$var,$name,$maxLen=4000,$type=false)
473         {
474
475                 if ($type) $this->_stmt->bindParam($name,$var,$type,$maxLen);
476                 else $this->_stmt->bindParam($name, $var);
477         }
478
479         function Affected_Rows()
480         {
481                 return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
482         }
483
484         function ErrorMsg()
485         {
486                 if ($this->_stmt) $arr = $this->_stmt->errorInfo();
487                 else $arr = $this->_connectionID->errorInfo();
488
489                 if (is_array($arr)) {
490                         if ((integer) $arr[0] && isset($arr[2])) return $arr[2];
491                         else return '';
492                 } else return '-1';
493         }
494
495         function NumCols()
496         {
497                 return ($this->_stmt) ? $this->_stmt->columnCount() : 0;
498         }
499
500         function ErrorNo()
501         {
502                 if ($this->_stmt) return $this->_stmt->errorCode();
503                 else return $this->_connectionID->errorInfo();
504         }
505 }
506
507 /*--------------------------------------------------------------------------------------
508          Class Name: Recordset
509 --------------------------------------------------------------------------------------*/
510
511 class ADORecordSet_pdo extends ADORecordSet {
512
513         var $bind = false;
514         var $databaseType = "pdo";
515         var $dataProvider = "pdo";
516
517         function ADORecordSet_pdo($id,$mode=false)
518         {
519                 if ($mode === false) {
520                         global $ADODB_FETCH_MODE;
521                         $mode = $ADODB_FETCH_MODE;
522                 }
523                 $this->adodbFetchMode = $mode;
524                 switch($mode) {
525                 case ADODB_FETCH_NUM: $mode = PDO::FETCH_NUM; break;
526                 case ADODB_FETCH_ASSOC:  $mode = PDO::FETCH_ASSOC; break;
527
528                 case ADODB_FETCH_BOTH:
529                 default: $mode = PDO::FETCH_BOTH; break;
530                 }
531                 $this->fetchMode = $mode;
532
533                 $this->_queryID = $id;
534                 $this->ADORecordSet($id);
535         }
536
537
538         function Init()
539         {
540                 if ($this->_inited) return;
541                 $this->_inited = true;
542                 if ($this->_queryID) @$this->_initrs();
543                 else {
544                         $this->_numOfRows = 0;
545                         $this->_numOfFields = 0;
546                 }
547                 if ($this->_numOfRows != 0 && $this->_currentRow == -1) {
548                         $this->_currentRow = 0;
549                         if ($this->EOF = ($this->_fetch() === false)) {
550                                 $this->_numOfRows = 0; // _numOfRows could be -1
551                         }
552                 } else {
553                         $this->EOF = true;
554                 }
555         }
556
557         function _initrs()
558         {
559         global $ADODB_COUNTRECS;
560
561                 $this->_numOfRows = ($ADODB_COUNTRECS) ? @$this->_queryID->rowCount() : -1;
562                 if (!$this->_numOfRows) $this->_numOfRows = -1;
563                 $this->_numOfFields = $this->_queryID->columnCount();
564         }
565
566         // returns the field object
567         function FetchField($fieldOffset = -1)
568         {
569                 $off=$fieldOffset+1; // offsets begin at 1
570
571                 $o= new ADOFieldObject();
572                 $arr = @$this->_queryID->getColumnMeta($fieldOffset);
573                 if (!$arr) {
574                         $o->name = 'bad getColumnMeta()';
575                         $o->max_length = -1;
576                         $o->type = 'VARCHAR';
577                         $o->precision = 0;
578         #               $false = false;
579                         return $o;
580                 }
581                 //adodb_pr($arr);
582                 $o->name = $arr['name'];
583                 if (isset($arr['native_type']) && $arr['native_type'] <> "null") $o->type = $arr['native_type'];
584                 else $o->type = adodb_pdo_type($arr['pdo_type']);
585                 $o->max_length = $arr['len'];
586                 $o->precision = $arr['precision'];
587
588                 if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
589                 else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
590                 return $o;
591         }
592
593         function _seek($row)
594         {
595                 return false;
596         }
597
598         function _fetch()
599         {
600                 if (!$this->_queryID) return false;
601
602                 $this->fields = $this->_queryID->fetch($this->fetchMode);
603                 return !empty($this->fields);
604         }
605
606         function _close()
607         {
608                 $this->_queryID = false;
609         }
610
611         function Fields($colname)
612         {
613                 if ($this->adodbFetchMode != ADODB_FETCH_NUM) return @$this->fields[$colname];
614
615                 if (!$this->bind) {
616                         $this->bind = array();
617                         for ($i=0; $i < $this->_numOfFields; $i++) {
618                                 $o = $this->FetchField($i);
619                                 $this->bind[strtoupper($o->name)] = $i;
620                         }
621                 }
622                  return $this->fields[$this->bind[strtoupper($colname)]];
623         }
624
625 }