PageRenderTime 81ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/libs/dibi/dibi.min.php

https://github.com/vrana/mvc-exception-demo
PHP | 1788 lines | 1765 code | 4 blank | 19 comment | 3 complexity | fdbfd30d5494967a62e2557b54c3fd73 MD5 | raw file
  1. <?php //netteloader=DibiVariable,IDataSource,IDibiProfiler,IDibiDriver,IDibiResultDriver,IDibiReflector,DibiObject,DibiLazyStorageBase,DibiLazyStorage,DibiException,DibiDriverException,DibiConnection,DibiResult,DibiResultIterator,DibiRow,DibiTranslator,DibiDataSource,DibiFluent,DibiDatabaseInfo,DibiTableInfo,DibiResultInfo,DibiColumnInfo,DibiForeignKeyInfo,DibiIndexInfo,DibiProfiler,dibi,DibiMySqlReflector,DibiMySqlDriver,DibiMySqliDriver,DibiOdbcDriver,DibiPdoDriver,DibiPostgreDriver,DibiSqliteReflector,DibiSqliteDriver,DibiSqlite3Driver
  2. /**
  3. * dibi - tiny'n'smart database abstraction layer
  4. * ----------------------------------------------
  5. *
  6. * Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
  7. *
  8. * This source file is subject to the "dibi license" that is bundled
  9. * with this package in the file license.txt, and/or GPL license.
  10. *
  11. * For more information please see http://dibiphp.com
  12. *
  13. * @copyright Copyright (c) 2005, 2010 David Grudl
  14. * @license http://dibiphp.com/license dibi license
  15. * @link http://dibiphp.com
  16. * @package dibi
  17. */
  18. if(version_compare(PHP_VERSION,'5.2.0','<')){throw
  19. new
  20. Exception('dibi needs PHP 5.2.0 or newer.');}@set_magic_quotes_runtime(FALSE);if(!class_exists('NotImplementedException',FALSE)){class
  21. NotImplementedException
  22. extends
  23. LogicException{}}if(!class_exists('NotSupportedException',FALSE)){class
  24. NotSupportedException
  25. extends
  26. LogicException{}}if(!class_exists('MemberAccessException',FALSE)){class
  27. MemberAccessException
  28. extends
  29. LogicException{}}if(!class_exists('InvalidStateException',FALSE)){class
  30. InvalidStateException
  31. extends
  32. RuntimeException{}}if(!class_exists('IOException',FALSE)){class
  33. IOException
  34. extends
  35. RuntimeException{}}if(!class_exists('FileNotFoundException',FALSE)){class
  36. FileNotFoundException
  37. extends
  38. IOException{}}if(!class_exists('PcreException',FALSE)){class
  39. PcreException
  40. extends
  41. Exception{public
  42. function
  43. __construct(){static$messages=array(PREG_INTERNAL_ERROR=>'Internal error.',PREG_BACKTRACK_LIMIT_ERROR=>'Backtrack limit was exhausted.',PREG_RECURSION_LIMIT_ERROR=>'Recursion limit was exhausted.',PREG_BAD_UTF8_ERROR=>'Malformed UTF-8 data.',5=>'Offset didn\'t correspond to the begin of a valid UTF-8 code point.');$code=preg_last_error();parent::__construct(isset($messages[$code])?$messages[$code]:'Unknown error.',$code);}}}if(!interface_exists('IDebugPanel',FALSE)){interface
  44. IDebugPanel{function
  45. getTab();function
  46. getPanel();function
  47. getId();}}if(!class_exists('DateTime53',FALSE)){class
  48. DateTime53
  49. extends
  50. DateTime{public
  51. function
  52. __sleep(){$this->fix=array($this->format('Y-m-d H:i:s'),$this->getTimezone()->getName());return
  53. array('fix');}public
  54. function
  55. __wakeup(){$this->__construct($this->fix[0],new
  56. DateTimeZone($this->fix[1]));unset($this->fix);}public
  57. function
  58. getTimestamp(){return(int)$this->format('U');}public
  59. function
  60. setTimestamp($timestamp){return$this->__construct(date('Y-m-d H:i:s',$timestamp),new
  61. DateTimeZone($this->getTimezone()->getName()));}}}class
  62. DibiVariable
  63. extends
  64. DateTime53{function
  65. __construct($val){parent::__construct($val);}}interface
  66. IDataSource
  67. extends
  68. Countable,IteratorAggregate{}interface
  69. IDibiProfiler{const
  70. CONNECT=1;const
  71. SELECT=4;const
  72. INSERT=8;const
  73. DELETE=16;const
  74. UPDATE=32;const
  75. QUERY=60;const
  76. BEGIN=64;const
  77. COMMIT=128;const
  78. ROLLBACK=256;const
  79. TRANSACTION=448;const
  80. EXCEPTION=512;const
  81. ALL=1023;function
  82. before(DibiConnection$connection,$event,$sql=NULL);function
  83. after($ticket,$result=NULL);function
  84. exception(DibiDriverException$exception);}interface
  85. IDibiDriver{function
  86. connect(array&$config);function
  87. disconnect();function
  88. query($sql);function
  89. getAffectedRows();function
  90. getInsertId($sequence);function
  91. begin($savepoint=NULL);function
  92. commit($savepoint=NULL);function
  93. rollback($savepoint=NULL);function
  94. getResource();function
  95. getReflector();function
  96. escape($value,$type);function
  97. applyLimit(&$sql,$limit,$offset);}interface
  98. IDibiResultDriver{function
  99. getRowCount();function
  100. seek($row);function
  101. fetch($type);function
  102. free();function
  103. getResultColumns();function
  104. getResultResource();function
  105. unescape($value,$type);}interface
  106. IDibiReflector{function
  107. getTables();function
  108. getColumns($table);function
  109. getIndexes($table);function
  110. getForeignKeys($table);}abstract
  111. class
  112. DibiObject{private
  113. static$extMethods;final
  114. public
  115. function
  116. getClass(){return
  117. get_class($this);}final
  118. public
  119. function
  120. getReflection(){return
  121. new
  122. ReflectionObject($this);}public
  123. function
  124. __call($name,$args){$class=get_class($this);if($name===''){throw
  125. new
  126. MemberAccessException("Call to class '$class' method without name.");}if(preg_match('#^on[A-Z]#',$name)){$rp=new
  127. ReflectionProperty($class,$name);if($rp->isPublic()&&!$rp->isStatic()){$list=$this->$name;if(is_array($list)||$list
  128. instanceof
  129. Traversable){foreach($list
  130. as$handler){if(is_object($handler)){call_user_func_array(array($handler,'__invoke'),$args);}else{call_user_func_array($handler,$args);}}}return
  131. NULL;}}if($cb=self::extensionMethod("$class::$name")){array_unshift($args,$this);return
  132. call_user_func_array($cb,$args);}throw
  133. new
  134. MemberAccessException("Call to undefined method $class::$name().");}public
  135. static
  136. function
  137. __callStatic($name,$args){$class=get_called_class();throw
  138. new
  139. MemberAccessException("Call to undefined static method $class::$name().");}public
  140. static
  141. function
  142. extensionMethod($name,$callback=NULL){if(self::$extMethods===NULL||$name===NULL){$list=get_defined_functions();foreach($list['user']as$fce){$pair=explode('_prototype_',$fce);if(count($pair)===2){self::$extMethods[$pair[1]][$pair[0]]=$fce;self::$extMethods[$pair[1]]['']=NULL;}}if($name===NULL)return
  143. NULL;}$name=strtolower($name);$a=strrpos($name,':');if($a===FALSE){$class=strtolower(get_called_class());$l=&self::$extMethods[$name];}else{$class=substr($name,0,$a-1);$l=&self::$extMethods[substr($name,$a+1)];}if($callback!==NULL){$l[$class]=$callback;$l['']=NULL;return
  144. NULL;}if(empty($l)){return
  145. FALSE;}elseif(isset($l[''][$class])){return$l[''][$class];}$cl=$class;do{$cl=strtolower($cl);if(isset($l[$cl])){return$l[''][$class]=$l[$cl];}}while(($cl=get_parent_class($cl))!==FALSE);foreach(class_implements($class)as$cl){$cl=strtolower($cl);if(isset($l[$cl])){return$l[''][$class]=$l[$cl];}}return$l[''][$class]=FALSE;}public
  146. function&__get($name){$class=get_class($this);if($name===''){throw
  147. new
  148. MemberAccessException("Cannot read a class '$class' property without name.");}$name[0]=$name[0]&"\xDF";$m='get'.$name;if(self::hasAccessor($class,$m)){$val=$this->$m();return$val;}$m='is'.$name;if(self::hasAccessor($class,$m)){$val=$this->$m();return$val;}$name=func_get_arg(0);throw
  149. new
  150. MemberAccessException("Cannot read an undeclared property $class::\$$name.");}public
  151. function
  152. __set($name,$value){$class=get_class($this);if($name===''){throw
  153. new
  154. MemberAccessException("Cannot assign to a class '$class' property without name.");}$name[0]=$name[0]&"\xDF";if(self::hasAccessor($class,'get'.$name)||self::hasAccessor($class,'is'.$name)){$m='set'.$name;if(self::hasAccessor($class,$m)){$this->$m($value);return;}else{$name=func_get_arg(0);throw
  155. new
  156. MemberAccessException("Cannot assign to a read-only property $class::\$$name.");}}$name=func_get_arg(0);throw
  157. new
  158. MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");}public
  159. function
  160. __isset($name){$name[0]=$name[0]&"\xDF";return$name!==''&&self::hasAccessor(get_class($this),'get'.$name);}public
  161. function
  162. __unset($name){$class=get_class($this);throw
  163. new
  164. MemberAccessException("Cannot unset the property $class::\$$name.");}private
  165. static
  166. function
  167. hasAccessor($c,$m){static$cache;if(!isset($cache[$c])){$cache[$c]=array_flip(get_class_methods($c));}return
  168. isset($cache[$c][$m]);}}abstract
  169. class
  170. DibiLazyStorageBase{private$callback;public
  171. function
  172. __construct($callback){$this->setCallback($callback);}public
  173. function
  174. setCallback($callback){if(!is_callable($callback)){$able=is_callable($callback,TRUE,$textual);throw
  175. new
  176. InvalidArgumentException("Handler '$textual' is not ".($able?'callable.':'valid PHP callback.'));}$this->callback=$callback;}public
  177. function
  178. getCallback(){return$this->callback;}}final
  179. class
  180. DibiLazyStorage
  181. extends
  182. DibiLazyStorageBase{public
  183. function
  184. __get($nm){if(is_array($nm)){$nm=$nm[1];}if($nm==''){throw
  185. new
  186. InvalidStateException('Missing identifier name.');}return$this->$nm=call_user_func($this->getCallback(),$nm);}}class
  187. DibiException
  188. extends
  189. Exception
  190. implements
  191. IDebugPanel{private$sql;public
  192. function
  193. __construct($message=NULL,$code=0,$sql=NULL){parent::__construct($message,(int)$code);$this->sql=$sql;}final
  194. public
  195. function
  196. getSql(){return$this->sql;}public
  197. function
  198. __toString(){return
  199. parent::__toString().($this->sql?"\nSQL: ".$this->sql:'');}public
  200. function
  201. getTab(){return'SQL';}public
  202. function
  203. getPanel(){return$this->sql?dibi::dump($this->sql,TRUE):NULL;}public
  204. function
  205. getId(){return
  206. __CLASS__;}}class
  207. DibiDriverException
  208. extends
  209. DibiException{private
  210. static$errorMsg;public
  211. static
  212. function
  213. tryError(){set_error_handler(array(__CLASS__,'_errorHandler'),E_ALL);self::$errorMsg=NULL;}public
  214. static
  215. function
  216. catchError(&$message){restore_error_handler();$message=self::$errorMsg;self::$errorMsg=NULL;return$message!==NULL;}public
  217. static
  218. function
  219. _errorHandler($code,$message){restore_error_handler();if(ini_get('html_errors')){$message=strip_tags($message);$message=html_entity_decode($message);}self::$errorMsg=$message;}}class
  220. DibiConnection
  221. extends
  222. DibiObject{private$config;private$driver;private$translator;private$profiler;private$connected=FALSE;public
  223. function
  224. __construct($config,$name=NULL){if(is_string($config)){parse_str($config,$config);}elseif($config
  225. instanceof
  226. Traversable){$tmp=array();foreach($config
  227. as$key=>$val){$tmp[$key]=$val
  228. instanceof
  229. Traversable?iterator_to_array($val):$val;}$config=$tmp;}elseif(!is_array($config)){throw
  230. new
  231. InvalidArgumentException('Configuration must be array, string or object.');}self::alias($config,'username','user');self::alias($config,'password','pass');self::alias($config,'host','hostname');self::alias($config,'result|detectTypes','resultDetectTypes');self::alias($config,'result|formatDateTime','resultDateTime');if(!isset($config['driver'])){$config['driver']=dibi::$defaultDriver;}$driver=preg_replace('#[^a-z0-9_]#','_',strtolower($config['driver']));$class="Dibi".$driver."Driver";if(!class_exists($class,FALSE)){ include_once dirname(__FILE__)."/../drivers/$driver.php";if(!class_exists($class,FALSE)){throw
  232. new
  233. DibiException("Unable to create instance of dibi driver '$class'.");}}$config['name']=$name;$this->config=$config;$this->driver=new$class;$this->translator=new
  234. DibiTranslator($this->driver);$profilerCfg=&$config['profiler'];if(is_scalar($profilerCfg)){$profilerCfg=array('run'=>(bool)$profilerCfg,'class'=>strlen($profilerCfg)>1?$profilerCfg:NULL);}if(!empty($profilerCfg['run'])){$class=isset($profilerCfg['class'])?$profilerCfg['class']:'DibiProfiler';if(!class_exists($class)){throw
  235. new
  236. DibiException("Unable to create instance of dibi profiler '$class'.");}$this->setProfiler(new$class($profilerCfg));}if(!empty($config['substitutes'])){foreach($config['substitutes']as$key=>$value){dibi::addSubst($key,$value);}}if(empty($config['lazy'])){$this->connect();}}public
  237. function
  238. __destruct(){$this->connected&&$this->disconnect();}final
  239. public
  240. function
  241. connect(){if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::CONNECT);}$this->driver->connect($this->config);$this->connected=TRUE;if(isset($ticket)){$this->profiler->after($ticket);}}final
  242. public
  243. function
  244. disconnect(){$this->driver->disconnect();$this->connected=FALSE;}final
  245. public
  246. function
  247. isConnected(){return$this->connected;}final
  248. public
  249. function
  250. getConfig($key=NULL,$default=NULL){if($key===NULL){return$this->config;}elseif(isset($this->config[$key])){return$this->config[$key];}else{return$default;}}public
  251. static
  252. function
  253. alias(&$config,$key,$alias){$foo=&$config;foreach(explode('|',$key)as$key)$foo=&$foo[$key];if(!isset($foo)&&isset($config[$alias])){$foo=$config[$alias];unset($config[$alias]);}}final
  254. public
  255. function
  256. getDriver(){$this->connected||$this->connect();return$this->driver;}final
  257. public
  258. function
  259. query($args){$this->connected||$this->connect();$args=func_get_args();return$this->nativeQuery($this->translator->translate($args));}final
  260. public
  261. function
  262. translate($args){$this->connected||$this->connect();$args=func_get_args();return$this->translator->translate($args);}function
  263. sql($args){trigger_error(__METHOD__.'() is deprecated; use translate() instead.',E_USER_NOTICE);$this->connected||$this->connect();$args=func_get_args();return$this->translator->translate($args);}final
  264. public
  265. function
  266. test($args){$this->connected||$this->connect();$args=func_get_args();try{dibi::dump($this->translator->translate($args));return
  267. TRUE;}catch(DibiException$e){dibi::dump($e->getSql());return
  268. FALSE;}}final
  269. public
  270. function
  271. dataSource($args){$this->connected||$this->connect();$args=func_get_args();return
  272. new
  273. DibiDataSource($this->translator->translate($args),$this);}final
  274. public
  275. function
  276. nativeQuery($sql){$this->connected||$this->connect();if($this->profiler!==NULL){$event=IDibiProfiler::QUERY;if(preg_match('#\s*(SELECT|UPDATE|INSERT|DELETE)#i',$sql,$matches)){static$events=array('SELECT'=>IDibiProfiler::SELECT,'UPDATE'=>IDibiProfiler::UPDATE,'INSERT'=>IDibiProfiler::INSERT,'DELETE'=>IDibiProfiler::DELETE);$event=$events[strtoupper($matches[1])];}$ticket=$this->profiler->before($this,$event,$sql);}dibi::$sql=$sql;if($res=$this->driver->query($sql)){$res=new
  277. DibiResult($res,$this->config['result']);}else{$res=$this->driver->getAffectedRows();}if(isset($ticket)){$this->profiler->after($ticket,$res);}return$res;}public
  278. function
  279. getAffectedRows(){$this->connected||$this->connect();$rows=$this->driver->getAffectedRows();if(!is_int($rows)||$rows<0)throw
  280. new
  281. DibiException('Cannot retrieve number of affected rows.');return$rows;}public
  282. function
  283. affectedRows(){return$this->getAffectedRows();}public
  284. function
  285. getInsertId($sequence=NULL){$this->connected||$this->connect();$id=$this->driver->getInsertId($sequence);if($id<1)throw
  286. new
  287. DibiException('Cannot retrieve last generated ID.');return(int)$id;}public
  288. function
  289. insertId($sequence=NULL){return$this->getInsertId($sequence);}public
  290. function
  291. begin($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::BEGIN,$savepoint);}$this->driver->begin($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  292. function
  293. commit($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::COMMIT,$savepoint);}$this->driver->commit($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  294. function
  295. rollback($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::ROLLBACK,$savepoint);}$this->driver->rollback($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  296. function
  297. command(){return
  298. new
  299. DibiFluent($this);}public
  300. function
  301. select($args){$args=func_get_args();return$this->command()->__call('select',$args);}public
  302. function
  303. update($table,$args){if(!(is_array($args)||$args
  304. instanceof
  305. Traversable)){throw
  306. new
  307. InvalidArgumentException('Arguments must be array or Traversable.');}return$this->command()->update('%n',$table)->set($args);}public
  308. function
  309. insert($table,$args){if($args
  310. instanceof
  311. Traversable){$args=iterator_to_array($args);}elseif(!is_array($args)){throw
  312. new
  313. InvalidArgumentException('Arguments must be array or Traversable.');}return$this->command()->insert()->into('%n',$table,'(%n)',array_keys($args))->values('%l',$args);}public
  314. function
  315. delete($table){return$this->command()->delete()->from('%n',$table);}public
  316. function
  317. setProfiler(IDibiProfiler$profiler=NULL){$this->profiler=$profiler;return$this;}public
  318. function
  319. getProfiler(){return$this->profiler;}public
  320. function
  321. fetch($args){$args=func_get_args();return$this->query($args)->fetch();}public
  322. function
  323. fetchAll($args){$args=func_get_args();return$this->query($args)->fetchAll();}public
  324. function
  325. fetchSingle($args){$args=func_get_args();return$this->query($args)->fetchSingle();}public
  326. function
  327. fetchPairs($args){$args=func_get_args();return$this->query($args)->fetchPairs();}public
  328. function
  329. loadFile($file){$this->connected||$this->connect();@set_time_limit(0);$handle=@fopen($file,'r');if(!$handle){throw
  330. new
  331. FileNotFoundException("Cannot open file '$file'.");}$count=0;$sql='';while(!feof($handle)){$s=fgets($handle);$sql.=$s;if(substr(rtrim($s),-1)===';'){$this->driver->query($sql);$sql='';$count++;}}fclose($handle);return$count;}public
  332. function
  333. getDatabaseInfo(){$this->connected||$this->connect();return
  334. new
  335. DibiDatabaseInfo($this->driver->getReflector(),isset($this->config['database'])?$this->config['database']:NULL);}public
  336. function
  337. __wakeup(){throw
  338. new
  339. NotSupportedException('You cannot serialize or unserialize '.$this->getClass().' instances.');}public
  340. function
  341. __sleep(){throw
  342. new
  343. NotSupportedException('You cannot serialize or unserialize '.$this->getClass().' instances.');}}class
  344. DibiResult
  345. extends
  346. DibiObject
  347. implements
  348. IDataSource{private$driver;private$types;private$meta;private$fetched=FALSE;private$rowClass='DibiRow';private$dateFormat='';public
  349. function
  350. __construct($driver,$config){$this->driver=$driver;if(!empty($config['detectTypes'])){$this->detectTypes();}if(!empty($config['formatDateTime'])){$this->dateFormat=is_string($config['formatDateTime'])?$config['formatDateTime']:'';}}final
  351. public
  352. function
  353. getResource(){return$this->getDriver()->getResultResource();}final
  354. public
  355. function
  356. free(){if($this->driver!==NULL){$this->driver->free();$this->driver=$this->meta=NULL;}}private
  357. function
  358. getDriver(){if($this->driver===NULL){throw
  359. new
  360. InvalidStateException('Result-set was released from memory.');}return$this->driver;}final
  361. public
  362. function
  363. seek($row){return($row!==0||$this->fetched)?(bool)$this->getDriver()->seek($row):TRUE;}final
  364. public
  365. function
  366. count(){return$this->getDriver()->getRowCount();}final
  367. public
  368. function
  369. getRowCount(){return$this->getDriver()->getRowCount();}final
  370. public
  371. function
  372. rowCount(){return$this->getDriver()->getRowCount();}final
  373. public
  374. function
  375. getIterator(){if(func_num_args()){trigger_error(__METHOD__.' arguments $offset & $limit have been dropped; use SQL clauses instead.',E_USER_WARNING);}return
  376. new
  377. DibiResultIterator($this);}public
  378. function
  379. setRowClass($class){$this->rowClass=$class;return$this;}public
  380. function
  381. getRowClass(){return$this->rowClass;}final
  382. public
  383. function
  384. fetch(){$row=$this->getDriver()->fetch(TRUE);if(!is_array($row))return
  385. FALSE;$this->fetched=TRUE;if($this->types!==NULL){foreach($this->types
  386. as$col=>$type){if(isset($row[$col])){$row[$col]=$this->convert($row[$col],$type);}}}return
  387. new$this->rowClass($row);}final
  388. public
  389. function
  390. fetchSingle(){$row=$this->getDriver()->fetch(TRUE);if(!is_array($row))return
  391. FALSE;$this->fetched=TRUE;$value=reset($row);$key=key($row);if(isset($this->types[$key])){return$this->convert($value,$this->types[$key]);}return$value;}final
  392. public
  393. function
  394. fetchAll($offset=NULL,$limit=NULL){$limit=$limit===NULL?-1:(int)$limit;$this->seek((int)$offset);$row=$this->fetch();if(!$row)return
  395. array();$data=array();do{if($limit===0)break;$limit--;$data[]=$row;}while($row=$this->fetch());return$data;}final
  396. public
  397. function
  398. fetchAssoc($assoc){if(strpos($assoc,',')!==FALSE){return$this->oldFetchAssoc($assoc);}$this->seek(0);$row=$this->fetch();if(!$row)return
  399. array();$data=NULL;$assoc=preg_split('#(\[\]|->|=|\|)#',$assoc,NULL,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);foreach($assoc
  400. as$as){if($as!=='[]'&&$as!=='='&&$as!=='->'&&$as!=='|'&&!property_exists($row,$as)){throw
  401. new
  402. InvalidArgumentException("Unknown column '$as' in associative descriptor.");}}if($as==='->'){array_pop($assoc);}if(empty($assoc)){$assoc[]='[]';}do{$x=&$data;foreach($assoc
  403. as$i=>$as){if($as==='[]'){$x=&$x[];}elseif($as==='='){$x=$row->{$assoc[$i+1]};continue
  404. 2;}elseif($as==='->'){if($x===NULL){$x=clone$row;$x=&$x->{$assoc[$i+1]};$x=NULL;}else{$x=&$x->{$assoc[$i+1]};}}elseif($as!=='|'){$x=&$x[$row->$as];}}if($x===NULL){$x=$row;}}while($row=$this->fetch());unset($x);return$data;}private
  405. function
  406. oldFetchAssoc($assoc){$this->seek(0);$row=$this->fetch();if(!$row)return
  407. array();$data=NULL;$assoc=explode(',',$assoc);$leaf='@';$last=count($assoc)-1;while($assoc[$last]==='='||$assoc[$last]==='@'){$leaf=$assoc[$last];unset($assoc[$last]);$last--;if($last<0){$assoc[]='#';break;}}do{$x=&$data;foreach($assoc
  408. as$i=>$as){if($as==='#'){$x=&$x[];}elseif($as==='='){if($x===NULL){$x=$row->toArray();$x=&$x[$assoc[$i+1]];$x=NULL;}else{$x=&$x[$assoc[$i+1]];}}elseif($as==='@'){if($x===NULL){$x=clone$row;$x=&$x->{$assoc[$i+1]};$x=NULL;}else{$x=&$x->{$assoc[$i+1]};}}else{$x=&$x[$row->$as];}}if($x===NULL){if($leaf==='='){$x=$row->toArray();}else{$x=$row;}}}while($row=$this->fetch());unset($x);return$data;}final
  409. public
  410. function
  411. fetchPairs($key=NULL,$value=NULL){$this->seek(0);$row=$this->fetch();if(!$row)return
  412. array();$data=array();if($value===NULL){if($key!==NULL){throw
  413. new
  414. InvalidArgumentException("Either none or both columns must be specified.");}$tmp=array_keys($row->toArray());$key=$tmp[0];if(count($row)<2){do{$data[]=$row[$key];}while($row=$this->fetch());return$data;}$value=$tmp[1];}else{if(!property_exists($row,$value)){throw
  415. new
  416. InvalidArgumentException("Unknown value column '$value'.");}if($key===NULL){do{$data[]=$row[$value];}while($row=$this->fetch());return$data;}if(!property_exists($row,$key)){throw
  417. new
  418. InvalidArgumentException("Unknown key column '$key'.");}}do{$data[$row[$key]]=$row[$value];}while($row=$this->fetch());return$data;}final
  419. public
  420. function
  421. setType($col,$type){$this->types[$col]=$type;return$this;}final
  422. public
  423. function
  424. detectTypes(){foreach($this->getInfo()->getColumns()as$col){$this->types[$col->getName()]=$col->getType();}}final
  425. public
  426. function
  427. setTypes(array$types){$this->types=$types;return$this;}final
  428. public
  429. function
  430. getType($col){return
  431. isset($this->types[$col])?$this->types[$col]:NULL;}protected
  432. function
  433. convert($value,$type){if($value===NULL||$value===FALSE){return
  434. NULL;}switch($type){case
  435. dibi::TEXT:return(string)$value;case
  436. dibi::BINARY:return$this->getDriver()->unescape($value,$type);case
  437. dibi::INTEGER:return(int)$value;case
  438. dibi::FLOAT:return(float)$value;case
  439. dibi::DATE:case
  440. dibi::DATETIME:if((int)$value===0){return
  441. NULL;}elseif($this->dateFormat===''){return
  442. new
  443. DateTime53(is_numeric($value)?date('Y-m-d H:i:s',$value):$value);}elseif($this->dateFormat==='U'){return
  444. is_numeric($value)?(int)$value:strtotime($value);}elseif(is_numeric($value)){return
  445. date($this->dateFormat,$value);}else{$value=new
  446. DateTime53($value);return$value->format($this->dateFormat);}case
  447. dibi::BOOL:return((bool)$value)&&$value!=='f'&&$value!=='F';default:return$value;}}public
  448. function
  449. getInfo(){if($this->meta===NULL){$this->meta=new
  450. DibiResultInfo($this->getDriver());}return$this->meta;}final
  451. public
  452. function
  453. getColumns(){return$this->getInfo()->getColumns();}public
  454. function
  455. getColumnNames($fullNames=FALSE){return$this->getInfo()->getColumnNames($fullNames);}final
  456. public
  457. function
  458. dump(){$i=0;$this->seek(0);while($row=$this->fetch()){if($i===0){echo"\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";foreach($row
  459. as$col=>$foo){echo"\t\t<th>".htmlSpecialChars($col)."</th>\n";}echo"\t</tr>\n</thead>\n<tbody>\n";}echo"\t<tr>\n\t\t<th>",$i,"</th>\n";foreach($row
  460. as$col){echo"\t\t<td>",htmlSpecialChars($col),"</td>\n";}echo"\t</tr>\n";$i++;}if($i===0){echo'<p><em>empty result set</em></p>';}else{echo"</tbody>\n</table>\n";}}}class
  461. DibiResultIterator
  462. implements
  463. Iterator,Countable{private$result;private$row;private$pointer;public
  464. function
  465. __construct(DibiResult$result){$this->result=$result;}public
  466. function
  467. rewind(){$this->pointer=0;$this->result->seek(0);$this->row=$this->result->fetch();}public
  468. function
  469. key(){return$this->pointer;}public
  470. function
  471. current(){return$this->row;}public
  472. function
  473. next(){$this->row=$this->result->fetch();$this->pointer++;}public
  474. function
  475. valid(){return!empty($this->row);}public
  476. function
  477. count(){return$this->result->getRowCount();}}class
  478. DibiRow
  479. implements
  480. ArrayAccess,IteratorAggregate,Countable{public
  481. function
  482. __construct($arr){foreach($arr
  483. as$k=>$v)$this->$k=$v;}public
  484. function
  485. toArray(){return(array)$this;}public
  486. function
  487. asDateTime($key,$format=NULL){$time=$this[$key];if((int)$time===0){return
  488. NULL;}$dt=new
  489. DateTime53(is_numeric($time)?date('Y-m-d H:i:s',$time):$time);return$format===NULL?$dt:$dt->format($format);}public
  490. function
  491. asTimestamp($key){$time=$this[$key];return(int)$time===0?NULL:(is_numeric($time)?(int)$time:strtotime($time));}public
  492. function
  493. asBool($key){$value=$this[$key];if($value===NULL||$value===FALSE){return$value;}else{return((bool)$value)&&$value!=='f'&&$value!=='F';}}public
  494. function
  495. asDate($key,$format=NULL){if($format===NULL){return$this->asTimestamp($key);}else{return$this->asDateTime($key,$format===TRUE?NULL:$format);}}final
  496. public
  497. function
  498. count(){return
  499. count((array)$this);}final
  500. public
  501. function
  502. getIterator(){return
  503. new
  504. ArrayIterator($this);}final
  505. public
  506. function
  507. offsetSet($nm,$val){$this->$nm=$val;}final
  508. public
  509. function
  510. offsetGet($nm){return$this->$nm;}final
  511. public
  512. function
  513. offsetExists($nm){return
  514. isset($this->$nm);}final
  515. public
  516. function
  517. offsetUnset($nm){unset($this->$nm);}}final
  518. class
  519. DibiTranslator
  520. extends
  521. DibiObject{private$driver;private$cursor;private$args;private$hasError;private$comment;private$ifLevel;private$ifLevelStart;private$limit;private$offset;private$identifiers;public
  522. function
  523. __construct(IDibiDriver$driver){$this->driver=$driver;$this->identifiers=new
  524. DibiLazyStorage(array($this,'delimite'));}public
  525. function
  526. translate(array$args){$args=array_values($args);while(count($args)===1&&is_array($args[0])){$args=array_values($args[0]);}$this->args=$args;$this->limit=-1;$this->offset=0;$this->hasError=FALSE;$commandIns=NULL;$lastArr=NULL;$cursor=&$this->cursor;$cursor=0;$this->ifLevel=$this->ifLevelStart=0;$comment=&$this->comment;$comment=FALSE;$sql=array();while($cursor<count($this->args)){$arg=$this->args[$cursor];$cursor++;if(is_string($arg)){$toSkip=strcspn($arg,'`[\'":%');if(strlen($arg)===$toSkip){$sql[]=$arg;}else{$sql[]=substr($arg,0,$toSkip).preg_replace_callback('/(?=[`[\'":%?])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?)|%([a-zA-Z]{1,4})(?![a-zA-Z])|(\?))/s',array($this,'cb'),substr($arg,$toSkip));if(preg_last_error())throw
  527. new
  528. PcreException;}continue;}if($comment){$sql[]='...';continue;}if($arg
  529. instanceof
  530. Traversable){$arg=iterator_to_array($arg);}if(is_array($arg)){if(is_string(key($arg))){if($commandIns===NULL){$commandIns=strtoupper(substr(ltrim($this->args[0]),0,6));$commandIns=$commandIns==='INSERT'||$commandIns==='REPLAC';$sql[]=$this->formatValue($arg,$commandIns?'v':'a');}else{if($lastArr===$cursor-1)$sql[]=',';$sql[]=$this->formatValue($arg,$commandIns?'l':'a');}$lastArr=$cursor;continue;}}$sql[]=$this->formatValue($arg,FALSE);}if($comment)$sql[]="*/";$sql=implode(' ',$sql);if($this->hasError){throw
  531. new
  532. DibiException('SQL translate error',0,$sql);}if($this->limit>-1||$this->offset>0){$this->driver->applyLimit($sql,$this->limit,$this->offset);}return$sql;}public
  533. function
  534. formatValue($value,$modifier){if($value
  535. instanceof
  536. Traversable){$value=iterator_to_array($value);}if(is_array($value)){$vx=$kx=array();switch($modifier){case'and':case'or':if(empty($value)){return'1=1';}foreach($value
  537. as$k=>$v){if(is_string($k)){$pair=explode('%',$k,2);$k=$this->identifiers->{$pair[0]}.' ';if(!isset($pair[1])){$v=$this->formatValue($v,FALSE);$vx[]=$k.($v==='NULL'?'IS ':'= ').$v;}elseif($pair[1]==='ex'){$vx[]=$k.$this->formatValue($v,'ex');}else{$v=$this->formatValue($v,$pair[1]);$vx[]=$k.($pair[1]==='l'||$pair[1]==='in'?'IN ':($v==='NULL'?'IS ':'= ')).$v;}}else{$vx[]=$this->formatValue($v,'ex');}}return'('.implode(') '.strtoupper($modifier).' (',$vx).')';case'n':foreach($value
  538. as$k=>$v){if(is_string($k)){$vx[]=$this->identifiers->$k.(empty($v)?'':' AS '.$v);}else{$pair=explode('%',$v,2);$vx[]=$this->identifiers->{$pair[0]};}}return
  539. implode(', ',$vx);case'a':foreach($value
  540. as$k=>$v){$pair=explode('%',$k,2);$vx[]=$this->identifiers->{$pair[0]}.'='.$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return
  541. implode(', ',$vx);case'in':case'l':foreach($value
  542. as$k=>$v){$pair=explode('%',$k,2);$vx[]=$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return'('.(($vx||$modifier==='l')?implode(', ',$vx):'NULL').')';case'v':foreach($value
  543. as$k=>$v){$pair=explode('%',$k,2);$kx[]=$this->identifiers->{$pair[0]};$vx[]=$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return'('.implode(', ',$kx).') VALUES ('.implode(', ',$vx).')';case'm':foreach($value
  544. as$k=>$v){if(is_array($v)){if(isset($proto)){if($proto!==array_keys($v)){$this->hasError=TRUE;return'**Multi-insert array "'.$k.'" is different.**';}}else{$proto=array_keys($v);}}else{$this->hasError=TRUE;return'**Unexpected type '.gettype($v).'**';}$pair=explode('%',$k,2);$kx[]=$this->identifiers->{$pair[0]};foreach($v
  545. as$k2=>$v2){$vx[$k2][]=$this->formatValue($v2,isset($pair[1])?$pair[1]:(is_array($v2)?'ex':FALSE));}}foreach($vx
  546. as$k=>$v){$vx[$k]='('.implode(', ',$v).')';}return'('.implode(', ',$kx).') VALUES '.implode(', ',$vx);case'by':foreach($value
  547. as$k=>$v){if(is_array($v)){$vx[]=$this->formatValue($v,'ex');}elseif(is_string($k)){$v=(is_string($v)&&strncasecmp($v,'d',1))||$v>0?'ASC':'DESC';$vx[]=$this->identifiers->$k.' '.$v;}else{$vx[]=$this->identifiers->$v;}}return
  548. implode(', ',$vx);case'ex':case'sql':$translator=new
  549. self($this->driver);return$translator->translate($value);default:foreach($value
  550. as$v){$vx[]=$this->formatValue($v,$modifier);}return
  551. implode(', ',$vx);}}if($modifier){if($value!==NULL&&!is_scalar($value)&&!($value
  552. instanceof
  553. DateTime)){$this->hasError=TRUE;return'**Unexpected type '.gettype($value).'**';}switch($modifier){case's':case'bin':case'b':return$value===NULL?'NULL':$this->driver->escape($value,$modifier);case'sN':case'sn':return$value==''?'NULL':$this->driver->escape($value,dibi::TEXT);case'iN':case'in':if($value=='')$value=NULL;case'i':case'u':if(is_string($value)&&preg_match('#[+-]?\d++(e\d+)?$#A',$value)){return$value;}else{return$value===NULL?'NULL':(string)(int)($value+0);}case'f':if(is_string($value)&&is_numeric($value)&&strpos($value,'x')===FALSE){return$value;}else{return$value===NULL?'NULL':rtrim(rtrim(number_format($value+0,5,'.',''),'0'),'.');}case'd':case't':if($value===NULL){return'NULL';}else{if(is_numeric($value)){$value=(int)$value;}elseif(is_string($value)){$value=new
  554. DateTime($value);}return$this->driver->escape($value,$modifier);}case'by':case'n':return$this->identifiers->$value;case'ex':case'sql':$value=(string)$value;$toSkip=strcspn($value,'`[\'":');if(strlen($value)!==$toSkip){$value=substr($value,0,$toSkip).preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?))/s',array($this,'cb'),substr($value,$toSkip));if(preg_last_error())throw
  555. new
  556. PcreException;}return$value;case'SQL':return(string)$value;case'and':case'or':case'a':case'l':case'v':$this->hasError=TRUE;return'**Unexpected type '.gettype($value).'**';default:$this->hasError=TRUE;return"**Unknown or invalid modifier %$modifier**";}}if(is_string($value)){return$this->driver->escape($value,dibi::TEXT);}elseif(is_int($value)){return(string)$value;}elseif(is_float($value)){return
  557. rtrim(rtrim(number_format($value,5,'.',''),'0'),'.');}elseif(is_bool($value)){return$this->driver->escape($value,dibi::BOOL);}elseif($value===NULL){return'NULL';}elseif($value
  558. instanceof
  559. DateTime){return$this->driver->escape($value,dibi::DATETIME);}else{$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}}private
  560. function
  561. cb($matches){if(!empty($matches[11])){$cursor=&$this->cursor;if($cursor>=count($this->args)){$this->hasError=TRUE;return"**Extra placeholder**";}$cursor++;return$this->formatValue($this->args[$cursor-1],FALSE);}if(!empty($matches[10])){$mod=$matches[10];$cursor=&$this->cursor;if($cursor>=count($this->args)&&$mod!=='else'&&$mod!=='end'){$this->hasError=TRUE;return"**Extra modifier %$mod**";}if($mod==='if'){$this->ifLevel++;$cursor++;if(!$this->comment&&!$this->args[$cursor-1]){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return"/*";}return'';}elseif($mod==='else'){if($this->ifLevelStart===$this->ifLevel){$this->ifLevelStart=0;$this->comment=FALSE;return"*/";}elseif(!$this->comment){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return"/*";}}elseif($mod==='end'){$this->ifLevel--;if($this->ifLevelStart===$this->ifLevel+1){$this->ifLevelStart=0;$this->comment=FALSE;return"*/";}return'';}elseif($mod==='ex'){array_splice($this->args,$cursor,1,$this->args[$cursor]);return'';}elseif($mod==='lmt'){if($this->args[$cursor]!==NULL)$this->limit=(int)$this->args[$cursor];$cursor++;return'';}elseif($mod==='ofs'){if($this->args[$cursor]!==NULL)$this->offset=(int)$this->args[$cursor];$cursor++;return'';}else{$cursor++;return$this->formatValue($this->args[$cursor-1],$mod);}}if($this->comment)return'...';if($matches[1])return$this->identifiers->{$matches[1]};if($matches[2])return$this->identifiers->{$matches[2]};if($matches[3])return$this->driver->escape(str_replace("''","'",$matches[4]),dibi::TEXT);if($matches[5])return$this->driver->escape(str_replace('""','"',$matches[6]),dibi::TEXT);if($matches[7]){$this->hasError=TRUE;return'**Alone quote**';}if($matches[8]){$m=substr($matches[8],0,-1);$m=isset(dibi::$substs[$m])?dibi::$substs[$m]:call_user_func(dibi::$substFallBack,$m);return$matches[9]==''?$this->formatValue($m,FALSE):$m.$matches[9];}die('this should be never executed');}public
  562. function
  563. delimite($value){$value=self::substitute($value);$parts=explode('.',$value);foreach($parts
  564. as&$v){if($v!=='*')$v=$this->driver->escape($v,dibi::IDENTIFIER);}return
  565. implode('.',$parts);}public
  566. static
  567. function
  568. substitute($value){if(strpos($value,':')!==FALSE){return
  569. preg_replace_callback('#:([^:\s]*):#',array(__CLASS__,'subCb'),$value);}return$value;}private
  570. static
  571. function
  572. subCb($m){$m=$m[1];return
  573. isset(dibi::$substs[$m])?dibi::$substs[$m]:call_user_func(dibi::$substFallBack,$m);}}class
  574. DibiDataSource
  575. extends
  576. DibiObject
  577. implements
  578. IDataSource{private$connection;private$sql;private$result;private$count;private$totalCount;private$cols=array();private$sorting=array();private$conds=array();private$offset;private$limit;public
  579. function
  580. __construct($sql,DibiConnection$connection){if(strpbrk($sql," \t\r\n")===FALSE){$this->sql=$connection->getDriver()->escape($sql,dibi::IDENTIFIER);}else{$this->sql='('.$sql.') t';}$this->connection=$connection;}public
  581. function
  582. select($col,$as=NULL){if(is_array($col)){$this->cols=$col;}else{$this->cols[$col]=$as;}$this->result=NULL;return$this;}public
  583. function
  584. where($cond){if(is_array($cond)){$this->conds[]=$cond;}else{$this->conds[]=func_get_args();}$this->result=$this->count=NULL;return$this;}public
  585. function
  586. orderBy($row,$sorting='ASC'){if(is_array($row)){$this->sorting=$row;}else{$this->sorting[$row]=$sorting;}$this->result=NULL;return$this;}public
  587. function
  588. applyLimit($limit,$offset=NULL){$this->limit=$limit;$this->offset=$offset;$this->result=$this->count=NULL;return$this;}final
  589. public
  590. function
  591. getConnection(){return$this->connection;}public
  592. function
  593. getResult(){if($this->result===NULL){$this->result=$this->connection->nativeQuery($this->__toString());}return$this->result;}public
  594. function
  595. getIterator(){return$this->getResult()->getIterator();}public
  596. function
  597. fetch(){return$this->getResult()->fetch();}public
  598. function
  599. fetchSingle(){return$this->getResult()->fetchSingle();}public
  600. function
  601. fetchAll(){return$this->getResult()->fetchAll();}public
  602. function
  603. fetchAssoc($assoc){return$this->getResult()->fetchAssoc($assoc);}public
  604. function
  605. fetchPairs($key=NULL,$value=NULL){return$this->getResult()->fetchPairs($key,$value);}public
  606. function
  607. release(){$this->result=$this->count=$this->totalCount=NULL;}public
  608. function
  609. toFluent(){return$this->connection->select('*')->from('(%SQL) AS t',$this->__toString());}public
  610. function
  611. toDataSource(){return
  612. new
  613. self($this->__toString(),$this->connection);}public
  614. function
  615. __toString(){return$this->connection->translate('
  616. SELECT %n',(empty($this->cols)?'*':$this->cols),'
  617. FROM %SQL',$this->sql,'
  618. %ex',$this->conds?array('WHERE %and',$this->conds):NULL,'
  619. %ex',$this->sorting?array('ORDER BY %by',$this->sorting):NULL,'
  620. %ofs %lmt',$this->offset,$this->limit);}public
  621. function
  622. count(){if($this->count===NULL){$this->count=$this->conds||$this->offset||$this->limit?(int)$this->connection->nativeQuery('SELECT COUNT(*) FROM ('.$this->__toString().') AS t')->fetchSingle():$this->getTotalCount();}return$this->count;}public
  623. function
  624. getTotalCount(){if($this->totalCount===NULL){$this->totalCount=(int)$this->connection->nativeQuery('SELECT COUNT(*) FROM '.$this->sql)->fetchSingle();}return$this->totalCount;}}class
  625. DibiFluent
  626. extends
  627. DibiObject
  628. implements
  629. IDataSource{const
  630. REMOVE=FALSE;public
  631. static$masks=array('SELECT'=>array('SELECT','DISTINCT','FROM','WHERE','GROUP BY','HAVING','ORDER BY','LIMIT','OFFSET'),'UPDATE'=>array('UPDATE','SET','WHERE','ORDER BY','LIMIT'),'INSERT'=>array('INSERT','INTO','VALUES','SELECT'),'DELETE'=>array('DELETE','FROM','USING','WHERE','ORDER BY','LIMIT'));public
  632. static$modifiers=array('SELECT'=>'%n','FROM'=>'%n','IN'=>'%in','VALUES'=>'%l','SET'=>'%a','WHERE'=>'%and','HAVING'=>'%and','ORDER BY'=>'%by','GROUP BY'=>'%by');public
  633. static$separators=array('SELECT'=>',','FROM'=>',','WHERE'=>'AND','GROUP BY'=>',','HAVING'=>'AND','ORDER BY'=>',','LIMIT'=>FALSE,'OFFSET'=>FALSE,'SET'=>',','VALUES'=>',','INTO'=>FALSE);public
  634. static$clauseSwitches=array('JOIN'=>'FROM','INNER JOIN'=>'FROM','LEFT JOIN'=>'FROM','RIGHT JOIN'=>'FROM');private$connection;private$command;private$clauses=array();private$flags=array();private$cursor;private
  635. static$normalizer;public
  636. function
  637. __construct(DibiConnection$connection){$this->connection=$connection;if(self::$normalizer===NULL){self::$normalizer=new
  638. DibiLazyStorage(array(__CLASS__,'_formatClause'));}}public
  639. function
  640. __call($clause,$args){$clause=self::$normalizer->$clause;if($this->command===NULL){if(isset(self::$masks[$clause])){$this->clauses=array_fill_keys(self::$masks[$clause],NULL);}$this->cursor=&$this->clauses[$clause];$this->cursor=array();$this->command=$clause;}if(isset(self::$clauseSwitches[$clause])){$this->cursor=&$this->clauses[self::$clauseSwitches[$clause]];}if(array_key_exists($clause,$this->clauses)){$this->cursor=&$this->clauses[$clause];if($args===array(self::REMOVE)){$this->cursor=NULL;return$this;}if(isset(self::$separators[$clause])){$sep=self::$separators[$clause];if($sep===FALSE){$this->cursor=array();}elseif(!empty($this->cursor)){$this->cursor[]=$sep;}}}else{if($args===array(self::REMOVE)){return$this;}$this->cursor[]=$clause;}if($this->cursor===NULL){$this->cursor=array();}if(count($args)===1){$arg=$args[0];if($arg===TRUE){return$this;}elseif(is_string($arg)&&preg_match('#^[a-z:_][a-z0-9_.:]*$#i',$arg)){$args=array('%n',$arg);}elseif($arg
  641. instanceof
  642. self){$args=array_merge(array('('),$arg->_export(),array(')'));}elseif(is_array($arg)||$arg
  643. instanceof
  644. Traversable){if(isset(self::$modifiers[$clause])){$args=array(self::$modifiers[$clause],$arg);}elseif(is_string(key($arg))){$args=array('%a',$arg);}}}foreach($args
  645. as$arg)$this->cursor[]=$arg;return$this;}public
  646. function
  647. clause($clause,$remove=FALSE){$this->cursor=&$this->clauses[self::$normalizer->$clause];if($remove){trigger_error(__METHOD__.'(..., TRUE) is deprecated; use removeClause() instead.',E_USER_NOTICE);$this->cursor=NULL;}elseif($this->cursor===NULL){$this->cursor=array();}return$this;}public
  648. function
  649. removeClause($clause){$this->clauses[self::$normalizer->$clause]=NULL;return$this;}public
  650. function
  651. setFlag($flag,$value=TRUE){$flag=strtoupper($flag);if($value){$this->flags[$flag]=TRUE;}else{unset($this->flags[$flag]);}return$this;}final
  652. public
  653. function
  654. getFlag($flag){return
  655. isset($this->flags[strtoupper($flag)]);}final
  656. public
  657. function
  658. getCommand(){return$this->command;}final
  659. public
  660. function
  661. getConnection(){return$this->connection;}public
  662. function
  663. execute($return=NULL){$res=$this->connection->query($this->_export());return$return===dibi::IDENTIFIER?$this->connection->getInsertId():$res;}public
  664. function
  665. fetch(){if($this->command==='SELECT'){return$this->connection->query($this->_export(NULL,array('%lmt',1)))->fetch();}else{return$this->connection->query($this->_export())->fetch();}}public
  666. function
  667. fetchSingle(){if($this->command==='SELECT'){return$this->connection->query($this->_export(NULL,array('%lmt',1)))->fetchSingle();}else{return$this->connection->query($this->_export())->fetchSingle();}}public
  668. function
  669. fetchAll($offset=NULL,$limit=NULL){return$this->connection->query($this->_export(NULL,array('%ofs %lmt',$offset,$limit)))->fetchAll();}public
  670. function
  671. fetchAssoc($assoc){return$this->connection->query($this->_export())->fetchAssoc($assoc);}public
  672. function
  673. fetchPairs($key=NULL,$value=NULL){return$this->connection->query($this->_export())->fetchPairs($key,$value);}public
  674. function
  675. getIterator($offset=NULL,$limit=NULL){return$this->connection->query($this->_export(NULL,array('%ofs %lmt',$offset,$limit)))->getIterator();}public
  676. function
  677. test($clause=NULL){return$this->connection->test($this->_export($clause));}public
  678. function
  679. count(){return(int)$this->connection->query('SELECT COUNT(*) FROM (%ex',$this->_export(),') AS [data]')->fetchSingle();}public
  680. function
  681. toDataSource(){return
  682. new
  683. DibiDataSource($this->connection->translate($this->_export()),$this->connection);}final
  684. public
  685. function
  686. __toString(){return$this->connection->translate($this->_export());}protected
  687. function
  688. _export($clause=NULL,$args=array()){if($clause===NULL){$data=$this->clauses;}else{$clause=self::$normalizer->$clause;if(array_key_exists($clause,$this->clauses)){$data=array($clause=>$this->clauses[$clause]);}else{return
  689. array();}}foreach($data
  690. as$clause=>$statement){if($statement!==NULL){$args[]=$clause;if($clause===$this->command&&$this->flags){$args[]=implode(' ',array_keys($this->flags));}foreach($statement
  691. as$arg)$args[]=$arg;}}return$args;}public
  692. static
  693. function
  694. _formatClause($s){if($s==='order'||$s==='group'){$s.='By';trigger_error("Did you mean '$s'?",E_USER_NOTICE);}return
  695. strtoupper(preg_replace('#[a-z](?=[A-Z])#','$0 ',$s));}public
  696. function
  697. __clone(){foreach($this->clauses
  698. as$clause=>$val){$this->clauses[$clause]=&$val;unset($val);}$this->cursor=&$foo;}}class
  699. DibiDatabaseInfo
  700. extends
  701. DibiObject{private$reflector;private$name;private$tables;public
  702. function
  703. __construct(IDibiReflector$reflector,$name){$this->reflector=$reflector;$this->name=$name;}public
  704. function
  705. getName(){return$this->name;}public
  706. function
  707. getTables(){$this->init();return
  708. array_values($this->tables);}public
  709. function
  710. getTableNames(){$this->init();$res=array();foreach($this->tables
  711. as$table){$res[]=$table->getName();}return$res;}public
  712. function
  713. getTable($name){$name=DibiTranslator::substitute($name);$this->init();$l=strtolower($name);if(isset($this->tables[$l])){return$this->tables[$l];}else{throw
  714. new
  715. DibiException("Database '$this->name' has no table '$name'.");}}public
  716. function
  717. hasTable($name){$name=DibiTranslator::substitute($name);$this->init();return
  718. isset($this->tables[strtolower($name)]);}protected
  719. function
  720. init(){if($this->tables===NULL){$this->tables=array();foreach($this->reflector->getTables()as$info){$this->tables[strtolower($info['name'])]=new
  721. DibiTableInfo($this->reflector,$info);}}}}class
  722. DibiTableInfo
  723. extends
  724. DibiObject{private$reflector;private$name;private$view;private$columns;private$foreignKeys;private$indexes;private$primaryKey;public
  725. function
  726. __construct(IDibiReflector$reflector,array$info){$this->reflector=$reflector;$this->name=$info['name'];$this->view=!empty($info['view']);}public
  727. function
  728. getName(){return$this->name;}public
  729. function
  730. isView(){return$this->view;}public
  731. function
  732. getColumns(){$this->initColumns();return
  733. array_values($this->columns);}public
  734. function
  735. getColumnNames(){$this->initColumns();$res=array();foreach($this->columns
  736. as$column){$res[]=$column->getName();}return$res;}public
  737. function
  738. getColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();$l=strtolower($name);if(isset($this->columns[$l])){return$this->columns[$l];}else{throw
  739. new
  740. DibiException("Table '$this->name' has no column '$name'.");}}public
  741. function
  742. hasColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();return
  743. isset($this->columns[strtolower($name)]);}public
  744. function
  745. getForeignKeys(){$this->initForeignKeys();return$this->foreignKeys;}public
  746. function
  747. getIndexes(){$this->initIndexes();return$this->indexes;}public
  748. function
  749. getPrimaryKey(){$this->initIndexes();return$this->primaryKey;}protected
  750. function
  751. initColumns(){if($this->columns===NULL){$this->columns=array();foreach($this->reflector->getColumns($this->name)as$info){$this->columns[strtolower($info['name'])]=new
  752. DibiColumnInfo($this->reflector,$info);}}}protected
  753. function
  754. initIndexes(){if($this->indexes===NULL){$this->initColumns();$this->indexes=array();foreach($this->reflector->getIndexes($this->name)as$info){foreach($info['columns']as$key=>$name){$info['columns'][$key]=$this->columns[strtolower($name)];}$this->indexes[strtolower($info['name'])]=new
  755. DibiIndexInfo($info);if(!empty($info['primary'])){$this->primaryKey=$this->indexes[strtolower($info['name'])];}}}}protected
  756. function
  757. initForeignKeys(){throw
  758. new
  759. NotImplementedException;}}class
  760. DibiResultInfo
  761. extends
  762. DibiObject{private$driver;private$columns;private$names;public
  763. function
  764. __construct(IDibiResultDriver$driver){$this->driver=$driver;}public
  765. function
  766. getColumns(){$this->initColumns();return
  767. array_values($this->columns);}public
  768. function
  769. getColumnNames($fullNames=FALSE){$this->initColumns();$res=array();foreach($this->columns
  770. as$column){$res[]=$fullNames?$column->getFullName():$column->getName();}return$res;}public
  771. function
  772. getColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();$l=strtolower($name);if(isset($this->names[$l])){return$this->names[$l];}else{throw
  773. new
  774. DibiException("Result set has no column '$name'.");}}public
  775. function
  776. hasColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();return
  777. isset($this->names[strtolower($name)]);}protected
  778. function
  779. initColumns(){if($this->columns===NULL){$this->columns=array();$reflector=$this->driver
  780. instanceof
  781. IDibiReflector?$this->driver:NULL;foreach($this->driver->getResultColumns()as$info){$this->columns[]=$this->names[$info['name']]=new
  782. DibiColumnInfo($reflector,$info);}}}}class
  783. DibiColumnInfo
  784. extends
  785. DibiObject{private
  786. static$types;private$reflector;private$info;public
  787. function
  788. __construct(IDibiReflector$reflector=NULL,array$info){$this->reflector=$reflector;$this->info=$info;}public
  789. function
  790. getName(){return$this->info['name'];}public
  791. function
  792. getFullName(){return
  793. isset($this->info['fullname'])?$this->info['fullname']:NULL;}public
  794. function
  795. hasTable(){return!empty($this->info['table']);}public
  796. function
  797. getTable(){if(empty($this->info['table'])||!$this->reflector){throw
  798. new
  799. DibiException("Table is unknown or not available.");}return
  800. new
  801. DibiTableInfo($this->reflector,array('name'=>$this->info['table']));}public
  802. function
  803. getTableName(){return
  804. isset($this->info['table'])?$this->info['table']:NULL;}public
  805. function
  806. getType(){if(self::$types===NULL){self::$types=new
  807. DibiLazyStorage(array(__CLASS__,'detectType'));}return$this->info['nativetype']?self::$types->{$this->info['nativetype']}:dibi::TEXT;}public
  808. function
  809. getNativeType(){return$this->info['nativetype'];}public
  810. function
  811. getSize(){return
  812. isset($this->info['size'])?(int)$this->info['size']:NULL;}public
  813. function
  814. isUnsigned(){return
  815. isset($this->info['unsigned'])?(bool)$this->info['unsigned']:NULL;}public
  816. function
  817. isNullable(){return
  818. isset($this->info['nullable'])?(bool)$this->info['nullable']:NULL;}public
  819. function
  820. isAutoIncrement(){return
  821. isset($this->info['autoincrement'])?(bool)$this->info['autoincrement']:NULL;}public
  822. function
  823. getDefault(){return
  824. isset($this->info['default'])?$this->info['default']:NULL;}public
  825. function
  826. getVendorInfo($key){return
  827. isset($this->info['vendor'][$key])?$this->info['vendor'][$key]:NULL;}public
  828. static
  829. function
  830. detectType($type){static$patterns=array('BYTEA|BLOB|BIN'=>dibi::BINARY,'TEXT|CHAR|BIGINT|LONGLONG'=>dibi::TEXT,'BYTE|COUNTER|SERIAL|INT|LONG'=>dibi::INTEGER,'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER'=>dibi::FLOAT,'^TIME$'=>dibi::TIME,'TIME'=>dibi::DATETIME,'YEAR|DATE'=>dibi::DATE,'BOOL|BIT'=>dibi::BOOL);foreach($patterns
  831. as$s=>$val){if(preg_match("#$s#i",$type)){return$val;}}return
  832. dibi::TEXT;}}class
  833. DibiForeignKeyInfo
  834. extends
  835. DibiObject{private$name;private$references;public
  836. function
  837. __construct($name,array$references){$this->name=$name;$this->references=$references;}public
  838. function
  839. getName(){return$this->name;}public
  840. function
  841. getReferences(){return$this->references;}}class
  842. DibiIndexInfo
  843. extends
  844. DibiObject{private$info;public
  845. function
  846. __construct(array$info){$this->info=$info;}public
  847. function
  848. getName(){return$this->info['name'];}public
  849. function
  850. getColumns(){return$this->info['columns'];}public
  851. function
  852. isUnique(){return!empty($this->info['unique']);}public
  853. function
  854. isPrimary(){return!empty($this->info['primary']);}}class
  855. DibiProfiler
  856. extends
  857. DibiObject
  858. implements
  859. IDibiProfiler,IDebugPanel{static
  860. public$maxQueries=30;static
  861. public$maxLength=1000;private$file;public$useFirebug;public$explainQuery=TRUE;private$filter=self::ALL;public
  862. static$tickets=array();public
  863. static$fireTable=array(array('Time','SQL Statement','Rows','Connection'));public
  864. function
  865. __construct(array$config){if(class_exists('Debug',FALSE)&&is_callable('Debug::addPanel')){Debug::addPanel($this);}$this->useFirebug=isset($_SERVER['HTTP_USER_AGENT'])&&strpos($_SERVER['HTTP_USER_AGENT'],'FirePHP/');if(isset($config['filter'])){$this->setFilter($config['filter']);}if(isset($config['explain'])){$this->explainQuery=(bool)$config['explain'];}}public
  866. function
  867. setFile($file){$this->file=$file;return$this;}public
  868. function
  869. setFilter($filter){$this->filter=(int)$filter;return$this;}public
  870. function
  871. before(DibiConnection$connection,$event,$sql=NULL){if($event&self::QUERY)dibi::$numOfQueries++;dibi::$elapsedTime=FALSE;self::$tickets[]=array($connection,$event,trim($sql),-microtime(TRUE),NULL,NULL);end(self::$tickets);return
  872. key(self::$tickets);}public
  873. function
  874. after($ticket,$res=NULL){if(!isset(self::$tickets[$ticket])){throw
  875. new
  876. InvalidArgumentException('Bad ticket number.');}$ticket=&self::$tickets[$ticket];$ticket[3]+=microtime(TRUE);list($connection,$event,$sql,$time)=$ticket;dibi::$elapsedTime=$time;dibi::$totalTime+=$time;if(($event&$this->filter)===0)return;if($event&self::QUERY){try{$ticket[4]=$count=$res
  877. instanceof
  878. DibiResult?count($res):'-';}catch(Exception$e){$count='?';}if(count(self::$fireTable)<self::$maxQueries){self::$fireTable[]=array(sprintf('%0.3f',$time*1000),strlen($sql)>self::$maxLength?substr($sql,0,self::$maxLength).'...':$sql,$count,$connection->getConfig('driver').'/'.$connection->getConfig('name'));if($this->explainQuery&&$event===self::SELECT){$tmpSql=dibi::$sql;try{$ticket[5]=dibi::dump($connection->setProfiler(NULL)->nativeQuery('EXPLAIN '.$sql),TRUE);}catch(DibiException$e){}$connection->setProfiler($this);dibi::$sql=$tmpSql;}if($this->useFirebug&&!headers_sent()){header('X-Wf-Protocol-dibi: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');header('X-Wf-dibi-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');header('X-Wf-dibi-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');$payload=json_encode(array(array('Type'=>'TABLE','Label'=>'dibi profiler ('.dibi::$numOfQueries.' SQL queries took '.sprintf('%0.3f',dibi::$totalTime*1000).' ms)'),self::$fireTable));foreach(str_split($payload,4990)as$num=>$s){$num++;header("X-Wf-dibi-1-1-d$num: |$s|\\");}header("X-Wf-dibi-1-1-d$num: |$s|");}}if($this->file){$this->writeFile("OK: ".$sql.($res
  879. instanceof
  880. DibiResult?";\n-- rows: ".$count:'')."\n-- takes: ".sprintf('%0.3f',$time*1000).' ms'."\n-- driver: ".$connection->getConfig('driver').'/'.$connection->getConfig('name')."\n-- ".date('Y-m-d H:i:s')."\n\n");}}}public
  881. function
  882. exception(DibiDriverException$exception){if((self::EXCEPTION&$this->filter)===0)return;if($this->useFirebug){}if($this->file){$message=$exception->getMessage();$code=$exception->getCode();if($code){$message="[$code] $message";}$this->writeFile("ERROR: $message"."\n-- SQL: ".dibi::$sql."\n-- driver: ".";\n-- ".date('Y-m-d H:i:s')."\n\n");}}private
  883. function
  884. writeFile($message){$handle=fopen($this->file,'a');if(!$handle)return;flock($handle,LOCK_EX);fwrite($handle,$message);fclose($handle);}public
  885. function
  886. getTab(){return'<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC">'.dibi::$numOfQueries.' queries';}public
  887. function
  888. getPanel(){if(!dibi::$numOfQueries)return;$content="
  889. <h1>Queries: ".dibi::$numOfQueries.(dibi::$totalTime===NULL?'':', time: '.sprintf('%0.3f',dibi::$totalTime*1000).' ms')."</h1>
  890. <style>
  891. #nette-debug-DibiProfiler td.dibi-sql { background: white }
  892. #nette-debug-DibiProfiler .nette-alt td.dibi-sql { background: #F5F5F5 }
  893. #nette-debug-DibiProfiler .dibi-sql div { display: none; margin-top: 10px; max-height: 150px; overflow:auto }
  894. </style>
  895. <div class='nette-inner'>
  896. <table>
  897. <tr>
  898. <th>Time</th><th>SQL Statement</th><th>Rows</th><th>Connection</th>
  899. </tr>
  900. ";$i=0;$classes=array('class="nette-alt"','');foreach(self::$tickets
  901. as$ticket){list($connection,$event,$sql,$time,$count,$explain)=$ticket;if(!($event&self::QUERY))continue;$content.="
  902. <tr {$classes[++$i%2]}>
  903. <td>".sprintf('%0.3f',$time*1000).($explain?"
  904. <br><a href='#' class='nette-toggler' rel='#nette-debug-DibiProfiler-row-$i'>explain&nbsp;&#x25ba;</a>":'')."</td>
  905. <td class='dibi-sql'>".dibi::dump(strlen($sql)>self::$maxLength?substr($sql,0,self::$maxLength).'...':$sql,TRUE).($explain?"
  906. <div id='nette-debug-DibiProfiler-row-$i'>{$explain}</div>":'')."</td>
  907. <td>{$count}</td>
  908. <td>".htmlSpecialChars($connection->getConfig('driver').'/'.$connection->getConfig('name'))."</td>
  909. </tr>
  910. ";}$content.='</table></div>';return$content;}public
  911. function
  912. getId(){return
  913. get_class($this);}}class
  914. dibi{const
  915. TEXT='s';const
  916. BINARY='bin';const
  917. BOOL='b';const
  918. INTEGER='i';const
  919. FLOAT='f';const
  920. DATE='d';const
  921. DATETIME='t';const
  922. TIME='t';const
  923. IDENTIFIER='n';const
  924. FIELD_TEXT=self::TEXT;const
  925. FIELD_BINARY=self::BINARY;const
  926. FIELD_BOOL=self::BOOL;const
  927. FIELD_INTEGER=self::INTEGER;const
  928. FIELD_FLOAT=self::FLOAT;const
  929. FIELD_DATE=self::DATE;const
  930. FIELD_DATETIME=self::DATETIME;const
  931. FIELD_TIME=self::TIME;const
  932. VERSION='1.3-dev';const
  933. REVISION='8dc164d released on 2010-08-05';const
  934. ASC='ASC',DESC='DESC';private
  935. static$registry=array();private
  936. static$connection;public
  937. static$substs=array();public
  938. static$substFallBack=array(__CLASS__,'defaultSubstFallback');private
  939. static$handlers=array();public
  940. static$sql;public
  941. static$elapsedTime;public
  942. static$totalTime;public
  943. static$numOfQueries=0;public
  944. static$defaultDriver='mysql';final
  945. public
  946. function
  947. __construct(){throw
  948. new
  949. LogicException("Cannot instantiate static class ".get_class($this));}public
  950. static
  951. function
  952. connect($config=array(),$name=0){return
  953. self::$connection=self::$registry[$name]=new
  954. DibiConnection($config,$name);}public
  955. static
  956. function
  957. disconnect(){self::getConnection()->disconnect();}public
  958. static
  959. function
  960. isConnected(){return(self::$connection!==NULL)&&self::$connection->isConnected();}public
  961. static
  962. function
  963. getConnection($name=NULL){if($name===NULL){if(self::$connection===NULL){throw
  964. new
  965. DibiException('Dibi is not connected to database.');}return
  966. self::$connection;}if(!isset(self::$registry[$name])){throw
  967. new
  968. DibiException("There is no connection named '$name'.");}return
  969. self::$registry[$name];}public
  970. static
  971. function
  972. activate($name){self::$connection=self::getConnection($name);}public
  973. static
  974. function
  975. getProfiler(){return
  976. self::getConnection()->getProfiler();}public
  977. static
  978. function
  979. query($args){$args=func_get_args();return
  980. self::getConnection()->query($args);}public
  981. static
  982. function
  983. nativeQuery($sql){return
  984. self::getConnection()->nativeQuery($sql);}public
  985. static
  986. function
  987. test($args){$args=func_get_args();return
  988. self::getConnection()->test($args);}public
  989. static
  990. function
  991. dataSource($args){$args=func_get_args();return
  992. self::getConnection()->dataSource($args);}public
  993. static
  994. function
  995. fetch($args){$args=func_get_args();return
  996. self::getConnection()->query($args)->fetch();}public
  997. static
  998. function
  999. fetchAll($args){$args=func_get_args();return
  1000. self::getConnection()->query($args)->fetchAll();}public
  1001. static
  1002. function
  1003. fetchSingle($args){$args=func_get_args();return
  1004. self::getConnection()->query($args)->fetchSingle();}public
  1005. static
  1006. function
  1007. fetchPairs($args){$args=func_get_args();return
  1008. self::getConnection()->query($args)->fetchPairs();}public
  1009. static
  1010. function
  1011. getAffectedRows(){return
  1012. self::getConnection()->getAffectedRows();}public
  1013. static
  1014. function
  1015. affectedRows(){return
  1016. self::getConnection()->getAffectedRows();}public
  1017. static
  1018. function
  1019. getInsertId($sequence=NULL){return
  1020. self::getConnection()->getInsertId($sequence);}public
  1021. static
  1022. function
  1023. insertId($sequence=NULL){return
  1024. self::getConnection()->getInsertId($sequence);}public
  1025. static
  1026. function
  1027. begin($savepoint=NULL){self::getConnection()->begin($savepoint);}public
  1028. static
  1029. function
  1030. commit($savepoint=NULL){self::getConnection()->commit($savepoint);}public
  1031. static
  1032. function
  1033. rollback($savepoint=NULL){self::getConnection()->rollback($savepoint);}public
  1034. static
  1035. function
  1036. getDatabaseInfo(){return
  1037. self::getConnection()->getDatabaseInfo();}public
  1038. static
  1039. function
  1040. loadFile($file){return
  1041. self::getConnection()->loadFile($file);}public
  1042. static
  1043. function
  1044. __callStatic($name,$args){return
  1045. call_user_func_array(array(self::getConnection(),$name),$args);}public
  1046. static
  1047. function
  1048. command(){return
  1049. self::getConnection()->command();}public
  1050. static
  1051. function
  1052. select($args){$args=func_get_args();return
  1053. call_user_func_array(array(self::getConnection(),'select'),$args);}public
  1054. static
  1055. function
  1056. update($table,$args){return
  1057. self::getConnection()->update($table,$args);}public
  1058. static
  1059. function
  1060. insert($table,$args){return
  1061. self::getConnection()->insert($table,$args);}public
  1062. static
  1063. function
  1064. delete($table){return
  1065. self::getConnection()->delete($table);}public
  1066. static
  1067. function
  1068. datetime($time=NULL){return
  1069. new
  1070. DateTime53(is_numeric($time)?date('Y-m-d H:i:s',$time):$time);}public
  1071. static
  1072. function
  1073. date($date=NULL){return
  1074. new
  1075. DateTime53(is_numeric($date)?date('Y-m-d',$date):$date);}public
  1076. static
  1077. function
  1078. addSubst($expr,$subst){if($expr===''){trigger_error(__METHOD__.': empty substitutions will probably be deprecated.',E_USER_NOTICE);}self::$substs[$expr]=$subst;}public
  1079. static
  1080. function
  1081. removeSubst($expr){if($expr===TRUE){self::$substs=array();}else{unset(self::$substs[$expr]);}}public
  1082. static
  1083. function
  1084. setSubstFallback($callback){if(!is_callable($callback)){$able=is_callable($callback,TRUE,$textual);throw
  1085. new
  1086. InvalidArgumentException("Handler '$textual' is not ".($able?'callable.':'valid PHP callback.'));}self::$substFallBack=$callback;}public
  1087. static
  1088. function
  1089. defaultSubstFallback($expr){throw
  1090. new
  1091. InvalidStateException("Missing substitution for '$expr' expression.");}public
  1092. static
  1093. function
  1094. dump($sql=NULL,$return=FALSE){ob_start();if($sql
  1095. instanceof
  1096. DibiResult){$sql->dump();}else{if($sql===NULL)$sql=self::$sql;static$keywords1='SELECT|UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';static$keywords2='ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';$sql=" $sql ";$sql=preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i","\n\$1",$sql);$sql=preg_replace('#[ \t]{2,}#'," ",$sql);$sql=wordwrap($sql,100);$sql=htmlSpecialChars($sql);$sql=preg_replace("#([ \t]*\r?\n){2,}#","\n",$sql);if(PHP_SAPI==='cli'){echo
  1097. trim($sql)."\n\n";}else{$sql=preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is",array('dibi','highlightCallback'),$sql);echo'<pre class="dump">',trim($sql),"</pre>\n";}}if($return){return
  1098. ob_get_clean();}else{ob_end_flush();}}private
  1099. static
  1100. function
  1101. highlightCallback($matches){if(!empty($matches[1]))return'<em style="color:gray">'.$matches[1].'</em>';if(!empty($matches[2]))return'<strong style="color:red">'.$matches[2].'</strong>';if(!empty($matches[3]))return'<strong style="color:blue">'.$matches[3].'</strong>';if(!empty($matches[4]))return'<strong style="color:green">'.$matches[4].'</strong>';}}class
  1102. DibiMySqlReflector
  1103. extends
  1104. DibiObject
  1105. implements
  1106. IDibiReflector{private$driver;public
  1107. function
  1108. __construct(IDibiDriver$driver){$this->driver=$driver;}public
  1109. function
  1110. getTables(){$this->driver->query("SHOW FULL TABLES");$res=array();while($row=$this->driver->fetch(FALSE)){$res[]=array('name'=>$row[0],'view'=>isset($row[1])&&$row[1]==='VIEW');}$this->driver->free();return$res;}public
  1111. function
  1112. getColumns($table){$this->driver->query("SHOW FULL COLUMNS FROM `$table`");$res=array();while($row=$this->driver->fetch(TRUE)){$type=explode('(',$row['Type']);$res[]=array('name'=>$row['Field'],'table'=>$table,'nativetype'=>strtoupper($type[0]),'size'=>isset($type[1])?(int)$type[1]:NULL,'unsigned'=>(bool)strstr($row['Type'],'unsigned'),'nullable'=>$row['Null']==='YES','default'=>$row['Default'],'autoincrement'=>$row['Extra']==='auto_increment','vendor'=>$row);}$this->driver->free();return$res;}public
  1113. function
  1114. getIndexes($table){$this->driver->query("SHOW INDEX FROM `$table`");$res=array();while($row=$this->driver->fetch(TRUE)){$res[$row['Key_name']]['name']=$row['Key_name'];$res[$row['Key_name']]['unique']=!$row['Non_unique'];$res[$row['Key_name']]['primary']=$row['Key_name']==='PRIMARY';$res[$row['Key_name']]['columns'][$row['Seq_in_index']-1]=$row['Column_name'];}$this->driver->free();return
  1115. array_values($res);}public
  1116. function
  1117. getForeignKeys($table){throw
  1118. new
  1119. NotImplementedException;}}class
  1120. DibiMySqlDriver
  1121. extends
  1122. DibiObject
  1123. implements
  1124. IDibiDriver,IDibiResultDriver{const
  1125. ERROR_ACCESS_DENIED=1045;const
  1126. ERROR_DUPLICATE_ENTRY=1062;const
  1127. ERROR_DATA_TRUNCATED=1265;private$connection;private$resultSet;private$buffered;public
  1128. function
  1129. __construct(){if(!extension_loaded('mysql')){throw
  1130. new
  1131. DibiDriverException("PHP extension 'mysql' is not loaded.");}}public
  1132. function
  1133. connect(array&$config){if(isset($config['resource'])){$this->connection=$config['resource'];}else{DibiConnection::alias($config,'flags','options');if(!isset($config['charset']))$config['charset']='utf8';if(!isset($config['username']))$config['username']=ini_get('mysql.default_user');if(!isset($config['password']))$config['password']=ini_get('mysql.default_password');if(!isset($config['host'])){$host=ini_get('mysql.default_host');if($host){$config['host']=$host;$config['port']=ini_get('mysql.default_port');}else{if(!isset($config['socket']))$config['socket']=ini_get('mysql.default_socket');$config['host']=NULL;}}if(empty($config['socket'])){$host=$config['host'].(empty($config['port'])?'':':'.$config['port']);}else{$host=':'.$config['socket'];}if(empty($config['persistent'])){$this->connection=@mysql_connect($host,$config['username'],$config['password'],TRUE,$config['flags']);}else{$this->connection=@mysql_pconnect($host,$config['username'],$config['password'],$config['flags']);}}if(!is_resource($this->connection)){throw
  1134. new
  1135. DibiDriverException(mysql_error(),mysql_errno());}if(isset($config['charset'])){$ok=FALSE;if(function_exists('mysql_set_charset')){$ok=@mysql_set_charset($config['charset'],$this->connection);}if(!$ok){$this->query("SET NAMES '$config[charset]'");}}if(isset($config['database'])){if(!@mysql_select_db($config['database'],$this->connection)){throw
  1136. new
  1137. DibiDriverException(mysql_error($this->connection),mysql_errno($this->connection));}}if(isset($config['sqlmode'])){$this->query("SET sql_mode='$config[sqlmode]'");}$this->query("SET time_zone='".date('P')."'");$this->buffered=empty($config['unbuffered']);}public
  1138. function
  1139. disconnect(){mysql_close($this->connection);}public
  1140. function
  1141. query($sql){if($this->buffered){$this->resultSet=@mysql_query($sql,$this->connection);}else{$this->resultSet=@mysql_unbuffered_query($sql,$this->connection);}if(mysql_errno($this->connection)){throw
  1142. new
  1143. DibiDriverException(mysql_error($this->connection),mysql_errno($this->connection),$sql);}return
  1144. is_resource($this->resultSet)?clone$this:NULL;}public
  1145. function
  1146. getInfo(){$res=array();preg_match_all('#(.+?): +(\d+) *#',mysql_info($this->connection),$matches,PREG_SET_ORDER);if(preg_last_error())throw
  1147. new
  1148. PcreException;foreach($matches
  1149. as$m){$res[$m[1]]=(int)$m[2];}return$res;}public
  1150. function
  1151. getAffectedRows(){return
  1152. mysql_affected_rows($this->connection);}public
  1153. function
  1154. getInsertId($sequence){return
  1155. mysql_insert_id($this->connection);}public
  1156. function
  1157. begin($savepoint=NULL){$this->query($savepoint?"SAVEPOINT $savepoint":'START TRANSACTION');}public
  1158. function
  1159. commit($savepoint=NULL){$this->query($savepoint?"RELEASE SAVEPOINT $savepoint":'COMMIT');}public
  1160. function
  1161. rollback($savepoint=NULL){$this->query($savepoint?"ROLLBACK TO SAVEPOINT $savepoint":'ROLLBACK');}public
  1162. function
  1163. getResource(){return$this->connection;}public
  1164. function
  1165. getReflector(){return
  1166. new
  1167. DibiMySqlReflector($this);}public
  1168. function
  1169. escape($value,$type){switch($type){case
  1170. dibi::TEXT:return"'".mysql_real_escape_string($value,$this->connection)."'";case
  1171. dibi::BINARY:return"_binary'".mysql_real_escape_string($value,$this->connection)."'";case
  1172. dibi::IDENTIFIER:return'`'.str_replace('`','``',$value).'`';case
  1173. dibi::BOOL:return$value?1:0;case
  1174. dibi::DATE:return$value
  1175. instanceof
  1176. DateTime?$value->format("'Y-m-d'"):date("'Y-m-d'",$value);case
  1177. dibi::DATETIME:return$value
  1178. instanceof
  1179. DateTime?$value->format("'Y-m-d H:i:s'"):date("'Y-m-d H:i:s'",$value);default:throw
  1180. new
  1181. InvalidArgumentException('Unsupported type.');}}public
  1182. function
  1183. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1184. new
  1185. InvalidArgumentException('Unsupported type.');}public
  1186. function
  1187. applyLimit(&$sql,$limit,$offset){if($limit<0&&$offset<1)return;$sql.=' LIMIT '.($limit<0?'18446744073709551615':(int)$limit).($offset>0?' OFFSET '.(int)$offset:'');}public
  1188. function
  1189. getRowCount(){if(!$this->buffered){throw
  1190. new
  1191. DibiDriverException('Row count is not available for unbuffered queries.');}return
  1192. mysql_num_rows($this->resultSet);}public
  1193. function
  1194. fetch($assoc){return
  1195. mysql_fetch_array($this->resultSet,$assoc?MYSQL_ASSOC:MYSQL_NUM);}public
  1196. function
  1197. seek($row){if(!$this->buffered){throw
  1198. new
  1199. DibiDriverException('Cannot seek an unbuffered result set.');}return
  1200. mysql_data_seek($this->resultSet,$row);}public
  1201. function
  1202. free(){mysql_free_result($this->resultSet);$this->resultSet=NULL;}public
  1203. function
  1204. getResultColumns(){$count=mysql_num_fields($this->resultSet);$res=array();for($i=0;$i<$count;$i++){$row=(array)mysql_fetch_field($this->resultSet,$i);$res[]=array('name'=>$row['name'],'table'=>$row['table'],'fullname'=>$row['table']?$row['table'].'.'.$row['name']:$row['name'],'nativetype'=>strtoupper($row['type']),'vendor'=>$row);}return$res;}public
  1205. function
  1206. getResultResource(){return$this->resultSet;}}class
  1207. DibiMySqliDriver
  1208. extends
  1209. DibiObject
  1210. implements
  1211. IDibiDriver,IDibiResultDriver{const
  1212. ERROR_ACCESS_DENIED=1045;const
  1213. ERROR_DUPLICATE_ENTRY=1062;const
  1214. ERROR_DATA_TRUNCATED=1265;private$connection;private$resultSet;private$buffered;public
  1215. function
  1216. __construct(){if(!extension_loaded('mysqli')){throw
  1217. new
  1218. DibiDriverException("PHP extension 'mysqli' is not loaded.");}}public
  1219. function
  1220. connect(array&$config){mysqli_report(MYSQLI_REPORT_OFF);if(isset($config['resource'])){$this->connection=$config['resource'];}else{if(!isset($config['charset']))$config['charset']='utf8';if(!isset($config['username']))$config['username']=ini_get('mysqli.default_user');if(!isset($config['password']))$config['password']=ini_get('mysqli.default_pw');if(!isset($config['socket']))$config['socket']=ini_get('mysqli.default_socket');if(!isset($config['port']))$config['port']=NULL;if(!isset($config['host'])){$host=ini_get('mysqli.default_host');if($host){$config['host']=$host;$config['port']=ini_get('mysqli.default_port');}else{$config['host']=NULL;$config['port']=NULL;}}$foo=&$config['flags'];$foo=&$config['database'];$this->connection=mysqli_init();if(isset($config['options'])){if(is_scalar($config['options'])){$config['flags']=$config['options'];trigger_error(__CLASS__.": configuration item 'options' must be array; for constants MYSQLI_CLIENT_* use 'flags'.",E_USER_NOTICE);}else{foreach((array)$config['options']as$key=>$value){mysqli_options($this->connection,$key,$value);}}}@mysqli_real_connect($this->connection,$config['host'],$config['username'],$config['password'],$config['database'],$config['port'],$config['socket'],$config['flags']);if($errno=mysqli_connect_errno()){throw
  1221. new
  1222. DibiDriverException(mysqli_connect_error(),$errno);}}if(isset($config['charset'])){$ok=FALSE;if(version_compare(PHP_VERSION,'5.1.5','>=')){$ok=@mysqli_set_charset($this->connection,$config['charset']);}if(!$ok){$this->query("SET NAMES '$config[charset]'");}}if(isset($config['sqlmode'])){$this->query("SET sql_mode='$config[sqlmode]'");}$this->query("SET time_zone='".date('P')."'");$this->buffered=empty($config['unbuffered']);}public
  1223. function
  1224. disconnect(){mysqli_close($this->connection);}public
  1225. function
  1226. query($sql){$this->resultSet=@mysqli_query($this->connection,$sql,$this->buffered?MYSQLI_STORE_RESULT:MYSQLI_USE_RESULT);if(mysqli_errno($this->connection)){throw
  1227. new
  1228. DibiDriverException(mysqli_error($this->connection),mysqli_errno($this->connection),$sql);}return
  1229. is_object($this->resultSet)?clone$this:NULL;}public
  1230. function
  1231. getInfo(){$res=array();preg_match_all('#(.+?): +(\d+) *#',mysqli_info($this->connection),$matches,PREG_SET_ORDER);if(preg_last_error())throw
  1232. new
  1233. PcreException;foreach($matches
  1234. as$m){$res[$m[1]]=(int)$m[2];}return$res;}public
  1235. function
  1236. getAffectedRows(){return
  1237. mysqli_affected_rows($this->connection);}public
  1238. function
  1239. getInsertId($sequence){return
  1240. mysqli_insert_id($this->connection);}public
  1241. function
  1242. begin($savepoint=NULL){$this->query($savepoint?"SAVEPOINT $savepoint":'START TRANSACTION');}public
  1243. function
  1244. commit($savepoint=NULL){$this->query($savepoint?"RELEASE SAVEPOINT $savepoint":'COMMIT');}public
  1245. function
  1246. rollback($savepoint=NULL){$this->query($savepoint?"ROLLBACK TO SAVEPOINT $savepoint":'ROLLBACK');}public
  1247. function
  1248. getResource(){return$this->connection;}public
  1249. function
  1250. getReflector(){return
  1251. new
  1252. DibiMySqlReflector($this);}public
  1253. function
  1254. escape($value,$type){switch($type){case
  1255. dibi::TEXT:return"'".mysqli_real_escape_string($this->connection,$value)."'";case
  1256. dibi::BINARY:return"_binary'".mysqli_real_escape_string($this->connection,$value)."'";case
  1257. dibi::IDENTIFIER:return'`'.str_replace('`','``',$value).'`';case
  1258. dibi::BOOL:return$value?1:0;case
  1259. dibi::DATE:return$value
  1260. instanceof
  1261. DateTime?$value->format("'Y-m-d'"):date("'Y-m-d'",$value);case
  1262. dibi::DATETIME:return$value
  1263. instanceof
  1264. DateTime?$value->format("'Y-m-d H:i:s'"):date("'Y-m-d H:i:s'",$value);default:throw
  1265. new
  1266. InvalidArgumentException('Unsupported type.');}}public
  1267. function
  1268. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1269. new
  1270. InvalidArgumentException('Unsupported type.');}public
  1271. function
  1272. applyLimit(&$sql,$limit,$offset){if($limit<0&&$offset<1)return;$sql.=' LIMIT '.($limit<0?'18446744073709551615':(int)$limit).($offset>0?' OFFSET '.(int)$offset:'');}public
  1273. function
  1274. getRowCount(){if(!$this->buffered){throw
  1275. new
  1276. DibiDriverException('Row count is not available for unbuffered queries.');}return
  1277. mysqli_num_rows($this->resultSet);}public
  1278. function
  1279. fetch($assoc){return
  1280. mysqli_fetch_array($this->resultSet,$assoc?MYSQLI_ASSOC:MYSQLI_NUM);}public
  1281. function
  1282. seek($row){if(!$this->buffered){throw
  1283. new
  1284. DibiDriverException('Cannot seek an unbuffered result set.');}return
  1285. mysqli_data_seek($this->resultSet,$row);}public
  1286. function
  1287. free(){mysqli_free_result($this->resultSet);$this->resultSet=NULL;}public
  1288. function
  1289. getResultColumns(){static$types;if(empty($types)){$consts=get_defined_constants(TRUE);foreach($consts['mysqli']as$key=>$value){if(strncmp($key,'MYSQLI_TYPE_',12)===0){$types[$value]=substr($key,12);}}$types[MYSQLI_TYPE_TINY]=$types[MYSQLI_TYPE_SHORT]=$types[MYSQLI_TYPE_LONG]='INT';}$count=mysqli_num_fields($this->resultSet);$res=array();for($i=0;$i<$count;$i++){$row=(array)mysqli_fetch_field_direct($this->resultSet,$i);$res[]=array('name'=>$row['name'],'table'=>$row['orgtable'],'fullname'=>$row['table']?$row['table'].'.'.$row['name']:$row['name'],'nativetype'=>$types[$row['type']],'vendor'=>$row);}return$res;}public
  1290. function
  1291. getResultResource(){return$this->resultSet;}}class
  1292. DibiOdbcDriver
  1293. extends
  1294. DibiObject
  1295. implements
  1296. IDibiDriver,IDibiResultDriver,IDibiReflector{private$connection;private$resultSet;private$row=0;public
  1297. function
  1298. __construct(){if(!extension_loaded('odbc')){throw
  1299. new
  1300. DibiDriverException("PHP extension 'odbc' is not loaded.");}}public
  1301. function
  1302. connect(array&$config){if(isset($config['resource'])){$this->connection=$config['resource'];}else{if(!isset($config['username']))$config['username']=ini_get('odbc.default_user');if(!isset($config['password']))$config['password']=ini_get('odbc.default_pw');if(!isset($config['dsn']))$config['dsn']=ini_get('odbc.default_db');if(empty($config['persistent'])){$this->connection=@odbc_connect($config['dsn'],$config['username'],$config['password']);}else{$this->connection=@odbc_pconnect($config['dsn'],$config['username'],$config['password']);}}if(!is_resource($this->connection)){throw
  1303. new
  1304. DibiDriverException(odbc_errormsg().' '.odbc_error());}}public
  1305. function
  1306. disconnect(){odbc_close($this->connection);}public
  1307. function
  1308. query($sql){$this->resultSet=@odbc_exec($this->connection,$sql);if($this->resultSet===FALSE){throw
  1309. new
  1310. DibiDriverException(odbc_errormsg($this->connection).' '.odbc_error($this->connection),0,$sql);}return
  1311. is_resource($this->resultSet)?clone$this:NULL;}public
  1312. function
  1313. getAffectedRows(){return
  1314. odbc_num_rows($this->resultSet);}public
  1315. function
  1316. getInsertId($sequence){throw
  1317. new
  1318. NotSupportedException('ODBC does not support autoincrementing.');}public
  1319. function
  1320. begin($savepoint=NULL){if(!odbc_autocommit($this->connection,FALSE)){throw
  1321. new
  1322. DibiDriverException(odbc_errormsg($this->connection).' '.odbc_error($this->connection));}}public
  1323. function
  1324. commit($savepoint=NULL){if(!odbc_commit($this->connection)){throw
  1325. new
  1326. DibiDriverException(odbc_errormsg($this->connection).' '.odbc_error($this->connection));}odbc_autocommit($this->connection,TRUE);}public
  1327. function
  1328. rollback($savepoint=NULL){if(!odbc_rollback($this->connection)){throw
  1329. new
  1330. DibiDriverException(odbc_errormsg($this->connection).' '.odbc_error($this->connection));}odbc_autocommit($this->connection,TRUE);}public
  1331. function
  1332. inTransaction(){return!odbc_autocommit($this->connection);}public
  1333. function
  1334. getResource(){return$this->connection;}public
  1335. function
  1336. getReflector(){return$this;}public
  1337. function
  1338. escape($value,$type){switch($type){case
  1339. dibi::TEXT:case
  1340. dibi::BINARY:return"'".str_replace("'","''",$value)."'";case
  1341. dibi::IDENTIFIER:return'['.str_replace(array('[',']'),array('[[',']]'),$value).']';case
  1342. dibi::BOOL:return$value?1:0;case
  1343. dibi::DATE:return$value
  1344. instanceof
  1345. DateTime?$value->format("#m/d/Y#"):date("#m/d/Y#",$value);case
  1346. dibi::DATETIME:return$value
  1347. instanceof
  1348. DateTime?$value->format("#m/d/Y H:i:s#"):date("#m/d/Y H:i:s#",$value);default:throw
  1349. new
  1350. InvalidArgumentException('Unsupported type.');}}public
  1351. function
  1352. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1353. new
  1354. InvalidArgumentException('Unsupported type.');}public
  1355. function
  1356. applyLimit(&$sql,$limit,$offset){if($limit>=0){$sql='SELECT TOP '.(int)$limit.' * FROM ('.$sql.')';}if($offset)throw
  1357. new
  1358. InvalidArgumentException('Offset is not implemented in driver odbc.');}public
  1359. function
  1360. getRowCount(){return
  1361. odbc_num_rows($this->resultSet);}public
  1362. function
  1363. fetch($assoc){if($assoc){return
  1364. odbc_fetch_array($this->resultSet,++$this->row);}else{$set=$this->resultSet;if(!odbc_fetch_row($set,++$this->row))return
  1365. FALSE;$count=odbc_num_fields($set);$cols=array();for($i=1;$i<=$count;$i++)$cols[]=odbc_result($set,$i);return$cols;}}public
  1366. function
  1367. seek($row){$this->row=$row;return
  1368. TRUE;}public
  1369. function
  1370. free(){odbc_free_result($this->resultSet);$this->resultSet=NULL;}public
  1371. function
  1372. getResultColumns(){$count=odbc_num_fields($this->resultSet);$res=array();for($i=1;$i<=$count;$i++){$res[]=array('name'=>odbc_field_name($this->resultSet,$i),'table'=>NULL,'fullname'=>odbc_field_name($this->resultSet,$i),'nativetype'=>odbc_field_type($this->resultSet,$i));}return$res;}public
  1373. function
  1374. getResultResource(){return$this->resultSet;}public
  1375. function
  1376. getTables(){$result=odbc_tables($this->connection);$res=array();while($row=odbc_fetch_array($result)){if($row['TABLE_TYPE']==='TABLE'||$row['TABLE_TYPE']==='VIEW'){$res[]=array('name'=>$row['TABLE_NAME'],'view'=>$row['TABLE_TYPE']==='VIEW');}}odbc_free_result($result);return$res;}public
  1377. function
  1378. getColumns($table){$result=odbc_columns($this->connection);$res=array();while($row=odbc_fetch_array($result)){if($row['TABLE_NAME']===$table){$res[]=array('name'=>$row['COLUMN_NAME'],'table'=>$table,'nativetype'=>$row['TYPE_NAME'],'size'=>$row['COLUMN_SIZE'],'nullable'=>(bool)$row['NULLABLE'],'default'=>$row['COLUMN_DEF']);}}odbc_free_result($result);return$res;}public
  1379. function
  1380. getIndexes($table){throw
  1381. new
  1382. NotImplementedException;}public
  1383. function
  1384. getForeignKeys($table){throw
  1385. new
  1386. NotImplementedException;}}class
  1387. DibiPdoDriver
  1388. extends
  1389. DibiObject
  1390. implements
  1391. IDibiDriver,IDibiResultDriver{private$connection;private$resultSet;private$affectedRows=FALSE;private$driverName;public
  1392. function
  1393. __construct(){if(!extension_loaded('pdo')){throw
  1394. new
  1395. DibiDriverException("PHP extension 'pdo' is not loaded.");}}public
  1396. function
  1397. connect(array&$config){$foo=&$config['dsn'];$foo=&$config['options'];DibiConnection::alias($config,'resource','pdo');if($config['resource']instanceof
  1398. PDO){$this->connection=$config['resource'];}else
  1399. try{$this->connection=new
  1400. PDO($config['dsn'],$config['username'],$config['password'],$config['options']);}catch(PDOException$e){throw
  1401. new
  1402. DibiDriverException($e->getMessage(),$e->getCode());}if(!$this->connection){throw
  1403. new
  1404. DibiDriverException('Connecting error.');}$this->driverName=$this->connection->getAttribute(PDO::ATTR_DRIVER_NAME);}public
  1405. function
  1406. disconnect(){$this->connection=NULL;}public
  1407. function
  1408. query($sql){$cmd=strtoupper(substr(ltrim($sql),0,6));static$list=array('UPDATE'=>1,'DELETE'=>1,'INSERT'=>1,'REPLAC'=>1);if(isset($list[$cmd])){$this->resultSet=NULL;$this->affectedRows=$this->connection->exec($sql);if($this->affectedRows===FALSE){$err=$this->connection->errorInfo();throw
  1409. new
  1410. DibiDriverException("SQLSTATE[$err[0]]: $err[2]",$err[1],$sql);}return
  1411. NULL;}else{$this->resultSet=$this->connection->query($sql);$this->affectedRows=FALSE;if($this->resultSet===FALSE){$err=$this->connection->errorInfo();throw
  1412. new
  1413. DibiDriverException("SQLSTATE[$err[0]]: $err[2]",$err[1],$sql);}return
  1414. clone$this;}}public
  1415. function
  1416. getAffectedRows(){return$this->affectedRows;}public
  1417. function
  1418. getInsertId($sequence){return$this->connection->lastInsertId();}public
  1419. function
  1420. begin($savepoint=NULL){if(!$this->connection->beginTransaction()){$err=$this->connection->errorInfo();throw
  1421. new
  1422. DibiDriverException("SQLSTATE[$err[0]]: $err[2]",$err[1]);}}public
  1423. function
  1424. commit($savepoint=NULL){if(!$this->connection->commit()){$err=$this->connection->errorInfo();throw
  1425. new
  1426. DibiDriverException("SQLSTATE[$err[0]]: $err[2]",$err[1]);}}public
  1427. function
  1428. rollback($savepoint=NULL){if(!$this->connection->rollBack()){$err=$this->connection->errorInfo();throw
  1429. new
  1430. DibiDriverException("SQLSTATE[$err[0]]: $err[2]",$err[1]);}}public
  1431. function
  1432. getResource(){return$this->connection;}public
  1433. function
  1434. getReflector(){throw
  1435. new
  1436. NotSupportedException;}public
  1437. function
  1438. escape($value,$type){switch($type){case
  1439. dibi::TEXT:return$this->connection->quote($value,PDO::PARAM_STR);case
  1440. dibi::BINARY:return$this->connection->quote($value,PDO::PARAM_LOB);case
  1441. dibi::IDENTIFIER:switch($this->driverName){case'mysql':return'`'.str_replace('`','``',$value).'`';case'pgsql':return'"'.str_replace('"','""',$value).'"';case'sqlite':case'sqlite2':return'['.strtr($value,'[]',' ').']';case'odbc':case'oci':case'mssql':return'['.str_replace(array('[',']'),array('[[',']]'),$value).']';default:return$value;}case
  1442. dibi::BOOL:return$this->connection->quote($value,PDO::PARAM_BOOL);case
  1443. dibi::DATE:return$value
  1444. instanceof
  1445. DateTime?$value->format("'Y-m-d'"):date("'Y-m-d'",$value);case
  1446. dibi::DATETIME:return$value
  1447. instanceof
  1448. DateTime?$value->format("'Y-m-d H:i:s'"):date("'Y-m-d H:i:s'",$value);default:throw
  1449. new
  1450. InvalidArgumentException('Unsupported type.');}}public
  1451. function
  1452. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1453. new
  1454. InvalidArgumentException('Unsupported type.');}public
  1455. function
  1456. applyLimit(&$sql,$limit,$offset){if($limit<0&&$offset<1)return;switch($this->driverName){case'mysql':$sql.=' LIMIT '.($limit<0?'18446744073709551615':(int)$limit).($offset>0?' OFFSET '.(int)$offset:'');break;case'pgsql':if($limit>=0)$sql.=' LIMIT '.(int)$limit;if($offset>0)$sql.=' OFFSET '.(int)$offset;break;case'sqlite':case'sqlite2':$sql.=' LIMIT '.$limit.($offset>0?' OFFSET '.(int)$offset:'');break;case'oci':if($offset>0){$sql='SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM ('.$sql.') t '.($limit>=0?'WHERE ROWNUM <= '.((int)$offset+(int)$limit):'').') WHERE "__rnum" > '.(int)$offset;}elseif($limit>=0){$sql='SELECT * FROM ('.$sql.') WHERE ROWNUM <= '.(int)$limit;}break;case'odbc':case'mssql':if($offset<1){$sql='SELECT TOP '.(int)$limit.' * FROM ('.$sql.')';break;}default:throw
  1457. new
  1458. NotSupportedException('PDO or driver does not support applying limit or offset.');}}public
  1459. function
  1460. getRowCount(){return$this->resultSet->rowCount();}public
  1461. function
  1462. fetch($assoc){return$this->resultSet->fetch($assoc?PDO::FETCH_ASSOC:PDO::FETCH_NUM);}public
  1463. function
  1464. seek($row){throw
  1465. new
  1466. NotSupportedException('Cannot seek an unbuffered result set.');}public
  1467. function
  1468. free(){$this->resultSet=NULL;}public
  1469. function
  1470. getResultColumns(){$count=$this->resultSet->columnCount();$res=array();for($i=0;$i<$count;$i++){$row=@$this->resultSet->getColumnMeta($i);if($row===FALSE){throw
  1471. new
  1472. DibiDriverException('Driver does not support meta data.');}$row['table']=isset($row['table'])?$row['table']:NULL;$res[]=array('name'=>$row['name'],'table'=>$row['table'],'nativetype'=>$row['native_type'],'fullname'=>$row['table']?$row['table'].'.'.$row['name']:$row['name'],'vendor'=>$row);}return$res;}public
  1473. function
  1474. getResultResource(){return$this->resultSet;}}class
  1475. DibiPostgreDriver
  1476. extends
  1477. DibiObject
  1478. implements
  1479. IDibiDriver,IDibiResultDriver,IDibiReflector{private$connection;private$resultSet;private$escMethod=FALSE;public
  1480. function
  1481. __construct(){if(!extension_loaded('pgsql')){throw
  1482. new
  1483. DibiDriverException("PHP extension 'pgsql' is not loaded.");}}public
  1484. function
  1485. connect(array&$config){if(isset($config['resource'])){$this->connection=$config['resource'];}else{if(!isset($config['charset']))$config['charset']='utf8';if(isset($config['string'])){$string=$config['string'];}else{$string='';DibiConnection::alias($config,'user','username');DibiConnection::alias($config,'dbname','database');foreach(array('host','hostaddr','port','dbname','user','password','connect_timeout','options','sslmode','service')as$key){if(isset($config[$key]))$string.=$key.'='.$config[$key].' ';}}DibiDriverException::tryError();if(empty($config['persistent'])){$this->connection=pg_connect($string,PGSQL_CONNECT_FORCE_NEW);}else{$this->connection=pg_pconnect($string,PGSQL_CONNECT_FORCE_NEW);}if(DibiDriverException::catchError($msg)){throw
  1486. new
  1487. DibiDriverException($msg,0);}}if(!is_resource($this->connection)){throw
  1488. new
  1489. DibiDriverException('Connecting error.');}if(isset($config['charset'])){DibiDriverException::tryError();pg_set_client_encoding($this->connection,$config['charset']);if(DibiDriverException::catchError($msg)){throw
  1490. new
  1491. DibiDriverException($msg,0);}}if(isset($config['schema'])){$this->query('SET search_path TO "'.$config['schema'].'"');}$this->escMethod=version_compare(PHP_VERSION,'5.2.0','>=');}public
  1492. function
  1493. disconnect(){pg_close($this->connection);}public
  1494. function
  1495. query($sql){$this->resultSet=@pg_query($this->connection,$sql);if($this->resultSet===FALSE){throw
  1496. new
  1497. DibiDriverException(pg_last_error($this->connection),0,$sql);}return
  1498. is_resource($this->resultSet)&&pg_num_fields($this->resultSet)?clone$this:NULL;}public
  1499. function
  1500. getAffectedRows(){return
  1501. pg_affected_rows($this->resultSet);}public
  1502. function
  1503. getInsertId($sequence){if($sequence===NULL){$has=$this->query("SELECT LASTVAL()");}else{$has=$this->query("SELECT CURRVAL('$sequence')");}if(!$has)return
  1504. FALSE;$row=$this->fetch(FALSE);$this->free();return
  1505. is_array($row)?$row[0]:FALSE;}public
  1506. function
  1507. begin($savepoint=NULL){$this->query($savepoint?"SAVEPOINT $savepoint":'START TRANSACTION');}public
  1508. function
  1509. commit($savepoint=NULL){$this->query($savepoint?"RELEASE SAVEPOINT $savepoint":'COMMIT');}public
  1510. function
  1511. rollback($savepoint=NULL){$this->query($savepoint?"ROLLBACK TO SAVEPOINT $savepoint":'ROLLBACK');}public
  1512. function
  1513. inTransaction(){return!in_array(pg_transaction_status($this->connection),array(PGSQL_TRANSACTION_UNKNOWN,PGSQL_TRANSACTION_IDLE),TRUE);}public
  1514. function
  1515. getResource(){return$this->connection;}public
  1516. function
  1517. getReflector(){return$this;}public
  1518. function
  1519. escape($value,$type){switch($type){case
  1520. dibi::TEXT:if($this->escMethod){return"'".pg_escape_string($this->connection,$value)."'";}else{return"'".pg_escape_string($value)."'";}case
  1521. dibi::BINARY:if($this->escMethod){return"'".pg_escape_bytea($this->connection,$value)."'";}else{return"'".pg_escape_bytea($value)."'";}case
  1522. dibi::IDENTIFIER:return'"'.str_replace('"','""',$value).'"';case
  1523. dibi::BOOL:return$value?'TRUE':'FALSE';case
  1524. dibi::DATE:return$value
  1525. instanceof
  1526. DateTime?$value->format("'Y-m-d'"):date("'Y-m-d'",$value);case
  1527. dibi::DATETIME:return$value
  1528. instanceof
  1529. DateTime?$value->format("'Y-m-d H:i:s'"):date("'Y-m-d H:i:s'",$value);default:throw
  1530. new
  1531. InvalidArgumentException('Unsupported type.');}}public
  1532. function
  1533. unescape($value,$type){if($type===dibi::BINARY){return
  1534. pg_unescape_bytea($value);}throw
  1535. new
  1536. InvalidArgumentException('Unsupported type.');}public
  1537. function
  1538. applyLimit(&$sql,$limit,$offset){if($limit>=0)$sql.=' LIMIT '.(int)$limit;if($offset>0)$sql.=' OFFSET '.(int)$offset;}public
  1539. function
  1540. getRowCount(){return
  1541. pg_num_rows($this->resultSet);}public
  1542. function
  1543. fetch($assoc){return
  1544. pg_fetch_array($this->resultSet,NULL,$assoc?PGSQL_ASSOC:PGSQL_NUM);}public
  1545. function
  1546. seek($row){return
  1547. pg_result_seek($this->resultSet,$row);}public
  1548. function
  1549. free(){pg_free_result($this->resultSet);$this->resultSet=NULL;}public
  1550. function
  1551. getResultColumns(){$hasTable=version_compare(PHP_VERSION,'5.2.0','>=');$count=pg_num_fields($this->resultSet);$res=array();for($i=0;$i<$count;$i++){$row=array('name'=>pg_field_name($this->resultSet,$i),'table'=>$hasTable?pg_field_table($this->resultSet,$i):NULL,'nativetype'=>pg_field_type($this->resultSet,$i));$row['fullname']=$row['table']?$row['table'].'.'.$row['name']:$row['name'];$res[]=$row;}return$res;}public
  1552. function
  1553. getResultResource(){return$this->resultSet;}public
  1554. function
  1555. getTables(){$version=pg_version($this->connection);if($version['server']<8){throw
  1556. new
  1557. DibiDriverException('Reflection requires PostgreSQL 8.');}$this->query("
  1558. SELECT table_name as name, CAST(table_type = 'VIEW' AS INTEGER) as view
  1559. FROM information_schema.tables
  1560. WHERE table_schema = current_schema()
  1561. ");$res=pg_fetch_all($this->resultSet);$this->free();return$res?$res:array();}public
  1562. function
  1563. getColumns($table){$_table=$this->escape($table,dibi::TEXT);$this->query("
  1564. SELECT indkey
  1565. FROM pg_class
  1566. LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
  1567. WHERE pg_class.relname = $_table
  1568. ");$primary=(int)pg_fetch_object($this->resultSet)->indkey;$this->query("
  1569. SELECT *
  1570. FROM information_schema.columns
  1571. WHERE table_name = $_table AND table_schema = current_schema()
  1572. ORDER BY ordinal_position
  1573. ");$res=array();while($row=$this->fetch(TRUE)){$size=(int)max($row['character_maximum_length'],$row['numeric_precision']);$res[]=array('name'=>$row['column_name'],'table'=>$table,'nativetype'=>strtoupper($row['udt_name']),'size'=>$size?$size:NULL,'nullable'=>$row['is_nullable']==='YES','default'=>$row['column_default'],'autoincrement'=>(int)$row['ordinal_position']===$primary&&substr($row['column_default'],0,7)==='nextval','vendor'=>$row);}$this->free();return$res;}public
  1574. function
  1575. getIndexes($table){$_table=$this->escape($table,dibi::TEXT);$this->query("
  1576. SELECT ordinal_position, column_name
  1577. FROM information_schema.columns
  1578. WHERE table_name = $_table AND table_schema = current_schema()
  1579. ORDER BY ordinal_position
  1580. ");$columns=array();while($row=$this->fetch(TRUE)){$columns[$row['ordinal_position']]=$row['column_name'];}$this->query("
  1581. SELECT pg_class2.relname, indisunique, indisprimary, indkey
  1582. FROM pg_class
  1583. LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid
  1584. INNER JOIN pg_class as pg_class2 on pg_class2.oid = pg_index.indexrelid
  1585. WHERE pg_class.relname = $_table
  1586. ");$res=array();while($row=$this->fetch(TRUE)){$res[$row['relname']]['name']=$row['relname'];$res[$row['relname']]['unique']=$row['indisunique']==='t';$res[$row['relname']]['primary']=$row['indisprimary']==='t';foreach(explode(' ',$row['indkey'])as$index){$res[$row['relname']]['columns'][]=$columns[$index];}}$this->free();return
  1587. array_values($res);}public
  1588. function
  1589. getForeignKeys($table){throw
  1590. new
  1591. NotImplementedException;}}class
  1592. DibiSqliteReflector
  1593. extends
  1594. DibiObject
  1595. implements
  1596. IDibiReflector{private$driver;public
  1597. function
  1598. __construct(IDibiDriver$driver){$this->driver=$driver;}public
  1599. function
  1600. getTables(){$this->driver->query("
  1601. SELECT name, type = 'view' as view FROM sqlite_master WHERE type IN ('table', 'view')
  1602. UNION ALL
  1603. SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view')
  1604. ORDER BY name
  1605. ");$res=array();while($row=$this->driver->fetch(TRUE)){$res[]=$row;}$this->driver->free();return$res;}public
  1606. function
  1607. getColumns($table){$this->driver->query("
  1608. SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '$table'
  1609. UNION ALL
  1610. SELECT sql FROM sqlite_temp_master WHERE type = 'table' AND name = '$table'");$meta=$this->driver->fetch(TRUE);$this->driver->free();$this->driver->query("PRAGMA table_info([$table])");$res=array();while($row=$this->driver->fetch(TRUE)){$column=$row['name'];$pattern="/(\"$column\"|\[$column\]|$column)\s+[^,]+\s+PRIMARY\s+KEY\s+AUTOINCREMENT/Ui";$type=explode('(',$row['type']);$res[]=array('name'=>$column,'table'=>$table,'fullname'=>"$table.$column",'nativetype'=>strtoupper($type[0]),'size'=>isset($type[1])?(int)$type[1]:NULL,'nullable'=>$row['notnull']=='0','default'=>$row['dflt_value'],'autoincrement'=>(bool)preg_match($pattern,$meta['sql']),'vendor'=>$row);}$this->driver->free();return$res;}public
  1611. function
  1612. getIndexes($table){$this->driver->query("PRAGMA index_list([$table])");$res=array();while($row=$this->driver->fetch(TRUE)){$res[$row['name']]['name']=$row['name'];$res[$row['name']]['unique']=(bool)$row['unique'];}$this->driver->free();foreach($res
  1613. as$index=>$values){$this->driver->query("PRAGMA index_info([$index])");while($row=$this->driver->fetch(TRUE)){$res[$index]['columns'][$row['seqno']]=$row['name'];}}$this->driver->free();$columns=$this->driver->getColumns($table);foreach($res
  1614. as$index=>$values){$column=$res[$index]['columns'][0];$primary=FALSE;foreach($columns
  1615. as$info){if($column==$info['name']){$primary=$info['vendor']['pk'];break;}}$res[$index]['primary']=(bool)$primary;}if(!$res){foreach($columns
  1616. as$column){if($column['vendor']['pk']){$res[]=array('name'=>'ROWID','unique'=>TRUE,'primary'=>TRUE,'columns'=>array($column['name']));break;}}}return
  1617. array_values($res);}public
  1618. function
  1619. getForeignKeys($table){if(!($this->driver
  1620. instanceof
  1621. DibiSqlite3Driver)){}$this->driver->query("PRAGMA foreign_key_list([$table])");$res=array();while($row=$this->driver->fetch(TRUE)){$res[$row['id']]['name']=$row['id'];$res[$row['id']]['local'][$row['seq']]=$row['from'];$res[$row['id']]['table']=$row['table'];$res[$row['id']]['foreign'][$row['seq']]=$row['to'];$res[$row['id']]['onDelete']=$row['on_delete'];$res[$row['id']]['onUpdate']=$row['on_update'];if($res[$row['id']]['foreign'][0]==NULL){$res[$row['id']]['foreign']=NULL;}}$this->driver->free();return
  1622. array_values($res);}}class
  1623. DibiSqliteDriver
  1624. extends
  1625. DibiObject
  1626. implements
  1627. IDibiDriver,IDibiResultDriver{private$connection;private$resultSet;private$buffered;private$fmtDate,$fmtDateTime;private$dbcharset,$charset;public
  1628. function
  1629. __construct(){if(!extension_loaded('sqlite')){throw
  1630. new
  1631. DibiDriverException("PHP extension 'sqlite' is not loaded.");}}public
  1632. function
  1633. connect(array&$config){DibiConnection::alias($config,'database','file');$this->fmtDate=isset($config['formatDate'])?$config['formatDate']:'U';$this->fmtDateTime=isset($config['formatDateTime'])?$config['formatDateTime']:'U';$errorMsg='';if(isset($config['resource'])){$this->connection=$config['resource'];}elseif(empty($config['persistent'])){$this->connection=@sqlite_open($config['database'],0666,$errorMsg);}else{$this->connection=@sqlite_popen($config['database'],0666,$errorMsg);}if(!$this->connection){throw
  1634. new
  1635. DibiDriverException($errorMsg);}$this->buffered=empty($config['unbuffered']);$this->dbcharset=empty($config['dbcharset'])?'UTF-8':$config['dbcharset'];$this->charset=empty($config['charset'])?'UTF-8':$config['charset'];if(strcasecmp($this->dbcharset,$this->charset)===0){$this->dbcharset=$this->charset=NULL;}}public
  1636. function
  1637. disconnect(){sqlite_close($this->connection);}public
  1638. function
  1639. query($sql){if($this->dbcharset!==NULL){$sql=iconv($this->charset,$this->dbcharset.'//IGNORE',$sql);}DibiDriverException::tryError();if($this->buffered){$this->resultSet=sqlite_query($this->connection,$sql);}else{$this->resultSet=sqlite_unbuffered_query($this->connection,$sql);}if(DibiDriverException::catchError($msg)){throw
  1640. new
  1641. DibiDriverException($msg,sqlite_last_error($this->connection),$sql);}return
  1642. is_resource($this->resultSet)?clone$this:NULL;}public
  1643. function
  1644. getAffectedRows(){return
  1645. sqlite_changes($this->connection);}public
  1646. function
  1647. getInsertId($sequence){return
  1648. sqlite_last_insert_rowid($this->connection);}public
  1649. function
  1650. begin($savepoint=NULL){$this->query('BEGIN');}public
  1651. function
  1652. commit($savepoint=NULL){$this->query('COMMIT');}public
  1653. function
  1654. rollback($savepoint=NULL){$this->query('ROLLBACK');}public
  1655. function
  1656. getResource(){return$this->connection;}public
  1657. function
  1658. getReflector(){return
  1659. new
  1660. DibiSqliteReflector($this);}public
  1661. function
  1662. escape($value,$type){switch($type){case
  1663. dibi::TEXT:case
  1664. dibi::BINARY:return"'".sqlite_escape_string($value)."'";case
  1665. dibi::IDENTIFIER:return'['.strtr($value,'[]',' ').']';case
  1666. dibi::BOOL:return$value?1:0;case
  1667. dibi::DATE:return$value
  1668. instanceof
  1669. DateTime?$value->format($this->fmtDate):date($this->fmtDate,$value);case
  1670. dibi::DATETIME:return$value
  1671. instanceof
  1672. DateTime?$value->format($this->fmtDateTime):date($this->fmtDateTime,$value);default:throw
  1673. new
  1674. InvalidArgumentException('Unsupported type.');}}public
  1675. function
  1676. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1677. new
  1678. InvalidArgumentException('Unsupported type.');}public
  1679. function
  1680. applyLimit(&$sql,$limit,$offset){if($limit<0&&$offset<1)return;$sql.=' LIMIT '.$limit.($offset>0?' OFFSET '.(int)$offset:'');}public
  1681. function
  1682. getRowCount(){if(!$this->buffered){throw
  1683. new
  1684. DibiDriverException('Row count is not available for unbuffered queries.');}return
  1685. sqlite_num_rows($this->resultSet);}public
  1686. function
  1687. fetch($assoc){$row=sqlite_fetch_array($this->resultSet,$assoc?SQLITE_ASSOC:SQLITE_NUM);$charset=$this->charset===NULL?NULL:$this->charset.'//TRANSLIT';if($row&&($assoc||$charset)){$tmp=array();foreach($row
  1688. as$k=>$v){if($charset!==NULL&&is_string($v)){$v=iconv($this->dbcharset,$charset,$v);}$tmp[str_replace(array('[',']'),'',$k)]=$v;}return$tmp;}return$row;}public
  1689. function
  1690. seek($row){if(!$this->buffered){throw
  1691. new
  1692. DibiDriverException('Cannot seek an unbuffered result set.');}return
  1693. sqlite_seek($this->resultSet,$row);}public
  1694. function
  1695. free(){$this->resultSet=NULL;}public
  1696. function
  1697. getResultColumns(){$count=sqlite_num_fields($this->resultSet);$res=array();for($i=0;$i<$count;$i++){$name=str_replace(array('[',']'),'',sqlite_field_name($this->resultSet,$i));$pair=explode('.',$name);$res[]=array('name'=>isset($pair[1])?$pair[1]:$pair[0],'table'=>isset($pair[1])?$pair[0]:NULL,'fullname'=>$name,'nativetype'=>NULL);}return$res;}public
  1698. function
  1699. getResultResource(){return$this->resultSet;}public
  1700. function
  1701. registerFunction($name,$callback,$numArgs=-1){sqlite_create_function($this->connection,$name,$callback,$numArgs);}public
  1702. function
  1703. registerAggregateFunction($name,$rowCallback,$agrCallback,$numArgs=-1){sqlite_create_aggregate($this->connection,$name,$rowCallback,$agrCallback,$numArgs);}}class
  1704. DibiSqlite3Driver
  1705. extends
  1706. DibiObject
  1707. implements
  1708. IDibiDriver,IDibiResultDriver{private$connection;private$resultSet;private$fmtDate,$fmtDateTime;private$dbcharset,$charset;public
  1709. function
  1710. __construct(){if(!extension_loaded('sqlite3')){throw
  1711. new
  1712. DibiDriverException("PHP extension 'sqlite3' is not loaded.");}}public
  1713. function
  1714. connect(array&$config){DibiConnection::alias($config,'database','file');$this->fmtDate=isset($config['formatDate'])?$config['formatDate']:'U';$this->fmtDateTime=isset($config['formatDateTime'])?$config['formatDateTime']:'U';if(isset($config['resource'])&&$config['resource']instanceof
  1715. SQLite3){$this->connection=$config['resource'];}else
  1716. try{$this->connection=new
  1717. SQLite3($config['database']);}catch(Exception$e){throw
  1718. new
  1719. DibiDriverException($e->getMessage(),$e->getCode());}$this->dbcharset=empty($config['dbcharset'])?'UTF-8':$config['dbcharset'];$this->charset=empty($config['charset'])?'UTF-8':$config['charset'];if(strcasecmp($this->dbcharset,$this->charset)===0){$this->dbcharset=$this->charset=NULL;}$version=SQLite3::version();if($version['versionNumber']>='3006019'){$this->query("PRAGMA foreign_keys = ON");}}public
  1720. function
  1721. disconnect(){$this->connection->close();}public
  1722. function
  1723. query($sql){if($this->dbcharset!==NULL){$sql=iconv($this->charset,$this->dbcharset.'//IGNORE',$sql);}$this->resultSet=@$this->connection->query($sql);if($this->connection->lastErrorCode()){throw
  1724. new
  1725. DibiDriverException($this->connection->lastErrorMsg(),$this->connection->lastErrorCode(),$sql);}return$this->resultSet
  1726. instanceof
  1727. SQLite3Result?clone$this:NULL;}public
  1728. function
  1729. getAffectedRows(){return$this->connection->changes();}public
  1730. function
  1731. getInsertId($sequence){return$this->connection->lastInsertRowID();}public
  1732. function
  1733. begin($savepoint=NULL){$this->query($savepoint?"SAVEPOINT $savepoint":'BEGIN');}public
  1734. function
  1735. commit($savepoint=NULL){$this->query($savepoint?"RELEASE SAVEPOINT $savepoint":'COMMIT');}public
  1736. function
  1737. rollback($savepoint=NULL){$this->query($savepoint?"ROLLBACK TO SAVEPOINT $savepoint":'ROLLBACK');}public
  1738. function
  1739. getResource(){return$this->connection;}public
  1740. function
  1741. getReflector(){return
  1742. new
  1743. DibiSqliteReflector($this);}public
  1744. function
  1745. escape($value,$type){switch($type){case
  1746. dibi::TEXT:return"'".$this->connection->escapeString($value)."'";case
  1747. dibi::BINARY:return"X'".bin2hex((string)$value)."'";case
  1748. dibi::IDENTIFIER:return'['.strtr($value,'[]',' ').']';case
  1749. dibi::BOOL:return$value?1:0;case
  1750. dibi::DATE:return$value
  1751. instanceof
  1752. DateTime?$value->format($this->fmtDate):date($this->fmtDate,$value);case
  1753. dibi::DATETIME:return$value
  1754. instanceof
  1755. DateTime?$value->format($this->fmtDateTime):date($this->fmtDateTime,$value);default:throw
  1756. new
  1757. InvalidArgumentException('Unsupported type.');}}public
  1758. function
  1759. unescape($value,$type){if($type===dibi::BINARY){return$value;}throw
  1760. new
  1761. InvalidArgumentException('Unsupported type.');}public
  1762. function
  1763. applyLimit(&$sql,$limit,$offset){if($limit<0&&$offset<1)return;$sql.=' LIMIT '.$limit.($offset>0?' OFFSET '.(int)$offset:'');}public
  1764. function
  1765. getRowCount(){throw
  1766. new
  1767. NotSupportedException('Row count is not available for unbuffered queries.');}public
  1768. function
  1769. fetch($assoc){$row=$this->resultSet->fetchArray($assoc?SQLITE3_ASSOC:SQLITE3_NUM);$charset=$this->charset===NULL?NULL:$this->charset.'//TRANSLIT';if($row&&($assoc||$charset)){$tmp=array();foreach($row
  1770. as$k=>$v){if($charset!==NULL&&is_string($v)){$v=iconv($this->dbcharset,$charset,$v);}$tmp[str_replace(array('[',']'),'',$k)]=$v;}return$tmp;}return$row;}public
  1771. function
  1772. seek($row){throw
  1773. new
  1774. NotSupportedException('Cannot seek an unbuffered result set.');}public
  1775. function
  1776. free(){$this->resultSet=NULL;}public
  1777. function
  1778. getResultColumns(){$count=$this->resultSet->numColumns();$res=array();static$types=array(SQLITE3_INTEGER=>'int',SQLITE3_FLOAT=>'float',SQLITE3_TEXT=>'text',SQLITE3_BLOB=>'blob',SQLITE3_NULL=>'null');for($i=0;$i<$count;$i++){$res[]=array('name'=>$this->resultSet->columnName($i),'table'=>NULL,'fullname'=>$this->resultSet->columnName($i),'nativetype'=>$types[$this->resultSet->columnType($i)]);}return$res;}public
  1779. function
  1780. getResultResource(){return$this->resultSet;}public
  1781. function
  1782. registerFunction($name,$callback,$numArgs=-1){$this->connection->createFunction($name,$callback,$numArgs);}public
  1783. function
  1784. registerAggregateFunction($name,$rowCallback,$agrCallback,$numArgs=-1){$this->connection->createAggregate($name,$rowCallback,$agrCallback,$numArgs);}}