Re: [PDO] Re: [PHP-DEV] [PATCH] New PDO methods for PostgreSQL driver

[email protected] (Denis Gasparin) Tue, 25 May 2010 11:56:12 +0200 (CEST)
Newsgroups php.pdo
Message-ID <33528933.35408.1274781372025.JavaMail.root@mailserver.edistar.com>
> Lester Caine schrieb:
> > Christopher Jones wrote:
> >> Also I haven't seen anything to explain your earlier comment to
> >> Lester that
> >> "In particular you'll need two database connections (one with the
> >> original driver and one with PDO) in order to use the native copy*
> >> functions.".
> >
> > I see my name, but not connection with the quote ...
> >
> > But in addition to Denis's examples of where you need two database
> > connections, 2 phase commit across multiple databases has been part
> > of Firebird for
> > many years, and other databases are now copying it. This requires
> > combining database connections in the one transaction, and is
> > something that PDO is unable to handle at all? It's one of the items
> > on http://wiki.php.net/internals/pdo/brainstorming?s[]=pdo ... as is
> > the question "Is the goal to eventually replace the native
> > extensions?"
> >
> I see several possible ways without a complete new userland API to
> handle several database connections in PDO:
> 
> A basic driver specific dsn to handle several databases. Then you only
> need a driver specific handle switch function.
> beginTransaction would default to all databases in your DSN.
> 
> PDO::firebirdUseDatabase();
> 
> + Keeps the whole logic in the driver, can use optimized ways to
> handle transactions.
> - Driver specific, the dsn gets very long.
> - Removes the concept of PDO being a database instance.
> 
> A firebird specific pool driver could be used as well:
> 
> $dbh1 = new PDO(..);
> $dbh2 = new PDO(..);
> 
> $dbhpool = new PDO('firebird:pool');
> 
> $dbhpool->firebirdAttachChild($dbh1);
> $dbhpool->firebirdAttachChild($dbh2); $dbhpool->beginTransaction()
> 

Another way could be to maintain a generic PDO driver with a standard dsn (for example "username:password@host/dbname" or the PDO standard "db:host=..,dbname=...") and then to inject a "strategy" to use for database connection and other specific DBMS functions.

For example:

$fbDb = new PDOFirebirdDatabase();

$dbhpool = new PDO('user:pwd@pool/dbname',$fbDb);

$dbhpool->db->attachChild(new PDOFirebirdConnection(..));
$dbhpool->db->attachChild(new PDOFirebirdConnection(..));
$dbhpool->db->beginTransaction());


Another example:

$pgDb = new PDOPostgreSQLDatabase();
$dbh = new PDO('user:pwd@pool/dbname',$pgDb);
$dbh->db->connectionStatus();
$dbh->db->copyFromFile(...);


The strategy could also be determined automatically by the PDO main class using a prefix as mysql:, pgsql:, firebird: etc.
This is how the current PDO object works.

In order to check if a method is defined/supported  by the PDO object, it is possible to determine via object type ($dbhpool->db instanceof PDOFirebirdDatabase) or checking via reflection.

Example:

$dbh = new PDO('pgsql:host=pool;user=username;password=password;dbname=dbname');

if($dbh->db instanceof PDOPostgreSQLDatabase) {
   $dbh->db->copyFromFile(...);
}
else {
   $dbh->beginTransaction();
   $f = fgetcsv(...);
   foreach($f as $r) {
      $dbh->exec(..);
   }
   $dbh->commitTransaction();
}



Just my two cents

Denis



> + Separates the basic usage from the advance usage, for most people
> PDO still will be one database handle.
> 
> The other route would be a dummy driver for all drivers:
> Could be a bit problematical if you mix database drivers.
> 
> $dbhpool = new PDO('pool:');
> $dbhpool->poolAttach($dbh1); $dbhpool->poolAttach($dbh2);
> 
> $dbhpool->beginTransaction();
> 
> + With some emulation it may work across Servers and Drivers via
> transaction save points?
> + Allows one instance to have less good transaction support in the
> pool, will get commit first, then the others...
> - Not easy to handle, needs several hacks to hijack
> beginTransaction/commit - Against the low level design of PDO
> 
> Or the same as transaction object...
> 
> $tobj = new PDOCrossTransaction();
> $tobj->attach($dbh1); $tobj->attach($dbh2);
> $tobj->beginTransaction($options);
> 
> + Can change the function declaration for transaction options
> 
> So I don't think there is a really a need to change fundamental all
> stuff of PDO to support this...
> 
> Oskar Eisemuth
> 
> 
> -- PDO Working Group Mailing List (http://pdo.php.net)
> To unsubscribe, visit: http://www.php.net/unsub.php