PgSQLTableInfo.php

Go to the documentation of this file.
00001 <?php 00002 /* 00003 * $Id: PgSQLTableInfo.php,v 1.1 2004/04/28 17:51:31 micha 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 // ported 00023 00024 require_once 'creole/metadata/TableInfo.php'; 00025 00043 class PgSQLTableInfo extends TableInfo 00044 { 00049 function initColumns() 00050 { 00051 include_once 'creole/metadata/ColumnInfo.php'; 00052 include_once 'creole/drivers/pgsql/PgSQLTypes.php'; 00053 00054 // Get any default values for columns 00055 $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"); 00056 00057 if (!$result) { 00058 return new SQLException(CREOLE_ERROR, "Could not get defaults for columns in table: " . $this->name, pg_last_error($this->dblink)); 00059 } 00060 00061 $defaults = array(); 00062 while($row = pg_fetch_assoc($result)) { 00063 // [HL] for now I am going to not add default 00064 // values that are nextval(...) sequence values. 00065 // We need to resolve on a larger level whether these should 00066 // be returned. Maybe instead indicating that these columns are 00067 // sequences would be appropriate... 00068 if (!preg_match('/^nextval\(/', $row['def'])) { 00069 $defaults[ $row['num'] ] = $row['def']; 00070 } 00071 } 00072 00073 // Get the columns, types, etc. 00074 // based on SQL from ADOdb 00075 $result = pg_query($this->dblink, "SELECT a.attname, 00076 t.typname, 00077 a.attlen, 00078 a.atttypmod, 00079 a.attnotnull, 00080 a.atthasdef, 00081 a.attnum, 00082 CAST( 00083 CASE WHEN t.typtype = 'd' THEN 00084 CASE WHEN t.typbasetype IN (21, 23, 20) THEN 0 00085 WHEN t.typbasetype IN (1700) THEN (t.typtypmod - 4) & 65535 00086 ELSE null END 00087 ELSE 00088 CASE WHEN a.atttypid IN (21, 23, 20) THEN 0 00089 WHEN a.atttypid IN (1700) THEN (a.atttypmod - 4) & 65535 00090 ELSE null END 00091 END 00092 AS int) AS numeric_scale 00093 FROM pg_class c, 00094 pg_attribute a, 00095 pg_type t 00096 WHERE relkind = 'r' AND 00097 c.relname='".$this->name."' AND 00098 a.attnum > 0 AND 00099 a.atttypid = t.oid AND 00100 a.attrelid = c.oid 00101 ORDER BY a.attnum"); 00102 00103 if (!$result) { 00104 return new SQLException(CREOLE_ERROR, "Could not list fields for table: " . $this->name, pg_last_error($this->dblink)); 00105 } 00106 00107 while($row = pg_fetch_assoc($result)) { 00108 $name = $row['attname']; 00109 $type = $row['typname']; 00110 $size = $row['attlen']; 00111 $scale = $row['numeric_scale']; 00112 if ($size <= 0) { 00113 // maxlen for varchar is 4 larger than actual max length 00114 $size = $row['atttypmod'] - 4; 00115 if ($size <= 0) { 00116 $size = null; 00117 } 00118 } 00119 00120 $is_nullable = ($row['attnotnull'] == 't' ? true : false); 00121 $default = ($row['atthasdef'] == 't' && isset( $defaults[ $row['attnum'] ]) ? $defaults[ $row['attnum'] ] : null); 00122 $this->columns[$name] =& new ColumnInfo($this, $name, PgSQLTypes::getType($type), $type, $size, $scale, $is_nullable, $default); 00123 } 00124 00125 $this->colsLoaded = true; 00126 return true; 00127 } 00128 00133 function initForeignKeys() 00134 { 00135 include_once 'creole/metadata/ForeignKeyInfo.php'; 00136 00137 $result = pg_query($this->dblink, "SELECT tgargs 00138 FROM pg_trigger 00139 WHERE tgrelid = (select oid from pg_class where relname='".$this->name."') 00140 AND tgfoid = (select oid from pg_proc where proname='RI_FKey_check_ins')"); 00141 if (!$result) { 00142 return new SQLException(CREOLE_ERROR, "Could not list foreign keys for table: " . $this->name, pg_last_error($this->dblink)); 00143 } 00144 00145 // tgargs ($row[0]) looks like this: 00146 // _fk_1\000book\000publisher\000UNSPECIFIED\000publisher_id\000publisher_id\000 00147 // name? table references ? key fkey 00148 // 0 1 2 3 4 5 00149 00150 while($row = pg_fetch_row($result)) 00151 { 00152 $parts = explode('\000', $row[0]); 00153 $name = $parts[0]; 00154 $local_table = $parts[1]; 00155 $foreign_table = $parts[2]; 00156 $local_column = $parts[4]; 00157 $foreign_column = $parts[5]; 00158 00159 $foreignTable =& $this->database->getTable($foreign_table); 00160 if (Creole::isError($foreignTable)) return $foreignTable; 00161 00162 $foreignColumn =& $foreignTable->getColumn($foreign_column); 00163 if (Creole::isError($foreignColumn)) return $foreignColumn; 00164 00165 $localTable =& $this->database->getTable($local_table); 00166 if (Creole::isError($localTable)) return $localTable; 00167 00168 $localColumn =& $localTable->getColumn($local_column); 00169 if (Creole::isError($localColumn)) return $localColumn; 00170 00171 if (!isset($this->foreignKeys[$name])) { 00172 $this->foreignKeys[$name] =& new ForeignKeyInfo($name); 00173 } 00174 $this->foreignKeys[$name]->addReference($localColumn, $foreignColumn); 00175 } 00176 00177 $this->fksLoaded = true; 00178 return true; 00179 } 00180 00185 function initIndexes() 00186 { 00187 include_once 'creole/metadata/IndexInfo.php'; 00188 00189 // columns have to be loaded first 00190 if (!$this->colsLoaded) { 00191 if (($e = $this->initColumns()) !== true) { 00192 return $e; 00193 } 00194 } 00195 00196 // FIXME -- try this out! 00197 // then figure out if we need to add any information 00198 // to our index object to accommodate more complex backends 00199 00200 $result = pg_query($this->dblink, "SELECT c.relname as tablename, c.oid, c2.relname as indexname, 00201 00202 i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid) FROM 00203 00204 pg_catalog.pg_class c, 00205 00206 pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c.oid = i.indrelid AND 00207 00208 i.indexrelid = c2.oid AND c.relname = ".$this->name." ORDER BY i.indisprimary DESC, i.indisunique DESC, 00209 00210 c2.relname"); 00211 00212 if (!$result) { 00213 return new SQLException(CREOLE_ERROR, "Could not list indexes keys for table: " . $this->name, pg_last_error($this->dblink)); 00214 } 00215 00216 while($row = pg_fetch_assoc($result)) { 00217 $name = $row["indexname"]; 00218 if (!isset($this->indexes[$name])) { 00219 $this->indexes[$name] =& new IndexInfo($name); 00220 } 00221 $this->indexes[$name]->addColumn($this->columns[ $name ]); 00222 } 00223 00224 $this->indexesLoaded = true; 00225 return true; 00226 } 00227 00232 function initPrimaryKey() 00233 { 00234 include_once 'creole/metadata/PrimaryKeyInfo.php'; 00235 00236 // columns have to be loaded first 00237 if (!$this->colsLoaded) { 00238 if (($e = $this->initColumns()) !== true) { 00239 return $e; 00240 } 00241 } 00242 00243 // Primary Keys 00244 $result = pg_query($this->dblink, "SELECT ta.attname, ia.attnum 00245 FROM pg_attribute ta, pg_attribute ia, pg_class c, pg_index i 00246 WHERE c.relname = '".$this->name."_pkey' 00247 AND c.oid = i.indexrelid 00248 AND ia.attrelid = i.indexrelid 00249 AND ta.attrelid = i.indrelid 00250 AND ta.attnum = i.indkey[ia.attnum-1] 00251 ORDER BY ia.attnum"); 00252 00253 if (!$result) { 00254 return new SQLException(CREOLE_ERROR, "Could not list primary keys for table: " . $this->name, pg_last_error($this->dblink)); 00255 } 00256 00257 // Loop through the returned results, grouping the same key_name together 00258 // adding each column for that key. 00259 00260 while($row = pg_fetch_assoc($result)) { 00261 $name = $row["attname"]; 00262 if (!isset($this->primaryKey)) { 00263 $this->primaryKey =& new PrimaryKeyInfo($name); 00264 } 00265 $this->primaryKey->addColumn($this->columns[ $name ]); 00266 } 00267 00268 $this->pkLoaded = true; 00269 return true; 00270 } 00271 00272 }

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


Copyright © 2004 Hans Lellelid  
Creole[php4] CVS