--- /dev/null
+<?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.3 2002/07/26 09:04:08 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
+\r
+ // @@ Should we bother querying for this?\r
+ var $_lastSystemOID = 18539;\r
+ var $_maxNameLen = 31;\r
+\r
+ function Postgres($host, $port, $database, $user, $password) {\r
+ $this->BaseDB('postgres7');\r
+\r
+// $this->conn->host = $host;\r
+ //$this->Port = $port;\r
+\r
+ $this->conn->connect($host, $user, $password, $database);\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
+ * 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
+ * Drops a database\r
+ * @param $database The name of the database to retrieve\r
+ * @return 0 success\r
+ */\r
+ function dropDatabase($database) {\r
+ $this->clean($database);\r
+ $sql = "DROP DATABASE \"{$database}\"";\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
+ // @@ Need create table - tricky!!\r
+ \r
+ /**\r
+ * Removes a table from the database\r
+ * @param $table\r
+ * @return 0 success\r
+ */\r
+ function dropTable($table) {\r
+ $this->clean($table);\r
+ \r
+ $sql = "DROP TABLE \"{$table}\"";\r
+\r
+ // @@ How do you do this?\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->clean($table);\r
+ $this->clean($newName);\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
+ 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, $limit) {\r
+ return $this->selectTable("SELECT * FROM \"{$table}\"", $offset, $limit);\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 relname FROM pg_class WHERE relkind = 'S'{$where} ORDER BY relname";\r
+ return $this->selectSet( $sql );\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->clean($table);\r
+ $this->clean($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->clean($table);\r
+ $this->arrayClean($fields);\r
+ $this->clean($name);\r
+ \r
+ if ($name != '')\r
+ $sql = "CREATE UNIQUE INDEX \"{$name}\" ON \"{$table}\"(\"" . join('","', $fields) . "\")";\r
+ else return -99; // Not supported\r
+\r
+ // @@ How do you do this?\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->clean($table);\r
+ $this->clean($name);\r
+ \r
+ $sql = "DROP INDEX \"{$name}\"";\r
+\r
+ // @@ How do you do this?\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->clean($table);\r
+ $this->clean($name);\r
+ \r
+ $sql = "DROP INDEX \"{$name}\"";\r
+\r
+ // @@ How do you do this?\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->clean($table);\r
+ $this->clean($owner);\r
+ \r
+ $sql = "ALTER TABLE \"{$table}\" OWNER TO \"{$owner}\"";\r
+\r
+ // @@ How do you do this?\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->clean($table);\r
+ $this->clean($column);\r
+ // @@ How the heck do you clean default clause?\r
+ \r
+ $sql = "ALTER TABLE \"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";\r
+\r
+ // @@ How do you do this?\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
+ $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->clean($table);\r
+ $this->clean($column);\r
+ $this->clean($newName);\r
+\r
+ $sql = "ALTER TABLE \"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";\r
+\r
+ // @@ how?\r
+ return $this->execute($sql);\r
+ }\r
+/*\r
+ function &getIndices()\r
+ function &getIndex()\r
+ function setIndex()\r
+ function delIndex()\r
+\r
+ function &getSequences()\r
+ function &getSequence()\r
+ function setSequence()\r
+ function delSequence()\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 hasRules() { return true; }\r
+ function hasLanguages() { return true; }\r
+\r
+}\r
+\r
+?>
\ No newline at end of file
/**\r
* List tables in a database\r
*\r
- * $Id: tables.php,v 1.3 2002/05/15 09:57:55 chriskl Exp $\r
+ * $Id: tables.php,v 1.4 2002/07/26 09:03:06 chriskl Exp $\r
*/\r
\r
// Include application functions\r
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';\r
$PHP_SELF = $_SERVER['PHP_SELF'];\r
\r
-?>\r
+ /**\r
+ * Show confirmation of drop and perform actual drop\r
+ */\r
+ function doDelRow($confirm) {\r
+ global $localData, $database;\r
+ global $PHP_SELF;\r
\r
-<html>\r
-<body>\r
+ if ($confirm) { \r
+ echo "<h2>", htmlspecialchars($_REQUEST['database']), ": Tables: ", htmlspecialchars($_REQUEST['table']), ": Delete Row</h2>\n";\r
\r
-<?php\r
+ echo "<p>Are you sure you want to delete this row?</p>\n";\r
+ \r
+ echo "<form action=\"$PHP_SELF\" method=\"post\">\n";\r
+ echo "<input type=hidden name=action value=delrow>\n";\r
+ echo "<input type=hidden name=table value=\"", htmlspecialchars($_REQUEST['table']), "\">\n";\r
+ echo "<input type=hidden name=database value=\"", htmlspecialchars($_REQUEST['database']), "\">\n";\r
+ echo "<input type=hidden name=offset value=\"", htmlspecialchars($_REQUEST['offset']), "\">\n";\r
+ echo "<input type=hidden name=limit value=\"", htmlspecialchars($_REQUEST['limit']), "\">\n";\r
+ echo "<input type=hidden name=key value=\"", htmlspecialchars(serialize($_REQUEST['key'])), "\">\n";\r
+ echo "<input type=submit name=choice value=\"Yes\"> <input type=submit name=choice value=\"No\">\n";\r
+ echo "</form>\n";\r
+ }\r
+ else {\r
+ $status = $localData->deleteRow($_POST['table'], unserialize($_POST['key']));\r
+ if ($status == 0)\r
+ doBrowse('Row deleted.');\r
+ else\r
+ doBrowse('Row deletion failed.');\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Browse a table\r
+ */\r
+ function doBrowse($msg = '') {\r
+ global $data, $localData, $misc;\r
+ global $PHP_SELF, $strActions;\r
+ \r
+ echo "<h2>", htmlspecialchars($_REQUEST['database']), ": ", htmlspecialchars($_REQUEST['table']), "</h2>\n";\r
+ $misc->printMsg($msg);\r
\r
-switch ($action) {\r
- case 'browse': \r
- echo "<h2>", htmlspecialchars($_GET['database']), ": ", htmlspecialchars($_GET['table']), "</h2>\n";\r
- $rs = &$localData->browseTable($_GET['table'], $_GET['offset'], $_GET['limit']);\r
+ $rs = &$localData->browseTable($_REQUEST['table'], $_REQUEST['offset'], $_REQUEST['limit']);\r
+ \r
+ // Fetch unique row identifier, if there is one\r
+ $key = $localData->getRowIdentifier($_REQUEST['table']);\r
\r
if ($rs->recordCount() > 0) {\r
echo "<table>\n<tr>";\r
reset($rs->f);\r
while(list($k, ) = each($rs->f)) {\r
echo "<th class=data>", htmlspecialchars($k), "</td>";\r
- } \r
- echo "<th colspan=2 class=data>{$strActions}</th>\n";\r
+ }\r
+ \r
+ // @@ CHECK THAT KEY ACTUALLY IS IN THE RESULT SET...\r
+ \r
+ if (sizeof($key) > 0)\r
+ echo "<th colspan=2 class=data>{$strActions}</th>\n";\r
\r
$i = 0;\r
reset($rs->f);\r
while(list(, $v) = each($rs->f)) {\r
echo "<td class=data{$id} nowrap>", nl2br(htmlspecialchars($v)), "</td>";\r
} \r
- echo "<td class=opbutton{$id}>Edit</td>\n";\r
- echo "<td class=opbutton{$id}>Delete</td>\n";\r
+ if (sizeof($key) > 0) {\r
+ $key_str = '';\r
+ foreach ($key as $v) {\r
+ if ($key_str != '') $key_str .= '&';\r
+ $key_str .= urlencode("key[{$v}]") . '=' . urlencode($rs->f[$v]);\r
+ }\r
+ \r
+ echo "<td class=opbutton{$id}><a href=\"{$PHP_SELF}?action=editrow&database=", urlencode($_REQUEST['database']),\r
+ "&table=", urlencode($_REQUEST['table']), "&offset=", $_REQUEST['offset'], "&limit=", $_REQUEST['limit'], "&{$key_str}\">Edit</a></td>\n";\r
+ echo "<td class=opbutton{$id}><a href=\"{$PHP_SELF}?action=confdelrow&database=", urlencode($_REQUEST['database']),\r
+ "&table=", urlencode($_REQUEST['table']), "&offset=", $_REQUEST['offset'], "&limit=", $_REQUEST['limit'], "&{$key_str}\">Delete</a></td>\n";\r
+ }\r
echo "</tr>\n";\r
$rs->moveNext();\r
$i++;\r
}\r
}\r
else echo "<p>No data.</p>\n";\r
- \r
- break;\r
- default:\r
- echo "<h2>", htmlspecialchars($_GET['database']), "</h2>\n";\r
+ }\r
+\r
+ /**\r
+ * Show default list of tables in the database\r
+ */\r
+ function doDefault($msg = '') {\r
+ global $data, $localData;\r
+ global $PHP_SELF, $strTable, $strOwner, $strActions, $strNoTables;\r
\r
+ echo "<h2>", htmlspecialchars($_GET['database']), "</h2>\n";\r
+ \r
$tables = &$localData->getTables();\r
\r
if ($tables->recordCount() > 0) {\r
else {\r
echo "<p>{$strNoTables}</p>\n";\r
}\r
- break;\r
-} \r
+ }\r
\r
+ echo "<html>\n";\r
+ echo "<body>\n";\r
+ \r
+ switch ($action) {\r
+ case 'delrow':\r
+ if ($_POST['choice'] == 'Yes') doDelRow(false);\r
+ else doBrowse();\r
+ break;\r
+ case 'confdelrow':\r
+ doDelRow(true);\r
+ break; \r
+ case 'browse':\r
+ doBrowse();\r
+ break;\r
+ default:\r
+ doDefault();\r
+ break;\r
+ } \r
+\r
+ echo "</body>\n";\r
+ echo "</html>\n";\r
+\r
?>\r
-</body>\r
-</html>
\ No newline at end of file