PgSQLTableInfo.php

Go to the documentation of this file.
00001 <?php 00002 /* 00003 * $Id: PgSQLTableInfo.php,v 1.24 2004/04/09 20:12:12 hlellelid Exp $ 00004 * 00005 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00006 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00007 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00008 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00009 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00010 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00011 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00012 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00013 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00014 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00015 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00016 * 00017 * This software consists of voluntary contributions made by many individuals 00018 * and is licensed under the LGPL. For more information please see 00019 * <http://creole.phpdb.org>. 00020 */ 00021 00022 require_once 'creole/metadata/TableInfo.php'; 00023 00040 class PgSQLTableInfo extends TableInfo { 00041 00043 protected function initColumns() { 00044 00045 include_once 'creole/metadata/ColumnInfo.php'; 00046 include_once 'creole/drivers/pgsql/PgSQLTypes.php'; 00047 00048 // Get any default values for columns 00049 $result = pg_query($this->dblink, "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='".$this->name."' order by d.adnum"); 00050 00051 if (!$result) { 00052 throw new SQLException("Could not get defaults for columns in table: " . $this->name, pg_last_error($this->dblink)); 00053 } 00054 00055 $defaults = array(); 00056 while($row = pg_fetch_assoc($result)) { 00057 // [HL] for now I am going to not add default 00058 // values that are nextval(...) sequence values. 00059 // We need to resolve on a larger level whether these should 00060 // be returned. Maybe instead indicating that these columns are 00061 // sequences would be appropriate... 00062 if (!preg_match('/^nextval\(/', $row['def'])) { 00063 $defaults[ $row['num'] ] = $row['def']; 00064 } 00065 } 00066 00067 // Get the columns, types, etc. 00068 // based on SQL from ADOdb 00069 $result = pg_query($this->dblink, "SELECT a.attname, 00070 t.typname, 00071 a.attlen, 00072 a.atttypmod, 00073 a.attnotnull, 00074 a.atthasdef, 00075 a.attnum, 00076 CAST( 00077 CASE WHEN t.typtype = 'd' THEN 00078 CASE WHEN t.typbasetype IN (21, 23, 20) THEN 0 00079 WHEN t.typbasetype IN (1700) THEN (t.typtypmod - 4) & 65535 00080 ELSE null END 00081 ELSE 00082 CASE WHEN a.atttypid IN (21, 23, 20) THEN 0 00083 WHEN a.atttypid IN (1700) THEN (a.atttypmod - 4) & 65535 00084 ELSE null END 00085 END 00086 AS int) AS numeric_scale 00087 FROM pg_class c, 00088 pg_attribute a, 00089 pg_type t 00090 WHERE relkind = 'r' AND 00091 c.relname='".$this->name."' AND 00092 a.attnum > 0 AND 00093 a.atttypid = t.oid AND 00094 a.attrelid = c.oid 00095 ORDER BY a.attnum"); 00096 00097 if (!$result) { 00098 throw new SQLException("Could not list fields for table: " . $this->name, pg_last_error($this->dblink)); 00099 } 00100 00101 while($row = pg_fetch_assoc($result)) { 00102 $name = $row['attname']; 00103 $type = $row['typname']; 00104 $size = $row['attlen']; 00105 $scale = $row['numeric_scale']; 00106 if ($size <= 0) { 00107 // maxlen for varchar is 4 larger than actual max length 00108 $size = $row['atttypmod'] - 4; 00109 if ($size <= 0) { 00110 $size = null; 00111 } 00112 } 00113 00114 $is_nullable = ($row['attnotnull'] == 't' ? true : false); 00115 $default = ($row['atthasdef'] == 't' && isset( $defaults[ $row['attnum'] ]) ? $defaults[ $row['attnum'] ] : null); 00116 $this->columns[$name] = new ColumnInfo($this, $name, PgSQLTypes::getType($type), $type, $size, $scale, $is_nullable, $default); 00117 } 00118 00119 $this->colsLoaded = true; 00120 } 00121 00123 protected function initForeignKeys() 00124 { 00125 include_once 'creole/metadata/ForeignKeyInfo.php'; 00126 00127 $result = pg_query($this->dblink, "SELECT tgargs 00128 FROM pg_trigger 00129 WHERE tgrelid = (select oid from pg_class where relname='".$this->name."') 00130 AND tgfoid = (select oid from pg_proc where proname='RI_FKey_check_ins')"); 00131 if (!$result) { 00132 throw new SQLException("Could not list foreign keys for table: " . $this->name, pg_last_error($this->dblink)); 00133 } 00134 00135 // tgargs ($row[0]) looks like this: 00136 // _fk_1\000book\000publisher\000UNSPECIFIED\000publisher_id\000publisher_id\000 00137 // name? table references ? key fkey 00138 // 0 1 2 3 4 5 00139 00140 while($row = pg_fetch_row($result)) { 00141 00142 $parts = explode('\000', $row[0]); 00143 $name = $parts[0]; 00144 $local_table = $parts[1]; 00145 $foreign_table = $parts[2]; 00146 $local_column = $parts[4]; 00147 $foreign_column = $parts[5]; 00148 00149 $foreignTable = $this->database->getTable($foreign_table); 00150 $foreignColumn = $foreignTable->getColumn($foreign_column); 00151 00152 $localTable = $this->database->getTable($local_table); 00153 $localColumn = $localTable->getColumn($local_column); 00154 00155 if (!isset($this->foreignKeys[$name])) { 00156 $this->foreignKeys[$name] = new ForeignKeyInfo($name); 00157 } 00158 $this->foreignKeys[$name]->addReference($localColumn, $foreignColumn); 00159 } 00160 00161 $this->fksLoaded = true; 00162 } 00163 00165 protected function initIndexes() 00166 { 00167 include_once 'creole/metadata/IndexInfo.php'; 00168 00169 // columns have to be loaded first 00170 if (!$this->colsLoaded) $this->initColumns(); 00171 00172 // FIXME -- try this out! 00173 // then figure out if we need to add any information 00174 // to our index object to accommodate more complex backends 00175 00176 $result = pg_query($this->dblink, "SELECT c.relname as tablename, c.oid, c2.relname as indexname, 00177 00178 i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid) FROM 00179 00180 pg_catalog.pg_class c, 00181 00182 pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c.oid = i.indrelid AND 00183 00184 i.indexrelid = c2.oid AND c.relname = ".$this->name." ORDER BY i.indisprimary DESC, i.indisunique DESC, 00185 00186 c2.relname"); 00187 00188 00189 if (!$result) { 00190 throw new SQLException("Could not list indexes keys for table: " . $this->name, pg_last_error($this->dblink)); 00191 } 00192 00193 while($row = pg_fetch_assoc($result)) { 00194 $name = $row["indexname"]; 00195 if (!isset($this->indexes[$name])) { 00196 $this->indexes[$name] = new IndexInfo($name); 00197 } 00198 $this->indexes[$name]->addColumn($this->columns[ $name ]); 00199 } 00200 00201 $this->indexesLoaded = true; 00202 } 00203 00205 protected function initPrimaryKey() { 00206 00207 include_once 'creole/metadata/PrimaryKeyInfo.php'; 00208 00209 00210 // columns have to be loaded first 00211 if (!$this->colsLoaded) $this->initColumns(); 00212 00213 // Primary Keys 00214 $result = pg_query($this->dblink, "select ta.attname, ia.attnum 00215 from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i 00216 where c.relname = '".$this->name."_pkey' 00217 AND c.oid = i.indexrelid 00218 AND ia.attrelid = i.indexrelid 00219 AND ta.attrelid = i.indrelid 00220 AND ta.attnum = i.indkey[ia.attnum-1] 00221 ORDER BY ia.attnum"); 00222 00223 if (!$result) { 00224 throw new SQLException("Could not list primary keys for table: " . $this->name, pg_last_error($this->dblink)); 00225 } 00226 00227 // Loop through the returned results, grouping the same key_name together 00228 // adding each column for that key. 00229 00230 while($row = pg_fetch_assoc($result)) { 00231 $name = $row["attname"]; 00232 if (!isset($this->primaryKey)) { 00233 $this->primaryKey = new PrimaryKeyInfo($name); 00234 } 00235 $this->primaryKey->addColumn($this->columns[ $name ]); 00236 } 00237 00238 $this->pkLoaded = true; 00239 } 00240 00241 }

This file is part of the Creole[php5] library.


Copyright © 2004 Hans Lellelid  
Creole[php5] CVS