diff --git a/dibi.compact/dibi.compact.php b/dibi.compact/dibi.compact.php index 39dd71e1..6f72b717 100644 --- a/dibi.compact/dibi.compact.php +++ b/dibi.compact/dibi.compact.php @@ -16,8 +16,8 @@ * @version 0.6 $Revision: 8 $ $Date: 2006-06-07 23:33:46 +0200 (st, 07 VI 2006) $ */define('DIBI','Version 0.6 $Revision: 8 $');if(version_compare(PHP_VERSION,'5.0.3','<'))die('dibi needs PHP 5.0.3 or newer'); if(!defined('DIBI'))die();abstract class DibiDriver{protected$config;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);abstract static public function connect($config);protected function __construct($config){$this->config=$config;}public function getConfig(){return$this->config;}abstract public function query($sql);abstract public function affectedRows();abstract public function insertId();abstract public function begin();abstract public function commit();abstract public function rollback();abstract public function escape($value,$appendQuotes=FALSE);abstract public function quoteName($value);abstract public function getMetaData();} - if(!defined('DIBI'))die();if(!interface_exists('Countable',false)){interface Countable{function count();}}abstract class DibiResult implements IteratorAggregate,Countable{const FIELD_TEXT='s',FIELD_BINARY='b',FIELD_BOOL='l',FIELD_INTEGER='i',FIELD_FLOAT='f',FIELD_DATE='d',FIELD_DATETIME='t',FIELD_UNKNOWN='?',FIELD_COUNTER='c';protected$convert;abstract public function seek($row);abstract public function rowCount();abstract public function getFields();abstract public function getMetaData($field);abstract protected function detectTypes();abstract protected function free();abstract protected function doFetch();final public function fetch(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){foreach($rec as$key=>$value){if(isset($t[$key]))$rec[$key]=$this->convert($value,$t[$key]);}}return$rec;}final function fetchSingle(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){$value=reset($rec);$key=key($rec);return isset($t[$key])?$this->convert($value,$t[$key]):$value;}return reset($rec);}final function fetchAll(){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$assocBy=func_get_args();$arr=array();if(!$assocBy){$value=count($rec)==1?key($rec):NULL;do{$arr[]=$value===NULL?$rec:$rec[$value];}while($rec=$this->fetch());return$arr;}do{foreach($assocBy as$n=>$assoc){$val[$n]=$rec[$assoc];unset($rec[$assoc]);}foreach($assocBy as$n=>$assoc){if($n==0)$tmp=&$arr[$val[$n]];else$tmp=&$tmp[$assoc][$val[$n]];if($tmp===NULL)$tmp=$rec;}}while($rec=$this->fetch());return$arr;}final function fetchPairs($key,$value){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$arr=array();do{$arr[$rec[$key]]=$rec[$value];}while($rec=$this->fetch());return$arr;}public function __destruct(){@$this->free();}public function setType($field,$type=NULL){if($field===TRUE)$this->detectTypes();elseif(is_array($field))$this->convert=$field;else$this->convert[$field]=$type;}public function getType($field){return isset($this->convert[$field])?$this->convert[$field]:NULL;}public function convert($value,$type){if($value===NULL||$value===FALSE)return$value;static$conv=array(self::FIELD_TEXT=>'string',self::FIELD_BINARY=>'string',self::FIELD_BOOL=>'bool',self::FIELD_INTEGER=>'int',self::FIELD_FLOAT=>'float',self::FIELD_COUNTER=>'int',);if(isset($conv[$type])){settype($value,$conv[$type]);return$value;}if($type==self::FIELD_DATE)return strtotime($value);if($type==self::FIELD_DATETIME)return strtotime($value);return$value;}public function getIterator($offset=NULL,$count=NULL){return new DibiResultIterator($this,$offset,$count);}public function count(){return$this->rowCount();}}class DibiResultIterator implements Iterator{private$result,$offset,$count,$record,$row;public function __construct(DibiResult$result,$offset=NULL,$count=NULL){$this->result=$result;$this->offset=(int)$offset;$this->count=$count===NULL?2147483647:(int)$count;}public function rewind(){$this->row=0;@$this->result->seek($this->offset);$this->record=$this->result->fetch();}public function key(){return$this->row;}public function current(){return$this->record;}public function next(){$this->record=$this->result->fetch();$this->row++;}public function valid(){return is_array($this->record)&&($this->row<$this->count);}} - if(!defined('DIBI'))die();class DibiParser{private$modifier,$hasError,$driver,$ifLevel,$ifLevelStart;public function parse($driver,$args){$this->driver=$driver;$this->hasError=FALSE;$command=null;$mod=&$this->modifier;$mod=FALSE;$this->ifLevel=$this->ifLevelStart=0;$comment=&$this->comment;$comment=FALSE;$sql=array();foreach($args as$arg){if($mod=='if'){$mod=FALSE;$this->ifLevel++;if(!$comment&&!$arg){$sql[]='/*';$this->ifLevelStart=$this->ifLevel;$comment=TRUE;}continue;}if(is_string($arg)&&!$mod){$sql[]=$this->formatValue($arg,'p');continue;}if(is_array($arg)&&!$mod&&is_string(key($arg))){if(!$command)$command=strtoupper(substr(ltrim($args[0]),0,6));$mod=($command=='INSERT'||$command=='REPLAC')?'V':'S';}$sql[]=$comment?'...':$this->formatValue($arg,$mod);$mod=FALSE;}if($comment)$sql[]='*/';$sql=implode(' ',$sql);if($this->hasError)return new DibiException('Errors during generating SQL',array('sql'=>$sql));return$sql;}private function formatValue($value,$modifier){if(is_array($value)){$vx=$kx=array();switch($modifier){case'S':foreach($value as$k=>$v){list($k,$mod)=explode('%',$k.'%',3);$vx[]=$this->driver->quoteName($k).'='.$this->formatValue($v,$mod);}return implode(', ',$vx);case'V':foreach($value as$k=>$v){list($k,$mod)=explode('%',$k.'%',3);$kx[]=$this->driver->quoteName($k);$vx[]=$this->formatValue($v,$mod);}return'('.implode(', ',$kx).') VALUES ('.implode(', ',$vx).')';default:foreach($value as$v)$vx[]=$this->formatValue($v,$modifier);return implode(', ',$vx);}}if($modifier){if($value instanceof IDibiVariable)return$value->toSql($this->driver,$modifier);if(!is_scalar($value)&&!is_null($value)){$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}switch($modifier){case"s":return$this->driver->escape($value,TRUE);case'b':return$value?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];case'i':case'u':case'd':return(string)(int)$value;case'f':return(string)(float)$value;case'D':return date($this->driver->formats['date'],is_string($value)?strtotime($value):$value);case'T':return date($this->driver->formats['datetime'],is_string($value)?strtotime($value):$value);case'n':return$this->driver->quoteName($value);case'p':$value=(string)$value;$toSkip=strcspn($value,'`[\'"%');if($toSkip==strlen($value))return$value;return substr($value,0,$toSkip).preg_replace_callback('/ + if(!defined('DIBI'))die();if(!interface_exists('Countable',false)){interface Countable{function count();}}abstract class DibiResult implements IteratorAggregate,Countable{protected$convert;abstract public function seek($row);abstract public function rowCount();abstract public function getFields();abstract public function getMetaData($field);abstract protected function detectTypes();abstract protected function free();abstract protected function doFetch();final public function fetch(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){foreach($rec as$key=>$value){if(isset($t[$key]))$rec[$key]=$this->convert($value,$t[$key]);}}return$rec;}final function fetchSingle(){$rec=$this->doFetch();if(!is_array($rec))return FALSE;if($t=$this->convert){$value=reset($rec);$key=key($rec);return isset($t[$key])?$this->convert($value,$t[$key]):$value;}return reset($rec);}final function fetchAll(){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$assocBy=func_get_args();$arr=array();if(!$assocBy){$value=count($rec)==1?key($rec):NULL;do{$arr[]=$value===NULL?$rec:$rec[$value];}while($rec=$this->fetch());return$arr;}do{foreach($assocBy as$n=>$assoc){$val[$n]=$rec[$assoc];unset($rec[$assoc]);}foreach($assocBy as$n=>$assoc){if($n==0)$tmp=&$arr[$val[$n]];else$tmp=&$tmp[$assoc][$val[$n]];if($tmp===NULL)$tmp=$rec;}}while($rec=$this->fetch());return$arr;}final function fetchPairs($key,$value){@$this->seek(0);$rec=$this->fetch();if(!$rec)return array();$arr=array();do{$arr[$rec[$key]]=$rec[$value];}while($rec=$this->fetch());return$arr;}public function __destruct(){@$this->free();}public function setType($field,$type=NULL){if($field===TRUE)$this->detectTypes();elseif(is_array($field))$this->convert=$field;else$this->convert[$field]=$type;}public function getType($field){return isset($this->convert[$field])?$this->convert[$field]:NULL;}public function convert($value,$type){if($value===NULL||$value===FALSE)return$value;static$conv=array(dibi::FIELD_TEXT=>'string',dibi::FIELD_BINARY=>'string',dibi::FIELD_BOOL=>'bool',dibi::FIELD_INTEGER=>'int',dibi::FIELD_FLOAT=>'float',dibi::FIELD_COUNTER=>'int',);if(isset($conv[$type])){settype($value,$conv[$type]);return$value;}if($type==dibi::FIELD_DATE)return strtotime($value);if($type==dibi::FIELD_DATETIME)return strtotime($value);return$value;}public function getIterator($offset=NULL,$count=NULL){return new DibiResultIterator($this,$offset,$count);}public function count(){return$this->rowCount();}}class DibiResultIterator implements Iterator{private$result,$offset,$count,$record,$row;public function __construct(DibiResult$result,$offset=NULL,$count=NULL){$this->result=$result;$this->offset=(int)$offset;$this->count=$count===NULL?2147483647:(int)$count;}public function rewind(){$this->row=0;@$this->result->seek($this->offset);$this->record=$this->result->fetch();}public function key(){return$this->row;}public function current(){return$this->record;}public function next(){$this->record=$this->result->fetch();$this->row++;}public function valid(){return is_array($this->record)&&($this->row<$this->count);}} + if(!defined('DIBI'))die();class DibiParser{private$modifier,$hasError,$driver,$ifLevel,$ifLevelStart;public function parse($driver,$args){$this->driver=$driver;$this->hasError=FALSE;$command=null;$mod=&$this->modifier;$mod=FALSE;$this->ifLevel=$this->ifLevelStart=0;$comment=&$this->comment;$comment=FALSE;$sql=array();foreach($args as$arg){if('if'==$mod){$mod=FALSE;$this->ifLevel++;if(!$comment&&!$arg){$sql[]='/*';$this->ifLevelStart=$this->ifLevel;$comment=TRUE;}continue;}if(is_string($arg)&&(!$mod||'p'==$mod)){$mod=FALSE;$sql[]=$this->formatValue($arg,'p');continue;}if(!$mod&&is_array($arg)&&is_string(key($arg))){if(!$command)$command=strtoupper(substr(ltrim($args[0]),0,6));$mod=('INSERT'==$command||'REPLAC'==$command)?'V':'S';}$sql[]=$comment?'...':$this->formatValue($arg,$mod);$mod=FALSE;}if($comment)$sql[]='*/';$sql=implode(' ',$sql);if($this->hasError)return new DibiException('Errors during generating SQL',array('sql'=>$sql));return$sql;}private function formatValue($value,$modifier){if(is_array($value)){$vx=$kx=array();switch($modifier){case'S':foreach($value as$k=>$v){$pair=explode('%',$k,2);if(isset($pair[1])){$mod=$pair[1];if(isset($mod[0])&&'?'==$mod[0]){if(NULL===$v)continue;$mod=substr($mod,1);}}else$mod=FALSE;$vx[]=$this->driver->quoteName($pair[0]).'='.$this->formatValue($v,$mod);}return implode(', ',$vx);case'V':foreach($value as$k=>$v){$pair=explode('%',$k,2);if(isset($pair[1])){$mod=$pair[1];if(isset($mod[0])&&'?'==$mod[0]){if($v===NULL)continue;$mod=substr($mod,1);}}else$mod=FALSE;$kx[]=$this->driver->quoteName($pair[0]);$vx[]=$this->formatValue($v,$mod);}return'('.implode(', ',$kx).') VALUES ('.implode(', ',$vx).')';default:foreach($value as$v)$vx[]=$this->formatValue($v,$modifier);return implode(', ',$vx);}}if($modifier){if($value instanceof IDibiVariable)return$value->toSql($this->driver,$modifier);if(!is_scalar($value)&&!is_null($value)){$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}switch($modifier){case"s":return$this->driver->escape($value,TRUE);case'b':return$value?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];case'i':case'u':case'd':return(string)(int)$value;case'f':return(string)(float)$value;case'D':return date($this->driver->formats['date'],is_string($value)?strtotime($value):$value);case't':case'T':return date($this->driver->formats['datetime'],is_string($value)?strtotime($value):$value);case'n':return$this->driver->quoteName($value);case'p':$value=(string)$value;$toSkip=strcspn($value,'`[\'"%');if(strlen($value)==$toSkip)return$value;return substr($value,0,$toSkip).preg_replace_callback('/ (?=`|\[|\'|"|%) ## speed-up (?: `(.+?)`| ## 1) `identifier` @@ -27,9 +27,9 @@ %(else|end)| ## 7) conditional SQL %([a-zA-Z]{1,2})$| ## 8) right modifier (\'|") ## 9) lone-quote - )/xs',array($this,'callback'),substr($value,$toSkip));case'S':case'V':$this->hasError=TRUE;return"**Unexpected ".gettype($value)."**";case'if':$this->hasError=TRUE;return"**The %$modifier is not allowed here**";default:$this->hasError=TRUE;return"**Unknown modifier %$modifier**";}}if(is_string($value))return$this->driver->escape($value,TRUE);if(is_int($value)||is_float($value))return(string)$value;if(is_bool($value))return$value?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];if(is_null($value))return$this->driver->formats['NULL'];if($value instanceof IDibiVariable)return$value->toSql($this->driver);$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}private function callback($matches){if($matches[1])return$this->driver->quoteName($matches[1]);if($matches[2])return$this->driver->quoteName($matches[2]);if($matches[3])return$this->comment?'...':$this->driver->escape(strtr($matches[4],array("''"=>"'")),TRUE);if($matches[5])return$this->comment?'...':$this->driver->escape(strtr($matches[6],array('""'=>'"')),TRUE);if($matches[7]){if(!$this->ifLevel){$this->hasError=TRUE;return"**Unexpected condition $matches[8]**";}if($matches[7]=='end'){$this->ifLevel--;if($this->ifLevelStart==$this->ifLevel+1){$this->ifLevelStart=0;$this->comment=FALSE;return'*/';}return'';}if($this->ifLevelStart==$this->ifLevel){$this->ifLevelStart=0;$this->comment=FALSE;return'*/';}elseif(!$this->comment){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return'/*';}}if($matches[8]){$this->modifier=$matches[8];return'';}if($matches[9]){$this->hasError=TRUE;return'**Alone quote**';}die('this should be never executed');}} - if(!defined('DIBI'))die();class DibiException extends Exception{private$info;public function __construct($message,$info=NULL){$this->info=$info;if(isset($info['message']))$message="$message: $info[message]";parent::__construct($message);}public function getSql(){return@$this->info['sql'];}}function is_error($var){return($var===FALSE)||($var instanceof Exception);} if(function_exists('date_default_timezone_set'))date_default_timezone_set('Europe/Prague');interface IDibiVariable{public function toSQL($driver,$modifier=NULL);}class dibi{static private$registry=array();static private$conn;static private$parser;static public$sql;static public$error;static public$logfile;static public$debug=false;static private$query=array();static public function connect($config,$name='def'){if(!self::$parser)self::$parser=new DibiParser();if(isset(self::$registry[$name]))return new DibiException("Connection named '$name' already exists.");if(empty($config['driver']))return new DibiException('Driver is not specified.');$className="Dibi$config[driver]Driver"; if(!class_exists($className))return new DibiException("Unable to create instance of dibi driver class '$className'.");$conn=call_user_func(array($className,'connect'),$config);if(self::$logfile!=NULL){if(is_error($conn))$msg="Can't connect to DB '$config[driver]': ".$conn->getMessage();else$msg="Successfully connected to DB '$config[driver]'";$f=fopen(self::$logfile,'a');fwrite($f,"$msg\r\n\r\n");fclose($f);}if(is_error($conn)){if(self::$debug)echo'[dibi error] '.$conn->getMessage();return$conn;}self::$conn=self::$registry[$name]=$conn;return TRUE;}static public function isConnected(){return(bool)self::$conn;}static public function getConnection($name=NULL){return$name===NULL?self::$conn:@self::$registry[$name];}static public function activate($name){if(!isset(self::$registry[$name]))return FALSE;self::$conn=self::$registry[$name];return TRUE;}static public function query(){if(!self::$conn)return new DibiException('Dibi is not connected to DB');$args=func_num_args()?func_get_args():self::$query;self::$query=array();self::$sql=self::$parser->parse(self::$conn,$args);if(is_error(self::$sql))return self::$sql;$timer=-microtime(true);$res=self::$conn->query(self::$sql);$timer+=microtime(true);if(is_error($res)){if(self::$debug){echo'[dibi error] '.$res->getMessage();self::dump(self::$sql);}self::$error=$res;}else{self::$error=FALSE;}if(self::$logfile!=NULL){if(is_error($res))$msg=$res->getMessage();elseif($res instanceof DibiResult)$msg='object('.get_class($res).') rows: '.$res->rowCount();else$msg='OK';$f=fopen(self::$logfile,'a');fwrite($f,self::$sql.";\r\n-- Result: $msg"."\r\n-- Takes: ".sprintf('%0.3f',$timer*1000).' ms'."\r\n\r\n");fclose($f);}return$res;}static public function test(){if(!self::$conn)return FALSE;$args=func_num_args()?func_get_args():self::$query;self::$query=array();$sql=self::$parser->parse(self::$conn,$args);if(is_error($sql)){self::dump($sql->getSql());return$sql->getSql();}else{self::dump($sql);return$sql;}}static public function insertId(){if(!self::$conn)return FALSE;return self::$conn->insertId();}static public function affectedRows(){if(!self::$conn)return FALSE;return self::$conn->affectedRows();}static private function dumpHighlight($matches){if(!empty($matches[1]))return''.$matches[1].'';if(!empty($matches[2]))return''.$matches[2].'';if(!empty($matches[3]))return''.$matches[3].'';if(!empty($matches[4]))return''.$matches[4].'';}static public function dump($sql){static$keywords2='ALL|DISTINCT|AS|ON|INTO|AND|OR|AS';static$keywords1='SELECT|UPDATE|INSERT|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN';$sql=preg_replace("#\\b(?:$keywords1)\\b#","\n\$0",$sql);$sql=trim($sql);$sql=wordwrap($sql,100);$sql=htmlSpecialChars($sql);$sql=strtr($sql,array("\n"=>'
'));$sql=preg_replace_callback("#(/\*.+?\*/)|(\*\*.+?\*\*)|\\b($keywords1)\\b|\\b($keywords2)\\b#",array('dibi','dumpHighlight'),$sql);echo'
',$sql,'
';}static public function dumpResult(DibiResult$res){echo'';echo'';$fieldCount=$res->fieldCount();for($i=0;$i<$fieldCount;$i++){$info=$res->fieldMeta($i);echo'';}echo'';foreach($res as$row=>$fields){echo'';foreach($fields as$field){if(is_object($field))$field=$field->__toString();echo'';}echo'';}echo'
Row'.htmlSpecialChars($info['name']).'
',$row,'',htmlSpecialChars($field),'
';}} - if(!defined('DIBI'))die();class DibiMySqlDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysql'))return new DibiException("PHP extension 'mysql' is not loaded");if(empty($config['host']))$config['host']='localhost';if(@$config['protocol']==='unix')$host=':'.$config['host'];else$host=$config['host'].(empty($config['port'])?'':$config['port']);if(function_exists('ini_set'))$save=ini_set('track_errors',TRUE);$php_errormsg='';if(empty($config['persistent']))$conn=@mysql_connect($host,@$config['username'],@$config['password']);else$conn=@mysql_pconnect($host,@$config['username'],@$config['password']);if(function_exists('ini_set'))ini_set('track_errors',$save);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>mysql_error()?mysql_error():$php_errormsg,'code'=>mysql_errno(),));if(!empty($config['charset'])){$succ=@mysql_query('SET CHARACTER SET '.$config['charset'],$conn);}if(!empty($config['database'])){if(!@mysql_select_db($config['database'],$conn))return new DibiException("Connecting error",array('message'=>mysql_error($conn),'code'=>mysql_errno($conn),));}$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$res=@mysql_query($sql,$this->conn);if(is_resource($res))return new DibiMySqlResult($res);if($res===FALSE)return new DibiException("Query error",array('message'=>mysql_error($this->conn),'code'=>mysql_errno($this->conn),'sql'=>$sql,));$this->affectedRows=mysql_affected_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=mysql_insert_id($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return mysql_query('BEGIN',$this->conn);}public function commit(){return mysql_query('COMMIT',$this->conn);}public function rollback(){return mysql_query('ROLLBACK',$this->conn);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysql_real_escape_string($value,$this->conn)."'":mysql_real_escape_string($value,$this->conn);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqlResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysql_num_rows($this->resource);}protected function doFetch(){return mysql_fetch_assoc($this->resource);}public function seek($row){return mysql_data_seek($this->resource,$row);}protected function free(){mysql_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array('ENUM'=>self::FIELD_TEXT,'SET'=>self::FIELD_TEXT,'CHAR'=>self::FIELD_TEXT,'VARCHAR'=>self::FIELD_TEXT,'STRING'=>self::FIELD_TEXT,'TINYTEXT'=>self::FIELD_TEXT,'TEXT'=>self::FIELD_TEXT,'MEDIUMTEXT'=>self::FIELD_TEXT,'LONGTEXT'=>self::FIELD_TEXT,'BINARY'=>self::FIELD_BINARY,'VARBINARY'=>self::FIELD_BINARY,'TINYBLOB'=>self::FIELD_BINARY,'BLOB'=>self::FIELD_BINARY,'MEDIUMBLOB'=>self::FIELD_BINARY,'LONGBLOB'=>self::FIELD_BINARY,'DATE'=>self::FIELD_DATE,'DATETIME'=>self::FIELD_DATETIME,'TIMESTAMP'=>self::FIELD_DATETIME,'TIME'=>self::FIELD_DATETIME,'BIT'=>self::FIELD_BOOL,'YEAR'=>self::FIELD_INTEGER,'TINYINT'=>self::FIELD_INTEGER,'SMALLINT'=>self::FIELD_INTEGER,'MEDIUMINT'=>self::FIELD_INTEGER,'INT'=>self::FIELD_INTEGER,'INTEGER'=>self::FIELD_INTEGER,'BIGINT'=>self::FIELD_INTEGER,'FLOAT'=>self::FIELD_FLOAT,'DOUBLE'=>self::FIELD_FLOAT,'REAL'=>self::FIELD_FLOAT,'DECIMAL'=>self::FIELD_FLOAT,'NUMERIC'=>self::FIELD_FLOAT,);$count=mysql_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info['native']=$native=strtoupper(mysql_field_type($this->resource,$index));$info['flags']=explode(' ',mysql_field_flags($this->resource,$index));$info['length']=mysql_field_len($this->resource,$index);$info['table']=mysql_field_table($this->resource,$index);if(in_array('auto_increment',$info['flags']))$info['type']=self::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN;}$name=mysql_field_name($this->resource,$index);$this->meta[$name]=$info;$this->convert[$name]=$info['type'];}}} - if(!defined('DIBI'))die();class DibiMySqliDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysqli'))return new DibiException("PHP extension 'mysqli' is not loaded");if(empty($config['host']))$config['host']='localhost';$conn=@mysqli_connect($config['host'],@$config['username'],@$config['password'],@$config['database'],@$config['port']);if(!$conn)return new DibiException("Connecting error",array('message'=>mysqli_connect_error(),'code'=>mysqli_connect_errno(),));if(!empty($config['charset']))mysqli_query($conn,'SET CHARACTER SET '.$config['charset']);$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$res=@mysqli_query($this->conn,$sql);if(is_object($res))return new DibiMySqliResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));$this->affectedRows=mysqli_affected_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=mysqli_insert_id($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return mysqli_autocommit($this->conn,FALSE);}public function commit(){$ok=mysqli_commit($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=mysqli_rollback($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>mysqli_error($this->conn),'code'=>mysqli_errno($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysqli_real_escape_string($this->conn,$value)."'":mysqli_real_escape_string($this->conn,$value);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqliResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysqli_num_rows($this->resource);}protected function doFetch(){return mysqli_fetch_assoc($this->resource);}public function seek($row){return mysqli_data_seek($this->resource,$row);}protected function free(){mysqli_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array(MYSQLI_TYPE_FLOAT=>self::FIELD_FLOAT,MYSQLI_TYPE_DOUBLE=>self::FIELD_FLOAT,MYSQLI_TYPE_DECIMAL=>self::FIELD_FLOAT,MYSQLI_TYPE_TINY=>self::FIELD_INTEGER,MYSQLI_TYPE_SHORT=>self::FIELD_INTEGER,MYSQLI_TYPE_LONG=>self::FIELD_INTEGER,MYSQLI_TYPE_LONGLONG=>self::FIELD_INTEGER,MYSQLI_TYPE_INT24=>self::FIELD_INTEGER,MYSQLI_TYPE_YEAR=>self::FIELD_INTEGER,MYSQLI_TYPE_GEOMETRY=>self::FIELD_INTEGER,MYSQLI_TYPE_DATE=>self::FIELD_DATE,MYSQLI_TYPE_NEWDATE=>self::FIELD_DATE,MYSQLI_TYPE_TIMESTAMP=>self::FIELD_DATETIME,MYSQLI_TYPE_TIME=>self::FIELD_DATETIME,MYSQLI_TYPE_DATETIME=>self::FIELD_DATETIME,MYSQLI_TYPE_ENUM=>self::FIELD_TEXT,MYSQLI_TYPE_SET=>self::FIELD_TEXT,MYSQLI_TYPE_STRING=>self::FIELD_TEXT,MYSQLI_TYPE_VAR_STRING=>self::FIELD_TEXT,MYSQLI_TYPE_TINY_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_MEDIUM_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_LONG_BLOB=>self::FIELD_BINARY,MYSQLI_TYPE_BLOB=>self::FIELD_BINARY,);$count=mysqli_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info=(array)mysqli_fetch_field_direct($this->resource,$index);$native=$info['native']=$info['type'];if($info['flags']&MYSQLI_AUTO_INCREMENT_FLAG)$info['type']=self::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN;}$this->meta[$info['name']]=$info;$this->convert[$info['name']]=$info['type'];}}} - if(!defined('DIBI'))die();class DibiOdbcDriver extends DibiDriver{private$conn,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"-1",'FALSE'=>"0",'date'=>"#m/d/Y#",'datetime'=>"#m/d/Y H:i:s#",);public static function connect($config){if(!extension_loaded('odbc'))return new DibiException("PHP extension 'odbc' is not loaded");if(@$config['persistent'])$conn=@odbc_pconnect($config['database'],$config['username'],$config['password']);else$conn=@odbc_connect($config['database'],$config['username'],$config['password']);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>odbc_errormsg(),'code'=>odbc_error(),));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->affectedRows=FALSE;$res=@odbc_exec($this->conn,$sql);if(is_resource($res))return new DibiOdbcResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));$this->affectedRows=odbc_num_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return FALSE;}public function begin(){return odbc_autocommit($this->conn,FALSE);}public function commit(){$ok=odbc_commit($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=odbc_rollback($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>odbc_errormsg($this->conn),'code'=>odbc_error($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){$value=str_replace("'","''",$value);return$appendQuotes?"'".$value."'":$value;}public function quoteName($value){return'['.strtr($value,array('.'=>'].[')).']';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiOdbcResult extends DibiResult{private$resource,$meta,$row=0;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return odbc_num_rows($this->resource);}protected function doFetch(){return odbc_fetch_array($this->resource,$this->row++);}public function seek($row){$this->row=$row;}protected function free(){odbc_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){if($this->meta!==NULL)return$this->meta;static$types=array('CHAR'=>self::FIELD_TEXT,'COUNTER'=>self::FIELD_COUNTER,'VARCHAR'=>self::FIELD_TEXT,'LONGCHAR'=>self::FIELD_TEXT,'INTEGER'=>self::FIELD_INTEGER,'DATETIME'=>self::FIELD_DATETIME,'CURRENCY'=>self::FIELD_FLOAT,'BIT'=>self::FIELD_BOOL,'LONGBINARY'=>self::FIELD_BINARY,'SMALLINT'=>self::FIELD_INTEGER,'BYTE'=>self::FIELD_INTEGER,'BIGINT'=>self::FIELD_INTEGER,'INT'=>self::FIELD_INTEGER,'TINYINT'=>self::FIELD_INTEGER,'REAL'=>self::FIELD_FLOAT,'DOUBLE'=>self::FIELD_FLOAT,'DECIMAL'=>self::FIELD_FLOAT,'NUMERIC'=>self::FIELD_FLOAT,'MONEY'=>self::FIELD_FLOAT,'SMALLMONEY'=>self::FIELD_FLOAT,'FLOAT'=>self::FIELD_FLOAT,'YESNO'=>self::FIELD_BOOL,);$count=odbc_num_fields($this->resource);$this->meta=$this->convert=array();for($index=1;$index<=$count;$index++){$native=strtoupper(odbc_field_type($this->resource,$index));$name=odbc_field_name($this->resource,$index);$this->meta[$name]=array('type'=>isset($types[$native])?$types[$native]:self::FIELD_UNKNOWN,'native'=>$native,'length'=>odbc_field_len($this->resource,$index),'scale'=>odbc_field_scale($this->resource,$index),'precision'=>odbc_field_precision($this->resource,$index),);$this->convert[$name]=$this->meta[$name]['type'];}}} - if(!defined('DIBI'))die();class DibiSqliteDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('sqlite'))return new DibiException("PHP extension 'sqlite' is not loaded");if(empty($config['database']))return new DibiException("Database must be specified");$errorMsg='';if(empty($config['persistent']))$conn=@sqlite_open($config['database'],@$config['mode'],$errorMsg);else$conn=@sqlite_popen($config['database'],@$config['mode'],$errorMsg);if(!$conn)return new DibiException("Connecting error",array('message'=>$errorMsg,));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$errorMsg='';$res=@sqlite_query($this->conn,$sql,SQLITE_ASSOC,$errorMsg);if($res===FALSE)return new DibiException("Query error",array('message'=>$errorMsg,'sql'=>$sql,));if(is_resource($res))return new DibiSqliteResult($res);$this->affectedRows=sqlite_changes($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=sqlite_last_insert_rowid($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return sqlite_query($this->conn,'BEGIN');}public function commit(){return sqlite_query($this->conn,'COMMIT');}public function rollback(){return sqlite_query($this->conn,'ROLLBACK');}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".sqlite_escape_string($value)."'":sqlite_escape_string($value);}public function quoteName($value){return$value;}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiSqliteResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return sqlite_num_rows($this->resource);}protected function doFetch(){return sqlite_fetch_array($this->resource,SQLITE_ASSOC);}public function seek($row){return sqlite_seek($this->resource,$row);}protected function free(){}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){$count=sqlite_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$name=sqlite_field_name($this->resource,$index);$this->meta[$name]=array('type'=>self::FIELD_UNKNOWN);$this->convert[$name]=self::FIELD_UNKNOWN;}}}?> \ No newline at end of file + )/xs',array($this,'callback'),substr($value,$toSkip));case'S':case'V':$this->hasError=TRUE;return"**Unexpected ".gettype($value)."**";case'if':$this->hasError=TRUE;return"**The %$modifier is not allowed here**";default:$this->hasError=TRUE;return"**Unknown modifier %$modifier**";}}if(is_string($value))return$this->driver->escape($value,TRUE);if(is_int($value)||is_float($value))return(string)$value;if(is_bool($value))return$value?$this->driver->formats['TRUE']:$this->driver->formats['FALSE'];if(is_null($value))return$this->driver->formats['NULL'];if($value instanceof IDibiVariable)return$value->toSql($this->driver);$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}private function callback($matches){if($matches[1])return$this->driver->quoteName($matches[1]);if($matches[2])return$this->driver->quoteName($matches[2]);if($matches[3])return$this->comment?'...':$this->driver->escape(strtr($matches[4],array("''"=>"'")),TRUE);if($matches[5])return$this->comment?'...':$this->driver->escape(strtr($matches[6],array('""'=>'"')),TRUE);if($matches[7]){if(!$this->ifLevel){$this->hasError=TRUE;return"**Unexpected condition $matches[8]**";}if('end'==$matches[7]){$this->ifLevel--;if($this->ifLevelStart==$this->ifLevel+1){$this->ifLevelStart=0;$this->comment=FALSE;return'*/';}return'';}if($this->ifLevelStart==$this->ifLevel){$this->ifLevelStart=0;$this->comment=FALSE;return'*/';}elseif(!$this->comment){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return'/*';}}if($matches[8]){$this->modifier=$matches[8];return'';}if($matches[9]){$this->hasError=TRUE;return'**Alone quote**';}die('this should be never executed');}} + if(!defined('DIBI'))die();class DibiException extends Exception{private$info;public function __construct($message,$info=NULL){$this->info=$info;if(isset($info['message']))$message="$message: $info[message]";parent::__construct($message);}public function getSql(){return@$this->info['sql'];}}function is_error($var){return($var===FALSE)||($var instanceof Exception);} if(function_exists('date_default_timezone_set'))date_default_timezone_set('Europe/Prague');interface IDibiVariable{public function toSQL($driver,$modifier=NULL);}class dibi{const FIELD_TEXT='s',FIELD_BINARY='b',FIELD_BOOL='l',FIELD_INTEGER='i',FIELD_FLOAT='f',FIELD_DATE='d',FIELD_DATETIME='t',FIELD_UNKNOWN='?',FIELD_COUNTER='c';static private$registry=array();static private$conn;static private$parser;static public$sql;static public$error;static public$logfile;static public$debug=false;static private$query=array();static public function connect($config,$name='def'){if(!self::$parser)self::$parser=new DibiParser();if(isset(self::$registry[$name]))return new DibiException("Connection named '$name' already exists.");if(empty($config['driver']))return new DibiException('Driver is not specified.');$className="Dibi$config[driver]Driver"; if(!class_exists($className))return new DibiException("Unable to create instance of dibi driver class '$className'.");$conn=call_user_func(array($className,'connect'),$config);if(self::$logfile!=NULL){if(is_error($conn))$msg="Can't connect to DB '$config[driver]': ".$conn->getMessage();else$msg="Successfully connected to DB '$config[driver]'";$f=fopen(self::$logfile,'a');fwrite($f,"$msg\r\n\r\n");fclose($f);}if(is_error($conn)){if(self::$debug)echo'[dibi error] '.$conn->getMessage();return$conn;}self::$conn=self::$registry[$name]=$conn;return TRUE;}static public function isConnected(){return(bool)self::$conn;}static public function getConnection($name=NULL){return NULL===$name?self::$conn:@self::$registry[$name];}static public function activate($name){if(!isset(self::$registry[$name]))return FALSE;self::$conn=self::$registry[$name];return TRUE;}static public function query(){if(!self::$conn)return new DibiException('Dibi is not connected to DB');$args=func_num_args()?func_get_args():self::$query;self::$query=array();self::$sql=self::$parser->parse(self::$conn,$args);if(is_error(self::$sql))return self::$sql;$timer=-microtime(true);$res=self::$conn->query(self::$sql);$timer+=microtime(true);if(is_error($res)){if(self::$debug){echo'[dibi error] '.$res->getMessage();self::dump(self::$sql);}self::$error=$res;}else{self::$error=FALSE;}if(self::$logfile!=NULL){if(is_error($res))$msg=$res->getMessage();elseif($res instanceof DibiResult)$msg='object('.get_class($res).') rows: '.$res->rowCount();else$msg='OK';$f=fopen(self::$logfile,'a');fwrite($f,self::$sql.";\r\n-- Result: $msg"."\r\n-- Takes: ".sprintf('%0.3f',$timer*1000).' ms'."\r\n\r\n");fclose($f);}return$res;}static public function test(){if(!self::$conn)return FALSE;$args=func_num_args()?func_get_args():self::$query;self::$query=array();$sql=self::$parser->parse(self::$conn,$args);if(is_error($sql)){self::dump($sql->getSql());return$sql->getSql();}else{self::dump($sql);return$sql;}}static public function insertId(){if(!self::$conn)return FALSE;return self::$conn->insertId();}static public function affectedRows(){if(!self::$conn)return FALSE;return self::$conn->affectedRows();}static private function dumpHighlight($matches){if(!empty($matches[1]))return''.$matches[1].'';if(!empty($matches[2]))return''.$matches[2].'';if(!empty($matches[3]))return''.$matches[3].'';if(!empty($matches[4]))return''.$matches[4].'';}static public function dump($sql){static$keywords2='ALL|DISTINCT|AS|ON|INTO|AND|OR|AS';static$keywords1='SELECT|UPDATE|INSERT|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN';$sql=preg_replace("#\\b(?:$keywords1)\\b#","\n\$0",$sql);$sql=trim($sql);$sql=wordwrap($sql,100);$sql=htmlSpecialChars($sql);$sql=strtr($sql,array("\n"=>'
'));$sql=preg_replace_callback("#(/\*.+?\*/)|(\*\*.+?\*\*)|\\b($keywords1)\\b|\\b($keywords2)\\b#",array('dibi','dumpHighlight'),$sql);echo'
',$sql,'
';}static public function dumpResult(DibiResult$res){echo'';echo'';$fieldCount=$res->fieldCount();for($i=0;$i<$fieldCount;$i++){$info=$res->fieldMeta($i);echo'';}echo'';foreach($res as$row=>$fields){echo'';foreach($fields as$field){if(is_object($field))$field=$field->__toString();echo'';}echo'';}echo'
Row'.htmlSpecialChars($info['name']).'
',$row,'',htmlSpecialChars($field),'
';}} + if(!defined('DIBI'))die();class DibiMySqlDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysql'))return new DibiException("PHP extension 'mysql' is not loaded");if(empty($config['host']))$config['host']='localhost';if(@$config['protocol']==='unix')$host=':'.$config['host'];else$host=$config['host'].(empty($config['port'])?'':$config['port']);if(function_exists('ini_set'))$save=ini_set('track_errors',TRUE);$php_errormsg='';if(empty($config['persistent']))$conn=@mysql_connect($host,@$config['username'],@$config['password']);else$conn=@mysql_pconnect($host,@$config['username'],@$config['password']);if(function_exists('ini_set'))ini_set('track_errors',$save);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>mysql_error()?mysql_error():$php_errormsg,'code'=>mysql_errno(),));if(!empty($config['charset'])){$succ=@mysql_query('SET CHARACTER SET '.$config['charset'],$conn);}if(!empty($config['database'])){if(!@mysql_select_db($config['database'],$conn))return new DibiException("Connecting error",array('message'=>mysql_error($conn),'code'=>mysql_errno($conn),));}$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$res=@mysql_query($sql,$this->conn);if(is_resource($res))return new DibiMySqlResult($res);if($res===FALSE)return new DibiException("Query error",array('message'=>mysql_error($this->conn),'code'=>mysql_errno($this->conn),'sql'=>$sql,));$this->affectedRows=mysql_affected_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=mysql_insert_id($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return mysql_query('BEGIN',$this->conn);}public function commit(){return mysql_query('COMMIT',$this->conn);}public function rollback(){return mysql_query('ROLLBACK',$this->conn);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysql_real_escape_string($value,$this->conn)."'":mysql_real_escape_string($value,$this->conn);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqlResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysql_num_rows($this->resource);}protected function doFetch(){return mysql_fetch_assoc($this->resource);}public function seek($row){return mysql_data_seek($this->resource,$row);}protected function free(){mysql_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array('ENUM'=>dibi::FIELD_TEXT,'SET'=>dibi::FIELD_TEXT,'CHAR'=>dibi::FIELD_TEXT,'VARCHAR'=>dibi::FIELD_TEXT,'STRING'=>dibi::FIELD_TEXT,'TINYTEXT'=>dibi::FIELD_TEXT,'TEXT'=>dibi::FIELD_TEXT,'MEDIUMTEXT'=>dibi::FIELD_TEXT,'LONGTEXT'=>dibi::FIELD_TEXT,'BINARY'=>dibi::FIELD_BINARY,'VARBINARY'=>dibi::FIELD_BINARY,'TINYBLOB'=>dibi::FIELD_BINARY,'BLOB'=>dibi::FIELD_BINARY,'MEDIUMBLOB'=>dibi::FIELD_BINARY,'LONGBLOB'=>dibi::FIELD_BINARY,'DATE'=>dibi::FIELD_DATE,'DATETIME'=>dibi::FIELD_DATETIME,'TIMESTAMP'=>dibi::FIELD_DATETIME,'TIME'=>dibi::FIELD_DATETIME,'BIT'=>dibi::FIELD_BOOL,'YEAR'=>dibi::FIELD_INTEGER,'TINYINT'=>dibi::FIELD_INTEGER,'SMALLINT'=>dibi::FIELD_INTEGER,'MEDIUMINT'=>dibi::FIELD_INTEGER,'INT'=>dibi::FIELD_INTEGER,'INTEGER'=>dibi::FIELD_INTEGER,'BIGINT'=>dibi::FIELD_INTEGER,'FLOAT'=>dibi::FIELD_FLOAT,'DOUBLE'=>dibi::FIELD_FLOAT,'REAL'=>dibi::FIELD_FLOAT,'DECIMAL'=>dibi::FIELD_FLOAT,'NUMERIC'=>dibi::FIELD_FLOAT,);$count=mysql_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info['native']=$native=strtoupper(mysql_field_type($this->resource,$index));$info['flags']=explode(' ',mysql_field_flags($this->resource,$index));$info['length']=mysql_field_len($this->resource,$index);$info['table']=mysql_field_table($this->resource,$index);if(in_array('auto_increment',$info['flags']))$info['type']=dibi::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:dibi::FIELD_UNKNOWN;}$name=mysql_field_name($this->resource,$index);$this->meta[$name]=$info;$this->convert[$name]=$info['type'];}}} + if(!defined('DIBI'))die();class DibiMySqliDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('mysqli'))return new DibiException("PHP extension 'mysqli' is not loaded");if(empty($config['host']))$config['host']='localhost';$conn=@mysqli_connect($config['host'],@$config['username'],@$config['password'],@$config['database'],@$config['port']);if(!$conn)return new DibiException("Connecting error",array('message'=>mysqli_connect_error(),'code'=>mysqli_connect_errno(),));if(!empty($config['charset']))mysqli_query($conn,'SET CHARACTER SET '.$config['charset']);$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$res=@mysqli_query($this->conn,$sql);if(is_object($res))return new DibiMySqliResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));$this->affectedRows=mysqli_affected_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=mysqli_insert_id($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return mysqli_autocommit($this->conn,FALSE);}public function commit(){$ok=mysqli_commit($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=mysqli_rollback($this->conn);mysqli_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>mysqli_error($this->conn),'code'=>mysqli_errno($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".mysqli_real_escape_string($this->conn,$value)."'":mysqli_real_escape_string($this->conn,$value);}public function quoteName($value){return'`'.strtr($value,array('.'=>'`.`')).'`';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiMySqliResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return mysqli_num_rows($this->resource);}protected function doFetch(){return mysqli_fetch_assoc($this->resource);}public function seek($row){return mysqli_data_seek($this->resource,$row);}protected function free(){mysqli_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){static$types=array(MYSQLI_TYPE_FLOAT=>dibi::FIELD_FLOAT,MYSQLI_TYPE_DOUBLE=>dibi::FIELD_FLOAT,MYSQLI_TYPE_DECIMAL=>dibi::FIELD_FLOAT,MYSQLI_TYPE_TINY=>dibi::FIELD_INTEGER,MYSQLI_TYPE_SHORT=>dibi::FIELD_INTEGER,MYSQLI_TYPE_LONG=>dibi::FIELD_INTEGER,MYSQLI_TYPE_LONGLONG=>dibi::FIELD_INTEGER,MYSQLI_TYPE_INT24=>dibi::FIELD_INTEGER,MYSQLI_TYPE_YEAR=>dibi::FIELD_INTEGER,MYSQLI_TYPE_GEOMETRY=>dibi::FIELD_INTEGER,MYSQLI_TYPE_DATE=>dibi::FIELD_DATE,MYSQLI_TYPE_NEWDATE=>dibi::FIELD_DATE,MYSQLI_TYPE_TIMESTAMP=>dibi::FIELD_DATETIME,MYSQLI_TYPE_TIME=>dibi::FIELD_DATETIME,MYSQLI_TYPE_DATETIME=>dibi::FIELD_DATETIME,MYSQLI_TYPE_ENUM=>dibi::FIELD_TEXT,MYSQLI_TYPE_SET=>dibi::FIELD_TEXT,MYSQLI_TYPE_STRING=>dibi::FIELD_TEXT,MYSQLI_TYPE_VAR_STRING=>dibi::FIELD_TEXT,MYSQLI_TYPE_TINY_BLOB=>dibi::FIELD_BINARY,MYSQLI_TYPE_MEDIUM_BLOB=>dibi::FIELD_BINARY,MYSQLI_TYPE_LONG_BLOB=>dibi::FIELD_BINARY,MYSQLI_TYPE_BLOB=>dibi::FIELD_BINARY,);$count=mysqli_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$info=(array)mysqli_fetch_field_direct($this->resource,$index);$native=$info['native']=$info['type'];if($info['flags']&MYSQLI_AUTO_INCREMENT_FLAG)$info['type']=dibi::FIELD_COUNTER;else{$info['type']=isset($types[$native])?$types[$native]:dibi::FIELD_UNKNOWN;}$this->meta[$info['name']]=$info;$this->convert[$info['name']]=$info['type'];}}} + if(!defined('DIBI'))die();class DibiOdbcDriver extends DibiDriver{private$conn,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"-1",'FALSE'=>"0",'date'=>"#m/d/Y#",'datetime'=>"#m/d/Y H:i:s#",);public static function connect($config){if(!extension_loaded('odbc'))return new DibiException("PHP extension 'odbc' is not loaded");if(@$config['persistent'])$conn=@odbc_pconnect($config['database'],$config['username'],$config['password']);else$conn=@odbc_connect($config['database'],$config['username'],$config['password']);if(!is_resource($conn))return new DibiException("Connecting error",array('message'=>odbc_errormsg(),'code'=>odbc_error(),));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->affectedRows=FALSE;$res=@odbc_exec($this->conn,$sql);if(is_resource($res))return new DibiOdbcResult($res);if($res===FALSE)return new DibiException("Query error",$this->errorInfo($sql));$this->affectedRows=odbc_num_rows($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return FALSE;}public function begin(){return odbc_autocommit($this->conn,FALSE);}public function commit(){$ok=odbc_commit($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}public function rollback(){$ok=odbc_rollback($this->conn);odbc_autocommit($this->conn,TRUE);return$ok;}private function errorInfo($sql=NULL){return array('message'=>odbc_errormsg($this->conn),'code'=>odbc_error($this->conn),'sql'=>$sql,);}public function escape($value,$appendQuotes=FALSE){$value=str_replace("'","''",$value);return$appendQuotes?"'".$value."'":$value;}public function quoteName($value){return'['.strtr($value,array('.'=>'].[')).']';}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiOdbcResult extends DibiResult{private$resource,$meta,$row=0;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return odbc_num_rows($this->resource);}protected function doFetch(){return odbc_fetch_array($this->resource,$this->row++);}public function seek($row){$this->row=$row;}protected function free(){odbc_free_result($this->resource);}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){if($this->meta!==NULL)return$this->meta;static$types=array('CHAR'=>dibi::FIELD_TEXT,'COUNTER'=>dibi::FIELD_COUNTER,'VARCHAR'=>dibi::FIELD_TEXT,'LONGCHAR'=>dibi::FIELD_TEXT,'INTEGER'=>dibi::FIELD_INTEGER,'DATETIME'=>dibi::FIELD_DATETIME,'CURRENCY'=>dibi::FIELD_FLOAT,'BIT'=>dibi::FIELD_BOOL,'LONGBINARY'=>dibi::FIELD_BINARY,'SMALLINT'=>dibi::FIELD_INTEGER,'BYTE'=>dibi::FIELD_INTEGER,'BIGINT'=>dibi::FIELD_INTEGER,'INT'=>dibi::FIELD_INTEGER,'TINYINT'=>dibi::FIELD_INTEGER,'REAL'=>dibi::FIELD_FLOAT,'DOUBLE'=>dibi::FIELD_FLOAT,'DECIMAL'=>dibi::FIELD_FLOAT,'NUMERIC'=>dibi::FIELD_FLOAT,'MONEY'=>dibi::FIELD_FLOAT,'SMALLMONEY'=>dibi::FIELD_FLOAT,'FLOAT'=>dibi::FIELD_FLOAT,'YESNO'=>dibi::FIELD_BOOL,);$count=odbc_num_fields($this->resource);$this->meta=$this->convert=array();for($index=1;$index<=$count;$index++){$native=strtoupper(odbc_field_type($this->resource,$index));$name=odbc_field_name($this->resource,$index);$this->meta[$name]=array('type'=>isset($types[$native])?$types[$native]:dibi::FIELD_UNKNOWN,'native'=>$native,'length'=>odbc_field_len($this->resource,$index),'scale'=>odbc_field_scale($this->resource,$index),'precision'=>odbc_field_precision($this->resource,$index),);$this->convert[$name]=$this->meta[$name]['type'];}}} + if(!defined('DIBI'))die();class DibiSqliteDriver extends DibiDriver{private$conn,$insertId=FALSE,$affectedRows=FALSE;public$formats=array('NULL'=>"NULL",'TRUE'=>"1",'FALSE'=>"0",'date'=>"'Y-m-d'",'datetime'=>"'Y-m-d H:i:s'",);public static function connect($config){if(!extension_loaded('sqlite'))return new DibiException("PHP extension 'sqlite' is not loaded");if(empty($config['database']))return new DibiException("Database must be specified");$errorMsg='';if(empty($config['persistent']))$conn=@sqlite_open($config['database'],@$config['mode'],$errorMsg);else$conn=@sqlite_popen($config['database'],@$config['mode'],$errorMsg);if(!$conn)return new DibiException("Connecting error",array('message'=>$errorMsg,));$obj=new self($config);$obj->conn=$conn;return$obj;}public function query($sql){$this->insertId=$this->affectedRows=FALSE;$errorMsg='';$res=@sqlite_query($this->conn,$sql,SQLITE_ASSOC,$errorMsg);if($res===FALSE)return new DibiException("Query error",array('message'=>$errorMsg,'sql'=>$sql,));if(is_resource($res))return new DibiSqliteResult($res);$this->affectedRows=sqlite_changes($this->conn);if($this->affectedRows<0)$this->affectedRows=FALSE;$this->insertId=sqlite_last_insert_rowid($this->conn);if($this->insertId<1)$this->insertId=FALSE;return TRUE;}public function affectedRows(){return$this->affectedRows;}public function insertId(){return$this->insertId;}public function begin(){return sqlite_query($this->conn,'BEGIN');}public function commit(){return sqlite_query($this->conn,'COMMIT');}public function rollback(){return sqlite_query($this->conn,'ROLLBACK');}public function escape($value,$appendQuotes=FALSE){return$appendQuotes?"'".sqlite_escape_string($value)."'":sqlite_escape_string($value);}public function quoteName($value){return$value;}public function getMetaData(){trigger_error('Meta is not implemented yet.',E_USER_WARNING);}}class DibiSqliteResult extends DibiResult{private$resource,$meta;public function __construct($resource){$this->resource=$resource;}public function rowCount(){return sqlite_num_rows($this->resource);}protected function doFetch(){return sqlite_fetch_array($this->resource,SQLITE_ASSOC);}public function seek($row){return sqlite_seek($this->resource,$row);}protected function free(){}public function getFields(){if($this->meta===NULL)$this->createMeta();return array_keys($this->meta);}protected function detectTypes(){if($this->meta===NULL)$this->createMeta();}public function getMetaData($field){if($this->meta===NULL)$this->createMeta();return isset($this->meta[$field])?$this->meta[$field]:FALSE;}private function createMeta(){$count=sqlite_num_fields($this->resource);$this->meta=$this->convert=array();for($index=0;$index<$count;$index++){$name=sqlite_field_name($this->resource,$index);$this->meta[$name]=array('type'=>dibi::FIELD_UNKNOWN);$this->convert[$name]=dibi::FIELD_UNKNOWN;}}}?> \ No newline at end of file diff --git a/dibi/dibi.php b/dibi/dibi.php index 13d6040d..8b3a3348 100644 --- a/dibi/dibi.php +++ b/dibi/dibi.php @@ -67,6 +67,23 @@ interface IDibiVariable */ class dibi { + /** + * Column type in relation to PHP native type + */ + const + FIELD_TEXT = 's', // as 'string' + FIELD_BINARY = 'b', + FIELD_BOOL = 'l', // as 'logical' + FIELD_INTEGER = 'i', + FIELD_FLOAT = 'f', + FIELD_DATE = 'd', + FIELD_DATETIME = 't', + FIELD_UNKNOWN = '?', + + // special + FIELD_COUNTER = 'c'; // counter or autoincrement, is integer + + /** * Connection registry storage for DibiDriver objects * @var array @@ -191,7 +208,7 @@ class dibi */ static public function getConnection($name = NULL) { - return $name === NULL + return NULL === $name ? self::$conn : @self::$registry[$name]; } diff --git a/dibi/drivers/mysql.php b/dibi/drivers/mysql.php index 5bf66d8c..e5f2dabc 100644 --- a/dibi/drivers/mysql.php +++ b/dibi/drivers/mysql.php @@ -273,38 +273,38 @@ class DibiMySqlResult extends DibiResult private function createMeta() { static $types = array( - 'ENUM' => self::FIELD_TEXT, // eventually self::FIELD_INTEGER - 'SET' => self::FIELD_TEXT, // eventually self::FIELD_INTEGER - 'CHAR' => self::FIELD_TEXT, - 'VARCHAR' => self::FIELD_TEXT, - 'STRING' => self::FIELD_TEXT, - 'TINYTEXT' => self::FIELD_TEXT, - 'TEXT' => self::FIELD_TEXT, - 'MEDIUMTEXT'=> self::FIELD_TEXT, - 'LONGTEXT' => self::FIELD_TEXT, - 'BINARY' => self::FIELD_BINARY, - 'VARBINARY' => self::FIELD_BINARY, - 'TINYBLOB' => self::FIELD_BINARY, - 'BLOB' => self::FIELD_BINARY, - 'MEDIUMBLOB'=> self::FIELD_BINARY, - 'LONGBLOB' => self::FIELD_BINARY, - 'DATE' => self::FIELD_DATE, - 'DATETIME' => self::FIELD_DATETIME, - 'TIMESTAMP' => self::FIELD_DATETIME, - 'TIME' => self::FIELD_DATETIME, - 'BIT' => self::FIELD_BOOL, - 'YEAR' => self::FIELD_INTEGER, - 'TINYINT' => self::FIELD_INTEGER, - 'SMALLINT' => self::FIELD_INTEGER, - 'MEDIUMINT' => self::FIELD_INTEGER, - 'INT' => self::FIELD_INTEGER, - 'INTEGER' => self::FIELD_INTEGER, - 'BIGINT' => self::FIELD_INTEGER, - 'FLOAT' => self::FIELD_FLOAT, - 'DOUBLE' => self::FIELD_FLOAT, - 'REAL' => self::FIELD_FLOAT, - 'DECIMAL' => self::FIELD_FLOAT, - 'NUMERIC' => self::FIELD_FLOAT, + 'ENUM' => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER + 'SET' => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER + 'CHAR' => dibi::FIELD_TEXT, + 'VARCHAR' => dibi::FIELD_TEXT, + 'STRING' => dibi::FIELD_TEXT, + 'TINYTEXT' => dibi::FIELD_TEXT, + 'TEXT' => dibi::FIELD_TEXT, + 'MEDIUMTEXT'=> dibi::FIELD_TEXT, + 'LONGTEXT' => dibi::FIELD_TEXT, + 'BINARY' => dibi::FIELD_BINARY, + 'VARBINARY' => dibi::FIELD_BINARY, + 'TINYBLOB' => dibi::FIELD_BINARY, + 'BLOB' => dibi::FIELD_BINARY, + 'MEDIUMBLOB'=> dibi::FIELD_BINARY, + 'LONGBLOB' => dibi::FIELD_BINARY, + 'DATE' => dibi::FIELD_DATE, + 'DATETIME' => dibi::FIELD_DATETIME, + 'TIMESTAMP' => dibi::FIELD_DATETIME, + 'TIME' => dibi::FIELD_DATETIME, + 'BIT' => dibi::FIELD_BOOL, + 'YEAR' => dibi::FIELD_INTEGER, + 'TINYINT' => dibi::FIELD_INTEGER, + 'SMALLINT' => dibi::FIELD_INTEGER, + 'MEDIUMINT' => dibi::FIELD_INTEGER, + 'INT' => dibi::FIELD_INTEGER, + 'INTEGER' => dibi::FIELD_INTEGER, + 'BIGINT' => dibi::FIELD_INTEGER, + 'FLOAT' => dibi::FIELD_FLOAT, + 'DOUBLE' => dibi::FIELD_FLOAT, + 'REAL' => dibi::FIELD_FLOAT, + 'DECIMAL' => dibi::FIELD_FLOAT, + 'NUMERIC' => dibi::FIELD_FLOAT, ); $count = mysql_num_fields($this->resource); @@ -317,12 +317,12 @@ class DibiMySqlResult extends DibiResult $info['table'] = mysql_field_table($this->resource, $index); if (in_array('auto_increment', $info['flags'])) // or 'primary_key' ? - $info['type'] = self::FIELD_COUNTER; + $info['type'] = dibi::FIELD_COUNTER; else { - $info['type'] = isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN; + $info['type'] = isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN; -// if ($info['type'] == self::FIELD_TEXT && $info['length'] > 255) -// $info['type'] = self::FIELD_LONG_TEXT; +// if ($info['type'] == dibi::FIELD_TEXT && $info['length'] > 255) +// $info['type'] = dibi::FIELD_LONG_TEXT; } $name = mysql_field_name($this->resource, $index); diff --git a/dibi/drivers/mysqli.php b/dibi/drivers/mysqli.php index feaa22c1..54ab590c 100644 --- a/dibi/drivers/mysqli.php +++ b/dibi/drivers/mysqli.php @@ -233,31 +233,31 @@ class DibiMySqliResult extends DibiResult private function createMeta() { static $types = array( - MYSQLI_TYPE_FLOAT => self::FIELD_FLOAT, - MYSQLI_TYPE_DOUBLE => self::FIELD_FLOAT, - MYSQLI_TYPE_DECIMAL => self::FIELD_FLOAT, - // MYSQLI_TYPE_NEWDECIMAL=> self::FIELD_FLOAT, - // MYSQLI_TYPE_BIT => self::FIELD_INTEGER, - MYSQLI_TYPE_TINY => self::FIELD_INTEGER, - MYSQLI_TYPE_SHORT => self::FIELD_INTEGER, - MYSQLI_TYPE_LONG => self::FIELD_INTEGER, - MYSQLI_TYPE_LONGLONG => self::FIELD_INTEGER, - MYSQLI_TYPE_INT24 => self::FIELD_INTEGER, - MYSQLI_TYPE_YEAR => self::FIELD_INTEGER, - MYSQLI_TYPE_GEOMETRY => self::FIELD_INTEGER, - MYSQLI_TYPE_DATE => self::FIELD_DATE, - MYSQLI_TYPE_NEWDATE => self::FIELD_DATE, - MYSQLI_TYPE_TIMESTAMP => self::FIELD_DATETIME, - MYSQLI_TYPE_TIME => self::FIELD_DATETIME, - MYSQLI_TYPE_DATETIME => self::FIELD_DATETIME, - MYSQLI_TYPE_ENUM => self::FIELD_TEXT, // eventually self::FIELD_INTEGER - MYSQLI_TYPE_SET => self::FIELD_TEXT, // eventually self::FIELD_INTEGER - MYSQLI_TYPE_STRING => self::FIELD_TEXT, - MYSQLI_TYPE_VAR_STRING=> self::FIELD_TEXT, - MYSQLI_TYPE_TINY_BLOB => self::FIELD_BINARY, - MYSQLI_TYPE_MEDIUM_BLOB=> self::FIELD_BINARY, - MYSQLI_TYPE_LONG_BLOB => self::FIELD_BINARY, - MYSQLI_TYPE_BLOB => self::FIELD_BINARY, + MYSQLI_TYPE_FLOAT => dibi::FIELD_FLOAT, + MYSQLI_TYPE_DOUBLE => dibi::FIELD_FLOAT, + MYSQLI_TYPE_DECIMAL => dibi::FIELD_FLOAT, + // MYSQLI_TYPE_NEWDECIMAL=> dibi::FIELD_FLOAT, + // MYSQLI_TYPE_BIT => dibi::FIELD_INTEGER, + MYSQLI_TYPE_TINY => dibi::FIELD_INTEGER, + MYSQLI_TYPE_SHORT => dibi::FIELD_INTEGER, + MYSQLI_TYPE_LONG => dibi::FIELD_INTEGER, + MYSQLI_TYPE_LONGLONG => dibi::FIELD_INTEGER, + MYSQLI_TYPE_INT24 => dibi::FIELD_INTEGER, + MYSQLI_TYPE_YEAR => dibi::FIELD_INTEGER, + MYSQLI_TYPE_GEOMETRY => dibi::FIELD_INTEGER, + MYSQLI_TYPE_DATE => dibi::FIELD_DATE, + MYSQLI_TYPE_NEWDATE => dibi::FIELD_DATE, + MYSQLI_TYPE_TIMESTAMP => dibi::FIELD_DATETIME, + MYSQLI_TYPE_TIME => dibi::FIELD_DATETIME, + MYSQLI_TYPE_DATETIME => dibi::FIELD_DATETIME, + MYSQLI_TYPE_ENUM => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER + MYSQLI_TYPE_SET => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER + MYSQLI_TYPE_STRING => dibi::FIELD_TEXT, + MYSQLI_TYPE_VAR_STRING=> dibi::FIELD_TEXT, + MYSQLI_TYPE_TINY_BLOB => dibi::FIELD_BINARY, + MYSQLI_TYPE_MEDIUM_BLOB=> dibi::FIELD_BINARY, + MYSQLI_TYPE_LONG_BLOB => dibi::FIELD_BINARY, + MYSQLI_TYPE_BLOB => dibi::FIELD_BINARY, ); $count = mysqli_num_fields($this->resource); @@ -267,11 +267,11 @@ class DibiMySqliResult extends DibiResult $native = $info['native'] = $info['type']; if ($info['flags'] & MYSQLI_AUTO_INCREMENT_FLAG) // or 'primary_key' ? - $info['type'] = self::FIELD_COUNTER; + $info['type'] = dibi::FIELD_COUNTER; else { - $info['type'] = isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN; -// if ($info['type'] == self::FIELD_TEXT && $info['length'] > 255) -// $info['type'] = self::FIELD_LONG_TEXT; + $info['type'] = isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN; +// if ($info['type'] == dibi::FIELD_TEXT && $info['length'] > 255) +// $info['type'] = dibi::FIELD_LONG_TEXT; } $this->meta[$info['name']] = $info; diff --git a/dibi/drivers/odbc.php b/dibi/drivers/odbc.php index 96962f15..849503e9 100644 --- a/dibi/drivers/odbc.php +++ b/dibi/drivers/odbc.php @@ -230,28 +230,28 @@ class DibiOdbcResult extends DibiResult return $this->meta; static $types = array( - 'CHAR' => self::FIELD_TEXT, - 'COUNTER' => self::FIELD_COUNTER, - 'VARCHAR' => self::FIELD_TEXT, - 'LONGCHAR' => self::FIELD_TEXT, - 'INTEGER' => self::FIELD_INTEGER, - 'DATETIME' => self::FIELD_DATETIME, - 'CURRENCY' => self::FIELD_FLOAT, - 'BIT' => self::FIELD_BOOL, - 'LONGBINARY'=> self::FIELD_BINARY, - 'SMALLINT' => self::FIELD_INTEGER, - 'BYTE' => self::FIELD_INTEGER, - 'BIGINT' => self::FIELD_INTEGER, - 'INT' => self::FIELD_INTEGER, - 'TINYINT' => self::FIELD_INTEGER, - 'REAL' => self::FIELD_FLOAT, - 'DOUBLE' => self::FIELD_FLOAT, - 'DECIMAL' => self::FIELD_FLOAT, - 'NUMERIC' => self::FIELD_FLOAT, - 'MONEY' => self::FIELD_FLOAT, - 'SMALLMONEY'=> self::FIELD_FLOAT, - 'FLOAT' => self::FIELD_FLOAT, - 'YESNO' => self::FIELD_BOOL, + 'CHAR' => dibi::FIELD_TEXT, + 'COUNTER' => dibi::FIELD_COUNTER, + 'VARCHAR' => dibi::FIELD_TEXT, + 'LONGCHAR' => dibi::FIELD_TEXT, + 'INTEGER' => dibi::FIELD_INTEGER, + 'DATETIME' => dibi::FIELD_DATETIME, + 'CURRENCY' => dibi::FIELD_FLOAT, + 'BIT' => dibi::FIELD_BOOL, + 'LONGBINARY'=> dibi::FIELD_BINARY, + 'SMALLINT' => dibi::FIELD_INTEGER, + 'BYTE' => dibi::FIELD_INTEGER, + 'BIGINT' => dibi::FIELD_INTEGER, + 'INT' => dibi::FIELD_INTEGER, + 'TINYINT' => dibi::FIELD_INTEGER, + 'REAL' => dibi::FIELD_FLOAT, + 'DOUBLE' => dibi::FIELD_FLOAT, + 'DECIMAL' => dibi::FIELD_FLOAT, + 'NUMERIC' => dibi::FIELD_FLOAT, + 'MONEY' => dibi::FIELD_FLOAT, + 'SMALLMONEY'=> dibi::FIELD_FLOAT, + 'FLOAT' => dibi::FIELD_FLOAT, + 'YESNO' => dibi::FIELD_BOOL, // and many others? ); @@ -261,7 +261,7 @@ class DibiOdbcResult extends DibiResult $native = strtoupper(odbc_field_type($this->resource, $index)); $name = odbc_field_name($this->resource, $index); $this->meta[$name] = array( - 'type' => isset($types[$native]) ? $types[$native] : self::FIELD_UNKNOWN, + 'type' => isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN, 'native' => $native, 'length' => odbc_field_len($this->resource, $index), 'scale' => odbc_field_scale($this->resource, $index), diff --git a/dibi/drivers/sqlite.php b/dibi/drivers/sqlite.php index 0a13f218..c23ddd82 100644 --- a/dibi/drivers/sqlite.php +++ b/dibi/drivers/sqlite.php @@ -226,8 +226,8 @@ class DibiSqliteResult extends DibiResult $this->meta = $this->convert = array(); for ($index = 0; $index < $count; $index++) { $name = sqlite_field_name($this->resource, $index); - $this->meta[$name] = array('type' => self::FIELD_UNKNOWN); - $this->convert[$name] = self::FIELD_UNKNOWN; + $this->meta[$name] = array('type' => dibi::FIELD_UNKNOWN); + $this->convert[$name] = dibi::FIELD_UNKNOWN; } } diff --git a/dibi/libs/parser.php b/dibi/libs/parser.php index e5bc3c0b..72229198 100644 --- a/dibi/libs/parser.php +++ b/dibi/libs/parser.php @@ -57,9 +57,9 @@ class DibiParser // iterate $sql = array(); foreach ($args as $arg) - { - // %if was opened - if ($mod == 'if') { + { + // %if was opened + if ('if' == $mod) { $mod = FALSE; $this->ifLevel++; if (!$comment && !$arg) { @@ -72,17 +72,19 @@ class DibiParser } // simple string means SQL - if (is_string($arg) && !$mod) { - $sql[] = $this->formatValue($arg, 'p'); // preserve it + if (is_string($arg) && (!$mod || 'p'==$mod)) { + $mod = FALSE; + // will generate new mod + $sql[] = $this->formatValue($arg, 'p'); continue; } - // array without modifier - autoselect between SET or VALUES - if (is_array($arg) && !$mod && is_string(key($arg))) { + // associative array without modifier - autoselect between SET or VALUES + if (!$mod && is_array($arg) && is_string(key($arg))) { if (!$command) $command = strtoupper(substr(ltrim($args[0]), 0, 6)); - $mod = ($command == 'INSERT' || $command == 'REPLAC') ? 'V' : 'S'; + $mod = ('INSERT' == $command || 'REPLAC' == $command) ? 'V' : 'S'; } // default processing @@ -116,20 +118,44 @@ class DibiParser switch ($modifier) { case 'S': // SET foreach ($value as $k => $v) { - list($k, $mod) = explode('%', $k.'%', 3); // split modifier - $vx[] = $this->driver->quoteName($k) . '=' . $this->formatValue($v, $mod); + // split into identifier & modifier + $pair = explode('%', $k, 2); + + if (isset($pair[1])) { + $mod = $pair[1]; + // %? skips NULLS + if (isset($mod[0]) && '?' == $mod[0]) { + if (NULL === $v) continue; + $mod = substr($mod, 1); + } + } else $mod = FALSE; + + // generate array + $vx[] = $this->driver->quoteName($pair[0]) . '=' . $this->formatValue($v, $mod); } - return implode(', ', $vx); + case 'V': // VALUES foreach ($value as $k => $v) { - list($k, $mod) = explode('%', $k.'%', 3); // split modifier - $kx[] = $this->driver->quoteName($k); + // split into identifier & modifier + $pair = explode('%', $k, 2); + + if (isset($pair[1])) { + $mod = $pair[1]; + // %m? skips NULLS + if (isset($mod[0]) && '?' == $mod[0]) { + if ($v === NULL) continue; + $mod = substr($mod, 1); + } + } else $mod = FALSE; + + // generate arrays + $kx[] = $this->driver->quoteName($pair[0]); $vx[] = $this->formatValue($v, $mod); } - return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; + default: // LIST foreach ($value as $v) @@ -154,7 +180,9 @@ class DibiParser case "s": // string return $this->driver->escape($value, TRUE); case 'b': // boolean - return $value ? $this->driver->formats['TRUE'] : $this->driver->formats['FALSE']; + return $value + ? $this->driver->formats['TRUE'] + : $this->driver->formats['FALSE']; case 'i': case 'u': // unsigned int case 'd': // signed int @@ -162,9 +190,14 @@ class DibiParser case 'f': // float return (string) (float) $value; // something like -9E-005 is accepted by SQL case 'D': // date - return date($this->driver->formats['date'], is_string($value) ? strtotime($value) : $value); + return date($this->driver->formats['date'], is_string($value) + ? strtotime($value) + : $value); + case 't': // datetime case 'T': // datetime - return date($this->driver->formats['datetime'], is_string($value) ? strtotime($value) : $value); + return date($this->driver->formats['datetime'], is_string($value) + ? strtotime($value) + : $value); case 'n': // identifier name return $this->driver->quoteName($value); case 'p': // preserve as SQL @@ -173,7 +206,7 @@ class DibiParser // speed-up - is regexp required? $toSkip = strcspn($value, '`[\'"%'); - if ($toSkip == strlen($value)) // needn't be translated + if (strlen($value) == $toSkip) // needn't be translated return $value; // note: only this can change $this->modifier @@ -245,8 +278,8 @@ class DibiParser // [4] => string // [5] => " // [6] => string - // [7] => right modifier - // [8] => %else | %end + // [7] => %else | %end + // [8] => right modifier // [9] => lone-quote if ($matches[1]) // SQL identifiers: `ident` @@ -271,7 +304,7 @@ class DibiParser return "**Unexpected condition $matches[8]**"; } - if ($matches[7] == 'end') { + if ('end' == $matches[7]) { $this->ifLevel--; if ($this->ifLevelStart == $this->ifLevel + 1) { // close comment diff --git a/dibi/libs/resultset.php b/dibi/libs/resultset.php index 19825853..57720445 100644 --- a/dibi/libs/resultset.php +++ b/dibi/libs/resultset.php @@ -45,23 +45,6 @@ if (!interface_exists('Countable', false)) { */ abstract class DibiResult implements IteratorAggregate, Countable { - /** - * Column type in relation to PHP native type - */ - const - FIELD_TEXT = 's', // as 'string' - FIELD_BINARY = 'b', - FIELD_BOOL = 'l', // as 'logical' - FIELD_INTEGER = 'i', - FIELD_FLOAT = 'f', - FIELD_DATE = 'd', - FIELD_DATETIME = 't', - FIELD_UNKNOWN = '?', - - // special - FIELD_COUNTER = 'c'; // counter or autoincrement, is integer - - /** * Describes columns types * @var array @@ -270,12 +253,12 @@ abstract class DibiResult implements IteratorAggregate, Countable return $value; static $conv = array( - self::FIELD_TEXT => 'string', - self::FIELD_BINARY => 'string', - self::FIELD_BOOL => 'bool', - self::FIELD_INTEGER => 'int', - self::FIELD_FLOAT => 'float', - self::FIELD_COUNTER => 'int', + dibi::FIELD_TEXT => 'string', + dibi::FIELD_BINARY => 'string', + dibi::FIELD_BOOL => 'bool', + dibi::FIELD_INTEGER => 'int', + dibi::FIELD_FLOAT => 'float', + dibi::FIELD_COUNTER => 'int', ); if (isset($conv[$type])) { @@ -283,10 +266,10 @@ abstract class DibiResult implements IteratorAggregate, Countable return $value; } - if ($type == self::FIELD_DATE) + if ($type == dibi::FIELD_DATE) return strtotime($value); // !!! not good - if ($type == self::FIELD_DATETIME) + if ($type == dibi::FIELD_DATETIME) return strtotime($value); // !!! not good return $value; diff --git a/examples/metatypes.php b/examples/metatypes.php index a1e602ca..eba646ac 100644 --- a/examples/metatypes.php +++ b/examples/metatypes.php @@ -21,7 +21,7 @@ if (is_error($res)) // auto-convert this field to integer -$res->setType('inumber', DibiResult::FIELD_INTEGER); +$res->setType('inumber', Dibi::FIELD_INTEGER); $record = $res->fetch(); var_dump($record); diff --git a/examples/sql-builder.php b/examples/sql-builder.php index 74d6e7fb..c1961470 100644 --- a/examples/sql-builder.php +++ b/examples/sql-builder.php @@ -26,10 +26,11 @@ $arr3 = array( 'col3' => 'three', ); $arr4 = array( - 'a' => 12, - 'b' => NULL, - 'c%T' => time(), // modifier 'T' means datetime - 'd' => 'any string', + 'a' => 12, + 'b' => NULL, + 'c%?' => NULL, + 'd%T' => time(), // modifier 'T' means datetime + 'e' => 'any string', ); $arr5 = array('RAND()', '[col1] > [col2]');