A big rearrangement.
authorchriskl <chriskl>
Fri, 26 Jul 2002 09:03:06 +0000 (09:03 +0000)
committerchriskl <chriskl>
Fri, 26 Jul 2002 09:03:06 +0000 (09:03 +0000)
* Moved class functions around so that they appear in the first database
version that supports them.  Lots of stuff moved to BaseDB and Postgres
* More support for new 7.3 features
* Known bug in schema support at the moment - I'm working on it
* Looked at Raymond's sequence stuff, did a few things:
 - Moved the getSequences function to Postgres instead of Postgres71 since
   sequences are found in all versions of postgres
 - Added a comment for the function
 - Added support for showing system sequences or not
 - Used like instead of regexp, just looks nicer
 - Fixed missing /table tag that was causing display probs
 - Note: I think the code layout in sequences.php probably should be
   made to match that of the rest of the codebase (coding standards???)
 - Obviously it's an early cut, but it's going in the right direction
* Added support for deleting rows when browsing, using a function that
  finds a unique identifying get for tables.
* Edit row next

classes/Misc.php
classes/database/BaseDB.php
classes/database/Postgres.php [new file with mode: 0755]
classes/database/Postgres71.php
classes/database/Postgres73.php
public_html/sequences.php
public_html/tables.php
public_html/views.php
themes/default/global.css

index c8c9057b40b8e5c6ec238360b4ed6574c1ef6fd5..30eba7cf78497e2f253db761fd19633c000b3ca5 100644 (file)
@@ -2,7 +2,7 @@
        /**\r
         * Class to hold various commonly used functions\r
         *\r
-        * $Id: Misc.php,v 1.1 2002/04/15 11:57:28 chriskl Exp $\r
+        * $Id: Misc.php,v 1.2 2002/07/26 09:03:06 chriskl Exp $\r
         */\r
         \r
        class Misc {\r
                        if ($msg != '') echo "<p class=message>", htmlspecialchars($msg), "</p>\n";\r
                }\r
                \r
+               /**\r
+                * Creates a database accessor\r
+                */\r
+               function &getDatabaseAccessor($type, $host, $port, $database, $username, $password) {\r
+                       include_once('../classes/database/' . $type . '.php');\r
+                       $localData = new $type( $host,\r
+                                                                                       $port,\r
+                                                                                       $database,\r
+                                                                                       $username,\r
+                                                                                       $password);\r
+                       \r
+                       return $localData;\r
+               }\r
+               \r
        \r
        }\r
 ?>
\ No newline at end of file
index e8780fe8f4dba0a1cf970cf30138db9c787f63fe..c3a7e677bbf9aa5534c707d240d8f0f3fb5c0c88 100644 (file)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres\r
  * Note: This class uses ADODB and returns RecordSets.\r
  *\r
- * $Id: BaseDB.php,v 1.2 2002/02/18 13:06:13 chriskl Exp $\r
+ * $Id: BaseDB.php,v 1.3 2002/07/26 09:03:06 chriskl Exp $\r
  */\r
 \r
 include_once('../classes/database/ADODB_base.php');\r
