drop and create indexes REL_0-5-0
authorchriskl <chriskl>
Sat, 14 Dec 2002 10:56:26 +0000 (10:56 +0000)
committerchriskl <chriskl>
Sat, 14 Dec 2002 10:56:26 +0000 (10:56 +0000)
classes/database/Postgres.php
public_html/tblproperties.php

index a534c768ab8bfa242bd36132a270f60ae9eefcc1..a24521822eaae1b90b80411013ef5d8e27c022be 100755 (executable)
-<?php\r
-\r
-/**\r
- * A class that implements the DB interface for Postgres\r
- * Note: This class uses ADODB and returns RecordSets.\r
- *\r
- * $Id: Postgres.php,v 1.24 2002/11/18 05:49:55 chriskl Exp $\r
- */\r
-\r
-// @@@ THOUGHT: What about inherits? ie. use of ONLY???\r
-\r
-include_once('../classes/database/BaseDB.php');\r
-\r
-class Postgres extends BaseDB {\r
-\r
-       var $dbFields = array('dbname' => 'datname', 'dbcomment' => 'description');\r
-       var $tbFields = array('tbname' => 'tablename', 'tbowner' => 'tableowner');\r
-       var $vwFields = array('vwname' => 'viewname', 'vwowner' => 'viewowner', 'vwdef' => 'definition');\r
-       var $uFields = array('uname' => 'usename', 'usuper' => 'usesuper', 'ucreatedb' => 'usecreatedb', 'uexpires' => 'valuntil');\r
-       var $sqFields = array('seqname' => 'relname', 'seqowner' => 'usename', 'lastvalue' => 'last_value', 'incrementby' => 'increment_by', 'maxvalue' => 'max_value', 'minvalue'=> 'min_value', 'cachevalue' => 'cache_value', 'logcount' => 'log_cnt', 'iscycled' => 'is_cycled', 'iscalled' => 'is_called' );\r
-       var $ixFields = array('idxname' => 'relname', 'idxdef' => 'pg_get_indexdef', 'uniquekey' => 'indisunique', 'primarykey' => 'indisprimary');\r
-       var $tgFields = array('tgname' => 'tgname');\r
-\r
-       // Last oid assigned to a system object\r
-       var $_lastSystemOID = 18539;\r
-       var $_maxNameLen = 31;\r
-       \r
-       // Name of id column\r
-       var $id = 'oid';\r
-\r
-       function Postgres($host, $port, $database, $user, $password) {\r
-               $this->BaseDB('postgres7');\r
-\r
-               //$this->conn->host = $host\r
-               //$this->Port = $port;\r
-               $pghost = "$host:$port";\r
-\r
-               $this->conn->connect($pghost, $user, $password, $database);\r
-       }\r
-       \r
-       /**\r
-        * A function to check that the database functions are installed\r
-        * and running.\r
-        * @return True on success, false otherwise\r
-        */\r
-       function isLoaded() {\r
-               return function_exists('pg_connect');\r
-       }\r
-       \r
-       // Table functions\r
-       \r
-       /**\r
-        * Get the fields for uniquely identifying a row in a table\r
-        * @param $table The table for which to retrieve the identifier\r
-        * @return An array mapping attribute number to attribute name, empty for no identifiers\r
-        * @return -1 error\r
-        */\r
-       function getRowIdentifier($table) {\r
-               $this->clean($table);\r
-               \r
-               $status = $this->beginTransaction();\r
-               if ($status != 0) return -1;\r
-               \r
-               $sql = "SELECT indrelid, indkey FROM pg_index WHERE indisprimary AND indrelid=(SELECT oid FROM pg_class WHERE relname='{$table}')";\r
-               $rs = $this->selectSet($sql);\r
-               \r
-               // If none, search for OID column\r
-               if ($rs->recordCount() == 0) {\r
-                       $sql = "SELECT relhasoids FROM pg_class WHERE relname='{$table}'";\r
-                       $rs2 = $this->selectSet($sql);\r
-                       if ($rs2->recordCount() == 0) {\r
-                               $this->rollbackTransaction();\r
-                               return -1;\r
-                       }\r
-                       elseif ($rs2->f['relhasoids'] == 'f') {\r
-                               $this->endTransaction();\r
-                               return array();\r
-                       }\r
-                       else {\r
-                               $this->endTransaction();\r
-                               return array(-2 => 'oid');\r
-                       }\r
-               }\r
-               // Otherwise select to find the names of the keys\r
-               else {          \r
-                       $in = str_replace(' ', ',', $rs->f['indkey']);\r
-                       $sql = "SELECT attnum, attname FROM pg_attribute WHERE attrelid='{$rs->f['indrelid']}' AND attnum IN ({$in})";\r
-                       $rs2 = $this->selectSet($sql);\r
-                       if ($rs2->recordCount() == 0) {\r
-                               $this->rollbackTransaction();\r
-                               return -1;\r
-                       }\r
-                       else {\r
-                               $temp = array();\r
-                               while (!$rs2->EOF) {\r
-                                       $temp[$rs2->f['attnum']] = $rs2->f['attname'];\r
-                                       $rs2->moveNext();\r
-                               }\r
-                               $this->endTransaction();\r
-                               return $temp;\r
-                       }                       \r
-               }                       \r
-       }\r
-       \r
-       /**\r
-        * Outputs the HTML code for a particular field\r
-        * @param $name The name to give the field\r
-        * @param $value The value of the field.  Note this could be 'numeric(7,2)' sort of thing...\r
-        * @param $type The database type of the field\r
-        */\r
-       function printField($name, $value, $type) {\r
-               switch ($type) {\r
-                       case 'bool':\r
-                       case 'boolean':\r
-                               echo "<select name=\"", htmlspecialchars($name), "\">\n";\r
-                               echo "<option value=\"Y\"", ($value) ? ' selected' : '', ">Yes</option>\n";\r
-                               echo "<option value=\"N\"", (!$value) ? ' selected' : '', ">No</option>\n";\r
-                               echo "</select>\n";\r
-                               break;\r
-                       case 'text':\r
-                       case 'bytea':\r
-                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=5 cols=28 wrap=virtual style=\"width: 100%\">\n";\r
-                               echo htmlspecialchars($value);\r
-                               echo "</textarea>\n";\r
-                               break;\r
-                       default:\r
-                               echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=35>\n";\r
-                               break;\r
-               }               \r
-       }       \r
-\r
-       /**\r
-        * Return all database available on the server\r
-        * @return A list of databases, sorted alphabetically\r
-        */\r
-       function &getLanguages() {\r
-               $sql = "";\r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-       /**\r
-        * Return all information about a particular database\r
-        * @param $database The name of the database to retrieve\r
-        * @return The database info\r
-        */\r
-       function &getLanguage($database) {\r
-               $this->clean($database);\r
-               $sql = "SELECT * FROM pg_database WHERE datname='{$database}'";\r
-               return $this->selectRow($sql);\r
-       }\r
-\r
-       /**\r
-        * Creates a database\r
-        * @param $database The name of the database to create\r
-        * @return 0 success\r
-        */\r
-       function createDatabase($database) {\r
-               $this->clean($database);\r
-               $sql = "CREATE DATABASE \"{$database}\"";\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Drops a database\r
-        * @param $database The name of the database to drop\r
-        * @return 0 success\r
-        */\r
-       function dropDatabase($database) {\r
-               $this->clean($database);\r
-               $sql = "DROP DATABASE \"{$database}\"";\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       // Table functions\r
-\r
-       /**\r
-        * Return all tables in current database\r
-        * @return All tables, sorted alphabetically \r
-        */\r
-       function &getTables() {\r
-               if (!$this->_showSystem) $where = "WHERE tablename NOT LIKE 'pg_%' ";\r
-               else $where = '';\r
-               $sql = "SELECT tablename, tableowner FROM pg_tables {$where}ORDER BY tablename";\r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-       /**\r
-        * Return all information relating to a table\r
-        * @param $table The name of the table\r
-        * @return Table information\r
-        */\r
-       function &getTableByName($table) {\r
-               $this->clean($table);\r
-               $sql = "SELECT * FROM pg_class WHERE relname='{$table}'";\r
-               return $this->selectRow($sql);\r
-       }\r
-\r
-       /**\r
-        * Retrieve the attribute definition of a table\r
-        * @param $table The name of the table\r
-        * @param $field (optional) The name of a field to return\r
-        * @return All attributes in order\r
-        */\r
-       function &getTableAttributes($table, $field = '') {\r
-               $this->clean($table);\r
-               $this->clean($field);\r
-               \r
-               if ($field == '') {\r
-                       $sql = "SELECT\r
-                                       a.attname, t.typname as type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum\r
-                               FROM\r
-                                       pg_class c, pg_attribute a, pg_type t\r
-                               WHERE\r
-                                       c.relname = '{$table}' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\r
-                               ORDER BY a.attnum";\r
-               }\r
-               else {\r
-                       $sql = "SELECT\r
-                                       a.attname, t.typname as type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum\r
-                               FROM\r
-                                       pg_class c, pg_attribute a, pg_type t\r
-                               WHERE\r
-                                       c.relname = '{$table}' AND a.attname='{$column}' AND a.attrelid = c.oid AND a.atttypid = t.oid\r
-                               ORDER BY a.attnum";                             \r
-               }\r
-               \r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-       /**\r
-        * Drops a column from a table\r
-        * @param $table The table from which to drop a column\r
-        * @param $column The column to be dropped\r
-        * @param $behavior CASCADE or RESTRICT or empty\r
-        * @return 0 success\r
-        * @return -99 not implemented\r
-        */\r
-       function dropColumn($table, $column, $behavior) {\r
-               return -99;\r
-       }\r
-       \r
-       /**\r
-        * Alters a column in a table\r
-        * @param $table The table in which the column resides\r
-        * @param $column The column to alter\r
-        * @param $name The new name for the column\r
-        * @param $notnull (boolean) True if not null, false otherwise\r
-        * @param $default The new default for the column\r
-        * @return 0 success\r
-        * @return -1 set not null error\r
-        * @return -2 set default error\r
-        * @return -3 rename column error\r
-        */\r
-       function alterColumn($table, $column, $name, $notnull, $default) {\r
-               $this->beginTransaction();\r
-\r
-               // @@ NEED TO HANDLE "NESTED" TRANSACTION HERE\r
-               $status = $this->setColumnNull($table, $column, !$notnull);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -1;\r
-               }\r
-\r
-               $status = $this->setColumnDefault($table, $column, $default);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -2;\r
-               }\r
-\r
-               $status = $this->renameColumn($table, $column, $name);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -3;\r
-               }\r
-\r
-               return $this->endTransaction();\r
-       }       \r
-\r
-       /**\r
-        * Creates a new table in the database\r
-        * @param $name The name of the table\r
-        * @param $fields The number of fields\r
-        * @param $field An array of field names\r
-        * @param $type An array of field types\r
-        * @param $length An array of field lengths\r
-        * @param $notnull An array of not null\r
-        * @param $default An array of default values\r
-        * @return 0 success\r
-        * @return -1 no fields supplied\r
-        */\r
-       function createTable($name, $fields, $field, $type, $length, $notnull, $default) {\r
-               // @@ NOTE: $default field not being cleaned - how on earth DO we clean it??\r
-               $this->fieldClean($name);\r
-       \r
-               $found = false;\r
-               $sql = "CREATE TABLE \"{$name}\" (";\r
-               \r
-               for ($i = 0; $i < $fields; $i++) {\r
-                       $this->fieldClean($field[$i]);\r
-                       $this->clean($type[$i]);\r
-                       $this->clean($length[$i]);\r
-                       \r
-                       // Skip blank columns - for user convenience\r
-                       if ($field[$i] == '' || $type[$i] == '') continue;\r
-                       \r
-                       $sql .= "\"{$field[$i]}\" {$type[$i]}";\r
-                       if ($length[$i] != '') $sql .= "({$length[$i]})";\r
-                       if (isset($notnull[$i])) $sql .= " NOT NULL";\r
-                       if ($default[$i] != '') $sql .= " DEFAULT {$default[$i]}";\r
-                       if ($i != $fields - 1) $sql .= ", ";\r
-\r
-                       $found = true;\r
-               }\r
-               \r
-               if (!$found) return -1;\r
-               \r
-               $sql .= ")";\r
-               \r
-               return $this->execute($sql);\r
-       }       \r
-       \r
-       /**\r
-        * Removes a table from the database\r
-        * @param $table The table to drop\r
-        * @return 0 success\r
-        */\r
-       function dropTable($table) {\r
-               $this->fieldClean($table);\r
-\r
-               $sql = "DROP TABLE \"{$table}\"";\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Empties a table in the database\r
-        * @param $table The table to be emptied\r
-        * @return 0 success\r
-        */\r
-       function emptyTable($table) {\r
-               $this->fieldClean($table);\r
-\r
-               $sql = "DELETE FROM \"{$table}\"";\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Renames a table\r
-        * @param $table The table to be renamed\r
-        * @param $newName The new name for the table\r
-        * @return 0 success\r
-        */\r
-       function renameTable($table, $newName) {\r
-               $this->fieldClean($table);\r
-               $this->fieldClean($newName);\r
-               \r
-               $sql = "ALTER TABLE \"{$table}\" RENAME TO \"{$newName}\"";\r
-\r
-               // @@ How do you do this?\r
-               return $this->execute($sql);\r
-       }\r
-       \r
-       /**\r
-        * Returns a recordset of all columns in a table\r
-        * @param $table The name of a table\r
-        * @param $offset The offset into the table\r
-        * @param $limit The maximum number of records to return at once\r
-        * @return A recordset\r
-        */\r
-       function &getTableRows($table) {\r
-               $this->fieldClean($table);              \r
-\r
-               return $this->selectTable("SELECT COUNT(*) FROM \"{$table}\"", $offset, $limit);\r
-       }       \r
-       \r
-       /**\r
-        * Returns a recordset of all columns in a table\r
-        * @param $table The name of a table\r
-        * @param $offset The offset into the table\r
-        * @param $limit The maximum number of records to return at once\r
-        * @return A recordset\r
-        */\r
-       function &browseTable($table, $offset = null, $limit = null) {\r
-               $this->fieldClean($table);              \r
-               \r
-               return $this->selectTable("SELECT oid, * FROM \"{$table}\"", $offset, $limit);\r
-       }\r
-\r
-       /**\r
-        * Returns a recordset of all columns in a table\r
-        * @param $table The name of a table\r
-        * @param $key The associative array holding the key to retrieve\r
-        * @return A recordset\r
-        */\r
-       function &browseRow($table, $key) {\r
-               $this->fieldClean($table);\r
-               \r
-               $sql = "SELECT * FROM \"{$table}\" WHERE true";\r
-               foreach ($key as $k => $v) {\r
-                       $this->fieldClean($k);\r
-                       $this->clean($v);\r
-                       $sql .= " AND \"{$k}\"='{$v}'";\r
-               }\r
-\r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-       /**\r
-        *\r
-        */\r
-       function &selectTable($sql, $offset, $limit) {\r
-               return $this->selectSet($sql, $offset, $limit);\r
-       }\r
-\r
-       // Sequence functions\r
-       \r
-       /**\r
-        * Returns all sequences in the current database\r
-        * @return A recordset\r
-        */\r
-       function &getSequences() {\r
-               if (!$this->_showSystem) $where = " AND relname NOT LIKE 'pg_%'";\r
-               else $where = '';\r
-               $sql = "SELECT c.relname, u.usename  FROM pg_class c, pg_user u WHERE c.relowner=u.usesysid AND c.relkind = 'S'{$where} ORDER BY relname";\r
-               return $this->selectSet( $sql );\r
-       }\r
-\r
-       /**\r
-        * Returns properties of a single sequence\r
-        * @return A recordset\r
-        */\r
-       function &getSequence($sequence) {\r
-               if (!$this->_showSystem) $where = " AND relname NOT LIKE 'pg_%'";\r
-               else $where = '';\r
-               $sql = "SELECT sequence_name as relname,* FROM $sequence"; \r
-               return $this->selectSet( $sql );\r
-       }\r
-\r
-       /** \r
-        * Drops a given sequence\r
-        * @return 0 success\r
-        */\r
-       function &dropSequence($sequence) {\r
-               $this->clean($sequence);\r
-               $sql = "DROP SEQUENCE {$sequence} ";\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /** \r
-        * Creates a new sequence\r
-        * @return 0 success\r
-        */\r
-       function &setSequence($sequence,$startval=1) {\r
-               $this->clean($sequence);\r
-               $sql = "CREATE SEQUENCE $seq_name START $startval";\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /** \r
-        * Modifies permissions on a given sequence\r
-        * @return 0 success\r
-        */\r
-       function &setSequencePermissions($sequence) {\r
-\r
-       }\r
-\r
-       /** \r
-        * Resets  a given sequence to 1\r
-        * @return 0 success\r
-        */\r
-       function &resetSequence($sequence) {\r
-               $this->clean($sequence);\r
-               $sql = "SELECT setval('$sequence',1)";\r
-               return $this->execute($sql);\r
-       }\r
-\r
-\r
-\r
-\r
-       /**\r
-        * Adds a check constraint to a table\r
-        * @param $table The table to which to add the check\r
-        * @param $definition The definition of the check\r
-        * @param $name (optional) The name to give the check, otherwise default name is assigned\r
-        * @return 0 success\r
-        */\r
-       function addCheckConstraint($table, $definition, $name = '') {\r
-               $this->fieldClean($table);\r
-               $this->fieldClean($name);\r
-               // @@ how the heck do you clean definition???\r
-               \r
-               if ($name != '')\r
-                       $sql = "ALTER TABLE \"{$table}\" ADD CONSTRAINT \"{$name}\" CHECK ({$definition})";\r
-               else\r
-                       $sql = "ALTER TABLE \"{$table}\" ADD CHECK ({$definition})";\r
-\r
-               // @@ How do you do this?\r
-               return $this->execute($sql);\r
-       }\r
-       \r
-       /**\r
-        * Drops a check constraint from a table\r
-        * @param $table The table from which to drop the check\r
-        * @param $name The name of the check to be dropped\r
-        * @return 0 success\r
-        * @return -2 transaction error\r
-        * @return -3 lock error\r
-        * @return -4 check drop error\r
-        */\r
-       function dropCheckConstraint($table, $name) {\r
-               $this->clean($table);\r
-               $this->clean($name);\r
-               \r
-               // Begin transaction\r
-               $status = $this->beginTransaction();\r
-               if ($status != 0) return -2;\r
-\r
-               // Properly lock the table\r
-               $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE";\r
-               $status = $this->execute($sql);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -3;\r
-               }\r
-\r
-               // Delete the check constraint\r
-               $sql = "DELETE FROM pg_relcheck WHERE rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}') AND rcname='{$name}'";\r
-          $status = $this->execute($sql);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -4;\r
-               }\r
-               \r
-               // Update the pg_class catalog to reflect the new number of checks\r
-               $sql = "UPDATE pg_class SET relchecks=(SELECT COUNT(*) FROM pg_relcheck WHERE \r
-                                       rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}')) \r
-                                       WHERE relname='{$table}'";\r
-          $status = $this->execute($sql);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -4;\r
-               }\r
-\r
-               // Otherwise, close the transaction\r
-               return $this->endTransaction();\r
-       }       \r
-\r
-       /**\r
-        * Adds a unique constraint to a table\r
-        * @param $table The table to which to add the unique\r
-        * @param $fields (array) An array of fields over which to add the unique\r
-        * @param $name (optional) The name to give the unique, otherwise default name is assigned\r
-        * @return 0 success\r
-        */\r
-       function addUniqueConstraint($table, $fields, $name = '') {\r
-               $this->fieldClean($table);\r
-               $this->arrayClean($fields);\r
-               $this->fieldClean($name);\r
-               \r
-               if ($name != '')\r
-                       $sql = "CREATE UNIQUE INDEX \"{$name}\" ON \"{$table}\"(\"" . join('","', $fields) . "\")";\r
-               else return -99; // Not supported\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Drops a unique constraint from a table\r
-        * @param $table The table from which to drop the unique\r
-        * @param $name The name of the unique\r
-        * @return 0 success\r
-        */\r
-       function dropUniqueConstraint($table, $name) {\r
-               $this->fieldClean($name);\r
-               \r
-               $sql = "DROP INDEX \"{$name}\"";\r
-\r
-               return $this->execute($sql);\r
-       }       \r
-        \r
-       /**\r
-        * Adds a primary key constraint to a table\r
-        * @param $table The table to which to add the primery key\r
-        * @param $fields (array) An array of fields over which to add the primary key\r
-        * @param $name (optional) The name to give the key, otherwise default name is assigned\r
-        * @return 0 success\r
-        */\r
-       function addPrimaryKeyConstraint($table, $fields, $name = '') {\r
-               // This function can be faked with a unique index and a catalog twiddle, however\r
-               // how do we ensure that it's only used on NOT NULL fields?\r
-               return -99; // Not supported.\r
-       }\r
-\r
-       /**\r
-        * Drops a primary key constraint from a table\r
-        * @param $table The table from which to drop the primary key\r
-        * @param $name The name of the primary key\r
-        * @return 0 success\r
-        */\r
-       function dropPrimaryKeyConstraint($table, $name) {\r
-               $this->fieldClean($name);\r
-               \r
-               $sql = "DROP INDEX \"{$name}\"";\r
-\r
-               return $this->execute($sql);\r
-       }       \r
-       \r
-       /**\r
-        * Changes the owner of a table\r
-        * @param $table The table whose owner is to change\r
-        * @param $owner The new owner (username) of the table\r
-        * @return 0 success\r
-        */\r
-       function setOwnerOfTable($table, $owner) {\r
-               $this->fieldClean($table);\r
-               $this->fieldClean($owner);\r
-               \r
-               $sql = "ALTER TABLE \"{$table}\" OWNER TO \"{$owner}\"";\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       // Column Functions\r
-\r
-       /**\r
-        * Add a new column to a table\r
-        * @param $table The table to add to\r
-        * @param $column The name of the new column\r
-        * @param $type The type of the column\r
-        * @param $size (optional) The optional size of the column (ie. 30 for varchar(30))\r
-        * @return 0 success\r
-        */\r
-       function addColumnToTable($table, $column, $type, $size = '') {\r
-               $this->clean($table);\r
-               $this->clean($column);\r
-               $this->clean($type);\r
-               $this->clean($size);\r
-               // @@ How the heck do you properly clean type and size?\r
-               \r
-               if ($size == '')\r
-                       $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}";\r
-               else\r
-                       $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}({$size})";\r
-\r
-               // @@ How do you do this?\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Drops a column from a table\r
-        * @param $table The table from which to drop\r
-        * @param $column The column name to drop\r
-        * @return 0 success\r
-        */\r
-       function dropColumnFromTable($table, $column) {\r
-               return -99; // Not implemented\r
-       }\r
-\r
-       /**\r
-        * Sets default value of a column\r
-        * @param $table The table from which to drop\r
-        * @param $column The column name to set\r
-        * @param $default The new default value\r
-        * @return 0 success\r
-        */\r
-       function setColumnDefault($table, $column, $default) {\r
-               $this->fieldClean($table);\r
-               $this->fieldClean($column);\r
-               // @@ How the heck do you clean default clause?\r
-               \r
-               $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Drops default value of a column\r
-        * @param $table The table from which to drop\r
-        * @param $column The column name to drop default\r
-        * @return 0 success\r
-        */\r
-       function dropColumnDefault($table, $column) {\r
-               $this->clean($table);\r
-               $this->clean($column);\r
-\r
-               $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT";\r
-\r
-               // @@ How do you do this?\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Sets whether or not a column can contain NULLs\r
-        * @param $table The table that contains the column\r
-        * @param $column The column to alter\r
-        * @param $state True to set null, false to set not null\r
-        * @return 0 success\r
-        * @return -1 attempt to set not null, but column contains nulls\r
-        * @return -2 transaction error\r
-        * @return -3 lock error\r
-        * @return -4 update error\r
-        */\r
-       function setColumnNull($table, $column, $state) {\r
-               $this->clean($table);\r
-               $this->clean($column);\r
-\r
-               // Begin transaction\r
-               $status = $this->beginTransaction();\r
-               if ($status != 0) return -2;\r
-\r
-               // Properly lock the table\r
-               $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE";\r
-               $status = $this->execute($sql);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -3;\r
-               }\r
-\r
-               // Check for existing nulls\r
-               if (!$state) {\r
-                       $sql = "SELECT COUNT(*) AS total FROM \"{$table}\" WHERE \"{$column}\" IS NULL";\r
-                       $result = $this->selectField($sql, 'total');\r
-                       if ($result > 0) {\r
-                               $this->rollbackTransaction();\r
-                               return -1;\r
-                       }\r
-               }\r
-\r
-               // Otherwise update the table.  Note the reverse-sensed $state variable\r
-               $sql = "UPDATE pg_attribute SET attnotnull = " . (($state) ? 'false' : 'true') . " \r
-                                       WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '{$table}') \r
-                                       AND attname = '{$column}'";\r
-\r
-          $status = $this->execute($sql);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -4;\r
-               }\r
-\r
-               // Otherwise, close the transaction\r
-               return $this->endTransaction();\r
-       }\r
-\r
-       /**\r
-        * Renames a column in a table\r
-        * @param $table The table containing the column to be renamed\r
-        * @param $column The column to be renamed\r
-        * @param $newName The new name for the column\r
-        * @return 0 success\r
-        */\r
-       function renameColumn($table, $column, $newName) {\r
-               $this->fieldClean($table);\r
-               $this->fieldClean($column);\r
-               $this->fieldClean($newName);\r
-\r
-               $sql = "ALTER TABLE \"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";\r
-\r
-               return $this->execute($sql);\r
-       }\r
-\r
-       /**\r
-        * Grabs a list of indicies in the database or table\r
-        * @param $table (optional) The name of a table to get the indicies for\r
-        */\r
-       function &getIndicies($table = '') {\r
-               $this->clean($table);\r
-\r
-               $sql = "SELECT c2.relname, i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid)\r
-                       FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\r
-                       WHERE c.oid = '16977' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\r
-                       ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname";\r
-\r
-               \r
-               if ($table != '')\r
-                       $where = "WHERE relname='{$table}' AND ";\r
-               elseif (!$this->_showSystem)\r
-                       $where = "WHERE relname NOT LIKE 'pg_%' AND ";\r
-               else $where  = '';\r
-               \r
-               $sql = "SELECT relname FROM pg_class {$where} relkind ='i' ORDER BY relname";\r
-\r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-       function &getIndex($idxname) {\r
-               $sql = "SELECT\r
-                                       ic.relname AS relname,\r
-                                       bc.relname AS tab_name,\r
-                                       ta.attname AS column_name,\r
-                                       i.indisunique AS unique_key,\r
-                                       i.indisprimary AS primary_key\r
-                               FROM\r
-                                       pg_class bc,\r
-                                       pg_class ic,\r
-                                       pg_index i,\r
-                                       pg_attribute ta,\r
-                                       pg_attribute ia\r
-                               WHERE\r
-                                       bc.oid = i.indrelid\r
-                                       AND ic.oid = i.indexrelid\r
-                                       AND ia.attrelid = i.indexrelid\r
-                                       AND ta.attrelid = bc.oid\r
-                                       AND ic.relname = '$idxname'\r
-                                       AND ta.attrelid = i.indrelid\r
-                                       AND ta.attnum = i.indkey[ia.attnum-1]\r
-                               ORDER BY\r
-                                       relname, tab_name, column_name";\r
-\r
-               return $this->selectSet($sql);\r
-       }\r
-\r
-\r
-/*\r
-       function setIndex()\r
-       function delIndex()\r
-\r
-\r
-       // DML Functions\r
-\r
-       function doSelect()\r
-       function doDelete()\r
-       function doUpdate()\r
-*/\r
-\r
-       // View functions\r
-       \r
-       /**\r
-        * Returns a list of all views in the database\r
-        * @return All views\r
-        */\r
-       function getViews() {\r
-               if (!$this->_showSystem)\r
-                       $where = "WHERE viewname NOT LIKE 'pg_%'";\r
-               else $where  = '';\r
-               \r
-               $sql = "SELECT viewname, viewowner FROM pg_views {$where} ORDER BY viewname";\r
-\r
-               return $this->selectSet($sql);\r
-       }\r
-       \r
-       /**\r
-        * Returns all details for a particular view\r
-        * @param $view The name of the view to retrieve\r
-        * @return View info\r
-        */\r
-       function getView($view) {\r
-               $this->clean($view);\r
-               \r
-               $sql = "SELECT viewname, viewowner, definition FROM pg_views WHERE viewname='$view'";\r
-\r
-               return $this->selectSet($sql);\r
-       }       \r
-\r
-       /**\r
-        * Creates a new view.\r
-        * @param $viewname The name of the view to create\r
-        * @param $definition The definition for the new view\r
-        * @return 0 success\r
-        */\r
-       function createView($viewname, $definition) {\r
-               $this->clean($viewname);\r
-               // Note: $definition not cleaned\r
-               \r
-               $sql = "CREATE VIEW \"{$viewname}\" AS {$definition}";\r
-               \r
-               return $this->execute($sql);\r
-       }\r
-       \r
-       /**\r
-        * Drops a view.\r
-        * @param $viewname The name of the view to drop\r
-        * @return 0 success\r
-        */\r
-       function dropView($viewname) {\r
-               $this->clean($viewname);\r
-               \r
-               $sql = "DROP VIEW \"{$viewname}\"";\r
-               \r
-               return $this->execute($sql);\r
-       }\r
-       \r
-       /**\r
-        * Updates a view.  Postgres doesn't have CREATE OR REPLACE view,\r
-        * so we do it with a drop and a recreate.\r
-        * @param $viewname The name fo the view to update\r
-        * @param $definition The new definition for the view\r
-        * @return 0 success\r
-        * @return -1 transaction error\r
-        * @return -2 drop view error\r
-        * @return -3 create view error\r
-        */\r
-       function setView($viewname, $definition) {\r
-               $status = $this->beginTransaction();\r
-               if ($status != 0) return -1;\r
-               \r
-               $status = $this->dropView($viewname);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -2;\r
-               }\r
-               \r
-               $status = $this->createView($viewname, $definition);\r
-               if ($status != 0) {\r
-                       $this->rollbackTransaction();\r
-                       return -3;\r
-               }\r
-               \r
-               $status = $this->endTransaction();\r
-               return ($status == 0) ? 0 : -1;\r
-       }       \r
-\r
-       // Operator functions\r
-       \r
-       /**\r
-        * Returns a list of all operators in the database\r
-        * @return All operators\r
-        */\r
-       function getOperators() {\r
-               if (!$this->_showSystem)\r
-                       $where = "WHERE po.oid > '{$this->_lastSystemOID}'::oid";\r
-               else $where  = '';\r
-               \r
-               $sql = "\r
-                       SELECT\r
-            po.oid,\r
-                               po.oprname,\r
-                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprleft) AS oprleftname,\r
-                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprright) AS oprrightname,\r
-                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprresult) AS resultname\r
-                       FROM\r
-                               pg_operator po\r
-                       {$where}                                \r
-                       ORDER BY\r
-                               po.oprname, po.oid\r
-               ";\r
-\r
-               return $this->selectSet($sql);\r
-       }\r
-       \r
-       \r
-       /**\r
-        * Creates a new operator\r
-        */\r
-\r
-       // User and group functions\r
-       \r
-       /**\r
-        * Returns all users in the database cluster\r
-        * @return All users\r
-        */\r
-       function &getUsers() {\r
-               $sql = "SELECT usename, usesuper, usecreatedb, valuntil FROM pg_shadow ORDER BY usename";\r
-               \r
-               return $this->selectSet($sql);\r
-       }\r
-       \r
-       /**\r
-        * Return information about a single user\r
-        * @param $username The username of the user to retrieve\r
-        * @return The user's data\r
-        */\r
-       function &getUser($username) {\r
-               $this->clean($username);\r
-               \r
-               $sql = "SELECT usename, usesuper, usecreatedb, valuntil FROM pg_shadow WHERE usename='{$username}'";\r
-               \r
-               return $this->selectSet($sql);\r
-       }\r
-       \r
-       /**\r
-        * Creates a new user\r
-        * @param $username The username of the user to create\r
-        * @param $password A password for the user\r
-        * @param $createdb boolean Whether or not the user can create databases\r
-        * @param $createuser boolean Whether or not the user can create other users\r
-        * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'.  When the account expires.\r
-        * @param $group (array) The groups to create the user in\r
-        * @return 0 success\r
-        */\r
-       function createUser($username, $password, $createdb, $createuser, $expiry, $groups) {\r
-               $this->clean($username);\r
-               // @@ THIS IS A PROBLEM FOR TRIMMING PASSWORD!!!\r
-               $this->clean($password);\r
-               $this->clean($expiry);\r
-               $this->arrayClean($groups);             \r
-               \r
-               $sql = "CREATE USER \"{$username}\"";\r
-               if ($password != '') $sql .= " WITH PASSWORD '{$password}'";\r
-               $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';\r
-               $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';\r
-               if (is_array($groups) && sizeof($groups) > 0) $sql .= " IN GROUP '" . join("', '", $groups) . "'";\r
-               if ($expiry != '') $sql .= " VALID UNTIL '{$expiry}'";\r
-               \r
-               return $this->execute($sql);\r
-       }       \r
-       \r
-       /**\r
-        * Adjusts a user's info\r
-        * @param $username The username of the user to modify\r
-        * @param $password A new password for the user\r
-        * @param $createdb boolean Whether or not the user can create databases\r
-        * @param $createuser boolean Whether or not the user can create other users\r
-        * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'.  When the account expires.\r
-        * @return 0 success\r
-        */\r
-       function setUser($username, $password, $createdb, $createuser, $expiry) {\r
-               $this->clean($username);\r
-               $this->clean($password);\r
-               $this->clean($expiry);\r
-               \r
-               $sql = "ALTER USER \"{$username}\"";\r
-               if ($password != '') $sql .= " WITH PASSWORD '{$password}'";\r
-               $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';\r
-               $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';\r
-               if ($expiry != '') $sql .= " VALID UNTIL '{$expiry}'";\r
-               \r
-               return $this->execute($sql);\r
-       }       \r
-       \r
-       /**\r
-        * Removes a user\r
-        * @param $username The username of the user to drop\r
-        * @return 0 success\r
-        */\r
-       function dropUser($username) {\r
-               $this->clean($username);\r
-               \r
-               $sql = "DROP USER \"{$username}\"";\r
-               \r
-               return $this->execute($sql);\r
-       }\r
-        \r
-       // Capabilities\r
-       function hasTables() { return true; }\r
-       function hasViews() { return true; }\r
-       function hasSequences() { return true; }\r
-       function hasFunctions() { return true; }\r
-       function hasTriggers() { return true; }\r
-       function hasOperators() { return true; }\r
-       function hasTypes() { return true; }\r
-       function hasAggregates() { return true; }\r
-       function hasIndicies() { return true; }\r
-       function hasRules() { return true; }\r
-       function hasLanguages() { return true; }\r
-\r
-}\r
-\r
-?>\r
+<?php
+
+/**
+ * A class that implements the DB interface for Postgres
+ * Note: This class uses ADODB and returns RecordSets.
+ *
+ * $Id: Postgres.php,v 1.25 2002/12/14 10:56:26 chriskl Exp $
+ */
+
+// @@@ THOUGHT: What about inherits? ie. use of ONLY???
+
+include_once('../classes/database/BaseDB.php');
+
+class Postgres extends BaseDB {
+
+       var $dbFields = array('dbname' => 'datname', 'dbcomment' => 'description');
+       var $tbFields = array('tbname' => 'tablename', 'tbowner' => 'tableowner');
+       var $vwFields = array('vwname' => 'viewname', 'vwowner' => 'viewowner', 'vwdef' => 'definition');
+       var $uFields = array('uname' => 'usename', 'usuper' => 'usesuper', 'ucreatedb' => 'usecreatedb', 'uexpires' => 'valuntil');
+       var $sqFields = array('seqname' => 'relname', 'seqowner' => 'usename', 'lastvalue' => 'last_value', 'incrementby' => 'increment_by', 'maxvalue' => 'max_value', 'minvalue'=> 'min_value', 'cachevalue' => 'cache_value', 'logcount' => 'log_cnt', 'iscycled' => 'is_cycled', 'iscalled' => 'is_called' );
+       var $ixFields = array('idxname' => 'relname', 'idxdef' => 'pg_get_indexdef', 'uniquekey' => 'indisunique', 'primarykey' => 'indisprimary');
+       var $tgFields = array('tgname' => 'tgname');
+
+       // Last oid assigned to a system object
+       var $_lastSystemOID = 18539;
+       var $_maxNameLen = 31;
+       
+       // Name of id column
+       var $id = 'oid';
+
+       function Postgres($host, $port, $database, $user, $password) {
+               $this->BaseDB('postgres7');
+
+               //$this->conn->host = $host
+               //$this->Port = $port;
+               $pghost = "$host:$port";
+
+               $this->conn->connect($pghost, $user, $password, $database);
+       }
+       
+       /**
+        * A function to check that the database functions are installed
+        * and running.
+        * @return True on success, false otherwise
+        */
+       function isLoaded() {
+               return function_exists('pg_connect');
+       }
+       
+       // Table functions
+       
+       /**
+        * Get the fields for uniquely identifying a row in a table
+        * @param $table The table for which to retrieve the identifier
+        * @return An array mapping attribute number to attribute name, empty for no identifiers
+        * @return -1 error
+        */
+       function getRowIdentifier($table) {
+               $this->clean($table);
+               
+               $status = $this->beginTransaction();
+               if ($status != 0) return -1;
+               
+               $sql = "SELECT indrelid, indkey FROM pg_index WHERE indisprimary AND indrelid=(SELECT oid FROM pg_class WHERE relname='{$table}')";
+               $rs = $this->selectSet($sql);
+               
+               // If none, search for OID column
+               if ($rs->recordCount() == 0) {
+                       $sql = "SELECT relhasoids FROM pg_class WHERE relname='{$table}'";
+                       $rs2 = $this->selectSet($sql);
+                       if ($rs2->recordCount() == 0) {
+                               $this->rollbackTransaction();
+                               return -1;
+                       }
+                       elseif ($rs2->f['relhasoids'] == 'f') {
+                               $this->endTransaction();
+                               return array();
+                       }
+                       else {
+                               $this->endTransaction();
+                               return array(-2 => 'oid');
+                       }
+               }
+               // Otherwise select to find the names of the keys
+               else {          
+                       $in = str_replace(' ', ',', $rs->f['indkey']);
+                       $sql = "SELECT attnum, attname FROM pg_attribute WHERE attrelid='{$rs->f['indrelid']}' AND attnum IN ({$in})";
+                       $rs2 = $this->selectSet($sql);
+                       if ($rs2->recordCount() == 0) {
+                               $this->rollbackTransaction();
+                               return -1;
+                       }
+                       else {
+                               $temp = array();
+                               while (!$rs2->EOF) {
+                                       $temp[$rs2->f['attnum']] = $rs2->f['attname'];
+                                       $rs2->moveNext();
+                               }
+                               $this->endTransaction();
+                               return $temp;
+                       }                       
+               }                       
+       }
+       
+       /**
+        * Outputs the HTML code for a particular field
+        * @param $name The name to give the field
+        * @param $value The value of the field.  Note this could be 'numeric(7,2)' sort of thing...
+        * @param $type The database type of the field
+        */
+       function printField($name, $value, $type) {
+               switch ($type) {
+                       case 'bool':
+                       case 'boolean':
+                               echo "<select name=\"", htmlspecialchars($name), "\">\n";
+                               echo "<option value=\"Y\"", ($value) ? ' selected' : '', ">Yes</option>\n";
+                               echo "<option value=\"N\"", (!$value) ? ' selected' : '', ">No</option>\n";
+                               echo "</select>\n";
+                               break;
+                       case 'text':
+                       case 'bytea':
+                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=5 cols=28 wrap=virtual style=\"width: 100%\">\n";
+                               echo htmlspecialchars($value);
+                               echo "</textarea>\n";
+                               break;
+                       default:
+                               echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=35>\n";
+                               break;
+               }               
+       }       
+
+       /**
+        * Return all database available on the server
+        * @return A list of databases, sorted alphabetically
+        */
+       function &getLanguages() {
+               $sql = "";
+               return $this->selectSet($sql);
+       }
+
+       /**
+        * Return all information about a particular database
+        * @param $database The name of the database to retrieve
+        * @return The database info
+        */
+       function &getLanguage($database) {
+               $this->clean($database);
+               $sql = "SELECT * FROM pg_database WHERE datname='{$database}'";
+               return $this->selectRow($sql);
+       }
+
+       /**
+        * Creates a database
+        * @param $database The name of the database to create
+        * @return 0 success
+        */
+       function createDatabase($database) {
+               $this->clean($database);
+               $sql = "CREATE DATABASE \"{$database}\"";
+               return $this->execute($sql);
+       }
+
+       /**
+        * Drops a database
+        * @param $database The name of the database to drop
+        * @return 0 success
+        */
+       function dropDatabase($database) {
+               $this->clean($database);
+               $sql = "DROP DATABASE \"{$database}\"";
+               return $this->execute($sql);
+       }
+
+       // Table functions
+
+       /**
+        * Return all tables in current database
+        * @return All tables, sorted alphabetically 
+        */
+       function &getTables() {
+               if (!$this->_showSystem) $where = "WHERE tablename NOT LIKE 'pg_%' ";
+               else $where = '';
+               $sql = "SELECT tablename, tableowner FROM pg_tables {$where}ORDER BY tablename";
+               return $this->selectSet($sql);
+       }
+
+       /**
+        * Return all information relating to a table
+        * @param $table The name of the table
+        * @return Table information
+        */
+       function &getTableByName($table) {
+               $this->clean($table);
+               $sql = "SELECT * FROM pg_class WHERE relname='{$table}'";
+               return $this->selectRow($sql);
+       }
+
+       /**
+        * Retrieve the attribute definition of a table
+        * @param $table The name of the table
+        * @param $field (optional) The name of a field to return
+        * @return All attributes in order
+        */
+       function &getTableAttributes($table, $field = '') {
+               $this->clean($table);
+               $this->clean($field);
+               
+               if ($field == '') {
+                       $sql = "SELECT
+                                       a.attname, t.typname as type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+                               FROM
+                                       pg_class c, pg_attribute a, pg_type t
+                               WHERE
+                                       c.relname = '{$table}' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid
+                               ORDER BY a.attnum";
+               }
+               else {
+                       $sql = "SELECT
+                                       a.attname, t.typname as type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+                               FROM
+                                       pg_class c, pg_attribute a, pg_type t
+                               WHERE
+                                       c.relname = '{$table}' AND a.attname='{$column}' AND a.attrelid = c.oid AND a.atttypid = t.oid
+                               ORDER BY a.attnum";                             
+               }
+               
+               return $this->selectSet($sql);
+       }
+
+       /**
+        * Drops a column from a table
+        * @param $table The table from which to drop a column
+        * @param $column The column to be dropped
+        * @param $behavior CASCADE or RESTRICT or empty
+        * @return 0 success
+        * @return -99 not implemented
+        */
+       function dropColumn($table, $column, $behavior) {
+               return -99;
+       }
+       
+       /**
+        * Alters a column in a table
+        * @param $table The table in which the column resides
+        * @param $column The column to alter
+        * @param $name The new name for the column
+        * @param $notnull (boolean) True if not null, false otherwise
+        * @param $default The new default for the column
+        * @return 0 success
+        * @return -1 set not null error
+        * @return -2 set default error
+        * @return -3 rename column error
+        */
+       function alterColumn($table, $column, $name, $notnull, $default) {
+               $this->beginTransaction();
+
+               // @@ NEED TO HANDLE "NESTED" TRANSACTION HERE
+               $status = $this->setColumnNull($table, $column, !$notnull);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -1;
+               }
+
+               $status = $this->setColumnDefault($table, $column, $default);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -2;
+               }
+
+               $status = $this->renameColumn($table, $column, $name);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -3;
+               }
+
+               return $this->endTransaction();
+       }       
+
+       /**
+        * Creates a new table in the database
+        * @param $name The name of the table
+        * @param $fields The number of fields
+        * @param $field An array of field names
+        * @param $type An array of field types
+        * @param $length An array of field lengths
+        * @param $notnull An array of not null
+        * @param $default An array of default values
+        * @return 0 success
+        * @return -1 no fields supplied
+        */
+       function createTable($name, $fields, $field, $type, $length, $notnull, $default) {
+               // @@ NOTE: $default field not being cleaned - how on earth DO we clean it??
+               $this->fieldClean($name);
+       
+               $found = false;
+               $sql = "CREATE TABLE \"{$name}\" (";
+               
+               for ($i = 0; $i < $fields; $i++) {
+                       $this->fieldClean($field[$i]);
+                       $this->clean($type[$i]);
+                       $this->clean($length[$i]);
+                       
+                       // Skip blank columns - for user convenience
+                       if ($field[$i] == '' || $type[$i] == '') continue;
+                       
+                       $sql .= "\"{$field[$i]}\" {$type[$i]}";
+                       if ($length[$i] != '') $sql .= "({$length[$i]})";
+                       if (isset($notnull[$i])) $sql .= " NOT NULL";
+                       if ($default[$i] != '') $sql .= " DEFAULT {$default[$i]}";
+                       if ($i != $fields - 1) $sql .= ", ";
+
+                       $found = true;
+               }
+               
+               if (!$found) return -1;
+               
+               $sql .= ")";
+               
+               return $this->execute($sql);
+       }       
+       
+       /**
+        * Removes a table from the database
+        * @param $table The table to drop
+        * @return 0 success
+        */
+       function dropTable($table) {
+               $this->fieldClean($table);
+
+               $sql = "DROP TABLE \"{$table}\"";
+
+               return $this->execute($sql);
+       }
+
+       /**
+        * Empties a table in the database
+        * @param $table The table to be emptied
+        * @return 0 success
+        */
+       function emptyTable($table) {
+               $this->fieldClean($table);
+
+               $sql = "DELETE FROM \"{$table}\"";
+
+               return $this->execute($sql);
+       }
+
+       /**
+        * Renames a table
+        * @param $table The table to be renamed
+        * @param $newName The new name for the table
+        * @return 0 success
+        */
+       function renameTable($table, $newName) {
+               $this->fieldClean($table);
+               $this->fieldClean($newName);
+               
+               $sql = "ALTER TABLE \"{$table}\" RENAME TO \"{$newName}\"";
+
+               // @@ How do you do this?
+               return $this->execute($sql);
+       }
+       
+       /**
+        * Returns a recordset of all columns in a table
+        * @param $table The name of a table
+        * @param $offset The offset into the table
+        * @param $limit The maximum number of records to return at once
+        * @return A recordset
+        */
+       function &getTableRows($table) {
+               $this->fieldClean($table);              
+
+               return $this->selectTable("SELECT COUNT(*) FROM \"{$table}\"", $offset, $limit);
+       }       
+       
+       /**
+        * Returns a recordset of all columns in a table
+        * @param $table The name of a table
+        * @param $offset The offset into the table
+        * @param $limit The maximum number of records to return at once
+        * @return A recordset
+        */
+       function &browseTable($table, $offset = null, $limit = null) {
+               $this->fieldClean($table);              
+               
+               return $this->selectTable("SELECT oid, * FROM \"{$table}\"", $offset, $limit);
+       }
+
+       /**
+        * Returns a recordset of all columns in a table
+        * @param $table The name of a table
+        * @param $key The associative array holding the key to retrieve
+        * @return A recordset
+        */
+       function &browseRow($table, $key) {
+               $this->fieldClean($table);
+               
+               $sql = "SELECT * FROM \"{$table}\" WHERE true";
+               foreach ($key as $k => $v) {
+                       $this->fieldClean($k);
+                       $this->clean($v);
+                       $sql .= " AND \"{$k}\"='{$v}'";
+               }
+
+               return $this->selectSet($sql);
+       }
+
+       /**
+        *
+        */
+       function &selectTable($sql, $offset, $limit) {
+               return $this->selectSet($sql, $offset, $limit);
+       }
+
+       // Sequence functions
+       
+       /**
+        * Returns all sequences in the current database
+        * @return A recordset
+        */
+       function &getSequences() {
+               if (!$this->_showSystem) $where = " AND relname NOT LIKE 'pg_%'";
+               else $where = '';
+               $sql = "SELECT c.relname, u.usename  FROM pg_class c, pg_user u WHERE c.relowner=u.usesysid AND c.relkind = 'S'{$where} ORDER BY relname";
+               return $this->selectSet( $sql );
+       }
+
+       /**
+        * Returns properties of a single sequence
+        * @return A recordset
+        */
+       function &getSequence($sequence) {
+               if (!$this->_showSystem) $where = " AND relname NOT LIKE 'pg_%'";
+               else $where = '';
+               $sql = "SELECT sequence_name as relname,* FROM $sequence"; 
+               return $this->selectSet( $sql );
+       }
+
+       /** 
+        * Drops a given sequence
+        * @return 0 success
+        */
+       function &dropSequence($sequence) {
+               $this->clean($sequence);
+               $sql = "DROP SEQUENCE {$sequence} ";
+               return $this->execute($sql);
+       }
+
+       /** 
+        * Creates a new sequence
+        * @return 0 success
+        */
+       function &setSequence($sequence,$startval=1) {
+               $this->clean($sequence);
+               $sql = "CREATE SEQUENCE $seq_name START $startval";
+               return $this->execute($sql);
+       }
+
+       /** 
+        * Modifies permissions on a given sequence
+        * @return 0 success
+        */
+       function &setSequencePermissions($sequence) {
+
+       }
+
+       /** 
+        * Resets  a given sequence to 1
+        * @return 0 success
+        */
+       function &resetSequence($sequence) {
+               $this->clean($sequence);
+               $sql = "SELECT setval('$sequence',1)";
+               return $this->execute($sql);
+       }
+
+
+
+
+       /**
+        * Adds a check constraint to a table
+        * @param $table The table to which to add the check
+        * @param $definition The definition of the check
+        * @param $name (optional) The name to give the check, otherwise default name is assigned
+        * @return 0 success
+        */
+       function addCheckConstraint($table, $definition, $name = '') {
+               $this->fieldClean($table);
+               $this->fieldClean($name);
+               // @@ how the heck do you clean definition???
+               
+               if ($name != '')
+                       $sql = "ALTER TABLE \"{$table}\" ADD CONSTRAINT \"{$name}\" CHECK ({$definition})";
+               else
+                       $sql = "ALTER TABLE \"{$table}\" ADD CHECK ({$definition})";
+
+               // @@ How do you do this?
+               return $this->execute($sql);
+       }
+       
+       /**
+        * Drops a check constraint from a table
+        * @param $table The table from which to drop the check
+        * @param $name The name of the check to be dropped
+        * @return 0 success
+        * @return -2 transaction error
+        * @return -3 lock error
+        * @return -4 check drop error
+        */
+       function dropCheckConstraint($table, $name) {
+               $this->clean($table);
+               $this->clean($name);
+               
+               // Begin transaction
+               $status = $this->beginTransaction();
+               if ($status != 0) return -2;
+
+               // Properly lock the table
+               $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE";
+               $status = $this->execute($sql);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -3;
+               }
+
+               // Delete the check constraint
+               $sql = "DELETE FROM pg_relcheck WHERE rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}') AND rcname='{$name}'";
+          $status = $this->execute($sql);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -4;
+               }
+               
+               // Update the pg_class catalog to reflect the new number of checks
+               $sql = "UPDATE pg_class SET relchecks=(SELECT COUNT(*) FROM pg_relcheck WHERE 
+                                       rcrelid=(SELECT oid FROM pg_class WHERE relname='{$table}')) 
+                                       WHERE relname='{$table}'";
+          $status = $this->execute($sql);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -4;
+               }
+
+               // Otherwise, close the transaction
+               return $this->endTransaction();
+       }       
+
+       /**
+        * Adds a unique constraint to a table
+        * @param $table The table to which to add the unique
+        * @param $fields (array) An array of fields over which to add the unique
+        * @param $name (optional) The name to give the unique, otherwise default name is assigned
+        * @return 0 success
+        */
+       function addUniqueConstraint($table, $fields, $name = '') {
+               $this->fieldClean($table);
+               $this->arrayClean($fields);
+               $this->fieldClean($name);
+               
+               if ($name != '')
+                       $sql = "CREATE UNIQUE INDEX \"{$name}\" ON \"{$table}\"(\"" . join('","', $fields) . "\")";
+               else return -99; // Not supported
+
+               return $this->execute($sql);
+       }
+
+       /**
+        * Drops a unique constraint from a table
+        * @param $table The table from which to drop the unique
+        * @param $name The name of the unique
+        * @return 0 success
+        */
+       function dropUniqueConstraint($table, $name) {
+               $this->fieldClean($name);
+               
+               $sql = "DROP INDEX \"{$name}\"";
+
+               return $this->execute($sql);
+       }       
+        
+       /**
+        * Adds a primary key constraint to a table
+        * @param $table The table to which to add the primery key
+        * @param $fields (array) An array of fields over which to add the primary key
+        * @param $name (optional) The name to give the key, otherwise default name is assigned
+        * @return 0 success
+        */
+       function addPrimaryKeyConstraint($table, $fields, $name = '') {
+               // This function can be faked with a unique index and a catalog twiddle, however
+               // how do we ensure that it's only used on NOT NULL fields?
+               return -99; // Not supported.
+       }
+
+       /**
+        * Drops a primary key constraint from a table
+        * @param $table The table from which to drop the primary key
+        * @param $name The name of the primary key
+        * @return 0 success
+        */
+       function dropPrimaryKeyConstraint($table, $name) {
+               $this->fieldClean($name);
+               
+               $sql = "DROP INDEX \"{$name}\"";
+
+               return $this->execute($sql);
+       }
+       
+       /**
+        * Changes the owner of a table
+        * @param $table The table whose owner is to change
+        * @param $owner The new owner (username) of the table
+        * @return 0 success
+        */
+       function setOwnerOfTable($table, $owner) {
+               $this->fieldClean($table);
+               $this->fieldClean($owner);
+               
+               $sql = "ALTER TABLE \"{$table}\" OWNER TO \"{$owner}\"";
+
+               return $this->execute($sql);
+       }
+
+       // Column Functions
+
+       /**
+        * Add a new column to a table
+        * @param $table The table to add to
+        * @param $column The name of the new column
+        * @param $type The type of the column
+        * @param $size (optional) The optional size of the column (ie. 30 for varchar(30))
+        * @return 0 success
+        */
+       function addColumnToTable($table, $column, $type, $size = '') {
+               $this->clean($table);
+               $this->clean($column);
+               $this->clean($type);
+               $this->clean($size);
+               // @@ How the heck do you properly clean type and size?
+               
+               if ($size == '')
+                       $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}";
+               else
+                       $sql = "ALTER TABLE \"{$table}\" ADD COLUMN \"{$column}\" {$type}({$size})";
+
+               // @@ How do you do this?
+               return $this->execute($sql);
+       }
+
+       /**
+        * Drops a column from a table
+        * @param $table The table from which to drop
+        * @param $column The column name to drop
+        * @return 0 success
+        */
+       function dropColumnFromTable($table, $column) {
+               return -99; // Not implemented
+       }
+
+       /**
+        * Sets default value of a column
+        * @param $table The table from which to drop
+        * @param $column The column name to set
+        * @param $default The new default value
+        * @return 0 success
+        */
+       function setColumnDefault($table, $column, $default) {
+               $this->fieldClean($table);
+               $this->fieldClean($column);
+               // @@ How the heck do you clean default clause?
+               
+               $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";
+
+               return $this->execute($sql);
+       }
+
+       /**
+        * Drops default value of a column
+        * @param $table The table from which to drop
+        * @param $column The column name to drop default
+        * @return 0 success
+        */
+       function dropColumnDefault($table, $column) {
+               $this->clean($table);
+               $this->clean($column);
+
+               $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT";
+
+               // @@ How do you do this?
+               return $this->execute($sql);
+       }
+
+       /**
+        * Sets whether or not a column can contain NULLs
+        * @param $table The table that contains the column
+        * @param $column The column to alter
+        * @param $state True to set null, false to set not null
+        * @return 0 success
+        * @return -1 attempt to set not null, but column contains nulls
+        * @return -2 transaction error
+        * @return -3 lock error
+        * @return -4 update error
+        */
+       function setColumnNull($table, $column, $state) {
+               $this->clean($table);
+               $this->clean($column);
+
+               // Begin transaction
+               $status = $this->beginTransaction();
+               if ($status != 0) return -2;
+
+               // Properly lock the table
+               $sql = "LOCK TABLE \"{$table}\" IN ACCESS EXCLUSIVE MODE";
+               $status = $this->execute($sql);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -3;
+               }
+
+               // Check for existing nulls
+               if (!$state) {
+                       $sql = "SELECT COUNT(*) AS total FROM \"{$table}\" WHERE \"{$column}\" IS NULL";
+                       $result = $this->selectField($sql, 'total');
+                       if ($result > 0) {
+                               $this->rollbackTransaction();
+                               return -1;
+                       }
+               }
+
+               // Otherwise update the table.  Note the reverse-sensed $state variable
+               $sql = "UPDATE pg_attribute SET attnotnull = " . (($state) ? 'false' : 'true') . " 
+                                       WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '{$table}') 
+                                       AND attname = '{$column}'";
+
+          $status = $this->execute($sql);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -4;
+               }
+
+               // Otherwise, close the transaction
+               return $this->endTransaction();
+       }
+
+       /**
+        * Renames a column in a table
+        * @param $table The table containing the column to be renamed
+        * @param $column The column to be renamed
+        * @param $newName The new name for the column
+        * @return 0 success
+        */
+       function renameColumn($table, $column, $newName) {
+               $this->fieldClean($table);
+               $this->fieldClean($column);
+               $this->fieldClean($newName);
+
+               $sql = "ALTER TABLE \"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";
+
+               return $this->execute($sql);
+       }
+
+       /**
+        * Grabs a list of indicies in the database or table
+        * @param $table (optional) The name of a table to get the indicies for
+        */
+       function &getIndicies($table = '') {
+               $this->clean($table);
+
+               $sql = "SELECT c2.relname, i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid)
+                       FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
+                       WHERE c.oid = '16977' AND c.oid = i.indrelid AND i.indexrelid = c2.oid
+                       ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname";
+
+               
+               if ($table != '')
+                       $where = "WHERE relname='{$table}' AND ";
+               elseif (!$this->_showSystem)
+                       $where = "WHERE relname NOT LIKE 'pg_%' AND ";
+               else $where  = '';
+               
+               $sql = "SELECT relname FROM pg_class {$where} relkind ='i' ORDER BY relname";
+
+               return $this->selectSet($sql);
+       }
+
+       function &getIndex($idxname) {
+               $sql = "SELECT
+                                       ic.relname AS relname,
+                                       bc.relname AS tab_name,
+                                       ta.attname AS column_name,
+                                       i.indisunique AS unique_key,
+                                       i.indisprimary AS primary_key
+                               FROM
+                                       pg_class bc,
+                                       pg_class ic,
+                                       pg_index i,
+                                       pg_attribute ta,
+                                       pg_attribute ia
+                               WHERE
+                                       bc.oid = i.indrelid
+                                       AND ic.oid = i.indexrelid
+                                       AND ia.attrelid = i.indexrelid
+                                       AND ta.attrelid = bc.oid
+                                       AND ic.relname = '$idxname'
+                                       AND ta.attrelid = i.indrelid
+                                       AND ta.attnum = i.indkey[ia.attnum-1]
+                               ORDER BY
+                                       relname, tab_name, column_name";
+
+               return $this->selectSet($sql);
+       }
+
+       /**
+        * Creates a database
+        * @param $database The name of the database to create
+        * @return 0 success
+        */
+       function createIndex($name, $table, $columns) {
+               $this->fieldClean($name);
+               $this->fieldClean($table);
+               $this->arrayClean($columns);
+
+               $sql = "CREATE INDEX \"{$name}\" ON \"{$table}\"(\"" .
+                       implode('","', $columns) . "\")";
+                       
+               return $this->execute($sql);
+       }
+
+       /**
+        * Removes an index from the database
+        * @param $index The index to drop
+        * @return 0 success
+        */
+       function dropIndex($index) {
+               $this->fieldClean($index);
+
+               $sql = "DROP INDEX \"{$index}\"";
+
+               return $this->execute($sql);
+       }
+
+       // View functions
+       
+       /**
+        * Returns a list of all views in the database
+        * @return All views
+        */
+       function getViews() {
+               if (!$this->_showSystem)
+                       $where = "WHERE viewname NOT LIKE 'pg_%'";
+               else $where  = '';
+               
+               $sql = "SELECT viewname, viewowner FROM pg_views {$where} ORDER BY viewname";
+
+               return $this->selectSet($sql);
+       }
+       
+       /**
+        * Returns all details for a particular view
+        * @param $view The name of the view to retrieve
+        * @return View info
+        */
+       function getView($view) {
+               $this->clean($view);
+               
+               $sql = "SELECT viewname, viewowner, definition FROM pg_views WHERE viewname='$view'";
+
+               return $this->selectSet($sql);
+       }       
+
+       /**
+        * Creates a new view.
+        * @param $viewname The name of the view to create
+        * @param $definition The definition for the new view
+        * @return 0 success
+        */
+       function createView($viewname, $definition) {
+               $this->clean($viewname);
+               // Note: $definition not cleaned
+               
+               $sql = "CREATE VIEW \"{$viewname}\" AS {$definition}";
+               
+               return $this->execute($sql);
+       }
+       
+       /**
+        * Drops a view.
+        * @param $viewname The name of the view to drop
+        * @return 0 success
+        */
+       function dropView($viewname) {
+               $this->clean($viewname);
+               
+               $sql = "DROP VIEW \"{$viewname}\"";
+               
+               return $this->execute($sql);
+       }
+       
+       /**
+        * Updates a view.  Postgres doesn't have CREATE OR REPLACE view,
+        * so we do it with a drop and a recreate.
+        * @param $viewname The name fo the view to update
+        * @param $definition The new definition for the view
+        * @return 0 success
+        * @return -1 transaction error
+        * @return -2 drop view error
+        * @return -3 create view error
+        */
+       function setView($viewname, $definition) {
+               $status = $this->beginTransaction();
+               if ($status != 0) return -1;
+               
+               $status = $this->dropView($viewname);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -2;
+               }
+               
+               $status = $this->createView($viewname, $definition);
+               if ($status != 0) {
+                       $this->rollbackTransaction();
+                       return -3;
+               }
+               
+               $status = $this->endTransaction();
+               return ($status == 0) ? 0 : -1;
+       }       
+
+       // Operator functions
+       
+       /**
+        * Returns a list of all operators in the database
+        * @return All operators
+        */
+       function getOperators() {
+               if (!$this->_showSystem)
+                       $where = "WHERE po.oid > '{$this->_lastSystemOID}'::oid";
+               else $where  = '';
+               
+               $sql = "
+                       SELECT
+            po.oid,
+                               po.oprname,
+                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprleft) AS oprleftname,
+                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprright) AS oprrightname,
+                               (SELECT typname FROM pg_type pt WHERE pt.oid=po.oprresult) AS resultname
+                       FROM
+                               pg_operator po
+                       {$where}                                
+                       ORDER BY
+                               po.oprname, po.oid
+               ";
+
+               return $this->selectSet($sql);
+       }
+       
+       
+       /**
+        * Creates a new operator
+        */
+
+       // User and group functions
+       
+       /**
+        * Returns all users in the database cluster
+        * @return All users
+        */
+       function &getUsers() {
+               $sql = "SELECT usename, usesuper, usecreatedb, valuntil FROM pg_shadow ORDER BY usename";
+               
+               return $this->selectSet($sql);
+       }
+       
+       /**
+        * Return information about a single user
+        * @param $username The username of the user to retrieve
+        * @return The user's data
+        */
+       function &getUser($username) {
+               $this->clean($username);
+               
+               $sql = "SELECT usename, usesuper, usecreatedb, valuntil FROM pg_shadow WHERE usename='{$username}'";
+               
+               return $this->selectSet($sql);
+       }
+       
+       /**
+        * Creates a new user
+        * @param $username The username of the user to create
+        * @param $password A password for the user
+        * @param $createdb boolean Whether or not the user can create databases
+        * @param $createuser boolean Whether or not the user can create other users
+        * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'.  When the account expires.
+        * @param $group (array) The groups to create the user in
+        * @return 0 success
+        */
+       function createUser($username, $password, $createdb, $createuser, $expiry, $groups) {
+               $this->clean($username);
+               // @@ THIS IS A PROBLEM FOR TRIMMING PASSWORD!!!
+               $this->clean($password);
+               $this->clean($expiry);
+               $this->arrayClean($groups);             
+               
+               $sql = "CREATE USER \"{$username}\"";
+               if ($password != '') $sql .= " WITH PASSWORD '{$password}'";
+               $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
+               $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';
+               if (is_array($groups) && sizeof($groups) > 0) $sql .= " IN GROUP '" . join("', '", $groups) . "'";
+               if ($expiry != '') $sql .= " VALID UNTIL '{$expiry}'";
+               
+               return $this->execute($sql);
+       }       
+       
+       /**
+        * Adjusts a user's info
+        * @param $username The username of the user to modify
+        * @param $password A new password for the user
+        * @param $createdb boolean Whether or not the user can create databases
+        * @param $createuser boolean Whether or not the user can create other users
+        * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'.  When the account expires.
+        * @return 0 success
+        */
+       function setUser($username, $password, $createdb, $createuser, $expiry) {
+               $this->clean($username);
+               $this->clean($password);
+               $this->clean($expiry);
+               
+               $sql = "ALTER USER \"{$username}\"";
+               if ($password != '') $sql .= " WITH PASSWORD '{$password}'";
+               $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
+               $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';
+               if ($expiry != '') $sql .= " VALID UNTIL '{$expiry}'";
+               
+               return $this->execute($sql);
+       }       
+       
+       /**
+        * Removes a user
+        * @param $username The username of the user to drop
+        * @return 0 success
+        */
+       function dropUser($username) {
+               $this->clean($username);
+               
+               $sql = "DROP USER \"{$username}\"";
+               
+               return $this->execute($sql);
+       }
+        
+       // Capabilities
+       function hasTables() { return true; }
+       function hasViews() { return true; }
+       function hasSequences() { return true; }
+       function hasFunctions() { return true; }
+       function hasTriggers() { return true; }
+       function hasOperators() { return true; }
+       function hasTypes() { return true; }
+       function hasAggregates() { return true; }
+       function hasIndicies() { return true; }
+       function hasRules() { return true; }
+       function hasLanguages() { return true; }
+
+}
+
+?>
index 93467b0f3b171e19ec5d59570d25cf3dd8991c1b..2dc62dcca5985b6f8e719f88d095784e82aa8e9c 100644 (file)
@@ -3,7 +3,7 @@
        /**
         * List tables in a database
         *
-        * $Id: tblproperties.php,v 1.8 2002/11/18 05:49:55 chriskl Exp $
+        * $Id: tblproperties.php,v 1.9 2002/12/14 10:56:26 chriskl Exp $
         */
 
        // Include application functions
                
                doNav();
                echo "<h2>", htmlspecialchars($_REQUEST['database']), ": ", htmlspecialchars($_REQUEST['table']), ": {$strTriggers}</h2>\n";
