PostgreSQL Port

thread: 43 messages  |  last: a year ago  |  started: friday, october 21, 2005, 2:31 pm pdt


#1  |  SudoUser (Mill Valley, CA)
Friday, October 21, 2005, 2:31 PM PDT

Mike,

I enjoyed the presentation at the Zend PHP Conference and would like to help anywhere I can. I run only PostgreSQL and would like to do the port for PostgreSQL. Please provide and information that may help me complete this task more efficiently.

Great Job!

Cheers,
-p

#2  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Friday, October 21, 2005, 8:11 PM PDT

Thanks for the feedback...

Hopefully, this can get you started in the right direction.

DB Platform-specific adapters all reside in /includes/qcodo/database_adapters.  As you can see, only two adapters exist so far... MySql and MySqli (the MySqli utilizes the “MySQL Improved” extension, while the MySQL utilizes the older MySQL extension).

Database adapters consist of 7 classes which extend from the DatabaseBase classes (/includes/qcodo/framework_objects).  Don't let that “7” number scare you... only one of those classes actually has code.  The other 6 are practically empty:
* DatabaseBase
 (so your new adapter would have a class called PostgreSqlDatabase, which extends DatabaseBase)
* DatabaseForeignKeyBase (PostgreSqlDatabaseForeignKey)
* DatabaseIndexBase (PostgreSqlDatabaseIndex)
* DatabaseFieldBase (PostgreSqlDatabaseField)
* DatabaseResultBase (PostgreSqlDatabaseResult)
* DatabaseRowBase (PostgreSqlDatabaseRow)
* DatabaseExceptionBase (PostgreSqlDatabaseExtension)

So the DatabaseBase class (or in your case, the PostgreSqlDatabase class) basically is a wrapper around the PostgreSql extension.  In fact, you should feel free to say that the class has protected member variable $objDbConnection which would store the resource returned by pg_connect.  And then any of the class to PostgreSqlDatabase->Query or >FetchArray or whatever, are simply calls to the appropriate pg_* method (passing in $this>objDbConnection as as the resource).

PostgreSqlDatabase will need to implement the following methods:
       // This connects to the database, reading in DBCONFIG_#_xxx constants
       // where # is the $intDatabaseIndex that's passed in
       abstract public function __construct($intDatabaseIndex);

       // Query is just to query given a sql string.  No query is for queries
       // the don't actually return a result (e.g. DELETE, UPDATE, INSERT).
       // QuerySet is not really implemented yet.
       abstract public function Query($strQuery);
       abstract public function QuerySet($strQueries);
       abstract public function NonQuery($strNonQuery);

       // GetTables will return an array of strings, which are list of table names
       // InsertID returns the identity or insert id of the most recently inserted
       // row (does PostgreSql support this?)
       abstract public function GetTables();
       abstract public function InsertId();

       // This will return an array of PostgreSqlDatabaseIndex objects
       // or an array of PostgreSqlForeignKey objects given the table name
       // This is probably where the bulk of your work will go... figuring out
       // a way to get that information via a combination of DESCRIBE, etc.
       abstract public function GetIndexesForTable($strTableName);
       abstract public function GetForeignKeysForTable($strTableName);

       // These handle transactions
       abstract public function TransactionBegin();
       abstract public function TransactionCommit();
       abstract public function TransactionRollBack();

       // These handle variable escpaing (e.g. to prevent sql injection atttacks)
       abstract public function SqlVariable($mixData, $blnIncludeEquality = false);
       abstract public function SqlLimitVariablePrefix($strLimitInfo);
       abstract public function SqlLimitVariableSuffix($strLimitInfo);
       abstract public function SqlSortByVariable($strSortByInfo);

       // Hopefully this is obvious ;^)
       abstract public function Close();

Hopefully, this should get you a good start.  Also, feel free to take a look at the MySqliDatabase class as a reference.