@@ -12,21 +12,12 @@ include_once('../classes/database/ADODB_base.php');
 class BaseDB extends ADODB_base {\r
 \r
        // Filter objects for user?\r
-//     var $_filterTables = true;\r
        var $_showSystem = false;\r
        \r
        function BaseDB($type) {\r
                $this->ADODB_base($type);\r
        }\r
 \r
-       /**\r
-        * Set object filtering for user\r
-        * @param $state (boolean)\r
-        */\r
-//     function setFilterTables($state) {\r
-//             $this->_filterTables = $state;\r
-//     }\r
-       \r
        /**\r
         * Turn off or on the showing of 'system' object\r
         * @param True to turn system objects on, false to turn them off\r
@@ -35,47 +26,33 @@ class BaseDB extends ADODB_base {
                $this->_showSystem = $state;\r
        }\r
        \r
-        \r
-\r
-/*\r
-       // Feature functions\r
-\r
-       // Is "ALTER TABLE" with add column supported? \r
-       function supportsAlterTableWithAddColumn() {}\r
+       // Table functions\r
        \r
-       // Is "ALTER TABLE" with drop column supported? \r
-       function supportsAlterTableWithDropColumn() \r
-\r
-       // Are both data definition and data manipulation statements within a transaction supported? \r
-       function supportsDataDefinitionAndDataManipulationTransactions() \r
-\r
-       // Are only data manipulation statements within a transaction supported? \r
-       function supportsDataManipulationTransactionsOnly() \r
-\r
-       // Does the database treat mixed case unquoted SQL identifiers as case sensitive and as a result store them in mixed case? A JDBC CompliantTM driver will always return false. \r
-       function supportsMixedCaseIdentifiers() \r
-\r
-       // Does the database treat mixed case quoted SQL identifiers as case sensitive and as a result store them in mixed case? A JDBC CompliantTM driver will always return true. \r
-       function supportsMixedCaseQuotedIdentifiers() \r
-\r
-       // Can columns be defined as non-nullable? A JDBC CompliantTM driver always returns true. \r
-       function supportsNonNullableColumns() \r
-\r
-       // Are stored procedure calls using the stored procedure escape syntax supported? \r
-       function supportsStoredProcedures() \r
+       /**\r
+        * Delete a row from a table\r
+        * @param $table The table from which to delete\r
+        * @param $key An array mapping column => value to delete\r
+        * @return 0 success\r
+        */\r
+       function deleteRow($table, $key) {\r
+               if (!is_array($key)) return -1;\r
+               else return $this->delete($table, $key);\r
+       }       \r
        \r
-       // Are transactions supported? If not, invoking the method commit is a noop and the isolation level is TRANSACTION_NONE. \r
-       function supportsTransactions() \r
-\r
-       // Can you define your own aggregates?\r
-       function supportsAggregates()\r
-\r
-       // Can you define your own operators?\r
-       function supportsOperators()\r
-\r
-       // Database manipulation\r
+       // Capabilities\r
+       function hasTables() { return false; }\r
+       function hasViews() { return false; }\r
+       function hasSequences() { return false; }\r
+       function hasFunctions() { return false; }\r
+       function hasTriggers() { return false; }\r
+       function hasOperators() { return false; }\r
+       function hasTypes() { return false; }\r
+       function hasAggregates() { return false; }\r
+       function hasRules() { return false; }\r
+       function hasLanguages() { return false; }\r
+       function hasSchemas() { return false; }\r
+       function hasConversions() { return false; }\r
 \r
-*/\r
 }\r
 \r
 ?>
\ No newline at end of file
diff --git a/classes/database/Postgres.php b/classes/database/Postgres.php
new file mode 100755 (executable)
index 0000000..9dd510b
--- /dev/null
@@ -0,0 +1,743 @@
+<?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
index b0e8f538780df1c31e399aa1423286e4f18b949a..ee18b3d1be779e14f3cb27a8c70cbde085a6a9c3 100644 (file)
@@ -4,14 +4,14 @@
  * A class that implements the DB interface for Postgres\r
  * Note: This class uses ADODB and returns RecordSets.\r
  *\r
- * $Id: Postgres71.php,v 1.10 2002/07/25 13:14:31 shunter10 Exp $\r
+ * $Id: Postgres71.php,v 1.11 2002/07/26 09:03:06 chriskl Exp $\r
  */\r
 \r
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???\r
 \r
-include_once('../classes/database/BaseDB.php');\r
+include_once('../classes/database/Postgres.php');\r
 \r