-               
+               $misc->printMsg($msg);
+
                $triggers = &$localData->getTriggers($_REQUEST['table']);
-               
+
                if ($triggers->recordCount() > 0) {
                        echo "<table>\n";
                        echo "<tr><th class=\"data\">{$strName}</th><th colspan=\"3\" class=\"data\">{$strActions}</th>\n";
                        $i = 0;
-                       
+
                        while (!$triggers->EOF) {
                                $id = ( ($i % 2 ) == 0 ? '1' : '2' );
                                echo "<tr><td class=\"data{$id}\">", htmlspecialchars( $triggers->f[$data->tgFields['tgname']]), "</td>";
                        }
                else
                        echo "<p>{$strNoTriggers}</p>\n";
+
+               echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=createtrigger&database=",
+                       urlencode($_REQUEST['database']), "&table=", htmlspecialchars($_REQUEST['table']), "\">{$strCreateTrigger}</a></p>\n";
+       }
+
+       /**
+        * Displays a screen where they can enter a new index
+        */
+       function doCreateIndex($msg = '') {
+               global $data, $localData, $misc;
+               global $PHP_SELF, $strName, $strDefinition;
+
+               if (!isset($_POST['formIndex'])) $_POST['formIndex'] = '';
+               if (!isset($_POST['formCols'])) $_POST['formCols'] = '';
+
+               echo "<h2>", htmlspecialchars($_REQUEST['database']), ": Indexes: Create Index</h2>\n";
+               $misc->printMsg($msg);
                
-               echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=createtrigger&database=", 
-                       urlencode($_REQUEST['database']), "&table=", htmlspecialchars($_REQUEST['table']), "\">{$strCreateTrigger}</a></p>\n";          
+               echo "<form action=\"$PHP_SELF\" method=post>\n";
+               echo "<table width=100%>\n";
+               echo "<tr><th class=data>{$strName}</th></tr>\n";
+               echo "<tr><td class=data1><input name=formIndex size={$data->_maxNameLen} maxlength={$data->_maxNameLen} value=\"",
+                       htmlspecialchars($_POST['formIndex']), "\"></td></tr>\n";
+               echo "<tr><th class=data>Columns</th></tr>\n";
+               echo "<tr><td class=data1><input name=formCols size={$data->_maxNameLen} value=\"",
+                       htmlspecialchars($_POST['formCols']), "\"> (eg. col1, col2)</td></tr>\n";
+               echo "</table>\n";
+               echo "<p><input type=hidden name=action value=save_create_index>\n";
+               echo "<input type=hidden name=database value=\"", htmlspecialchars($_REQUEST['database']), "\">\n";
+               echo "<input type=hidden name=table value=\"", htmlspecialchars($_REQUEST['table']), "\">\n";
+               echo "<input type=submit value=Save> <input type=reset></p>\n";
+               echo "</form>\n";
+               
+               echo "<p><a class=navlink href=\"$PHP_SELF?database=", urlencode($_REQUEST['database']),
+                       "&table=", urlencode($_REQUEST['table']), "&action=indicies\">Show All Indexes</a></p>\n";
+       }
+
+       /**
+        * Actually creates the new index in the database
+        * @@ Note: this function can't handle columns with commas in them
+        */
+       function doSaveCreateIndex() {
+               global $localData;
+
+               // Check that they've given a name and at least one column
+               if ($_POST['formIndex'] == '') doCreateIndex("Index needs a name.");
+               elseif ($_POST['formCols'] == '') doCreate("Index needs at least one column.");
+               else {
+                       $status = $localData->createIndex($_POST['formIndex'], $_POST['table'], explode(',', $_POST['formCols']));
+                       if ($status == 0)
+                               doIndicies('Index created.');
+                       else
+                               doCreateIndex('Index creation failed.');
+               }
+       }
+
+       /**
+        * Show confirmation of drop index and perform actual drop
+        */
+       function doDropIndex($confirm) {
+               global $localData, $database;
+               global $PHP_SELF;
+
+               if ($confirm) {
+                       echo "<h2>", htmlspecialchars($_REQUEST['database']), ": Tables: ",
+                               htmlspecialchars($_REQUEST['table']), ": " , htmlspecialchars($_REQUEST['index']), ": Drop</h2>\n";
+
+                       echo "<p>Are you sure you want to drop the index \"", htmlspecialchars($_REQUEST['index']),
+                               "\" from table \"", htmlspecialchars($_REQUEST['table']), "\"?</p>\n";
+                       
+                       echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+                       echo "<input type=hidden name=action value=drop_index>\n";
+                       echo "<input type=hidden name=table value=\"", htmlspecialchars($_REQUEST['table']), "\">\n";
+                       echo "<input type=hidden name=index value=\"", htmlspecialchars($_REQUEST['index']), "\">\n";
+                       echo "<input type=hidden name=database value=\"", htmlspecialchars($_REQUEST['database']), "\">\n";
+                       echo "<input type=submit name=choice value=\"Yes\"> <input type=submit name=choice value=\"No\">\n";
+                       echo "</form>\n";
+               }
+               else {
+                       $status = $localData->dropIndex($_POST['index'], 'RESTRICT');
+                       if ($status == 0)
+                               doIndicies('Index dropped.');
+                       else
+                               doIndicies('Index drop failed.');
+               }
+
        }
 
        function doIndicies($msg = '') {
-               global $data, $localData, $misc; 
+               global $data, $localData, $misc;
                global $PHP_SELF;
                global $strNoIndicies, $strIndicies, $strActions, $strName;
-               
+
                doNav();
                echo "<h2>", htmlspecialchars($_REQUEST['database']), ": ", htmlspecialchars($_REQUEST['table']), ": {$strIndicies}</h2>\n";
-               
+               $misc->printMsg($msg);
+
                $indexes = &$localData->getIndexes($_REQUEST['table']);
                
                if ($indexes->recordCount() > 0) {
                                echo "<tr><td class=\"data{$id}\">", htmlspecialchars( $indexes->f[$data->ixFields['idxname']]), "</td>";
                                echo "<td class=\"data{$id}\">", htmlspecialchars( $indexes->f[$data->ixFields['idxdef']]), "</td>";
                                echo "<td class=\"data{$id}\">";
-                               echo "<a href=\"$PHP_SELF?action=confirm_drop&database=", htmlspecialchars($_REQUEST['database']), "&index=", htmlspecialchars( $indexes->f[$data->ixFields['idxname']]), "\">Drop</td>\n"; 
+                               echo "<a href=\"$PHP_SELF?action=confirm_drop_index&database=", htmlspecialchars($_REQUEST['database']), "&index=", htmlspecialchars( $indexes->f[$data->ixFields['idxname']]), 
+                                       "&table=", htmlspecialchars($_REQUEST['table']), "\">Drop</td>\n";
                                echo "<td class=\"data{$id}\">";
-                               echo "<a href=\"$PHP_SELF?action=priviledges&database=", htmlspecialchars($_REQUEST['database']), "&index=", htmlspecialchars( $indexes->f[$data->ixFields['idxname']]), "\">Privileges</td></tr>\n"; 
+                               echo "<a href=\"$PHP_SELF?action=priviledges_index&database=", htmlspecialchars($_REQUEST['database']), "&index=", htmlspecialchars( $indexes->f[$data->ixFields['idxname']]), "\">Privileges</td></tr>\n";
                                
                                $indexes->movenext();
                                $i++;
                        }
-                       
+
                        echo "</table>\n";
                        }
                else
                        echo "<p>{$strNoIndicies}</p>\n";
                
