PgSQLTableInfo Class Reference

Inheritance diagram for PgSQLTableInfo:

TableInfo

List of all members.

Public Member Functions

 __construct (DatabaseInfo $database, $name, $version, $intOID)

Protected Member Functions

 initColumns ()
 Load the columns for this table.
 initForeignKeys ()
 Load foreign keys for this table.
 initIndexes ()
 Load indexes for this table.
 initPrimaryKey ()
 Loads the primary keys for this table.

Private Member Functions

 processLengthScale ($intTypmod, $strName)
 processDomain ($strDomain)

Private Attributes

 $version
 $oid


Detailed Description

Definition at line 40 of file PgSQLTableInfo.php.


Constructor & Destructor Documentation

PgSQLTableInfo::__construct ( DatabaseInfo database,
name,
version,
intOID 
)

Parameters:
string $table The table name.
string $database The database name.
resource $dblink The db connection resource.

Definition at line 59 of file PgSQLTableInfo.php.

References TableInfo::$name, and $version.

00059                                                                            {
00060         parent::__construct ($database, $name);
00061         $this->version = $version;
00062         $this->oid = $intOID;
00063     } // function __construct(DatabaseInfo $database, $name) {


Member Function Documentation

PgSQLTableInfo::initColumns (  )  [protected]

Load the columns for this table.

Reimplemented from TableInfo.

Definition at line 66 of file PgSQLTableInfo.php.

References TableInfo::$name, $result, PgSQLTypes::getType(), processDomain(), and processLengthScale().

Referenced by initIndexes(), and initPrimaryKey().