-class Postgres71 extends BaseDB {\r
+class Postgres71 extends Postgres {\r
 \r
        var $dbFields = array('dbname' => 'datname', 'dbcomment' => 'description');\r
        var $tbFields = array('tbname' => 'tablename', 'tbowner' => 'tableowner');\r
@@ -23,12 +23,7 @@ class Postgres71 extends BaseDB {
        var $_maxNameLen = 31;\r
 \r
        function Postgres71($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
+               $this->Postgres($host, $port, $database, $user, $password);\r
        }\r
 \r
        /**\r
@@ -436,15 +431,7 @@ class Postgres71 extends BaseDB {
        function doSelect()\r
        function doDelete()\r
        function doUpdate()\r
-*/\r
-\r
-    function &getSequences()\r
-    {\r
-               $sql = "SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relkind ='S' ORDER BY relname";\r
-               return $this->selectSet( $sql );\r
-    }\r
-\r
-    \r
+*/  \r
     \r
        // View functions\r
        \r
index 541b87b2ca6c56abc483cc6b0aacedb54f6a47ac..04a6f532e449d65960a1ab40f95416b489792725 100644 (file)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres\r
  * Note: This class uses ADODB and returns RecordSets.\r
  *\r
- * $Id: Postgres73.php,v 1.1 2002/07/11 06:02:57 chriskl Exp $\r
+ * $Id: Postgres73.php,v 1.2 2002/07/26 09:03:06 chriskl Exp $\r
  */\r
 \r
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???\r
@@ -14,9 +14,10 @@ include_once('../classes/database/Postgres71.php');
 class Postgres73 extends Postgres71 {\r
 \r
        var $nspFields = array('nspname' => 'nspname', 'nspowner' => 'nspowner');\r
+       var $conFields = array('conname' => 'conname', 'conowner' => 'conownder');\r
 \r
        // Store the current schema\r
-       var $_schema = 'public';\r
+       var $_schema;\r
 \r
        // @@ Should we bother querying for this?\r
        var $_lastSystemOID = 16568;\r
@@ -27,6 +28,32 @@ class Postgres73 extends Postgres71 {
 \r
        // Schema functions\r
        \r
+       /**\r
+        * Sets the current working schema\r
+        * @param $schema The the name of the schema to work in\r
+        * @return 0 success\r
+        * @return -3 setting search path failed\r
+        */\r
+       function setSchema($schema) {\r
+               $this->clean($schema);\r
+               \r
+               $sql = "SELECT nspname FROM pg_namespace WHERE nspname='{$schema}'";\r
+               \r
+               $rs = $this->selectRow($sql);\r
+               \r
+               // If the schema is found...\r
+               if ($rs->recordCount() == 1) {\r
+                       $status = $this->setSearchPath(array($rs->f['nspname']));\r
+                       if ($status == 0) {\r
+                               $this->_schema = $rs->f['nspname'];\r
+                               return 0;\r
+                       }\r
+                       else return $status;\r
+               }\r
+               else\r
+                       return -3;\r
+       }       \r
+       \r
        /**\r
         * Sets the current schema search path\r
         * @param $path An array of schemas in required search order\r
@@ -98,7 +125,62 @@ class Postgres73 extends Postgres71 {
                \r
                return $this->execute($sql);\r
        }\r
+       \r
+       // Conversions functions\r
+       \r
+       /**\r
+        * Return all conversions in the current database\r
+        * @return All conversions, sorted alphabetically\r
+        */\r
+       function &getConversions() {\r
+               $sql = "SELECT conname, conowner FROM pg_conversion ORDER BY conname";\r
+                                 \r
+               return $this->selectSet($sql);\r
+       }\r
+       \r
+       /**\r
+        * Return all information relating to a conversion\r
+        * @param $conversion The name of the conversion\r
+        * @return Conversion information\r
+        */\r
+       function &getConversionByName($conversion) {\r
+               $this->clean($conversion);\r
+               $sql = "SELECT * FROM pg_conversion WHERE conname='{$conversion}'";\r
+               return $this->selectRow($sql);\r
+       }\r
 \r
+       /**\r
+        * Creates a new conversion.\r
+        * @param $schemaname The name of the schema to create\r
+        * @param $authorization (optional) The username to create the schema for.\r
+        * @param $authorization (optional) If omitted, defaults to current user.\r
+        * @return 0 success\r
+        */\r
+        /*\r
+       function createSchema($schemaname, $authorization = '') {\r
+               $this->clean($schemaname);\r
+               $this->clean($authorization);\r
+               \r
+               $sql = "CREATE SCHEMA \"{$schemaname}\"";\r
+               if ($authorization != '') $sql .= " AUTHORIZATION \"{$authorization}\"";\r
+               \r
+               return $this->execute($sql);\r
+       }\r
+       */\r
+       /**\r
+        * Drops a schema.\r
+        * @param $schemaname The name of the schema to drop\r
+        * @return 0 success\r
+        */\r
+        /*\r
+       function dropSchema($schemaname) {\r
+               $this->clean($schemaname);\r
+               \r
+               $sql = "DROP SCHEMA \"{$schemaname}\"";\r
+               \r
+               return $this->execute($sql);\r
+       }       \r
+*/\r
        // Table functions\r
 \r
        /**\r
@@ -187,6 +269,7 @@ class Postgres73 extends Postgres71 {
         \r
        // Capabilities\r
        function hasSchemas() { return true; }\r
+       function hasConversions() { return true; }\r
 \r
 }\r
 \r
index a986489d7548a59a0c2b0e5efdfc098a5f835fd7..bb7d9ff8b47d24e2683b8e2d995381fe51a9b1f5 100644 (file)
@@ -3,7 +3,7 @@
  *  FILENAME:   sequence.php
  *  AUTHOR:     Ray Hunter <rhunter@venticon.com>
  *
- *  $Id: sequences.php,v 1.1 2002/07/25 13:22:51 shunter10 Exp $
+ *  $Id: sequences.php,v 1.2 2002/07/26 09:03:06 chriskl Exp $
  */
 
 include_once( '../conf/config.inc.php' );
@@ -40,6 +40,7 @@ function doDefault()
             //echo "<tr><td class=\"data{$id}", htmlspecialchars( $sequences->f[$data->seqFields['seqname']]), "</td>\n"; 
         }
         */
+        echo "</table>\n";
     }
     else
     {
index 2cfb3981404557f83bd7139d6bdd8a322c9f3e73..5da6210b9cf19ba23229905ced5dbc0f21f45a6d 100644 (file)
@@ -3,7 +3,7 @@
        /**\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
@@ -40,19 +79,35 @@ switch ($action) {
                                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
@@ -78,9 +133,28 @@ switch ($action) {
                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
index 04841165f0c732ac809728ffb67c42b28ed81033..783ee1921b00156d1d46f51cd95185975a4ad60b 100644 (file)
@@ -3,7 +3,7 @@
        /**\r
         * Manage views in a database\r
         *\r
-        * $Id: views.php,v 1.4 2002/07/11 06:01:14 chriskl Exp $\r
+        * $Id: views.php,v 1.5 2002/07/26 09:03:06 chriskl Exp $\r
         */\r
 \r
        // Include application functions\r
        echo "</body>\n";\r
        echo "</html>\n";\r
        \r
-?>
\ No newline at end of file
+?>\r
index f9c094486ad9a96cd190a16d42416382b9bc0e61..e9f7b7bd06e166bd392ae32ded95f6a132989766 100644 (file)
@@ -51,7 +51,6 @@ th.data
        background-color: #E6E6CC;
        text-align: center;
        font-family: verdana, arial, helvetica, sans-serif;
-       font-weight: bold;
        font-size: 14;
 }
 
@@ -61,8 +60,7 @@ td.data1
        background-color: #F3F3E9;
        text-align: left;
        font-family: verdana, arial, helvetica, sans-serif;
-       font-weight: bold;
-       font-size: 13;
+       font-size: 9pt;
 }
 
 td.data2
@@ -71,8 +69,7 @@ td.data2
        background-color: #E6E6CC;
        text-align: left;
        font-family: verdana, arial, helvetica, sans-serif;
-       font-weight: bold;
-       font-size: 13;
+       font-size: 9pt;
 }
 
 td.opbutton1 {