-               echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=createindex&database=", 
+               echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create_index&database=",
                        urlencode( $_REQUEST['database'] ), "&table=", htmlspecialchars($_REQUEST['table']), "\">Create Index</a></p>\n";               
        }       
 
                                        if ($column->f['attnotnull']) $_REQUEST['notnull'] = 'YES';
                                }                               
                                
-                               echo "<tr><td><input name=\"field\" size={$data->_maxNameLen} maxlength={$data->_maxNameLen} value=\"", 
+                               echo "<tr><td><input name=\"field\" size={$data->_maxNameLen} maxlength={$data->_maxNameLen} value=\"",
                                        htmlspecialchars($_REQUEST['field']), "\"></td>";
                                echo "<td>", htmlspecialchars($column->f['type']), "</td>";
                                echo "<td><input type=checkbox name=\"notnull\"", (isset($_REQUEST['notnull'])) ? ' checked' : '', "></td>\n";
                        }
                        echo "</table>\n";
                        echo "<br />\n";
-
-               echo "<table border=0>\n";
-               echo "<tr>\n";
-               echo "<th>$strKeyName</th>\n";
-               echo "<th>$strUnique</th>\n";
-               echo "<th>$strPrimary</th>\n";
-               echo "<th>$strField</th>\n";
-               echo "<th>$strAction</th>\n";
-               echo "</tr>\n";
-
-               $keys = &$localData->getTableKeys($_REQUEST['table']);
-
-               if ($keys->recordCount() > 0) {
-
-                       $keys->f['unique_key'] = $localData->phpBool($keys->f['unique_key']);
-                       $keys->f['primary_key'] = $localData->phpBool($keys->f['primary_key']);
-
-                       echo "<tr>\n";
-                       echo "<td>", htmlspecialchars($keys->f['index_name']), "</td>\n";
-                       echo "<td>", ($keys->f['unique_key'] ? 'Yes' : 'strNo'), "</td>\n";
-                       echo "<td>", ($keys->f['primary_key'] ? 'Yes' : 'strNo'), "</td>\n";
-                       echo "<td>", htmlspecialchars($keys->f['column_name']), "</td>\n";
-                       echo "<td><a href=\"\">$strDrop</a></td>\n";
-                       echo "</tr></table>\n";
-               } else {
-                       echo '<tr><td>No Keys Found</td></tr>';
-               }
        
 echo <<<EOF
                                
