<?php
/**
* Postgresql Driver file
* @package SODA
* @ignore
*/
ini_set('display_errors',1);
error_reporting(E_ALL);
/**
* driver_pg.php, extends SODA
* This class permit to manipulate postgresql databases
* @package SODA
* @subpackage drivers
* @author Salvan Gregory <dev@europeaweb.com>
* @version 1.1
* @copyright Copyright (c) 2008, Gregory Salvan europeaweb.com
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
final class driver_pg extends SODA
{
/*
* Protected constructor
* Because of the singleton pattern $this===parent::$instance
*/
protected function __construct($nom='',$pw='',$dbname='',$srv='localhost',$opt=array('_persistant'=>false))
{
$this->init_this();
$this->_user=$nom;
$this->_pwd=$pw;
$this->_server=$srv;
$this->_dbname=$dbname;
$this->_driver='driver_pg';
$this->_dbtype='pg';
if (is_array($opt)){
foreach ($opt as $key=>$val) {
$this->$key=$val;
}
}
}
/*---------------------------------------------------------------
* overloaded functions:
---------------------------------------------------------------*/
/**
* we override the parent static constructor
*
*/
public static function create($dbtype='pg',$nom='',$pw='',$dbname='',$srv='localhost',$opt=array('_persistant'=>false))
{
return parent::create($dbtype,$nom,$pw,$dbname,$srv,$opt);
}
/**
* Opens the connection to the Data Base
*
*/
public function connect()
{
$con="host=".$this->_server." user=".$this->_user." password=".$this->_pwd;
if (isset($this->_dbname))$con.=" dbname=".$this->_dbname;
if (isset($this->_hostaddr))$con.=" hostaddr=".$this->_hostaddr;
if (isset($this->_port))$con.=" port=".$this->_port;
if (isset($this->_connect_timeout))$con.=" connect_timeout=".$this->_connect_timeout;
if (isset($this->_options))$con.=" options=".$this->_options;
if (isset($this->_tty))$con.=" tty=".$this->_tty;
if (isset($this->_sslmode))$con.=" sslmode=".$this->_sslmode;
if (isset($this->_service))$con.=" service=".$this->_service;
$this->_connected=false;
if ($this->_persistant){
$this->_connection=@pg_pconnect($con);
} else {
$this->_connection=@pg_connect($con);
}
if ($this->_connection==false)$this->_connected=false;
else {
$this->_connected=true;
}
$this->_select_db=@pg_dbname()!=false;
if (!$this->_connected){
$this->_errors[]='Connection Error';
}
return $this->_connected;
}
/**
* Closes the connection to the Data Base
*
*/
public function close()
{
@pg_close($this->_connection);
$this->_connected=false;
unset($this->_connection);
$this->_select_db=false;
}
/**
* Selects a Data Base
*
*/
public function select_db($name)
{
$this->_dbname=$name;
$this->connect();
if (!$this->_select_db) $this->close();
return $this->_select_db;
}
/**
* Execute a query and return datas or false
* A property with the name or index $rname is created to store the request
* @param $sql string sql requests
* @param $rname int|string name or index of the request
* @param $type string 'array'|'object'|'row'|'field'|'assoc' set the type of returned values
* @param $len int 0|1|2 set the type of the property _lengths of the request object
*/
public function query($sql,$rname=-1,$type='row',$len=0)
{
//$dtype is defined 2 times because of dproto uses facilties
$dtype=array('array'=>'pg_fetch_array',
'object'=>'pg_fetch_object','row'=>'pg_fetch_row',
'field'=>'pg_fetch_field','assoc'=>'pg_fetch_assoc');
if (array_key_exists($rname,$this->_requests)) {
$this->_requests[$rname]->reset();
} else $rname=$this->prepare($sql,$rname,$type,$len);
//NOTE: take care about _requests because of overloading, $req is binded to it.(= -> &=)
$req=$this->_requests[$rname];
$this->connect();
$req->_result=@pg_query($this->_connection,$req->get_sql());
//the query return true because of INSERT request type
if ($req->_result==1) $req->_rows=@pg_affected_rows($req->_result);
elseif($req->_result==0){
$req->_errors[]=pg_result_error($req->_result);
}
//the query return values because of SELECT request type
else
{
$nb_field=@pg_num_fields($req->_result);
$f=$dtype[$type];
//for fields fetch $len is always set to 0
if ($type=='field') $len=0;
if ($len==1) {
$req['_lengths']= new Array_Object();
while ($row = @$f($req->_result)){
$req['_data'][]=$row;
for ($fi=0;$fi<$nb_field;$fi++)
$ar[]=@pg_prtlen($req->_result,$fi);
$req['_lengths'][]=$ar;
}
} elseif($len==2) {
for ($fi=0;$fi<$nb_field;$fi++)
$req['_lengths'][$fi]=0;
$row = @$f($req->_result);
$req['_data'][]=$row;
$req['_lengths']=@pg_fetch_lengths($req->_result);
while ($row = @$f($req->_result)) {
$req['_data'][]=$row;
for ($fi=0;$fi<$nb_field;$fi++)
$req['_lengths'][$fi]+=@pg_prtlen($req->_result,$fi);
}
} else {
//$len=0 :
$req['_lengths']=0;
//pg_fetch_field:
if ($req->_type=='field') {
for ($fi=0;$fi<$nb_field;$fi++) {
$req['_data'][$fi]->name= @pg_field_name($req->_result,$fi);
$req['_data'][$fi]->type= @pg_field_type($req->_result, $fi);
$req['_data'][$fi]->not_null=!@pg_field_is_null($req->_result,$fi);
$req['_data'][$fi]->table=@pg_field_table($req->_result,$fi);
$req['_data'][$fi]->numeric= preg_match('@int@',$req['_data'][$fi]->type)?true:$req['_data'][$fi]->type=='numeric';
$req['_data'][$fi]->blob= $req['_data'][$fi]->type=='text';
$req['_data'][$fi]->max_lenght=0;
if($req['_data'][$fi]->type=='int')$req['_data'][$fi]->unsigned=true;
}
while ($row = @pg_fetch_row($req->_result)) {
for ($fi=0;$fi<$nb_field;$fi++){
$l=@pg_field_prtlen($req->_result,$fi);
if($l>$req['_data'][$fi]->max_lenght)$req['_data'][$fi]->max_lenght=$l;
if(is_int($row[$fi])&& $row[$fi]<0)$req['_data'][$fi]->unsigned=false;
}
}
} else {
while ($row = @$f($req->_result)) {
$req['_data'][]=$row;
for ($fi=0;$fi<$nb_field;$fi++)
$req['_lengths']+=@pg_field_prtlen($req->_result,$fi);
}
}
}
$req['_fields']=@pg_num_fields($req->_result);
$req['_rows']=@pg_num_rows($req->_result);
@pg_free_result($req->_result);
$req->_result=true;
}
if ($req->_data!=false) $req->_data= new Array_Object($req->_data);
return $req->_data;
}
/**
* Prepare one or more queries and return the index or an array of indexes
* Parameters can be an array, an object or parameters like query.
* A property with the name or index $rname is created to store the request
* @param $sql string sql request
* @param $rname int|string name or index of the request
* @param $type string 'array'|'object'|'row'|'field'|'assoc' set the type of returned values
* @param $len int 0|1|2 set the type of the property _lengths of the request object
*/
public function prepare()
{
//$dtype is redefined because of dbproto
$dtype=array('array'=>'pg_fetch_array',
'object'=>'pg_fetch_object','row'=>'pg_fetch_row',
'field'=>'pg_fetch_field','assoc'=>'pg_fetch_assoc');
//
$arg_list = func_get_args();
if (is_array($arg_list[0]) && count($arg_list[0])>0) {
$r=array();
foreach ($arg_list[0] as $key=>$value)
{
$sql= isset($value[0])?$value[0]:'';
$rname = isset($value[1])?$value[1]:-1;
$type = (isset($value[2]) && array_key_exists($value[2],$dtype))?$value[2]:'row';
$len = isset($value[3])?$value[3]:0;
$r[$key]=$this->prepare($sql,$rname,$type,$len);
}
return $r;
} else {
$sql= isset($arg_list[0])?$arg_list[0]:'';
$rname = isset($arg_list[1])?$arg_list[1]:-1;
$type = (isset($arg_list[2])&& array_key_exists($arg_list[2],$dtype))?$arg_list[2]:'row';
$len = isset($arg_list[3])?$arg_list[3]:0;
if (!is_string($type) || !array_key_exists($type,$dtype)) $type='row';
//if $rname isn't set we use an integer index
if ($rname==-1)$rname=$this->_requests->count_num_index();
//if the request is set we delete it
if (isset($this->_requests[$rname]))$this->clean($rname);
$req=new request();
$req->_sql=$sql;
$req->_type=$type;
$req->_ltype=$len;
$this->_requests[$rname]=$req;
return $rname;
}
}
/**
* Execute one or more queries and return true if succeed otherwise false
* Parameter can be an array, an object of requests indexes or a string or int index.
* @param $req_id mixed index or indexes of requests if -1 or nothing all prepared requests are executed.
*/
public function exec($req_id=-1)
{
//if $req_id == -1 all requests are executed
if ($req_id==-1){
foreach ($this->_requests as $k=>$v){
$ar[$k]['_sql']=$v->_sql;
$ar[$k]['_type']=$v->_type;
$ar[$k]['_ltype']=$v->_ltype;
}
//As query modify $this->_requests we can't do it all in once
foreach($ar as $k=>$v)$this->query($ar[$k]['_sql'],$k,$ar[$k]['_type'],$ar[$k]['_ltype']);
return true;
}
//If $req_id is a valid index we return datas or false if the request isn't set
elseif (is_int($req_id) || is_string($req_id)) {
if (isset($this->_requests[$req_id])){
return $this->query($this->_requests[$req_id]->_sql,$req_id,$this->_requests[$req_id]->_type,$this->_requests[$req_id]->_ltype);
}
return false;
}
//else we execute all requests givens by the array or object $req_id
elseif (is_array($req_id) || (is_object($req_id) && (get_class($req_id)=='Array_Object'||get_class($req_id)=='stdClass')))
{
foreach ($req_id as $id) {
$this->query($this->_requests[$id]->_sql,$id,$this->_requests[$id]->_type,$this->_requests[$id]->_ltype);
}
return true;
}
return false;
}
/**
* Delete one or more queries and return true if succeed otherwise false
* Parameter can be an array, an object of requests indexes or a string or int index.
* @param $req_id mixed index or indexes of requests if -1 or nothing all prepared requests are deleted.
*/
public function clean($req_id=-1)
{
$r=true;
if ($req_id==-1)$this->_requests=new Array_Object();
elseif (is_int($req_id)||is_string($req_id)) {
if (isset($this->_requests[$req_id]))unset($this->_requests[$req_id]);
$r= !isset($this->_requests[$req_id]);
if (!$r) $this->_errors[]="Can't delete the request $req_id";
}
elseif (is_array($req_id))
{
foreach ($req_id as $id) {
$v=$this->clean($id);
$r=$v==false?false:$r;
}
}
return $r;
}
}//end of the class driver_pg
?>
|