00066                                       {
00067       // Include dependencies
00068       include_once ('creole/metadata/ColumnInfo.php');
00069       include_once ('creole/drivers/pgsql/PgSQLTypes.php');
00070 
00071       // Get the columns, types, etc.
00072       // Based on code from pgAdmin3 (http://www.pgadmin.org/)
00073       $result = pg_query ($this->conn->getResource(), sprintf ("SELECT 
00074                     att.attname,
00075                     att.atttypmod,
00076                     att.atthasdef,
00077                     att.attnotnull,
00078                     def.adsrc, 
00079                     CASE WHEN att.attndims > 0 THEN 1 ELSE 0 END AS isarray, 
00080                     CASE 
00081                       WHEN ty.typname = 'bpchar' 
00082                         THEN 'char' 
00083                       WHEN ty.typname = '_bpchar' 
00084                         THEN '_char' 
00085                       ELSE 
00086                         ty.typname 
00087                     END AS typname,
00088                     ty.typtype
00089                 FROM pg_attribute att
00090                   JOIN pg_type ty ON ty.oid=att.atttypid
00091                   LEFT OUTER JOIN pg_attrdef def ON adrelid=att.attrelid AND adnum=att.attnum
00092                 WHERE att.attrelid = %d AND att.attnum > 0
00093                   AND att.attisdropped IS FALSE
00094                 ORDER BY att.attnum", $this->oid));
00095 
00096         if (!$result) {
00097             throw new SQLException("Could not list fields for table: " . $this->name, pg_last_error($this->conn->getResource()));
00098         }
00099         while($row = pg_fetch_assoc($result)) {
00100           
00101           $size = null;
00102           $precision = null;
00103           $scale = null;
00104           
00105           // Check to ensure that this column isn't an array data type
00106           if (((int) $row['isarray']) === 1)
00107           {
00108             throw new SQLException (sprintf ("Array datatypes are not currently supported [%s.%s]", $this->name, $row['attname']));
00109           } // if (((int) $row['isarray']) === 1)
00110             $name = $row['attname'];
00111             // If they type is a domain, Process it
00112             if (strtolower ($row['typtype']) == 'd')
00113             {
00114               $arrDomain = $this->processDomain ($row['typname']);
00115               $type = $arrDomain['type'];
00116               $size = $arrDomain['length'];
00117               $precision = $size;
00118               $scale = $arrDomain['scale'];
00119               $boolHasDefault = (strlen (trim ($row['atthasdef'])) > 0) ? $row['atthasdef'] : $arrDomain['hasdefault'];
00120               $default = (strlen (trim ($row['adsrc'])) > 0) ? $row['adsrc'] : $arrDomain['default'];
00121               $is_nullable = (strlen (trim ($row['attnotnull'])) > 0) ? $row['attnotnull'] : $arrDomain['notnull'];
00122               $is_nullable = (($is_nullable == 't') ? false : true);
00123             } // if (strtolower ($row['typtype']) == 'd')
00124             else
00125             {
00126               $type = $row['typname'];
00127               $arrLengthPrecision = $this->processLengthScale ($row['atttypmod'], $type);
00128               $size = $arrLengthPrecision['length'];
00129               $precision = $size;
00130               $scale = $arrLengthPrecision['scale'];
00131               $boolHasDefault = $row['atthasdef'];
00132               $default = $row['adsrc'];
00133               $is_nullable = (($row['attnotnull'] == 't') ? false : true);
00134             } // else (strtolower ($row['typtype']) == 'd')
00135 
00136             $autoincrement = null;
00137                        
00138             // if column has a default
00139             if (($boolHasDefault == 't') && (strlen (trim ($default)) > 0))
00140             {
00141               if (!preg_match('/^nextval\(/', $default))
00142               {
00143                 $strDefault= preg_replace ('/::[\W\D]*/', '', $default);
00144                 $default = str_replace ("'", '', $strDefault);
00145               } // if (!preg_match('/^nextval\(/', $row['atthasdef']))
00146               else
00147               {
00148                 $autoincrement = true;
00149                 $default = null;
00150               } // else
00151             } // if (($boolHasDefault == 't') && (strlen (trim ($default)) > 0))
00152             else
00153             {
00154               $default = null;
00155             } // else (($boolHasDefault == 't') && (strlen (trim ($default)) > 0))
00156 
00157             $this->columns[$name] = new ColumnInfo($this, $name, PgSQLTypes::getType($type), $type, $size, $precision, $scale, $is_nullable, $default, $autoincrement);
00158         }
00159 
00160         $this->colsLoaded = true;
00161     } // protected function initColumns ()

PgSQLTableInfo::initForeignKeys (  )  [protected]

Load foreign keys for this table.

Reimplemented from TableInfo.

Definition at line 243 of file PgSQLTableInfo.php.

References TableInfo::$name, $result, ForeignKeyInfo::CASCADE, ForeignKeyInfo::NONE, ForeignKeyInfo::RESTRICT, ForeignKeyInfo::SETDEFAULT, and ForeignKeyInfo::SETNULL.

00244     {
00245         include_once 'creole/metadata/ForeignKeyInfo.php';
00246 
00247         $result = pg_query ($this->conn->getResource(), sprintf ("SELECT
00248                   conname,
00249                   confupdtype,
00250                   confdeltype,
00251                   cl.relname as fktab,
00252                   a2.attname as fkcol,
00253                   cr.relname as reftab,
00254                   a1.attname as refcol
00255             FROM pg_constraint ct
00256                  JOIN pg_class cl ON cl.oid=conrelid
00257                  JOIN pg_class cr ON cr.oid=confrelid
00258                  LEFT JOIN pg_catalog.pg_attribute a1 ON a1.attrelid = ct.confrelid
00259                  LEFT JOIN pg_catalog.pg_attribute a2 ON a2.attrelid = ct.conrelid
00260             WHERE
00261                  contype='f'
00262                  AND conrelid = %d
00263                  AND a2.attnum = ct.conkey[1]
00264                  AND a1.attnum = ct.confkey[1]
00265             ORDER BY conname", $this->oid));
00266         if (!$result) {
00267             throw new SQLException("Could not list foreign keys for table: " . $this->name, pg_last_error($this->conn->getResource()));
00268         }
00269 
00270         while($row = pg_fetch_assoc($result)) {
00271             $name = $row['conname'];
00272             $local_table = $row['fktab'];
00273             $local_column = $row['fkcol'];
00274             $foreign_table = $row['reftab'];
00275             $foreign_column = $row['refcol'];
00276 
00277             // On Update
00278             switch ($row['confupdtype']) {
00279               case 'c':
00280                 $onupdate = ForeignKeyInfo::CASCADE; break;
00281               case 'd':
00282                 $onupdate = ForeignKeyInfo::SETDEFAULT; break;
00283               case 'n':
00284                 $onupdate = ForeignKeyInfo::SETNULL; break;
00285               case 'r':
00286                 $onupdate = ForeignKeyInfo::RESTRICT; break;
00287               default:
00288               case 'a':
00289                 //NOACTION is the postgresql default
00290                 $onupdate = ForeignKeyInfo::NONE; break;
00291             }
00292             // On Delete
00293             switch ($row['confdeltype']) {
00294               case 'c':
00295                 $ondelete = ForeignKeyInfo::CASCADE; break;
00296               case 'd':
00297                 $ondelete = ForeignKeyInfo::SETDEFAULT; break;
00298               case 'n':
00299                 $ondelete = ForeignKeyInfo::SETNULL; break;
00300               case 'r':
00301                 $ondelete = ForeignKeyInfo::RESTRICT; break;
00302               default:
00303               case 'a':
00304                 //NOACTION is the postgresql default
00305                 $ondelete = ForeignKeyInfo::NONE; break;
00306             }
00307 
00308 
00309             $foreignTable = $this->database->getTable($foreign_table);
00310             $foreignColumn = $foreignTable->getColumn($foreign_column);
00311 
00312             $localTable   = $this->database->getTable($local_table);
00313             $localColumn   = $localTable->getColumn($local_column);
00314 
00315             if (!isset($this->foreignKeys[$name])) {
00316                 $this->foreignKeys[$name] = new ForeignKeyInfo($name);
00317             }
00318             $this->foreignKeys[$name]->addReference($localColumn, $foreignColumn, $ondelete, $onupdate);
00319         }
00320 
00321         $this->fksLoaded = true;
00322     }

PgSQLTableInfo::initIndexes (  )  [protected]

Load indexes for this table.

Reimplemented from TableInfo.

Definition at line 325 of file PgSQLTableInfo.php.

References TableInfo::$name, $result, TableInfo::indexesLoaded(), and initColumns().

00326     {
00327         include_once 'creole/metadata/IndexInfo.php';
00328 
00329         // columns have to be loaded first
00330         if (!$this->colsLoaded) $this->initColumns();
00331 
00332     $result = pg_query ($this->conn->getResource(), sprintf ("SELECT
00333                                 DISTINCT ON(cls.relname)
00334                                 cls.relname as idxname,
00335                                 indkey,
00336                                 indisunique
00337                           FROM pg_index idx
00338                                JOIN pg_class cls ON cls.oid=indexrelid
00339                           WHERE indrelid = %d AND NOT indisprimary
00340                           ORDER BY cls.relname", $this->oid));
00341 
00342 
00343         if (!$result) {
00344             throw new SQLException("Could not list indexes keys for table: " . $this->name, pg_last_error($this->conn->getResource()));
00345         }
00346 
00347         while($row = pg_fetch_assoc($result)) {
00348             $name = $row["idxname"];
00349             $unique = ($row["indisunique"] == 't') ? true : false;
00350             if (!isset($this->indexes[$name])) {
00351                 $this->indexes[$name] = new IndexInfo($name, $unique);
00352             }
00353             $arrColumns = explode (' ', $row['indkey']);
00354             foreach ($arrColumns as $intColNum)
00355             {
00356               $result2 = pg_query ($this->conn->getResource(), sprintf ("SELECT a.attname
00357                               FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
00358                               WHERE c.oid = '%s' AND a.attnum = %d AND NOT a.attisdropped
00359                               ORDER BY a.attnum", $this->oid, $intColNum));
00360         if (!$result2)
00361         {
00362                 throw new SQLException("Could not list indexes keys for table: " . $this->name, pg_last_error($this->conn->getResource()));
00363         }
00364         $row2 = pg_fetch_assoc($result2);
00365               $this->indexes[$name]->addColumn($this->columns[ $row2['attname'] ]);
00366       } // foreach ($arrColumns as $intColNum)
00367         }
00368 
00369         $this->indexesLoaded = true;
00370     }

PgSQLTableInfo::initPrimaryKey (  )  [protected]

Loads the primary keys for this table.

Reimplemented from TableInfo.

Definition at line 373 of file PgSQLTableInfo.php.

References $result, and initColumns().

00373                                         {
00374 
00375         include_once 'creole/metadata/PrimaryKeyInfo.php';
00376 
00377 
00378         // columns have to be loaded first
00379         if (!$this->colsLoaded) $this->initColumns();
00380 
00381         // Primary Keys
00382         
00383         $result = pg_query($this->conn->getResource(), sprintf ("SELECT
00384                                 DISTINCT ON(cls.relname)
00385                                 cls.relname as idxname,
00386                                 indkey,
00387                                 indisunique
00388                           FROM pg_index idx
00389                                JOIN pg_class cls ON cls.oid=indexrelid
00390                           WHERE indrelid = %s AND indisprimary
00391                           ORDER BY cls.relname", $this->oid));
00392         if (!$result) {
00393             throw new SQLException("Could not list primary keys for table: " . $this->name, pg_last_error($this->conn->getResource()));
00394         }
00395 
00396         // Loop through the returned results, grouping the same key_name together
00397         // adding each column for that key.
00398 
00399         while($row = pg_fetch_assoc($result)) {
00400             $arrColumns = explode (' ', $row['indkey']);
00401             foreach ($arrColumns as $intColNum)
00402             {
00403               $result2 = pg_query ($this->conn->getResource(), sprintf ("SELECT a.attname
00404                               FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
00405                               WHERE c.oid = '%s' AND a.attnum = %d AND NOT a.attisdropped
00406                               ORDER BY a.attnum", $this->oid, $intColNum));
00407         if (!$result2)
00408         {
00409                 throw new SQLException("Could not list indexes keys for table: " . $this->name, pg_last_error($this->conn->getResource()));
00410         }
00411         $row2 = pg_fetch_assoc($result2);
00412         if (!isset($this->primaryKey)) {
00413           $this->primaryKey = new PrimaryKeyInfo($row2['attname']);
00414         }
00415               $this->primaryKey->addColumn($this->columns[ $row2['attname'] ]);
00416       } // foreach ($arrColumns as $intColNum)
00417         }
00418         $this->pkLoaded = true;
00419     }

PgSQLTableInfo::processDomain ( strDomain  )  [private]

Definition at line 200 of file PgSQLTableInfo.php.

References $result, and processLengthScale().

Referenced by initColumns().

00201     {
00202       if (strlen (trim ($strDomain)) < 1)
00203       {
00204         throw new SQLException ("Invalid domain name [" . $strDomain . "]");
00205       } // if (strlen (trim ($strDomain)) < 1)
00206       $result = pg_query ($this->conn->getResource(), sprintf ("SELECT
00207                             d.typname as domname,
00208                             b.typname as basetype,
00209                             d.typlen,
00210                             d.typtypmod,
00211                             d.typnotnull,
00212                             d.typdefault
00213                           FROM pg_type d
00214                             INNER JOIN pg_type b ON b.oid = CASE WHEN d.typndims > 0 then d.typelem ELSE d.typbasetype END
00215                           WHERE
00216                             d.typtype = 'd'
00217                             AND d.typname = '%s'
00218                           ORDER BY d.typname", $strDomain));
00219 
00220         if (!$result) {
00221             throw new SQLException("Query for domain [" . $strDomain . "] failed.", pg_last_error($this->conn->getResource()));
00222         }
00223 
00224         $row = pg_fetch_assoc ($result);
00225         if (!$row)
00226         {
00227           throw new SQLException ("Domain [" . $strDomain . "] not found.");
00228         } // if (!$row)
00229         $arrDomain = array ();
00230         $arrDomain['type'] = $row['basetype'];
00231       $arrLengthPrecision = $this->processLengthScale ($row['typtypmod'], $row['basetype']);
00232       $arrDomain['length'] = $arrLengthPrecision['length'];
00233       $arrDomain['scale'] = $arrLengthPrecision['scale'];
00234       $arrDomain['notnull'] = $row['typnotnull'];
00235       $arrDomain['default'] = $row['typdefault'];
00236       $arrDomain['hasdefault'] = (strlen (trim ($row['typdefault'])) > 0) ? 't' : 'f';
00237 
00238       pg_free_result ($result);
00239       return $arrDomain;
00240     } // private function processDomain ($strDomain)

PgSQLTableInfo::processLengthScale ( intTypmod,
strName 
) [private]

Definition at line 163 of file PgSQLTableInfo.php.

References PgSQLTypes::getNativeType(), CreoleTypes::NUMERIC, CreoleTypes::TIME, and CreoleTypes::TIMESTAMP.

Referenced by initColumns(), and processDomain().

00164     {
00165       // Define the return array
00166       $arrRetVal = array ('length'=>null, 'scale'=>null);
00167 
00168       // Some datatypes don't have a Typmod
00169       if ($intTypmod == -1)
00170       {
00171         return $arrRetVal;
00172       } // if ($intTypmod == -1)
00173 
00174       // Numeric Datatype?
00175       if ($strName == PgSQLTypes::getNativeType (CreoleTypes::NUMERIC))
00176       {
00177         $intLen = ($intTypmod - 4) >> 16;
00178         $intPrec = ($intTypmod - 4) & 0xffff;
00179         $intLen = sprintf ("%ld", $intLen);
00180         if ($intPrec)
00181         {
00182           $intPrec = sprintf ("%ld", $intPrec);
00183         } // if ($intPrec)
00184         $arrRetVal['length'] = $intLen;
00185         $arrRetVal['scale'] = $intPrec;
00186       } // if ($strName == PgSQLTypes::getNativeType (CreoleTypes::NUMERIC))
00187       elseif ($strName == PgSQLTypes::getNativeType (CreoleTypes::TIME) || $strName == 'timetz'
00188         || $strName == PgSQLTypes::getNativeType (CreoleTypes::TIMESTAMP) || $strName == 'timestamptz'
00189         || $strName == 'interval' || $strName == 'bit')
00190       {
00191         $arrRetVal['length'] = sprintf ("%ld", $intTypmod);
00192       } // elseif (TIME, TIMESTAMP, INTERVAL, BIT)
00193       else
00194       {
00195         $arrRetVal['length'] = sprintf ("%ld", ($intTypmod - 4));
00196       } // else
00197       return $arrRetVal;
00198     } // private function processLengthScale ($intTypmod, $strName)


Member Data Documentation

PgSQLTableInfo::$oid [private]

Definition at line 52 of file PgSQLTableInfo.php.

PgSQLTableInfo::$version [private]

Definition at line 46 of file PgSQLTableInfo.php.

Referenced by __construct().


The documentation for this class was generated from the following file:

Generated on Wed May 6 23:10:50 2009 for fareofficelib by  doxygen 1.5.8