@@ -308,37 +367,15 @@ EOF;
                                        htmlspecialchars($_REQUEST['database']), "&table=", urlencode($_REQUEST['table']),"\">Insert</a></li>\n";
                                echo "<li><a href=\"$PHP_SELF?action=confirm_drop&database=",
                                        htmlspecialchars($_REQUEST['database']), "&table=", urlencode($_REQUEST['table']),"\">Drop</a></li>\n";
-
-echo <<<EOF
-
-<li><a href="tbl_privilege.php?server=2&db=mojo5&table=med_practice&goto=tbl_properties.php">Privileges</a>
-<li>
-       <form method="post" action="tbl_addfield.php">
-               Add new field: 
-               <select name="num_fields">
-               <option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option>            </select>
-
-               <input type="submit" value="Go">
-               <input type="hidden" name="table" value="med_practice">
-               <input type="hidden" name="db" value="mojo5">
-               <input type="hidden" name="server" value="2">
-       </form>
-<li><a href="ldi_table.php?server=2&db=mojo5&table=med_practice&goto=tbl_properties.php">Insert textfiles into table</a>
-<li>
-EOF;
-
-
                }
                else {
                        echo "<p>{$strNoTable}</p>\n";
                }
-               
-               echo "<p><a class=navlink href=\"tables.php?database=", urlencode($_REQUEST['database']), "\">{$strShowAllTables}</a></p>\n";
        }
 
        function doNav() {
                global $PHP_SELF;
-               
+
                $vars = 'database=' . urlencode($_REQUEST['database']) . '&table=' . urlencode($_REQUEST['table']);
                
                echo "<table class=\"navbar\" border=\"0\" width=\"100%\" cellpadding=\"5\" cellspacing=\"3\">\n";
@@ -358,6 +395,19 @@ EOF;
                case 'triggers':
                        doTriggers();
                        break;
+               case 'save_create_index':
+                       doSaveCreateIndex();
+                       break;
+               case 'create_index':
+                       doCreateIndex();
+                       break;
+               case 'drop_index':
+                       if ($_POST['choice'] == 'Yes') doDropIndex(false);
+                       else doIndicies();
+                       break;
+               case 'confirm_drop_index':
+                       doDropIndex(true);
+                       break;
                case 'indicies':
                        doIndicies();
                        break;
@@ -373,7 +423,7 @@ EOF;
                        break;
                case 'confirm_drop':
                        doDrop(true);
-                       break;                  
+                       break;
                default:
                        doDefault();
                        break;