If you have additional questions (which I'm sure you will ;^) please post 'em and I'll try and respond ASAP.

Thanks for your help!

#3  |  SudoUser (Mill Valley, CA)
Monday, October 24, 2005, 11:52 AM PDT

This is great! I'm on it and will be in touch soon.

Cheers,
Peter

#4  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Monday, October 24, 2005, 1:06 PM PDT

Great!  And if you need any help, I've uploaded a CodeGen Object Analyzer utility that I used when I was working on the MySQL adapter (and will be using when I work on the SQL Server adapter):

http://www.qcodo.com/downloads/category.php/3

#5  |  Jocelyn Bernier (Montréal, Canada) Canada
Saturday, December 31, 2005, 11:09 PM PST

Is anybody got the Postgresql port done ? With Postgresql 8.1 I think it would be easier.

#6  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Monday, January 2, 2006, 10:28 PM PST

No... there hasn't been anything posted as of yet.  If you'd like to help out, please definitely let us know.  We'd love your assistance!

#7  |  MattBenjamin (Ann Arbor, MI)
Wednesday, January 4, 2006, 3:04 PM PST

I think the main goal is to write as little redundant code as possible, while getting the most benefit.

The message below (from the lead developer of MDB2) clarifies what the 5.1 PHP manual means by not wanting to be a general abstraction layer for RDBMSs:

http://www.zend.com/lists/pear-dev/200405/msg00963.html

PDO will be a unified API for sending queries and retrieving results, transactions, and large objects.  It won't deal with schema.  MDB2 will continue to  deal with those issues, and provide a smooth transition from PHP4 to PHP5+, ie, PDO.

When you are working with these APIs, moreover, you can still get a PHP handle to a native connection object and use its native API if you wish, I believe, so why not re-use PEAR/MDB2 as a base, and use as much native functionality as makes sense, perhaps after profiling?

You might have:

DatabaseAdapter
     ^
     |
MDB2Adapter
     ^
     |
PostgresqlAdapter  [ Later, other adapters ]

Matt

Mike Ho wrote:

> Actually, Qcodo itself offers a level of DB abstraction by funneling everything through a DatabaseAdapter API � which is why I, too, preferred using native database extensions within each individual DB Adapter.
>
>  
>
> In terms of PearDB, specifically, I know that the future of PHP is to go towards PDO as a more-native DB abstraction layer, and actually I�ve already had discussions with a few people who have worked on PDO, itself � and we do plan on incorporating PDO support into Qcodo in the future which would coexist with the current set of already-existing and planned DB Adapters (MySQL, MySQLi, SQL Server, and hopefully Postgres and Oracle).
>
>  
>
> Thanks for starting the thread, I�ll start responding there.
>
>  
>
> --Mike
>
> ----------------------------------
> Original Message:
>  
>
> The pg_meta_data function will give us everything except relations.  I had looked at that but forgot to mention it.
>
> Moving in the direction of an abstracted API might help, I don't know.  I don't know enough about PearDB.  In the past I've mainly used ADODB, but don't know if it supports metadata extraction.
>
> On a completely personal note, one of the reasons I preferred Qcodo vs others was the fact that the db support was native.  This was mainly because of the speed it provided.  However, I would fully support moving to an abstracted DB framework, as there are advantages there too.  Perhaps we could just an abstraction to help with code generation? Just an idea.
>
> I've started a thread for this discussion in the forums.  http://qcodo.com/forums/topic.php/168
>
> Mike
>
> On 1/4/06, Mike Gatny wrote:
>
> Mike Ho wrote:
> > Does Postgres offer ANY sort of API to allow for db model analysis?
> > (e.g. a “DESCRIBE xxx” to analyze the “xxx” table?)
>
> The equivalent of DESCRIBE [TABLE] using the postgres executive is:
>
> \d [TABLE]
>
> The pg_meta_data() call might be useful:
> http://us3.php.net/manual/en/function.pg-meta-data.php
>
> However, the correct direction for multiple DB support is probably an abstracted
> API, e.g. PEAR::DB (probably MDB2, eventually?).  For example, instead of
> calling pg_meta_data(), we could just call PEAR::DB's tableInfo():
>
> # http://pear.php.net/manual/en/package.database.db.db-common.tableinfo.php
> $info = $db->tableInfo('tablename');
>
> --
> Mike Gatny
> The Linux Box Corporation
> http://www.linuxbox.com/

#8  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Wednesday, January 4, 2006, 3:34 PM PST

Matt, thanks for the information.

Are you saying that MDB2 provides a unified way of getting at Schema data for all the DB platforms it wraps around?

I see that the PEAR MDB2 does talk about a unified way of reverse-engineering databases, but is it working right now?

E.g. i can simply do the equivalent of
  MDB2::GetColumnList('some_table');
and I would get the list of columns for “some_table” regardless of which db platform i'm using?

Because in a sense, that is what the Qcodo DB adapter abstraction is attempting to do.  And you're right, if that's already implemented somewhere, then that where we should be looking to take advantage of the already-invented wheel.

#9  |  MattBenjamin (Ann Arbor, MI)
Wednesday, January 4, 2006, 4:41 PM PST

Mike,

Yes, have a look:

http://pear.php.net/package/MDB2/docs/latest/MDB2/MDB2_Driver_Manager_Common.html

#10  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Thursday, January 5, 2006, 11:42 AM PST

Matt, thanks for the info.  I spent some time researching it all a bit further, but I think for now, we'll stick with the original game plan for the core (as in included) Qcodo Db Adapters (although, that of course doesn't mean peeps (or even i, myself) shouldn't feel free to implement a db adapter on their own which utilizes MDB2 if they wish :) -- and in fact that might even be a good stop-gap solution until we have native support built into Qcodo...).

In more detail: IMHO all good frameworks (with the exception of Symphony, which is a great framework that was specifcally designed to be a collection of separate frameworks) need to be very careful about incorporating other OSS packages.  For one, you add an unknown dependency in terms of IP, versioning, design/architecture, maintenance, etc.  It also adds at the very least an added step for people to install.

Now I'm not saying that we're fantatic “Not Invented Here” freaks, nor am I saying that Qcodo will never incorporate other packages out there.  In fact, we're actively looking at Prototype, script.aculo.us and OpenRico to see if we can incorporate any of those to help with our AJAX implementations.  I'm just saying that there needs to be a very strong, compelling argument and benefit before going forward with outside-package incorporation.

And unfortunately, I don't think the argument for MDB2 is strong enough; it is considerably more heavy-weight than we need.  It's also written in PHP4, and while it does appear that it is compatible with PHP5, it does fail strict PHP5 compliance (as will any OO-based framework that wants to work be compatible with PHP4 and PHP5).

Also, given the way the Qcodo DB Adapter API is designed, and given its differences with the MDB2 class API, either significant parts of the CodeGenerator class would have to be rewritten, or a separate class wrapper would have to be written around the MDB2 class API.  The former would be such an large effort that it would likely be easier and take less time to just finish up the main two-missing adapters (Postgres and Oracle).  The latter would add yet another layer of abstraction which I fear would negatively impact performance.

Now, I reiterate, that doing the latter (writing a Qcodo MDB2 DB Adapter) might still be a good idea so that we can at least have a good temporary solution for people if they need Oracle, Postgres, etc. support immediately.  But i think that would be a separate solution (e.g. independently uploaded in the Downloads section) and wouldn't be part of the core release, but a good temporary solution that developers can use until the Qcodo-native DB support for these various vendors are in place.



Copyright © 2005 - 2010, Quasidea Development, LLC
This open-source framework for PHP is released under the terms of The MIT License.